From 9be3b7bb7ddd4e8ed466f41c6f43de34424aeb8c Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sun, 14 Sep 2025 14:44:55 +0300 Subject: [PATCH 001/684] dt-bindings: pinctrl: samsung: add exynos8890 compatible Document the pinctrl compatible for the exynos8890 SoC. Let the driver handle our clocks for pinctrl as well. Signed-off-by: Ivaylo Ivanov Reviewed-by: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/pinctrl/samsung,pinctrl.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml index f1094d65e84603..076d960a62c92e 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml @@ -52,6 +52,7 @@ properties: - samsung,exynos7870-pinctrl - samsung,exynos7885-pinctrl - samsung,exynos850-pinctrl + - samsung,exynos8890-pinctrl - samsung,exynos8895-pinctrl - samsung,exynos9810-pinctrl - samsung,exynos990-pinctrl @@ -133,7 +134,9 @@ allOf: properties: compatible: contains: - const: google,gs101-pinctrl + enum: + - google,gs101-pinctrl + - samsung,exynos8890-pinctrl then: required: - clocks From f416d35e6522f0c08d4e866e5d6930bfd504e645 Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sun, 14 Sep 2025 14:44:56 +0300 Subject: [PATCH 002/684] dt-bindings: pinctrl: samsung: add exynos8890-wakeup-eint compatible Add a dedicated compatible for exynos8890. Signed-off-by: Ivaylo Ivanov Signed-off-by: Krzysztof Kozlowski --- .../bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml index dd11c73a55da3f..f3c433015b125e 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml +++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml @@ -41,6 +41,7 @@ properties: - samsung,exynos7870-wakeup-eint - samsung,exynos7885-wakeup-eint - samsung,exynos850-wakeup-eint + - samsung,exynos8890-wakeup-eint - samsung,exynos8895-wakeup-eint - const: samsung,exynos7-wakeup-eint - items: From 5b6b7d39cee69373dc61ca22164d616e4faf60c6 Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sun, 14 Sep 2025 14:44:57 +0300 Subject: [PATCH 003/684] pinctrl: samsung: add exynos8890 SoC pinctrl configuration Add support for the pin-controller found on the exynos8890 SoC, used in Samsung Galaxy S7. Signed-off-by: Ivaylo Ivanov Reviewed-by: Igor Belwon Signed-off-by: Krzysztof Kozlowski --- .../pinctrl/samsung/pinctrl-exynos-arm64.c | 157 ++++++++++++++++++ drivers/pinctrl/samsung/pinctrl-samsung.c | 2 + drivers/pinctrl/samsung/pinctrl-samsung.h | 1 + 3 files changed, 160 insertions(+) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c index 323487dfa8c2cb..3258147deccad2 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c @@ -1485,6 +1485,163 @@ const struct samsung_pinctrl_of_match_data exynosautov920_of_data __initconst = .num_ctrl = ARRAY_SIZE(exynosautov920_pin_ctrl), }; +/* pin banks of exynos8890 pin-controller 0 (ALIVE) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks0[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS7870_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00), + EXYNOS7870_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04), + EXYNOS7870_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08), + EXYNOS7870_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c), +}; + +/* pin banks of exynos8890 pin-controller 1 (AUD) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks1[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(7, 0x000, "gph0", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 2 (CCORE) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks2[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(2, 0x000, "etc0", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 3 (ESE) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks3[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(5, 0x000, "gpf3", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 4 (FP) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks4[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(4, 0x000, "gpf2", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 5 (FSYS0) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks5[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(4, 0x000, "gpi1", 0x00), + EXYNOS8895_PIN_BANK_EINTG(8, 0x020, "gpi2", 0x04), +}; + +/* pin banks of exynos8890 pin-controller 6 (FSYS1) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks6[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(7, 0x000, "gpj0", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 7 (NFC) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks7[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(3, 0x000, "gpf0", 0x00), +}; + +/* pin banks of exynos8890 pin-controller 8 (PERIC0) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks8[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(6, 0x000, "gpi0", 0x00), + EXYNOS8895_PIN_BANK_EINTG(8, 0x020, "gpd0", 0x04), + EXYNOS8895_PIN_BANK_EINTG(6, 0x040, "gpd1", 0x08), + EXYNOS8895_PIN_BANK_EINTG(4, 0x060, "gpd2", 0x0c), + EXYNOS8895_PIN_BANK_EINTG(4, 0x080, "gpd3", 0x10), + EXYNOS8895_PIN_BANK_EINTG(2, 0x0A0, "gpb1", 0x14), + EXYNOS8895_PIN_BANK_EINTG(2, 0x0C0, "gpb2", 0x18), + EXYNOS8895_PIN_BANK_EINTG(3, 0x0E0, "gpb0", 0x1c), + EXYNOS8895_PIN_BANK_EINTG(5, 0x100, "gpc0", 0x20), + EXYNOS8895_PIN_BANK_EINTG(5, 0x120, "gpc1", 0x24), + EXYNOS8895_PIN_BANK_EINTG(6, 0x140, "gpc2", 0x28), + EXYNOS8895_PIN_BANK_EINTG(8, 0x160, "gpc3", 0x2c), + EXYNOS8895_PIN_BANK_EINTG(4, 0x180, "gpk0", 0x30), + EXYNOS8895_PIN_BANK_EINTG(7, 0x1A0, "etc1", 0x34), +}; + +/* pin banks of exynos8890 pin-controller 9 (PERIC1) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks9[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00), + EXYNOS8895_PIN_BANK_EINTG(8, 0x020, "gpe5", 0x04), + EXYNOS8895_PIN_BANK_EINTG(8, 0x040, "gpe6", 0x08), + EXYNOS8895_PIN_BANK_EINTG(8, 0x060, "gpj1", 0x0c), + EXYNOS8895_PIN_BANK_EINTG(2, 0x080, "gpj2", 0x10), + EXYNOS8895_PIN_BANK_EINTG(8, 0x0A0, "gpe2", 0x14), + EXYNOS8895_PIN_BANK_EINTG(8, 0x0C0, "gpe3", 0x18), + EXYNOS8895_PIN_BANK_EINTG(8, 0x0E0, "gpe4", 0x1c), + EXYNOS8895_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20), + EXYNOS8895_PIN_BANK_EINTG(4, 0x120, "gpe7", 0x24), + EXYNOS8895_PIN_BANK_EINTG(3, 0x140, "gpg0", 0x28), +}; + +/* pin banks of exynos8890 pin-controller 10 (TOUCH) */ +static const struct samsung_pin_bank_data exynos8890_pin_banks10[] __initconst = { + /* Must start with EINTG banks, ordered by EINT group number. */ + EXYNOS8895_PIN_BANK_EINTG(3, 0x000, "gpf1", 0x00), +}; + +static const struct samsung_pin_ctrl exynos8890_pin_ctrl[] __initconst = { + { + /* pin-controller instance 0 Alive data */ + .pin_banks = exynos8890_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks0), + .eint_wkup_init = exynos_eint_wkup_init, + }, { + /* pin-controller instance 1 AUD data */ + .pin_banks = exynos8890_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks1), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 2 CCORE data */ + .pin_banks = exynos8890_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks2), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 3 ESE data */ + .pin_banks = exynos8890_pin_banks3, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks3), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 4 FP data */ + .pin_banks = exynos8890_pin_banks4, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks4), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 5 FSYS0 data */ + .pin_banks = exynos8890_pin_banks5, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks5), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 6 FSYS1 data */ + .pin_banks = exynos8890_pin_banks6, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks6), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 7 NFC data */ + .pin_banks = exynos8890_pin_banks7, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks7), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 8 PERIC0 data */ + .pin_banks = exynos8890_pin_banks8, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks8), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 9 PERIC1 data */ + .pin_banks = exynos8890_pin_banks9, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks9), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 10 TOUCH data */ + .pin_banks = exynos8890_pin_banks10, + .nr_banks = ARRAY_SIZE(exynos8890_pin_banks10), + .eint_gpio_init = exynos_eint_gpio_init, + }, +}; + +const struct samsung_pinctrl_of_match_data exynos8890_of_data __initconst = { + .ctrl = exynos8890_pin_ctrl, + .num_ctrl = ARRAY_SIZE(exynos8890_pin_ctrl), +}; + /* pin banks of exynos8895 pin-controller 0 (ALIVE) */ static const struct samsung_pin_bank_data exynos8895_pin_banks0[] __initconst = { EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa0", 0x00), diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index c099195fc464e3..7974122799c4fb 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1498,6 +1498,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { .data = &exynos7885_of_data }, { .compatible = "samsung,exynos850-pinctrl", .data = &exynos850_of_data }, + { .compatible = "samsung,exynos8890-pinctrl", + .data = &exynos8890_of_data }, { .compatible = "samsung,exynos8895-pinctrl", .data = &exynos8895_of_data }, { .compatible = "samsung,exynos9810-pinctrl", diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 3e8ef91d94a36e..d00079ad673cea 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -395,6 +395,7 @@ extern const struct samsung_pinctrl_of_match_data exynos7_of_data; extern const struct samsung_pinctrl_of_match_data exynos7870_of_data; extern const struct samsung_pinctrl_of_match_data exynos7885_of_data; extern const struct samsung_pinctrl_of_match_data exynos850_of_data; +extern const struct samsung_pinctrl_of_match_data exynos8890_of_data; extern const struct samsung_pinctrl_of_match_data exynos8895_of_data; extern const struct samsung_pinctrl_of_match_data exynos9810_of_data; extern const struct samsung_pinctrl_of_match_data exynos990_of_data; From 8c644749ab6e42f51fce82e3325f58ffb70f87b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 7 Oct 2025 17:03:10 +0100 Subject: [PATCH 004/684] dt-bindings: clock: google,gs101-clock: add power-domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CMU can be part of a power domain, so we need to allow the relevant property 'power-domains'. Signed-off-by: André Draszik Acked-by: Rob Herring (Arm) Reviewed-by: Peter Griffin Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/clock/google,gs101-clock.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/google,gs101-clock.yaml b/Documentation/devicetree/bindings/clock/google,gs101-clock.yaml index caf442ead24bda..31e106ef913dea 100644 --- a/Documentation/devicetree/bindings/clock/google,gs101-clock.yaml +++ b/Documentation/devicetree/bindings/clock/google,gs101-clock.yaml @@ -46,6 +46,9 @@ properties: "#clock-cells": const: 1 + power-domains: + maxItems: 1 + reg: maxItems: 1 From 4914c17a76047ccbde24397cf9d406558183d756 Mon Sep 17 00:00:00 2001 From: Raghav Sharma Date: Mon, 15 Sep 2025 15:23:59 +0530 Subject: [PATCH 005/684] dt-bindings: clock: exynosautov920: add m2m clock definitions Add device tree clock binding definitions for CMU_M2M Signed-off-by: Raghav Sharma Acked-by: Rob Herring (Arm) Reviewed-by: Alim Akhtar Signed-off-by: Krzysztof Kozlowski --- .../clock/samsung,exynosautov920-clock.yaml | 21 +++++++++++++++++++ .../clock/samsung,exynosautov920.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml index 72f59db73f76c7..b2dfe6ed353aa9 100644 --- a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml +++ b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml @@ -38,6 +38,7 @@ properties: - samsung,exynosautov920-cmu-hsi0 - samsung,exynosautov920-cmu-hsi1 - samsung,exynosautov920-cmu-hsi2 + - samsung,exynosautov920-cmu-m2m - samsung,exynosautov920-cmu-misc - samsung,exynosautov920-cmu-peric0 - samsung,exynosautov920-cmu-peric1 @@ -226,6 +227,26 @@ allOf: - const: embd - const: ethernet + - if: + properties: + compatible: + contains: + const: samsung,exynosautov920-cmu-m2m + + then: + properties: + clocks: + items: + - description: External reference clock (38.4 MHz) + - description: CMU_M2M NOC clock (from CMU_TOP) + - description: CMU_M2M JPEG clock (from CMU_TOP) + + clock-names: + items: + - const: oscclk + - const: noc + - const: jpeg + required: - compatible - "#clock-cells" diff --git a/include/dt-bindings/clock/samsung,exynosautov920.h b/include/dt-bindings/clock/samsung,exynosautov920.h index 93e6233d1358c5..0342a988565a0c 100644 --- a/include/dt-bindings/clock/samsung,exynosautov920.h +++ b/include/dt-bindings/clock/samsung,exynosautov920.h @@ -295,4 +295,9 @@ #define CLK_DOUT_HSI2_ETHERNET 6 #define CLK_DOUT_HSI2_ETHERNET_PTP 7 +/* CMU_M2M */ +#define CLK_MOUT_M2M_JPEG_USER 1 +#define CLK_MOUT_M2M_NOC_USER 2 +#define CLK_DOUT_M2M_NOCP 3 + #endif /* _DT_BINDINGS_CLOCK_EXYNOSAUTOV920_H */ From 0b94201e327471d034d81cf5fd2131a5529eea19 Mon Sep 17 00:00:00 2001 From: Raghav Sharma Date: Thu, 25 Sep 2025 18:34:55 +0530 Subject: [PATCH 006/684] dt-bindings: clock: exynosautov920: add mfc clock definitions Add device tree clock binding definitions for CMU_MFC Signed-off-by: Raghav Sharma Reviewed-by: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski --- .../clock/samsung,exynosautov920-clock.yaml | 21 +++++++++++++++++++ .../clock/samsung,exynosautov920.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml index b2dfe6ed353aa9..5bf905f88a1ac1 100644 --- a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml +++ b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml @@ -39,6 +39,7 @@ properties: - samsung,exynosautov920-cmu-hsi1 - samsung,exynosautov920-cmu-hsi2 - samsung,exynosautov920-cmu-m2m + - samsung,exynosautov920-cmu-mfc - samsung,exynosautov920-cmu-misc - samsung,exynosautov920-cmu-peric0 - samsung,exynosautov920-cmu-peric1 @@ -247,6 +248,26 @@ allOf: - const: noc - const: jpeg + - if: + properties: + compatible: + contains: + const: samsung,exynosautov920-cmu-mfc + + then: + properties: + clocks: + items: + - description: External reference clock (38.4 MHz) + - description: CMU_MFC MFC clock (from CMU_TOP) + - description: CMU_MFC WFD clock (from CMU_TOP) + + clock-names: + items: + - const: oscclk + - const: mfc + - const: wfd + required: - compatible - "#clock-cells" diff --git a/include/dt-bindings/clock/samsung,exynosautov920.h b/include/dt-bindings/clock/samsung,exynosautov920.h index 0342a988565a0c..970d05167fc636 100644 --- a/include/dt-bindings/clock/samsung,exynosautov920.h +++ b/include/dt-bindings/clock/samsung,exynosautov920.h @@ -300,4 +300,9 @@ #define CLK_MOUT_M2M_NOC_USER 2 #define CLK_DOUT_M2M_NOCP 3 +/* CMU_MFC */ +#define CLK_MOUT_MFC_MFC_USER 1 +#define CLK_MOUT_MFC_WFD_USER 2 +#define CLK_DOUT_MFC_NOCP 3 + #endif /* _DT_BINDINGS_CLOCK_EXYNOSAUTOV920_H */ From ac5d829873c737edae220ee654e423d383163630 Mon Sep 17 00:00:00 2001 From: Raghav Sharma Date: Mon, 15 Sep 2025 15:24:00 +0530 Subject: [PATCH 007/684] clk: samsung: exynosautov920: add clock support Add support for CMU_M2M which provides clocks to M2M block, and register the required compatible and cmu_info for the same. Signed-off-by: Raghav Sharma Reviewed-by: Alim Akhtar Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynosautov920.c | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c index 572b6ace14acd7..75deec8bece542 100644 --- a/drivers/clk/samsung/clk-exynosautov920.c +++ b/drivers/clk/samsung/clk-exynosautov920.c @@ -27,6 +27,7 @@ #define CLKS_NR_HSI0 (CLK_DOUT_HSI0_PCIE_APB + 1) #define CLKS_NR_HSI1 (CLK_MOUT_HSI1_USBDRD + 1) #define CLKS_NR_HSI2 (CLK_DOUT_HSI2_ETHERNET_PTP + 1) +#define CLKS_NR_M2M (CLK_DOUT_M2M_NOCP + 1) /* ---- CMU_TOP ------------------------------------------------------------ */ @@ -1821,6 +1822,47 @@ static const struct samsung_cmu_info hsi2_cmu_info __initconst = { .clk_name = "noc", }; +/* ---- CMU_M2M --------------------------------------------------------- */ + +/* Register Offset definitions for CMU_M2M (0x1a800000) */ +#define PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER 0x600 +#define PLL_CON0_MUX_CLKCMU_M2M_NOC_USER 0x610 +#define CLK_CON_DIV_DIV_CLK_M2M_NOCP 0x1800 + +static const unsigned long m2m_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER, + PLL_CON0_MUX_CLKCMU_M2M_NOC_USER, + CLK_CON_DIV_DIV_CLK_M2M_NOCP, +}; + +/* List of parent clocks for Muxes in CMU_M2M */ +PNAME(mout_clkcmu_m2m_noc_user_p) = { "oscclk", "dout_clkcmu_m2m_noc" }; +PNAME(mout_clkcmu_m2m_jpeg_user_p) = { "oscclk", "dout_clkcmu_m2m_jpeg" }; + +static const struct samsung_mux_clock m2m_mux_clks[] __initconst = { + MUX(CLK_MOUT_M2M_JPEG_USER, "mout_clkcmu_m2m_jpeg_user", + mout_clkcmu_m2m_jpeg_user_p, PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER, 4, 1), + MUX(CLK_MOUT_M2M_NOC_USER, "mout_clkcmu_m2m_noc_user", + mout_clkcmu_m2m_noc_user_p, PLL_CON0_MUX_CLKCMU_M2M_NOC_USER, 4, 1), +}; + +static const struct samsung_div_clock m2m_div_clks[] __initconst = { + DIV(CLK_DOUT_M2M_NOCP, "dout_m2m_nocp", + "mout_clkcmu_m2m_noc_user", CLK_CON_DIV_DIV_CLK_M2M_NOCP, + 0, 3), +}; + +static const struct samsung_cmu_info m2m_cmu_info __initconst = { + .mux_clks = m2m_mux_clks, + .nr_mux_clks = ARRAY_SIZE(m2m_mux_clks), + .div_clks = m2m_div_clks, + .nr_div_clks = ARRAY_SIZE(m2m_div_clks), + .nr_clk_ids = CLKS_NR_M2M, + .clk_regs = m2m_clk_regs, + .nr_clk_regs = ARRAY_SIZE(m2m_clk_regs), + .clk_name = "noc", +}; + static int __init exynosautov920_cmu_probe(struct platform_device *pdev) { const struct samsung_cmu_info *info; @@ -1851,6 +1893,9 @@ static const struct of_device_id exynosautov920_cmu_of_match[] = { }, { .compatible = "samsung,exynosautov920-cmu-hsi2", .data = &hsi2_cmu_info, + }, { + .compatible = "samsung,exynosautov920-cmu-m2m", + .data = &m2m_cmu_info, }, { } }; From 25e476632cf7135aba11b27e3807a2692a3e5e13 Mon Sep 17 00:00:00 2001 From: Raghav Sharma Date: Thu, 25 Sep 2025 18:34:56 +0530 Subject: [PATCH 008/684] clk: samsung: exynosautov920: add block mfc clock support Add support for CMU_MFC which provides clocks to MFC block, and register the required compatible and cmu_info for the same. Signed-off-by: Raghav Sharma Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynosautov920.c | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c index 75deec8bece542..b90b73c3518fe3 100644 --- a/drivers/clk/samsung/clk-exynosautov920.c +++ b/drivers/clk/samsung/clk-exynosautov920.c @@ -28,6 +28,7 @@ #define CLKS_NR_HSI1 (CLK_MOUT_HSI1_USBDRD + 1) #define CLKS_NR_HSI2 (CLK_DOUT_HSI2_ETHERNET_PTP + 1) #define CLKS_NR_M2M (CLK_DOUT_M2M_NOCP + 1) +#define CLKS_NR_MFC (CLK_DOUT_MFC_NOCP + 1) /* ---- CMU_TOP ------------------------------------------------------------ */ @@ -1863,6 +1864,47 @@ static const struct samsung_cmu_info m2m_cmu_info __initconst = { .clk_name = "noc", }; +/* ---- CMU_MFC --------------------------------------------------------- */ + +/* Register Offset definitions for CMU_MFC (0x19c00000) */ +#define PLL_CON0_MUX_CLKCMU_MFC_MFC_USER 0x600 +#define PLL_CON0_MUX_CLKCMU_MFC_WFD_USER 0x610 +#define CLK_CON_DIV_DIV_CLK_MFC_NOCP 0x1800 + +static const unsigned long mfc_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_MFC_MFC_USER, + PLL_CON0_MUX_CLKCMU_MFC_WFD_USER, + CLK_CON_DIV_DIV_CLK_MFC_NOCP, +}; + +/* List of parent clocks for Muxes in CMU_MFC */ +PNAME(mout_clkcmu_mfc_mfc_user_p) = { "oscclk", "dout_clkcmu_mfc_mfc" }; +PNAME(mout_clkcmu_mfc_wfd_user_p) = { "oscclk", "dout_clkcmu_mfc_wfd" }; + +static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { + MUX(CLK_MOUT_MFC_MFC_USER, "mout_clkcmu_mfc_mfc_user", + mout_clkcmu_mfc_mfc_user_p, PLL_CON0_MUX_CLKCMU_MFC_MFC_USER, 4, 1), + MUX(CLK_MOUT_MFC_WFD_USER, "mout_clkcmu_mfc_wfd_user", + mout_clkcmu_mfc_wfd_user_p, PLL_CON0_MUX_CLKCMU_MFC_WFD_USER, 4, 1), +}; + +static const struct samsung_div_clock mfc_div_clks[] __initconst = { + DIV(CLK_DOUT_MFC_NOCP, "dout_mfc_nocp", + "mout_clkcmu_mfc_mfc_user", CLK_CON_DIV_DIV_CLK_MFC_NOCP, + 0, 3), +}; + +static const struct samsung_cmu_info mfc_cmu_info __initconst = { + .mux_clks = mfc_mux_clks, + .nr_mux_clks = ARRAY_SIZE(mfc_mux_clks), + .div_clks = mfc_div_clks, + .nr_div_clks = ARRAY_SIZE(mfc_div_clks), + .nr_clk_ids = CLKS_NR_MFC, + .clk_regs = mfc_clk_regs, + .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), + .clk_name = "noc", +}; + static int __init exynosautov920_cmu_probe(struct platform_device *pdev) { const struct samsung_cmu_info *info; @@ -1896,6 +1938,9 @@ static const struct of_device_id exynosautov920_cmu_of_match[] = { }, { .compatible = "samsung,exynosautov920-cmu-m2m", .data = &m2m_cmu_info, + }, { + .compatible = "samsung,exynosautov920-cmu-mfc", + .data = &mfc_cmu_info, }, { } }; From e671a1bb5d1cf9ca4dbab61b9a3e1e77579f99ba Mon Sep 17 00:00:00 2001 From: SeonGu Kang Date: Wed, 17 Sep 2025 12:30:03 +0530 Subject: [PATCH 009/684] dt-bindings: pinctrl: samsung: Add compatible for ARTPEC-9 SoC Document the compatible string for ARTPEC-9 SoC pinctrl block, which is similar to other Samsung SoC pinctrl blocks. Signed-off-by: SeonGu Kang Signed-off-by: Ravi Patel Acked-by: Conor Dooley Signed-off-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml index 076d960a62c92e..ddc5e2efff21fa 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml @@ -36,6 +36,7 @@ properties: compatible: enum: - axis,artpec8-pinctrl + - axis,artpec9-pinctrl - google,gs101-pinctrl - samsung,s3c64xx-pinctrl - samsung,s5pv210-pinctrl From 3cfc60e09bdc95483875f0b63cfdc23aea67135b Mon Sep 17 00:00:00 2001 From: SeonGu Kang Date: Wed, 17 Sep 2025 12:30:04 +0530 Subject: [PATCH 010/684] pinctrl: samsung: Add ARTPEC-9 SoC specific configuration Add Axis ARTPEC-9 SoC specific configuration data to enable pinctrl. Signed-off-by: SeonGu Kang Signed-off-by: Ravi Patel Signed-off-by: Krzysztof Kozlowski --- .../pinctrl/samsung/pinctrl-exynos-arm64.c | 49 +++++++++++++++++++ drivers/pinctrl/samsung/pinctrl-samsung.c | 2 + drivers/pinctrl/samsung/pinctrl-samsung.h | 1 + 3 files changed, 52 insertions(+) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c index 3258147deccad2..627dca504d7a92 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c @@ -2023,3 +2023,52 @@ const struct samsung_pinctrl_of_match_data artpec8_of_data __initconst = { .ctrl = artpec8_pin_ctrl, .num_ctrl = ARRAY_SIZE(artpec8_pin_ctrl), }; + +/* pin banks of artpec9 pin-controller (FSYS0) */ +static const struct samsung_pin_bank_data artpec9_pin_banks0[] __initconst = { + ARTPEC_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00), + ARTPEC_PIN_BANK_EINTG(8, 0x020, "gpf1", 0x04), + ARTPEC_PIN_BANK_EINTG(8, 0x040, "gpe0", 0x08), + ARTPEC_PIN_BANK_EINTG(8, 0x060, "gpe1", 0x0c), + ARTPEC_PIN_BANK_EINTG(8, 0x080, "gpe2", 0x10), + ARTPEC_PIN_BANK_EINTG(8, 0x0a0, "gpe3", 0x14), + ARTPEC_PIN_BANK_EINTG(2, 0x0c0, "gpe4", 0x18), + ARTPEC_PIN_BANK_EINTG(8, 0x0e0, "gps0", 0x1c), + ARTPEC_PIN_BANK_EINTG(8, 0x100, "gps1", 0x20), + ARTPEC_PIN_BANK_EINTG(5, 0x120, "gpi0", 0x24), +}; + +/* pin banks of artpec9 pin-controller (FSYS1) */ +static const struct samsung_pin_bank_data artpec9_pin_banks1[] __initconst = { + ARTPEC_PIN_BANK_EINTG(2, 0x000, "gpu0", 0x00), +}; + +/* pin banks of artpec9 pin-controller (PERIC) */ +static const struct samsung_pin_bank_data artpec9_pin_banks2[] __initconst = { + ARTPEC_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + ARTPEC_PIN_BANK_EINTG(8, 0x020, "gpa1", 0x04), +}; + +static const struct samsung_pin_ctrl artpec9_pin_ctrl[] __initconst = { + { + /* pin-controller instance 0 FSYS0 data */ + .pin_banks = artpec9_pin_banks0, + .nr_banks = ARRAY_SIZE(artpec9_pin_banks0), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 1 FSYS1 data */ + .pin_banks = artpec9_pin_banks1, + .nr_banks = ARRAY_SIZE(artpec9_pin_banks1), + .eint_gpio_init = exynos_eint_gpio_init, + }, { + /* pin-controller instance 2 PERIC data */ + .pin_banks = artpec9_pin_banks2, + .nr_banks = ARRAY_SIZE(artpec9_pin_banks2), + .eint_gpio_init = exynos_eint_gpio_init, + }, +}; + +const struct samsung_pinctrl_of_match_data artpec9_of_data __initconst = { + .ctrl = artpec9_pin_ctrl, + .num_ctrl = ARRAY_SIZE(artpec9_pin_ctrl), +}; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 7974122799c4fb..e374effba25a76 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1484,6 +1484,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { #ifdef CONFIG_PINCTRL_EXYNOS_ARM64 { .compatible = "axis,artpec8-pinctrl", .data = &artpec8_of_data }, + { .compatible = "axis,artpec9-pinctrl", + .data = &artpec9_of_data }, { .compatible = "google,gs101-pinctrl", .data = &gs101_of_data }, { .compatible = "samsung,exynos2200-pinctrl", diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index d00079ad673cea..0f7b2ea9815868 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -382,6 +382,7 @@ struct samsung_pmx_func { /* list of all exported SoC specific data */ extern const struct samsung_pinctrl_of_match_data artpec8_of_data; +extern const struct samsung_pinctrl_of_match_data artpec9_of_data; extern const struct samsung_pinctrl_of_match_data exynos2200_of_data; extern const struct samsung_pinctrl_of_match_data exynos3250_of_data; extern const struct samsung_pinctrl_of_match_data exynos4210_of_data; From 4b5dafe616a5553f377a5f96bd02a191187eba86 Mon Sep 17 00:00:00 2001 From: James Clark Date: Wed, 8 Oct 2025 13:42:00 +0100 Subject: [PATCH 011/684] perf tests: use strdup() in "Object code reading" Use strdup() instead of fixed PATH_MAX buffer for storing paths to not waste memory. Suggested-by: Ian Rogers Reviewed-by: Ian Rogers Signed-off-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/code-reading.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 4c9fbf6965c4ad..1acb12b1a2eb31 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -43,7 +43,7 @@ struct tested_section { struct rb_node rb_node; u64 addr; - char path[PATH_MAX]; + char *path; }; static bool tested_code_insert_or_exists(const char *path, u64 addr, @@ -79,7 +79,11 @@ static bool tested_code_insert_or_exists(const char *path, u64 addr, return true; data->addr = addr; - strlcpy(data->path, path, sizeof(data->path)); + data->path = strdup(path); + if (!data->path) { + free(data); + return true; + } rb_link_node(&data->rb_node, parent, node); rb_insert_color(&data->rb_node, tested_sections); return false; @@ -94,6 +98,7 @@ static void tested_sections__free(struct rb_root *root) rb_node); rb_erase(node, root); + free(ts->path); free(ts); } } From 12690401a4393238c391b7a6a861a28d26374013 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:14:21 -0700 Subject: [PATCH 012/684] perf stat: Additional verbose details for events If an event shows as "" in perf stat output, in verbose mode add the strerror output to help diagnose the issue. Consider: ``` $ perf stat -e cycles,data_read,instructions true Performance counter stats for 'true': 357,457 cycles:u MiB data_read:u 156,182 instructions:u # 0.44 insn per cycle 0.001250315 seconds time elapsed 0.001283000 seconds user 0.000000000 seconds sys ``` To understand why the data_read uncore event failed you can run it again with -v option. This change adds detailed message about the error and suggestion how to fix it potentially. Warning: data_read:u event is not supported by the kernel. Invalid event (data_read:u) in per-thread mode, enable system wide with '-a'. Signed-off-by: Ian Rogers [ simplified the commit message ] Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7006f848f87a63..84e06ec09cc270 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -624,8 +624,9 @@ static enum counter_recovery stat_handle_error(struct evsel *counter, int err) */ if (err == EINVAL || err == ENOSYS || err == ENOENT || err == ENXIO) { if (verbose > 0) { - ui__warning("%s event is not supported by the kernel.\n", - evsel__name(counter)); + evsel__open_strerror(counter, &target, err, msg, sizeof(msg)); + ui__warning("%s event is not supported by the kernel.\n%s\n", + evsel__name(counter), msg); } return COUNTER_SKIP; } @@ -649,10 +650,11 @@ static enum counter_recovery stat_handle_error(struct evsel *counter, int err) } } if (verbose > 0) { + evsel__open_strerror(counter, &target, err, msg, sizeof(msg)); ui__warning(err == EOPNOTSUPP - ? "%s event is not supported by the kernel.\n" - : "skipping event %s that kernel failed to open.\n", - evsel__name(counter)); + ? "%s event is not supported by the kernel.\n%s\n" + : "skipping event %s that kernel failed to open.\n%s\n", + evsel__name(counter), msg); } return COUNTER_SKIP; } From 6090e612cf24393335e709105db31b6d6e36d6ef Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 7 Oct 2025 08:38:35 -0700 Subject: [PATCH 013/684] perf build python: Don't leave a.out file when building with clang Testing clang features doesn't specify a "-o" option so an a.out file is created and left in the make directory (not the output). Fix this by specifying a "-o" of "/dev/null". Reorganize the code a little to help with readability. Signed-off-by: Ian Rogers Tested-by: Justin Stitt Signed-off-by: Namhyung Kim --- tools/perf/util/setup.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 9cae2c472f4ad4..b65b1792ca056f 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -23,10 +23,17 @@ src_feature_tests = f'{srctree}/tools/build/feature' def clang_has_option(option): - cmd = shlex.split(f"{cc} {cc_options} {option}") - cmd.append(path.join(src_feature_tests, "test-hello.c")) + error_substrings = ( + b"unknown argument", + b"is not supported", + b"unknown warning option" + ) + cmd = shlex.split(f"{cc} {cc_options} {option}") + [ + "-o", "/dev/null", + path.join(src_feature_tests, "test-hello.c") + ] cc_output = Popen(cmd, stderr=PIPE).stderr.readlines() - return [o for o in cc_output if ((b"unknown argument" in o) or (b"is not supported" in o) or (b"unknown warning option" in o))] == [ ] + return not any(any(error in line for error in error_substrings) for line in cc_output) if cc_is_clang: from sysconfig import get_config_vars From 2a67955de13624ec17d1c2504d2c9eeb37933b77 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 9 Oct 2025 06:29:11 -0700 Subject: [PATCH 014/684] perf bpf_counter: Fix opening of "any"(-1) CPU events The bperf BPF counter code doesn't handle "any"(-1) CPU events, always wanting to aggregate a count against a CPU, which avoids the need for atomics so let's not change that. Force evsels used for BPF counters to require a CPU when not in system-wide mode so that the "any"(-1) value isn't used during map propagation and evsel's CPU map matches that of the PMU. Fixes: b91917c0c6fa ("perf bpf_counter: Fix handling of cpumap fixing hybrid") Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 13 +++++++++++++ tools/perf/util/bpf_counter.c | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 84e06ec09cc270..4314012846ba34 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2542,6 +2542,7 @@ int cmd_stat(int argc, const char **argv) unsigned int interval, timeout; const char * const stat_subcommands[] = { "record", "report" }; char errbuf[BUFSIZ]; + struct evsel *counter; setlocale(LC_ALL, ""); @@ -2799,6 +2800,18 @@ int cmd_stat(int argc, const char **argv) evlist__warn_user_requested_cpus(evsel_list, target.cpu_list); + evlist__for_each_entry(evsel_list, counter) { + /* + * Setup BPF counters to require CPUs as any(-1) isn't + * supported. evlist__create_maps below will propagate this + * information to the evsels. Note, evsel__is_bperf isn't yet + * set up, and this change must happen early, so directly use + * the bpf_counter variable and target information. + */ + if ((counter->bpf_counter || target.use_bpf) && !target__has_cpu(&target)) + counter->core.requires_cpu = true; + } + if (evlist__create_maps(evsel_list, &target) < 0) { if (target__has_task(&target)) { pr_err("Problems finding threads of monitor\n"); diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c index ca5d01b9017dba..a5882b5822057b 100644 --- a/tools/perf/util/bpf_counter.c +++ b/tools/perf/util/bpf_counter.c @@ -460,6 +460,7 @@ static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd, struct bperf_leader_bpf *skel = bperf_leader_bpf__open(); int link_fd, diff_map_fd, err; struct bpf_link *link = NULL; + struct perf_thread_map *threads; if (!skel) { pr_err("Failed to open leader skeleton\n"); @@ -495,7 +496,11 @@ static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd, * following evsel__open_per_cpu call */ evsel->leader_skel = skel; - evsel__open(evsel, evsel->core.cpus, evsel->core.threads); + assert(!perf_cpu_map__has_any_cpu_or_is_empty(evsel->core.cpus)); + /* Always open system wide. */ + threads = thread_map__new_by_tid(-1); + evsel__open(evsel, evsel->core.cpus, threads); + perf_thread_map__put(threads); out: bperf_leader_bpf__destroy(skel); From d8d357b8a54f02ac5177ae5a69e0b47ea1cf584f Mon Sep 17 00:00:00 2001 From: Igor Belwon Date: Mon, 15 Sep 2025 14:46:23 +0200 Subject: [PATCH 015/684] dt-bindings: pinctrl: mediatek: Document MT6878 pin controller bindings Add device-tree bindings for the pin controller and the EINT controller found in the MediaTek MT6878 SoC. Signed-off-by: Igor Belwon Reviewed-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../pinctrl/mediatek,mt6878-pinctrl.yaml | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/mediatek,mt6878-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6878-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6878-pinctrl.yaml new file mode 100644 index 00000000000000..8d44194a793896 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6878-pinctrl.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/mediatek,mt6878-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6878 Pin Controller + +maintainers: + - AngeloGioacchino Del Regno + - Igor Belwon + +description: + The MediaTek MT6878 Pin controller is used to control SoC pins. + +properties: + compatible: + const: mediatek,mt6878-pinctrl + + reg: + items: + - description: pin controller base + - description: bl group IO + - description: bm group IO + - description: br group IO + - description: bl1 group IO + - description: br1 group IO + - description: lm group IO + - description: lt group IO + - description: rm group IO + - description: rt group IO + - description: EINT controller E block + - description: EINT controller S block + - description: EINT controller W block + - description: EINT controller C block + + reg-names: + items: + - const: base + - const: bl + - const: bm + - const: br + - const: bl1 + - const: br1 + - const: lm + - const: lt + - const: rm + - const: rt + - const: eint-e + - const: eint-s + - const: eint-w + - const: eint-c + + gpio-controller: true + + '#gpio-cells': + description: + Number of cells in GPIO specifier. Since the generic GPIO binding is used, + the amount of cells must be specified as 2. See the below mentioned gpio + binding representation for description of particular cells. + const: 2 + + gpio-ranges: + maxItems: 1 + + gpio-line-names: + maxItems: 216 + + interrupts: + description: The interrupt outputs to sysirq + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +# PIN CONFIGURATION NODES +patternProperties: + '-pins$': + type: object + additionalProperties: false + + patternProperties: + '^pins': + type: object + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml + - $ref: /schemas/pinctrl/pinmux-node.yaml + description: + A pinctrl node should contain at least one subnodes representing the + pinctrl groups available on the machine. Each subnode will list the + pins it needs, and how they should be configured, with regard to muxer + configuration, pullups, drive strength, input enable/disable and input + schmitt. + + properties: + pinmux: + description: + Integer array, represents gpio pin number and mux setting. + Supported pin number and mux are defined as macros in + arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h for this SoC. + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16] + + drive-strength-microamp: + enum: [125, 250, 500, 1000] + + bias-pull-down: + oneOf: + - type: boolean + - enum: [75000, 5000] + description: Pull down RSEL type resistance values (in ohms) + description: + For normal pull down type there is no need to specify a resistance + value, hence this can be specified as a boolean property. + For RSEL pull down type a resistance value (in ohms) can be added. + + bias-pull-up: + oneOf: + - type: boolean + - enum: [10000, 5000, 4000, 3000] + description: Pull up RSEL type resistance values (in ohms) + description: + For normal pull up type there is no need to specify a resistance + value, hence this can be specified as a boolean property. + For RSEL pull up type a resistance value (in ohms) can be added. + + bias-disable: true + + output-high: true + + output-low: true + + input-enable: true + + input-disable: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + required: + - pinmux + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +additionalProperties: false + +examples: + - | + #include + #include + #define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) + #define PINMUX_GPIO99__FUNC_SCL0 (MTK_PIN_NO(99) | 1) + #define PINMUX_GPIO100__FUNC_SDA0 (MTK_PIN_NO(100) | 1) + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6878-pinctrl"; + reg = <0x10005000 0x1000>, + <0x11d10000 0x1000>, + <0x11d30000 0x1000>, + <0x11d40000 0x1000>, + <0x11d50000 0x1000>, + <0x11d60000 0x1000>, + <0x11e20000 0x1000>, + <0x11e30000 0x1000>, + <0x11eb0000 0x1000>, + <0x11ec0000 0x1000>, + <0x11ce0000 0x1000>, + <0x11de0000 0x1000>, + <0x11e60000 0x1000>, + <0x1c01e000 0x1000>; + reg-names = "base", "bl", "bm", "br", "bl1", "br1", + "lm", "lt", "rm", "rt", "eint-e", "eint-s", + "eint-w", "eint-c"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 220>; + interrupt-controller; + interrupts = ; + #interrupt-cells = <2>; + + gpio-pins { + pins { + pinmux = ; + bias-pull-up = <4000>; + drive-strength = <6>; + }; + }; + + i2c0-pins { + pins-bus { + pinmux = , + ; + bias-pull-down = <75000>; + drive-strength-microamp = <1000>; + }; + }; + }; From 18349bfb391aa32ec7bb2c3496e1239196a51545 Mon Sep 17 00:00:00 2001 From: Igor Belwon Date: Mon, 15 Sep 2025 14:46:24 +0200 Subject: [PATCH 016/684] pinctrl: mediatek: Add debounce times for MT6878 MT6878 uses different debounce times than other SoCs. Add them to the EINT driver. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Igor Belwon Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/mtk-eint.c | 5 +++++ drivers/pinctrl/mediatek/mtk-eint.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c index 9f175c73613f84..c8c5097c11c4d1 100644 --- a/drivers/pinctrl/mediatek/mtk-eint.c +++ b/drivers/pinctrl/mediatek/mtk-eint.c @@ -66,6 +66,11 @@ const unsigned int debounce_time_mt6795[] = { }; EXPORT_SYMBOL_GPL(debounce_time_mt6795); +const unsigned int debounce_time_mt6878[] = { + 156, 313, 625, 1250, 20000, 40000, 80000, 160000, 320000, 640000, 0 +}; +EXPORT_SYMBOL_GPL(debounce_time_mt6878); + static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint, unsigned int eint_num, unsigned int offset) diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h index fc31a4c0c77bf2..3cdd6f6310cd0d 100644 --- a/drivers/pinctrl/mediatek/mtk-eint.h +++ b/drivers/pinctrl/mediatek/mtk-eint.h @@ -52,6 +52,7 @@ struct mtk_eint_pin { extern const unsigned int debounce_time_mt2701[]; extern const unsigned int debounce_time_mt6765[]; extern const unsigned int debounce_time_mt6795[]; +extern const unsigned int debounce_time_mt6878[]; struct mtk_eint; From 89c13ea3ab6ddf2b526915aa4190aec72cd202ed Mon Sep 17 00:00:00 2001 From: Igor Belwon Date: Mon, 15 Sep 2025 14:46:25 +0200 Subject: [PATCH 017/684] pinctrl: mediatek: Add support for MT6878 pinctrl Add driver support for the pin controller found in the MediaTek Dimensity 7300 (MT6878) SoC. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Igor Belwon Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/Kconfig | 10 + drivers/pinctrl/mediatek/Makefile | 1 + drivers/pinctrl/mediatek/pinctrl-mt6878.c | 1478 +++++++++++ drivers/pinctrl/mediatek/pinctrl-mtk-mt6878.h | 2248 +++++++++++++++++ 4 files changed, 3737 insertions(+) create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt6878.c create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6878.h diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 5b191e12a8aa9d..4819617d936836 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -181,6 +181,16 @@ config PINCTRL_MT6797 default ARM64 && ARCH_MEDIATEK select PINCTRL_MTK_PARIS +config PINCTRL_MT6878 + bool "MediaTek MT6878 pin control" + depends on OF + depends on ARM64 || COMPILE_TEST + default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_PARIS + help + Say yes here to support pin controller and gpio driver + on the MediaTek MT6878 SoC. + config PINCTRL_MT6893 bool "MediaTek Dimensity MT6893 pin control" depends on OF diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index 5d4646939ba3ab..ae765bd999657c 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_PINCTRL_MT6765) += pinctrl-mt6765.o obj-$(CONFIG_PINCTRL_MT6779) += pinctrl-mt6779.o obj-$(CONFIG_PINCTRL_MT6795) += pinctrl-mt6795.o obj-$(CONFIG_PINCTRL_MT6797) += pinctrl-mt6797.o +obj-$(CONFIG_PINCTRL_MT6878) += pinctrl-mt6878.o obj-$(CONFIG_PINCTRL_MT6893) += pinctrl-mt6893.o obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6878.c b/drivers/pinctrl/mediatek/pinctrl-mt6878.c new file mode 100644 index 00000000000000..b59ae089128a40 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt6878.c @@ -0,0 +1,1478 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Light Hsieh + * + * Copyright (C) 2025 Igor Belwon + */ + +#include +#include "pinctrl-mtk-mt6878.h" +#include "pinctrl-paris.h" + +/* MT6878 have multiple bases to program pin configuration listed as the below: + * GPIO_BASE: 0x10005000 + * IOCFG_BL_BASE: 0x11D10000 + * IOCFG_BM_BASE: 0x11D30000 + * IOCFG_BR_BASE: 0x11D40000 + * IOCFG_BL1_BASE: 0x11D50000 + * IOCFG_BR1_BASE: 0x11D60000 + * IOCFG_LM_BASE: 0x11E20000 + * IOCFG_LT_BASE: 0x11E30000 + * IOCFG_RM_BASE: 0x11EB0000 + * IOCFG_RT_BASE: 0x11EC0000 + * _i_based could be used to indicate what base the pin should be mapped into. + */ + +#define PIN_FIELD_BASE(s_pin, e_pin, i_base, s_addr, x_addrs, s_bit, x_bits) \ + PIN_FIELD_CALC(s_pin, e_pin, i_base, s_addr, x_addrs, s_bit, x_bits, \ + 32, 0) + +#define PINS_FIELD_BASE(s_pin, e_pin, i_base, s_addr, x_addrs, s_bit, x_bits) \ + PIN_FIELD_CALC(s_pin, e_pin, i_base, s_addr, x_addrs, s_bit, x_bits, \ + 32, 1) + +static const struct mtk_pin_field_calc mt6878_pin_mode_range[] = { + PIN_FIELD(0, 195, 0x300, 0x10, 0, 4), +}; + +static const struct mtk_pin_field_calc mt6878_pin_dir_range[] = { + PIN_FIELD(0, 195, 0x0, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_di_range[] = { + PIN_FIELD(0, 195, 0x200, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_do_range[] = { + PIN_FIELD(0, 195, 0x100, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_ies_range[] = { + PIN_FIELD_BASE(0, 0, 3, 0x0070, 0x10, 9, 1), + PIN_FIELD_BASE(1, 1, 3, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(2, 2, 3, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(3, 3, 3, 0x0070, 0x10, 12, 1), + PIN_FIELD_BASE(4, 4, 3, 0x0070, 0x10, 13, 1), + PIN_FIELD_BASE(5, 5, 3, 0x0070, 0x10, 14, 1), + PIN_FIELD_BASE(6, 6, 4, 0x0050, 0x10, 13, 1), + PIN_FIELD_BASE(7, 7, 4, 0x0050, 0x10, 14, 1), + PIN_FIELD_BASE(8, 8, 4, 0x0050, 0x10, 15, 1), + PIN_FIELD_BASE(9, 9, 4, 0x0050, 0x10, 16, 1), + PIN_FIELD_BASE(10, 10, 4, 0x0050, 0x10, 10, 1), + PIN_FIELD_BASE(11, 11, 4, 0x0050, 0x10, 11, 1), + PIN_FIELD_BASE(12, 12, 4, 0x0050, 0x10, 12, 1), + PIN_FIELD_BASE(13, 13, 6, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(14, 14, 6, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(15, 15, 6, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(16, 16, 6, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(17, 17, 6, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(18, 18, 6, 0x0070, 0x10, 9, 1), + PIN_FIELD_BASE(19, 19, 3, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(20, 20, 3, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(22, 22, 3, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(23, 23, 3, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(24, 24, 5, 0x0040, 0x10, 1, 1), + PIN_FIELD_BASE(25, 25, 3, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(26, 26, 3, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(27, 27, 3, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(28, 28, 3, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(29, 29, 6, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(30, 30, 6, 0x0070, 0x10, 12, 1), + PIN_FIELD_BASE(31, 31, 6, 0x0070, 0x10, 13, 1), + PIN_FIELD_BASE(32, 32, 6, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(33, 33, 9, 0x0050, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 9, 0x0050, 0x10, 1, 1), + PIN_FIELD_BASE(35, 35, 9, 0x0050, 0x10, 2, 1), + PIN_FIELD_BASE(36, 36, 8, 0x0090, 0x10, 0, 1), + PIN_FIELD_BASE(37, 37, 8, 0x0090, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 8, 0x0090, 0x10, 2, 1), + PIN_FIELD_BASE(39, 39, 8, 0x0090, 0x10, 3, 1), + PIN_FIELD_BASE(40, 40, 8, 0x0090, 0x10, 4, 1), + PIN_FIELD_BASE(41, 41, 4, 0x0050, 0x10, 20, 1), + PIN_FIELD_BASE(42, 42, 4, 0x0050, 0x10, 17, 1), + PIN_FIELD_BASE(43, 43, 4, 0x0050, 0x10, 19, 1), + PIN_FIELD_BASE(44, 44, 4, 0x0050, 0x10, 21, 1), + PIN_FIELD_BASE(45, 45, 4, 0x0050, 0x10, 18, 1), + PIN_FIELD_BASE(46, 46, 4, 0x0050, 0x10, 22, 1), + PIN_FIELD_BASE(47, 47, 4, 0x0050, 0x10, 23, 1), + PIN_FIELD_BASE(48, 48, 3, 0x0070, 0x10, 25, 1), + PIN_FIELD_BASE(49, 49, 3, 0x0070, 0x10, 23, 1), + PIN_FIELD_BASE(50, 50, 3, 0x0070, 0x10, 26, 1), + PIN_FIELD_BASE(51, 51, 3, 0x0070, 0x10, 24, 1), + PIN_FIELD_BASE(52, 52, 3, 0x0070, 0x10, 17, 1), + PIN_FIELD_BASE(53, 53, 3, 0x0070, 0x10, 18, 1), + PIN_FIELD_BASE(54, 54, 3, 0x0070, 0x10, 15, 1), + PIN_FIELD_BASE(55, 55, 3, 0x0070, 0x10, 16, 1), + PIN_FIELD_BASE(56, 56, 5, 0x0040, 0x10, 8, 1), + PIN_FIELD_BASE(57, 57, 5, 0x0040, 0x10, 9, 1), + PIN_FIELD_BASE(58, 58, 3, 0x0070, 0x10, 22, 1), + PIN_FIELD_BASE(59, 59, 3, 0x0070, 0x10, 21, 1), + PIN_FIELD_BASE(60, 60, 8, 0x0090, 0x10, 21, 1), + PIN_FIELD_BASE(61, 61, 8, 0x0090, 0x10, 22, 1), + PIN_FIELD_BASE(62, 62, 8, 0x0090, 0x10, 24, 1), + PIN_FIELD_BASE(63, 63, 8, 0x0090, 0x10, 23, 1), + PIN_FIELD_BASE(64, 64, 8, 0x0090, 0x10, 25, 1), + PIN_FIELD_BASE(65, 65, 8, 0x0090, 0x10, 26, 1), + PIN_FIELD_BASE(66, 66, 8, 0x0090, 0x10, 28, 1), + PIN_FIELD_BASE(67, 67, 8, 0x0090, 0x10, 27, 1), + PIN_FIELD_BASE(68, 68, 5, 0x0040, 0x10, 3, 1), + PIN_FIELD_BASE(69, 69, 5, 0x0040, 0x10, 4, 1), + PIN_FIELD_BASE(70, 70, 5, 0x0040, 0x10, 6, 1), + PIN_FIELD_BASE(71, 71, 5, 0x0040, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0x0040, 0x10, 10, 1), + PIN_FIELD_BASE(73, 73, 5, 0x0040, 0x10, 11, 1), + PIN_FIELD_BASE(74, 74, 5, 0x0040, 0x10, 13, 1), + PIN_FIELD_BASE(75, 75, 5, 0x0040, 0x10, 12, 1), + PIN_FIELD_BASE(76, 76, 5, 0x0040, 0x10, 0, 1), + PIN_FIELD_BASE(77, 77, 2, 0x0040, 0x10, 0, 1), + PIN_FIELD_BASE(78, 78, 2, 0x0040, 0x10, 1, 1), + PIN_FIELD_BASE(79, 79, 2, 0x0040, 0x10, 2, 1), + PIN_FIELD_BASE(80, 80, 2, 0x0040, 0x10, 3, 1), + PIN_FIELD_BASE(81, 81, 2, 0x0040, 0x10, 4, 1), + PIN_FIELD_BASE(82, 82, 2, 0x0040, 0x10, 5, 1), + PIN_FIELD_BASE(83, 83, 2, 0x0040, 0x10, 9, 1), + PIN_FIELD_BASE(84, 84, 2, 0x0040, 0x10, 11, 1), + PIN_FIELD_BASE(85, 85, 2, 0x0040, 0x10, 10, 1), + PIN_FIELD_BASE(86, 86, 2, 0x0040, 0x10, 12, 1), + PIN_FIELD_BASE(87, 87, 2, 0x0040, 0x10, 14, 1), + PIN_FIELD_BASE(88, 88, 2, 0x0040, 0x10, 13, 1), + PIN_FIELD_BASE(89, 89, 4, 0x0050, 0x10, 9, 1), + PIN_FIELD_BASE(90, 90, 4, 0x0050, 0x10, 24, 1), + PIN_FIELD_BASE(91, 91, 4, 0x0050, 0x10, 8, 1), + PIN_FIELD_BASE(92, 92, 8, 0x0090, 0x10, 5, 1), + PIN_FIELD_BASE(93, 93, 8, 0x0090, 0x10, 6, 1), + PIN_FIELD_BASE(94, 94, 8, 0x0090, 0x10, 7, 1), + PIN_FIELD_BASE(95, 95, 8, 0x0090, 0x10, 8, 1), + PIN_FIELD_BASE(96, 96, 8, 0x0090, 0x10, 9, 1), + PIN_FIELD_BASE(97, 97, 1, 0x0070, 0x10, 19, 1), + PIN_FIELD_BASE(98, 98, 1, 0x0070, 0x10, 18, 1), + PIN_FIELD_BASE(99, 99, 1, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(100, 100, 1, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(101, 101, 1, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(102, 102, 1, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(103, 103, 1, 0x0070, 0x10, 12, 1), + PIN_FIELD_BASE(104, 104, 1, 0x0070, 0x10, 13, 1), + PIN_FIELD_BASE(105, 105, 1, 0x0070, 0x10, 14, 1), + PIN_FIELD_BASE(106, 106, 1, 0x0070, 0x10, 15, 1), + PIN_FIELD_BASE(107, 107, 1, 0x0070, 0x10, 16, 1), + PIN_FIELD_BASE(108, 108, 1, 0x0070, 0x10, 17, 1), + PIN_FIELD_BASE(109, 109, 1, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(110, 110, 1, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(111, 111, 1, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(112, 112, 1, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(113, 113, 1, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(114, 114, 1, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(115, 115, 1, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(116, 116, 1, 0x0070, 0x10, 9, 1), + PIN_FIELD_BASE(117, 117, 1, 0x0070, 0x10, 20, 1), + PIN_FIELD_BASE(118, 118, 1, 0x0070, 0x10, 21, 1), + PIN_FIELD_BASE(119, 119, 1, 0x0070, 0x10, 22, 1), + PIN_FIELD_BASE(120, 120, 1, 0x0070, 0x10, 23, 1), + PIN_FIELD_BASE(121, 121, 1, 0x0070, 0x10, 24, 1), + PIN_FIELD_BASE(122, 122, 1, 0x0070, 0x10, 25, 1), + PIN_FIELD_BASE(123, 123, 1, 0x0070, 0x10, 26, 1), + PIN_FIELD_BASE(124, 124, 1, 0x0070, 0x10, 27, 1), + PIN_FIELD_BASE(125, 125, 8, 0x0090, 0x10, 20, 1), + PIN_FIELD_BASE(126, 126, 8, 0x0090, 0x10, 29, 1), + PIN_FIELD_BASE(127, 127, 8, 0x0090, 0x10, 30, 1), + PIN_FIELD_BASE(128, 128, 8, 0x0090, 0x10, 31, 1), + PIN_FIELD_BASE(129, 129, 8, 0x0090, 0x10, 10, 1), + PIN_FIELD_BASE(130, 130, 8, 0x0090, 0x10, 13, 1), + PIN_FIELD_BASE(131, 131, 6, 0x0070, 0x10, 14, 1), + PIN_FIELD_BASE(132, 132, 6, 0x0070, 0x10, 17, 1), + PIN_FIELD_BASE(133, 133, 8, 0x0090, 0x10, 11, 1), + PIN_FIELD_BASE(134, 134, 8, 0x0090, 0x10, 14, 1), + PIN_FIELD_BASE(135, 135, 6, 0x0070, 0x10, 15, 1), + PIN_FIELD_BASE(136, 136, 6, 0x0070, 0x10, 18, 1), + PIN_FIELD_BASE(137, 137, 6, 0x0070, 0x10, 16, 1), + PIN_FIELD_BASE(138, 138, 6, 0x0070, 0x10, 19, 1), + PIN_FIELD_BASE(139, 139, 6, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(140, 140, 6, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(141, 141, 6, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(142, 142, 6, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(143, 143, 8, 0x0090, 0x10, 12, 1), + PIN_FIELD_BASE(144, 144, 8, 0x0090, 0x10, 15, 1), + PIN_FIELD_BASE(145, 145, 5, 0x0040, 0x10, 2, 1), + PIN_FIELD_BASE(146, 146, 5, 0x0040, 0x10, 7, 1), + PIN_FIELD_BASE(147, 147, 3, 0x0070, 0x10, 19, 1), + PIN_FIELD_BASE(148, 148, 3, 0x0070, 0x10, 20, 1), + PIN_FIELD_BASE(149, 149, 8, 0x0090, 0x10, 16, 1), + PIN_FIELD_BASE(150, 150, 8, 0x0090, 0x10, 17, 1), + PIN_FIELD_BASE(151, 151, 8, 0x0090, 0x10, 18, 1), + PIN_FIELD_BASE(152, 152, 8, 0x0090, 0x10, 19, 1), + PIN_FIELD_BASE(153, 153, 2, 0x0040, 0x10, 6, 1), + PIN_FIELD_BASE(154, 154, 2, 0x0040, 0x10, 7, 1), + PIN_FIELD_BASE(155, 155, 2, 0x0040, 0x10, 8, 1), + PIN_FIELD_BASE(156, 156, 9, 0x0050, 0x10, 15, 1), + PIN_FIELD_BASE(157, 157, 9, 0x0050, 0x10, 16, 1), + PIN_FIELD_BASE(158, 158, 9, 0x0050, 0x10, 17, 1), + PIN_FIELD_BASE(159, 159, 9, 0x0050, 0x10, 18, 1), + PIN_FIELD_BASE(160, 160, 4, 0x0050, 0x10, 26, 1), + PIN_FIELD_BASE(161, 161, 4, 0x0050, 0x10, 25, 1), + PIN_FIELD_BASE(162, 162, 4, 0x0050, 0x10, 28, 1), + PIN_FIELD_BASE(163, 163, 4, 0x0050, 0x10, 27, 1), + PIN_FIELD_BASE(164, 164, 4, 0x0050, 0x10, 0, 1), + PIN_FIELD_BASE(165, 165, 4, 0x0050, 0x10, 7, 1), + PIN_FIELD_BASE(166, 166, 4, 0x0050, 0x10, 3, 1), + PIN_FIELD_BASE(167, 167, 4, 0x0050, 0x10, 4, 1), + PIN_FIELD_BASE(168, 168, 4, 0x0050, 0x10, 5, 1), + PIN_FIELD_BASE(169, 169, 4, 0x0050, 0x10, 6, 1), + PIN_FIELD_BASE(170, 170, 4, 0x0050, 0x10, 1, 1), + PIN_FIELD_BASE(171, 171, 4, 0x0050, 0x10, 2, 1), + PIN_FIELD_BASE(172, 172, 9, 0x0050, 0x10, 7, 1), + PIN_FIELD_BASE(173, 173, 9, 0x0050, 0x10, 8, 1), + PIN_FIELD_BASE(174, 174, 9, 0x0050, 0x10, 3, 1), + PIN_FIELD_BASE(175, 175, 9, 0x0050, 0x10, 4, 1), + PIN_FIELD_BASE(176, 176, 9, 0x0050, 0x10, 5, 1), + PIN_FIELD_BASE(177, 177, 9, 0x0050, 0x10, 9, 1), + PIN_FIELD_BASE(178, 178, 9, 0x0050, 0x10, 10, 1), + PIN_FIELD_BASE(179, 179, 9, 0x0050, 0x10, 11, 1), + PIN_FIELD_BASE(180, 180, 9, 0x0050, 0x10, 12, 1), + PIN_FIELD_BASE(181, 181, 9, 0x0050, 0x10, 13, 1), + PIN_FIELD_BASE(182, 182, 9, 0x0050, 0x10, 14, 1), + PIN_FIELD_BASE(183, 183, 9, 0x0050, 0x10, 6, 1), + PIN_FIELD_BASE(184, 184, 7, 0x0040, 0x10, 10, 1), + PIN_FIELD_BASE(185, 185, 7, 0x0040, 0x10, 0, 1), + PIN_FIELD_BASE(186, 186, 7, 0x0040, 0x10, 1, 1), + PIN_FIELD_BASE(187, 187, 7, 0x0040, 0x10, 11, 1), + PIN_FIELD_BASE(188, 188, 7, 0x0040, 0x10, 2, 1), + PIN_FIELD_BASE(189, 189, 7, 0x0040, 0x10, 3, 1), + PIN_FIELD_BASE(190, 190, 7, 0x0040, 0x10, 4, 1), + PIN_FIELD_BASE(191, 191, 7, 0x0040, 0x10, 5, 1), + PIN_FIELD_BASE(192, 192, 7, 0x0040, 0x10, 6, 1), + PIN_FIELD_BASE(193, 193, 7, 0x0040, 0x10, 7, 1), + PIN_FIELD_BASE(194, 194, 7, 0x0040, 0x10, 8, 1), + PIN_FIELD_BASE(195, 195, 7, 0x0040, 0x10, 9, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_smt_range[] = { + PIN_FIELD_BASE(0, 0, 3, 0x00e0, 0x10, 16, 1), + PIN_FIELD_BASE(1, 1, 3, 0x00e0, 0x10, 16, 1), + PIN_FIELD_BASE(2, 2, 3, 0x00e0, 0x10, 15, 1), + PIN_FIELD_BASE(3, 3, 3, 0x00e0, 0x10, 15, 1), + PIN_FIELD_BASE(4, 4, 3, 0x00e0, 0x10, 9, 1), + PIN_FIELD_BASE(5, 5, 3, 0x00e0, 0x10, 10, 1), + PIN_FIELD_BASE(6, 6, 4, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(7, 7, 4, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(8, 8, 4, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(9, 9, 4, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(10, 10, 4, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(11, 11, 4, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(12, 12, 4, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(13, 13, 6, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(14, 14, 6, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(15, 15, 6, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(16, 16, 6, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(17, 17, 6, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(18, 18, 6, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(19, 19, 3, 0x00e0, 0x10, 0, 1), + PIN_FIELD_BASE(20, 20, 3, 0x00e0, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x00e0, 0x10, 2, 1), + PIN_FIELD_BASE(22, 22, 3, 0x00e0, 0x10, 3, 1), + PIN_FIELD_BASE(23, 23, 3, 0x00e0, 0x10, 4, 1), + PIN_FIELD_BASE(24, 24, 5, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(25, 25, 3, 0x00e0, 0x10, 5, 1), + PIN_FIELD_BASE(26, 26, 3, 0x00e0, 0x10, 6, 1), + PIN_FIELD_BASE(27, 27, 3, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(28, 28, 3, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(29, 29, 6, 0x00e0, 0x10, 4, 1), + PIN_FIELD_BASE(30, 30, 6, 0x00e0, 0x10, 9, 1), + PIN_FIELD_BASE(31, 31, 6, 0x00e0, 0x10, 6, 1), + PIN_FIELD_BASE(32, 32, 6, 0x00e0, 0x10, 5, 1), + PIN_FIELD_BASE(33, 33, 9, 0x00f0, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 9, 0x00f0, 0x10, 1, 1), + PIN_FIELD_BASE(35, 35, 9, 0x00f0, 0x10, 2, 1), + PIN_FIELD_BASE(36, 36, 8, 0x0130, 0x10, 0, 1), + PIN_FIELD_BASE(37, 37, 8, 0x0130, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 8, 0x0130, 0x10, 2, 1), + PIN_FIELD_BASE(39, 39, 8, 0x0130, 0x10, 3, 1), + PIN_FIELD_BASE(40, 40, 8, 0x0130, 0x10, 4, 1), + PIN_FIELD_BASE(41, 41, 4, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(42, 42, 4, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(43, 43, 4, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(44, 44, 4, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(45, 45, 4, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(46, 46, 4, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(47, 47, 4, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(48, 48, 3, 0x00e0, 0x10, 16, 1), + PIN_FIELD_BASE(49, 49, 3, 0x00e0, 0x10, 16, 1), + PIN_FIELD_BASE(50, 50, 3, 0x00e0, 0x10, 14, 1), + PIN_FIELD_BASE(51, 51, 3, 0x00e0, 0x10, 14, 1), + PIN_FIELD_BASE(52, 52, 3, 0x00e0, 0x10, 12, 1), + PIN_FIELD_BASE(53, 53, 3, 0x00e0, 0x10, 13, 1), + PIN_FIELD_BASE(54, 54, 3, 0x00e0, 0x10, 17, 1), + PIN_FIELD_BASE(55, 55, 3, 0x00e0, 0x10, 11, 1), + PIN_FIELD_BASE(56, 56, 5, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(57, 57, 5, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(58, 58, 3, 0x00e0, 0x10, 21, 1), + PIN_FIELD_BASE(59, 59, 3, 0x00e0, 0x10, 20, 1), + PIN_FIELD_BASE(60, 60, 8, 0x0130, 0x10, 20, 1), + PIN_FIELD_BASE(61, 61, 8, 0x0130, 0x10, 21, 1), + PIN_FIELD_BASE(62, 62, 8, 0x0130, 0x10, 23, 1), + PIN_FIELD_BASE(63, 63, 8, 0x0130, 0x10, 22, 1), + PIN_FIELD_BASE(64, 64, 8, 0x0130, 0x10, 24, 1), + PIN_FIELD_BASE(65, 65, 8, 0x0130, 0x10, 25, 1), + PIN_FIELD_BASE(66, 66, 8, 0x0130, 0x10, 27, 1), + PIN_FIELD_BASE(67, 67, 8, 0x0130, 0x10, 26, 1), + PIN_FIELD_BASE(68, 68, 5, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(69, 69, 5, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(70, 70, 5, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(71, 71, 5, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(73, 73, 5, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(74, 74, 5, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(75, 75, 5, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(76, 76, 5, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(77, 77, 2, 0x00e0, 0x10, 0, 1), + PIN_FIELD_BASE(78, 78, 2, 0x00e0, 0x10, 1, 1), + PIN_FIELD_BASE(79, 79, 2, 0x00e0, 0x10, 2, 1), + PIN_FIELD_BASE(80, 80, 2, 0x00e0, 0x10, 3, 1), + PIN_FIELD_BASE(81, 81, 2, 0x00e0, 0x10, 4, 1), + PIN_FIELD_BASE(82, 82, 2, 0x00e0, 0x10, 5, 1), + PIN_FIELD_BASE(83, 83, 2, 0x00e0, 0x10, 6, 1), + PIN_FIELD_BASE(84, 84, 2, 0x00e0, 0x10, 9, 1), + PIN_FIELD_BASE(85, 85, 2, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(86, 86, 2, 0x00e0, 0x10, 10, 1), + PIN_FIELD_BASE(87, 87, 2, 0x00e0, 0x10, 12, 1), + PIN_FIELD_BASE(88, 88, 2, 0x00e0, 0x10, 11, 1), + PIN_FIELD_BASE(89, 89, 4, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(90, 90, 4, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(91, 91, 4, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(92, 92, 8, 0x0130, 0x10, 5, 1), + PIN_FIELD_BASE(93, 93, 8, 0x0130, 0x10, 6, 1), + PIN_FIELD_BASE(94, 94, 8, 0x0130, 0x10, 7, 1), + PIN_FIELD_BASE(95, 95, 8, 0x0130, 0x10, 8, 1), + PIN_FIELD_BASE(96, 96, 8, 0x0130, 0x10, 9, 1), + PIN_FIELD_BASE(97, 97, 1, 0x0120, 0x10, 25, 1), + PIN_FIELD_BASE(98, 98, 1, 0x0120, 0x10, 25, 1), + PIN_FIELD_BASE(99, 99, 1, 0x0120, 0x10, 0, 1), + PIN_FIELD_BASE(100, 100, 1, 0x0120, 0x10, 1, 1), + PIN_FIELD_BASE(101, 101, 1, 0x0120, 0x10, 10, 1), + PIN_FIELD_BASE(102, 102, 1, 0x0120, 0x10, 11, 1), + PIN_FIELD_BASE(103, 103, 1, 0x0120, 0x10, 12, 1), + PIN_FIELD_BASE(104, 104, 1, 0x0120, 0x10, 13, 1), + PIN_FIELD_BASE(105, 105, 1, 0x0120, 0x10, 14, 1), + PIN_FIELD_BASE(106, 106, 1, 0x0120, 0x10, 15, 1), + PIN_FIELD_BASE(107, 107, 1, 0x0120, 0x10, 16, 1), + PIN_FIELD_BASE(108, 108, 1, 0x0120, 0x10, 17, 1), + PIN_FIELD_BASE(109, 109, 1, 0x0120, 0x10, 2, 1), + PIN_FIELD_BASE(110, 110, 1, 0x0120, 0x10, 3, 1), + PIN_FIELD_BASE(111, 111, 1, 0x0120, 0x10, 4, 1), + PIN_FIELD_BASE(112, 112, 1, 0x0120, 0x10, 5, 1), + PIN_FIELD_BASE(113, 113, 1, 0x0120, 0x10, 6, 1), + PIN_FIELD_BASE(114, 114, 1, 0x0120, 0x10, 7, 1), + PIN_FIELD_BASE(115, 115, 1, 0x0120, 0x10, 8, 1), + PIN_FIELD_BASE(116, 116, 1, 0x0120, 0x10, 9, 1), + PIN_FIELD_BASE(117, 117, 1, 0x0120, 0x10, 18, 1), + PIN_FIELD_BASE(118, 118, 1, 0x0120, 0x10, 19, 1), + PIN_FIELD_BASE(119, 119, 1, 0x0120, 0x10, 20, 1), + PIN_FIELD_BASE(120, 120, 1, 0x0120, 0x10, 21, 1), + PIN_FIELD_BASE(121, 121, 1, 0x0120, 0x10, 22, 1), + PIN_FIELD_BASE(122, 122, 1, 0x0120, 0x10, 23, 1), + PIN_FIELD_BASE(123, 123, 1, 0x0120, 0x10, 24, 1), + PIN_FIELD_BASE(124, 124, 1, 0x0120, 0x10, 24, 1), + PIN_FIELD_BASE(125, 125, 8, 0x0130, 0x10, 19, 1), + PIN_FIELD_BASE(126, 126, 8, 0x0130, 0x10, 28, 1), + PIN_FIELD_BASE(127, 127, 8, 0x0130, 0x10, 29, 1), + PIN_FIELD_BASE(128, 128, 8, 0x0130, 0x10, 30, 1), + PIN_FIELD_BASE(129, 129, 8, 0x0130, 0x10, 10, 1), + PIN_FIELD_BASE(130, 130, 8, 0x0130, 0x10, 13, 1), + PIN_FIELD_BASE(131, 131, 6, 0x00e0, 0x10, 10, 1), + PIN_FIELD_BASE(132, 132, 6, 0x00e0, 0x10, 13, 1), + PIN_FIELD_BASE(133, 133, 8, 0x0130, 0x10, 11, 1), + PIN_FIELD_BASE(134, 134, 8, 0x0130, 0x10, 14, 1), + PIN_FIELD_BASE(135, 135, 6, 0x00e0, 0x10, 11, 1), + PIN_FIELD_BASE(136, 136, 6, 0x00e0, 0x10, 14, 1), + PIN_FIELD_BASE(137, 137, 6, 0x00e0, 0x10, 12, 1), + PIN_FIELD_BASE(138, 138, 6, 0x00e0, 0x10, 15, 1), + PIN_FIELD_BASE(139, 139, 6, 0x00e0, 0x10, 0, 1), + PIN_FIELD_BASE(140, 140, 6, 0x00e0, 0x10, 2, 1), + PIN_FIELD_BASE(141, 141, 6, 0x00e0, 0x10, 1, 1), + PIN_FIELD_BASE(142, 142, 6, 0x00e0, 0x10, 3, 1), + PIN_FIELD_BASE(143, 143, 8, 0x0130, 0x10, 12, 1), + PIN_FIELD_BASE(144, 144, 8, 0x0130, 0x10, 15, 1), + PIN_FIELD_BASE(145, 145, 5, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(146, 146, 5, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(147, 147, 3, 0x00e0, 0x10, 18, 1), + PIN_FIELD_BASE(148, 148, 3, 0x00e0, 0x10, 19, 1), + PIN_FIELD_BASE(149, 149, 8, 0x0130, 0x10, 16, 1), + PIN_FIELD_BASE(150, 150, 8, 0x0130, 0x10, 17, 1), + PIN_FIELD_BASE(151, 151, 8, 0x0130, 0x10, 18, 1), + PIN_FIELD_BASE(152, 152, 8, 0x0130, 0x10, 18, 1), + PIN_FIELD_BASE(153, 153, 2, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(154, 154, 2, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(155, 155, 2, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(156, 156, 9, 0x00f0, 0x10, 7, 1), + PIN_FIELD_BASE(157, 157, 9, 0x00f0, 0x10, 8, 1), + PIN_FIELD_BASE(158, 158, 9, 0x00f0, 0x10, 9, 1), + PIN_FIELD_BASE(159, 159, 9, 0x00f0, 0x10, 10, 1), + PIN_FIELD_BASE(160, 160, 4, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(161, 161, 4, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(162, 162, 4, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(163, 163, 4, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(164, 164, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(165, 165, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(166, 166, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(167, 167, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(168, 168, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(169, 169, 4, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(170, 170, 4, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(171, 171, 4, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(172, 172, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(173, 173, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(174, 174, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(175, 175, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(176, 176, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(177, 177, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(178, 178, 9, 0x00f0, 0x10, 6, 1), + PIN_FIELD_BASE(179, 179, 9, 0x00f0, 0x10, 6, 1), + PIN_FIELD_BASE(180, 180, 9, 0x00f0, 0x10, 6, 1), + PIN_FIELD_BASE(181, 181, 9, 0x00f0, 0x10, 3, 1), + PIN_FIELD_BASE(182, 182, 9, 0x00f0, 0x10, 4, 1), + PIN_FIELD_BASE(183, 183, 9, 0x00f0, 0x10, 5, 1), + PIN_FIELD_BASE(184, 184, 7, 0x00d0, 0x10, 10, 1), + PIN_FIELD_BASE(185, 185, 7, 0x00d0, 0x10, 0, 1), + PIN_FIELD_BASE(186, 186, 7, 0x00d0, 0x10, 1, 1), + PIN_FIELD_BASE(187, 187, 7, 0x00d0, 0x10, 11, 1), + PIN_FIELD_BASE(188, 188, 7, 0x00d0, 0x10, 2, 1), + PIN_FIELD_BASE(189, 189, 7, 0x00d0, 0x10, 3, 1), + PIN_FIELD_BASE(190, 190, 7, 0x00d0, 0x10, 4, 1), + PIN_FIELD_BASE(191, 191, 7, 0x00d0, 0x10, 5, 1), + PIN_FIELD_BASE(192, 192, 7, 0x00d0, 0x10, 6, 1), + PIN_FIELD_BASE(193, 193, 7, 0x00d0, 0x10, 7, 1), + PIN_FIELD_BASE(194, 194, 7, 0x00d0, 0x10, 8, 1), + PIN_FIELD_BASE(195, 195, 7, 0x00d0, 0x10, 9, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_pu_range[] = { + PIN_FIELD_BASE(0, 0, 3, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(1, 1, 3, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(2, 2, 3, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(3, 3, 3, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(4, 4, 3, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(5, 5, 3, 0x00b0, 0x10, 14, 1), + PIN_FIELD_BASE(6, 6, 4, 0x0090, 0x10, 13, 1), + PIN_FIELD_BASE(7, 7, 4, 0x0090, 0x10, 14, 1), + PIN_FIELD_BASE(8, 8, 4, 0x0090, 0x10, 15, 1), + PIN_FIELD_BASE(9, 9, 4, 0x0090, 0x10, 16, 1), + PIN_FIELD_BASE(10, 10, 4, 0x0090, 0x10, 10, 1), + PIN_FIELD_BASE(11, 11, 4, 0x0090, 0x10, 11, 1), + PIN_FIELD_BASE(12, 12, 4, 0x0090, 0x10, 12, 1), + PIN_FIELD_BASE(13, 13, 6, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(14, 14, 6, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(15, 15, 6, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(16, 16, 6, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(17, 17, 6, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(18, 18, 6, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(19, 19, 3, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(20, 20, 3, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(22, 22, 3, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(23, 23, 3, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(24, 24, 5, 0x0080, 0x10, 1, 1), + PIN_FIELD_BASE(25, 25, 3, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(26, 26, 3, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(27, 27, 3, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(28, 28, 3, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(29, 29, 6, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(30, 30, 6, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(31, 31, 6, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(32, 32, 6, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(36, 36, 8, 0x00d0, 0x10, 0, 1), + PIN_FIELD_BASE(37, 37, 8, 0x00d0, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 8, 0x00d0, 0x10, 2, 1), + PIN_FIELD_BASE(39, 39, 8, 0x00d0, 0x10, 3, 1), + PIN_FIELD_BASE(40, 40, 8, 0x00d0, 0x10, 4, 1), + PIN_FIELD_BASE(41, 41, 4, 0x0090, 0x10, 20, 1), + PIN_FIELD_BASE(42, 42, 4, 0x0090, 0x10, 17, 1), + PIN_FIELD_BASE(43, 43, 4, 0x0090, 0x10, 19, 1), + PIN_FIELD_BASE(44, 44, 4, 0x0090, 0x10, 21, 1), + PIN_FIELD_BASE(45, 45, 4, 0x0090, 0x10, 18, 1), + PIN_FIELD_BASE(46, 46, 4, 0x0090, 0x10, 22, 1), + PIN_FIELD_BASE(47, 47, 4, 0x0090, 0x10, 23, 1), + PIN_FIELD_BASE(48, 48, 3, 0x00b0, 0x10, 25, 1), + PIN_FIELD_BASE(49, 49, 3, 0x00b0, 0x10, 23, 1), + PIN_FIELD_BASE(50, 50, 3, 0x00b0, 0x10, 26, 1), + PIN_FIELD_BASE(51, 51, 3, 0x00b0, 0x10, 24, 1), + PIN_FIELD_BASE(52, 52, 3, 0x00b0, 0x10, 17, 1), + PIN_FIELD_BASE(53, 53, 3, 0x00b0, 0x10, 18, 1), + PIN_FIELD_BASE(54, 54, 3, 0x00b0, 0x10, 15, 1), + PIN_FIELD_BASE(55, 55, 3, 0x00b0, 0x10, 16, 1), + PIN_FIELD_BASE(56, 56, 5, 0x0080, 0x10, 8, 1), + PIN_FIELD_BASE(57, 57, 5, 0x0080, 0x10, 9, 1), + PIN_FIELD_BASE(58, 58, 3, 0x00b0, 0x10, 22, 1), + PIN_FIELD_BASE(59, 59, 3, 0x00b0, 0x10, 21, 1), + PIN_FIELD_BASE(60, 60, 8, 0x00d0, 0x10, 21, 1), + PIN_FIELD_BASE(61, 61, 8, 0x00d0, 0x10, 22, 1), + PIN_FIELD_BASE(62, 62, 8, 0x00d0, 0x10, 24, 1), + PIN_FIELD_BASE(63, 63, 8, 0x00d0, 0x10, 23, 1), + PIN_FIELD_BASE(64, 64, 8, 0x00d0, 0x10, 25, 1), + PIN_FIELD_BASE(65, 65, 8, 0x00d0, 0x10, 26, 1), + PIN_FIELD_BASE(66, 66, 8, 0x00d0, 0x10, 28, 1), + PIN_FIELD_BASE(67, 67, 8, 0x00d0, 0x10, 27, 1), + PIN_FIELD_BASE(68, 68, 5, 0x0080, 0x10, 3, 1), + PIN_FIELD_BASE(69, 69, 5, 0x0080, 0x10, 4, 1), + PIN_FIELD_BASE(70, 70, 5, 0x0080, 0x10, 6, 1), + PIN_FIELD_BASE(71, 71, 5, 0x0080, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0x0080, 0x10, 10, 1), + PIN_FIELD_BASE(73, 73, 5, 0x0080, 0x10, 11, 1), + PIN_FIELD_BASE(74, 74, 5, 0x0080, 0x10, 13, 1), + PIN_FIELD_BASE(75, 75, 5, 0x0080, 0x10, 12, 1), + PIN_FIELD_BASE(76, 76, 5, 0x0080, 0x10, 0, 1), + PIN_FIELD_BASE(89, 89, 4, 0x0090, 0x10, 9, 1), + PIN_FIELD_BASE(90, 90, 4, 0x0090, 0x10, 24, 1), + PIN_FIELD_BASE(91, 91, 4, 0x0090, 0x10, 8, 1), + PIN_FIELD_BASE(92, 92, 8, 0x00d0, 0x10, 5, 1), + PIN_FIELD_BASE(93, 93, 8, 0x00d0, 0x10, 6, 1), + PIN_FIELD_BASE(94, 94, 8, 0x00d0, 0x10, 7, 1), + PIN_FIELD_BASE(95, 95, 8, 0x00d0, 0x10, 8, 1), + PIN_FIELD_BASE(96, 96, 8, 0x00d0, 0x10, 9, 1), + PIN_FIELD_BASE(99, 99, 1, 0x00c0, 0x10, 0, 1), + PIN_FIELD_BASE(100, 100, 1, 0x00c0, 0x10, 1, 1), + PIN_FIELD_BASE(101, 101, 1, 0x00c0, 0x10, 10, 1), + PIN_FIELD_BASE(102, 102, 1, 0x00c0, 0x10, 11, 1), + PIN_FIELD_BASE(103, 103, 1, 0x00c0, 0x10, 12, 1), + PIN_FIELD_BASE(104, 104, 1, 0x00c0, 0x10, 13, 1), + PIN_FIELD_BASE(105, 105, 1, 0x00c0, 0x10, 14, 1), + PIN_FIELD_BASE(106, 106, 1, 0x00c0, 0x10, 15, 1), + PIN_FIELD_BASE(107, 107, 1, 0x00c0, 0x10, 16, 1), + PIN_FIELD_BASE(108, 108, 1, 0x00c0, 0x10, 17, 1), + PIN_FIELD_BASE(109, 109, 1, 0x00c0, 0x10, 2, 1), + PIN_FIELD_BASE(110, 110, 1, 0x00c0, 0x10, 3, 1), + PIN_FIELD_BASE(111, 111, 1, 0x00c0, 0x10, 4, 1), + PIN_FIELD_BASE(112, 112, 1, 0x00c0, 0x10, 5, 1), + PIN_FIELD_BASE(113, 113, 1, 0x00c0, 0x10, 6, 1), + PIN_FIELD_BASE(114, 114, 1, 0x00c0, 0x10, 7, 1), + PIN_FIELD_BASE(115, 115, 1, 0x00c0, 0x10, 8, 1), + PIN_FIELD_BASE(116, 116, 1, 0x00c0, 0x10, 9, 1), + PIN_FIELD_BASE(125, 125, 8, 0x00d0, 0x10, 20, 1), + PIN_FIELD_BASE(126, 126, 8, 0x00d0, 0x10, 29, 1), + PIN_FIELD_BASE(127, 127, 8, 0x00d0, 0x10, 30, 1), + PIN_FIELD_BASE(128, 128, 8, 0x00d0, 0x10, 31, 1), + PIN_FIELD_BASE(129, 129, 8, 0x00d0, 0x10, 10, 1), + PIN_FIELD_BASE(130, 130, 8, 0x00d0, 0x10, 13, 1), + PIN_FIELD_BASE(131, 131, 6, 0x00b0, 0x10, 14, 1), + PIN_FIELD_BASE(132, 132, 6, 0x00b0, 0x10, 17, 1), + PIN_FIELD_BASE(133, 133, 8, 0x00d0, 0x10, 11, 1), + PIN_FIELD_BASE(134, 134, 8, 0x00d0, 0x10, 14, 1), + PIN_FIELD_BASE(135, 135, 6, 0x00b0, 0x10, 15, 1), + PIN_FIELD_BASE(136, 136, 6, 0x00b0, 0x10, 18, 1), + PIN_FIELD_BASE(137, 137, 6, 0x00b0, 0x10, 16, 1), + PIN_FIELD_BASE(138, 138, 6, 0x00b0, 0x10, 19, 1), + PIN_FIELD_BASE(139, 139, 6, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(140, 140, 6, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(141, 141, 6, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(142, 142, 6, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(143, 143, 8, 0x00d0, 0x10, 12, 1), + PIN_FIELD_BASE(144, 144, 8, 0x00d0, 0x10, 15, 1), + PIN_FIELD_BASE(145, 145, 5, 0x0080, 0x10, 2, 1), + PIN_FIELD_BASE(146, 146, 5, 0x0080, 0x10, 7, 1), + PIN_FIELD_BASE(147, 147, 3, 0x00b0, 0x10, 19, 1), + PIN_FIELD_BASE(148, 148, 3, 0x00b0, 0x10, 20, 1), + PIN_FIELD_BASE(149, 149, 8, 0x00d0, 0x10, 16, 1), + PIN_FIELD_BASE(150, 150, 8, 0x00d0, 0x10, 17, 1), + PIN_FIELD_BASE(151, 151, 8, 0x00d0, 0x10, 18, 1), + PIN_FIELD_BASE(152, 152, 8, 0x00d0, 0x10, 19, 1), + PIN_FIELD_BASE(156, 156, 9, 0x00a0, 0x10, 0, 1), + PIN_FIELD_BASE(157, 157, 9, 0x00a0, 0x10, 1, 1), + PIN_FIELD_BASE(158, 158, 9, 0x00a0, 0x10, 2, 1), + PIN_FIELD_BASE(159, 159, 9, 0x00a0, 0x10, 3, 1), + PIN_FIELD_BASE(160, 160, 4, 0x0090, 0x10, 26, 1), + PIN_FIELD_BASE(161, 161, 4, 0x0090, 0x10, 25, 1), + PIN_FIELD_BASE(162, 162, 4, 0x0090, 0x10, 30, 1), + PIN_FIELD_BASE(163, 163, 4, 0x0090, 0x10, 29, 1), + PIN_FIELD_BASE(164, 164, 4, 0x0090, 0x10, 0, 1), + PIN_FIELD_BASE(165, 165, 4, 0x0090, 0x10, 7, 1), + PIN_FIELD_BASE(166, 166, 4, 0x0090, 0x10, 3, 1), + PIN_FIELD_BASE(167, 167, 4, 0x0090, 0x10, 4, 1), + PIN_FIELD_BASE(168, 168, 4, 0x0090, 0x10, 5, 1), + PIN_FIELD_BASE(169, 169, 4, 0x0090, 0x10, 6, 1), + PIN_FIELD_BASE(170, 170, 4, 0x0090, 0x10, 1, 1), + PIN_FIELD_BASE(171, 171, 4, 0x0090, 0x10, 2, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_pd_range[] = { + PIN_FIELD_BASE(0, 0, 3, 0x00a0, 0x10, 9, 1), + PIN_FIELD_BASE(1, 1, 3, 0x00a0, 0x10, 10, 1), + PIN_FIELD_BASE(2, 2, 3, 0x00a0, 0x10, 11, 1), + PIN_FIELD_BASE(3, 3, 3, 0x00a0, 0x10, 12, 1), + PIN_FIELD_BASE(4, 4, 3, 0x00a0, 0x10, 13, 1), + PIN_FIELD_BASE(5, 5, 3, 0x00a0, 0x10, 14, 1), + PIN_FIELD_BASE(6, 6, 4, 0x0080, 0x10, 13, 1), + PIN_FIELD_BASE(7, 7, 4, 0x0080, 0x10, 14, 1), + PIN_FIELD_BASE(8, 8, 4, 0x0080, 0x10, 15, 1), + PIN_FIELD_BASE(9, 9, 4, 0x0080, 0x10, 16, 1), + PIN_FIELD_BASE(10, 10, 4, 0x0080, 0x10, 10, 1), + PIN_FIELD_BASE(11, 11, 4, 0x0080, 0x10, 11, 1), + PIN_FIELD_BASE(12, 12, 4, 0x0080, 0x10, 12, 1), + PIN_FIELD_BASE(13, 13, 6, 0x00a0, 0x10, 4, 1), + PIN_FIELD_BASE(14, 14, 6, 0x00a0, 0x10, 5, 1), + PIN_FIELD_BASE(15, 15, 6, 0x00a0, 0x10, 6, 1), + PIN_FIELD_BASE(16, 16, 6, 0x00a0, 0x10, 7, 1), + PIN_FIELD_BASE(17, 17, 6, 0x00a0, 0x10, 8, 1), + PIN_FIELD_BASE(18, 18, 6, 0x00a0, 0x10, 9, 1), + PIN_FIELD_BASE(19, 19, 3, 0x00a0, 0x10, 0, 1), + PIN_FIELD_BASE(20, 20, 3, 0x00a0, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x00a0, 0x10, 2, 1), + PIN_FIELD_BASE(22, 22, 3, 0x00a0, 0x10, 3, 1), + PIN_FIELD_BASE(23, 23, 3, 0x00a0, 0x10, 4, 1), + PIN_FIELD_BASE(24, 24, 5, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(25, 25, 3, 0x00a0, 0x10, 5, 1), + PIN_FIELD_BASE(26, 26, 3, 0x00a0, 0x10, 6, 1), + PIN_FIELD_BASE(27, 27, 3, 0x00a0, 0x10, 7, 1), + PIN_FIELD_BASE(28, 28, 3, 0x00a0, 0x10, 8, 1), + PIN_FIELD_BASE(29, 29, 6, 0x00a0, 0x10, 10, 1), + PIN_FIELD_BASE(30, 30, 6, 0x00a0, 0x10, 12, 1), + PIN_FIELD_BASE(31, 31, 6, 0x00a0, 0x10, 13, 1), + PIN_FIELD_BASE(32, 32, 6, 0x00a0, 0x10, 11, 1), + PIN_FIELD_BASE(36, 36, 8, 0x00c0, 0x10, 0, 1), + PIN_FIELD_BASE(37, 37, 8, 0x00c0, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 8, 0x00c0, 0x10, 2, 1), + PIN_FIELD_BASE(39, 39, 8, 0x00c0, 0x10, 3, 1), + PIN_FIELD_BASE(40, 40, 8, 0x00c0, 0x10, 4, 1), + PIN_FIELD_BASE(41, 41, 4, 0x0080, 0x10, 20, 1), + PIN_FIELD_BASE(42, 42, 4, 0x0080, 0x10, 17, 1), + PIN_FIELD_BASE(43, 43, 4, 0x0080, 0x10, 19, 1), + PIN_FIELD_BASE(44, 44, 4, 0x0080, 0x10, 21, 1), + PIN_FIELD_BASE(45, 45, 4, 0x0080, 0x10, 18, 1), + PIN_FIELD_BASE(46, 46, 4, 0x0080, 0x10, 22, 1), + PIN_FIELD_BASE(47, 47, 4, 0x0080, 0x10, 23, 1), + PIN_FIELD_BASE(48, 48, 3, 0x00a0, 0x10, 25, 1), + PIN_FIELD_BASE(49, 49, 3, 0x00a0, 0x10, 23, 1), + PIN_FIELD_BASE(50, 50, 3, 0x00a0, 0x10, 26, 1), + PIN_FIELD_BASE(51, 51, 3, 0x00a0, 0x10, 24, 1), + PIN_FIELD_BASE(52, 52, 3, 0x00a0, 0x10, 17, 1), + PIN_FIELD_BASE(53, 53, 3, 0x00a0, 0x10, 18, 1), + PIN_FIELD_BASE(54, 54, 3, 0x00a0, 0x10, 15, 1), + PIN_FIELD_BASE(55, 55, 3, 0x00a0, 0x10, 16, 1), + PIN_FIELD_BASE(56, 56, 5, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(57, 57, 5, 0x0070, 0x10, 9, 1), + PIN_FIELD_BASE(58, 58, 3, 0x00a0, 0x10, 22, 1), + PIN_FIELD_BASE(59, 59, 3, 0x00a0, 0x10, 21, 1), + PIN_FIELD_BASE(60, 60, 8, 0x00c0, 0x10, 21, 1), + PIN_FIELD_BASE(61, 61, 8, 0x00c0, 0x10, 22, 1), + PIN_FIELD_BASE(62, 62, 8, 0x00c0, 0x10, 24, 1), + PIN_FIELD_BASE(63, 63, 8, 0x00c0, 0x10, 23, 1), + PIN_FIELD_BASE(64, 64, 8, 0x00c0, 0x10, 25, 1), + PIN_FIELD_BASE(65, 65, 8, 0x00c0, 0x10, 26, 1), + PIN_FIELD_BASE(66, 66, 8, 0x00c0, 0x10, 28, 1), + PIN_FIELD_BASE(67, 67, 8, 0x00c0, 0x10, 27, 1), + PIN_FIELD_BASE(68, 68, 5, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(69, 69, 5, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(70, 70, 5, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(71, 71, 5, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(73, 73, 5, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(74, 74, 5, 0x0070, 0x10, 13, 1), + PIN_FIELD_BASE(75, 75, 5, 0x0070, 0x10, 12, 1), + PIN_FIELD_BASE(76, 76, 5, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(89, 89, 4, 0x0080, 0x10, 9, 1), + PIN_FIELD_BASE(90, 90, 4, 0x0080, 0x10, 24, 1), + PIN_FIELD_BASE(91, 91, 4, 0x0080, 0x10, 8, 1), + PIN_FIELD_BASE(92, 92, 8, 0x00c0, 0x10, 5, 1), + PIN_FIELD_BASE(93, 93, 8, 0x00c0, 0x10, 6, 1), + PIN_FIELD_BASE(94, 94, 8, 0x00c0, 0x10, 7, 1), + PIN_FIELD_BASE(95, 95, 8, 0x00c0, 0x10, 8, 1), + PIN_FIELD_BASE(96, 96, 8, 0x00c0, 0x10, 9, 1), + PIN_FIELD_BASE(99, 99, 1, 0x00a0, 0x10, 0, 1), + PIN_FIELD_BASE(100, 100, 1, 0x00a0, 0x10, 1, 1), + PIN_FIELD_BASE(101, 101, 1, 0x00a0, 0x10, 10, 1), + PIN_FIELD_BASE(102, 102, 1, 0x00a0, 0x10, 11, 1), + PIN_FIELD_BASE(103, 103, 1, 0x00a0, 0x10, 12, 1), + PIN_FIELD_BASE(104, 104, 1, 0x00a0, 0x10, 13, 1), + PIN_FIELD_BASE(105, 105, 1, 0x00a0, 0x10, 14, 1), + PIN_FIELD_BASE(106, 106, 1, 0x00a0, 0x10, 15, 1), + PIN_FIELD_BASE(107, 107, 1, 0x00a0, 0x10, 16, 1), + PIN_FIELD_BASE(108, 108, 1, 0x00a0, 0x10, 17, 1), + PIN_FIELD_BASE(109, 109, 1, 0x00a0, 0x10, 2, 1), + PIN_FIELD_BASE(110, 110, 1, 0x00a0, 0x10, 3, 1), + PIN_FIELD_BASE(111, 111, 1, 0x00a0, 0x10, 4, 1), + PIN_FIELD_BASE(112, 112, 1, 0x00a0, 0x10, 5, 1), + PIN_FIELD_BASE(113, 113, 1, 0x00a0, 0x10, 6, 1), + PIN_FIELD_BASE(114, 114, 1, 0x00a0, 0x10, 7, 1), + PIN_FIELD_BASE(115, 115, 1, 0x00a0, 0x10, 8, 1), + PIN_FIELD_BASE(116, 116, 1, 0x00a0, 0x10, 9, 1), + PIN_FIELD_BASE(125, 125, 8, 0x00c0, 0x10, 20, 1), + PIN_FIELD_BASE(126, 126, 8, 0x00c0, 0x10, 29, 1), + PIN_FIELD_BASE(127, 127, 8, 0x00c0, 0x10, 30, 1), + PIN_FIELD_BASE(128, 128, 8, 0x00c0, 0x10, 31, 1), + PIN_FIELD_BASE(129, 129, 8, 0x00c0, 0x10, 10, 1), + PIN_FIELD_BASE(130, 130, 8, 0x00c0, 0x10, 13, 1), + PIN_FIELD_BASE(131, 131, 6, 0x00a0, 0x10, 14, 1), + PIN_FIELD_BASE(132, 132, 6, 0x00a0, 0x10, 17, 1), + PIN_FIELD_BASE(133, 133, 8, 0x00c0, 0x10, 11, 1), + PIN_FIELD_BASE(134, 134, 8, 0x00c0, 0x10, 14, 1), + PIN_FIELD_BASE(135, 135, 6, 0x00a0, 0x10, 15, 1), + PIN_FIELD_BASE(136, 136, 6, 0x00a0, 0x10, 18, 1), + PIN_FIELD_BASE(137, 137, 6, 0x00a0, 0x10, 16, 1), + PIN_FIELD_BASE(138, 138, 6, 0x00a0, 0x10, 19, 1), + PIN_FIELD_BASE(139, 139, 6, 0x00a0, 0x10, 0, 1), + PIN_FIELD_BASE(140, 140, 6, 0x00a0, 0x10, 2, 1), + PIN_FIELD_BASE(141, 141, 6, 0x00a0, 0x10, 1, 1), + PIN_FIELD_BASE(142, 142, 6, 0x00a0, 0x10, 3, 1), + PIN_FIELD_BASE(143, 143, 8, 0x00c0, 0x10, 12, 1), + PIN_FIELD_BASE(144, 144, 8, 0x00c0, 0x10, 15, 1), + PIN_FIELD_BASE(145, 145, 5, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(146, 146, 5, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(147, 147, 3, 0x00a0, 0x10, 19, 1), + PIN_FIELD_BASE(148, 148, 3, 0x00a0, 0x10, 20, 1), + PIN_FIELD_BASE(149, 149, 8, 0x00c0, 0x10, 16, 1), + PIN_FIELD_BASE(150, 150, 8, 0x00c0, 0x10, 17, 1), + PIN_FIELD_BASE(151, 151, 8, 0x00c0, 0x10, 18, 1), + PIN_FIELD_BASE(152, 152, 8, 0x00c0, 0x10, 19, 1), + PIN_FIELD_BASE(156, 156, 9, 0x0080, 0x10, 0, 1), + PIN_FIELD_BASE(157, 157, 9, 0x0080, 0x10, 1, 1), + PIN_FIELD_BASE(158, 158, 9, 0x0080, 0x10, 2, 1), + PIN_FIELD_BASE(159, 159, 9, 0x0080, 0x10, 3, 1), + PIN_FIELD_BASE(160, 160, 4, 0x0080, 0x10, 26, 1), + PIN_FIELD_BASE(161, 161, 4, 0x0080, 0x10, 25, 1), + PIN_FIELD_BASE(162, 162, 4, 0x0080, 0x10, 30, 1), + PIN_FIELD_BASE(163, 163, 4, 0x0080, 0x10, 29, 1), + PIN_FIELD_BASE(164, 164, 4, 0x0080, 0x10, 0, 1), + PIN_FIELD_BASE(165, 165, 4, 0x0080, 0x10, 7, 1), + PIN_FIELD_BASE(166, 166, 4, 0x0080, 0x10, 3, 1), + PIN_FIELD_BASE(167, 167, 4, 0x0080, 0x10, 4, 1), + PIN_FIELD_BASE(168, 168, 4, 0x0080, 0x10, 5, 1), + PIN_FIELD_BASE(169, 169, 4, 0x0080, 0x10, 6, 1), + PIN_FIELD_BASE(170, 170, 4, 0x0080, 0x10, 1, 1), + PIN_FIELD_BASE(171, 171, 4, 0x0080, 0x10, 2, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_pupd_range[] = { + PIN_FIELD_BASE(33, 33, 9, 0x0090, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 9, 0x0090, 0x10, 1, 1), + PIN_FIELD_BASE(35, 35, 9, 0x0090, 0x10, 2, 1), + PIN_FIELD_BASE(77, 77, 2, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(78, 78, 2, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(79, 79, 2, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(80, 80, 2, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(81, 81, 2, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(82, 82, 2, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(83, 83, 2, 0x0070, 0x10, 9, 1), + PIN_FIELD_BASE(84, 84, 2, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(85, 85, 2, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(86, 86, 2, 0x0070, 0x10, 12, 1), + PIN_FIELD_BASE(87, 87, 2, 0x0070, 0x10, 14, 1), + PIN_FIELD_BASE(88, 88, 2, 0x0070, 0x10, 13, 1), + PIN_FIELD_BASE(97, 97, 1, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(98, 98, 1, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(117, 117, 1, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(118, 118, 1, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(119, 119, 1, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(120, 120, 1, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(121, 121, 1, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(122, 122, 1, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(123, 123, 1, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(124, 124, 1, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(153, 153, 2, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(154, 154, 2, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(155, 155, 2, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(172, 172, 9, 0x0090, 0x10, 7, 1), + PIN_FIELD_BASE(173, 173, 9, 0x0090, 0x10, 8, 1), + PIN_FIELD_BASE(174, 174, 9, 0x0090, 0x10, 3, 1), + PIN_FIELD_BASE(175, 175, 9, 0x0090, 0x10, 4, 1), + PIN_FIELD_BASE(176, 176, 9, 0x0090, 0x10, 5, 1), + PIN_FIELD_BASE(177, 177, 9, 0x0090, 0x10, 9, 1), + PIN_FIELD_BASE(178, 178, 9, 0x0090, 0x10, 10, 1), + PIN_FIELD_BASE(179, 179, 9, 0x0090, 0x10, 11, 1), + PIN_FIELD_BASE(180, 180, 9, 0x0090, 0x10, 12, 1), + PIN_FIELD_BASE(181, 181, 9, 0x0090, 0x10, 13, 1), + PIN_FIELD_BASE(182, 182, 9, 0x0090, 0x10, 14, 1), + PIN_FIELD_BASE(183, 183, 9, 0x0090, 0x10, 6, 1), + PIN_FIELD_BASE(184, 184, 7, 0x0070, 0x10, 10, 1), + PIN_FIELD_BASE(185, 185, 7, 0x0070, 0x10, 0, 1), + PIN_FIELD_BASE(186, 186, 7, 0x0070, 0x10, 1, 1), + PIN_FIELD_BASE(187, 187, 7, 0x0070, 0x10, 11, 1), + PIN_FIELD_BASE(188, 188, 7, 0x0070, 0x10, 2, 1), + PIN_FIELD_BASE(189, 189, 7, 0x0070, 0x10, 3, 1), + PIN_FIELD_BASE(190, 190, 7, 0x0070, 0x10, 4, 1), + PIN_FIELD_BASE(191, 191, 7, 0x0070, 0x10, 5, 1), + PIN_FIELD_BASE(192, 192, 7, 0x0070, 0x10, 6, 1), + PIN_FIELD_BASE(193, 193, 7, 0x0070, 0x10, 7, 1), + PIN_FIELD_BASE(194, 194, 7, 0x0070, 0x10, 8, 1), + PIN_FIELD_BASE(195, 195, 7, 0x0070, 0x10, 9, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_r0_range[] = { + PIN_FIELD_BASE(33, 33, 9, 0x00b0, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 9, 0x00b0, 0x10, 1, 1), + PIN_FIELD_BASE(35, 35, 9, 0x00b0, 0x10, 2, 1), + PIN_FIELD_BASE(77, 77, 2, 0x0080, 0x10, 0, 1), + PIN_FIELD_BASE(78, 78, 2, 0x0080, 0x10, 1, 1), + PIN_FIELD_BASE(79, 79, 2, 0x0080, 0x10, 2, 1), + PIN_FIELD_BASE(80, 80, 2, 0x0080, 0x10, 3, 1), + PIN_FIELD_BASE(81, 81, 2, 0x0080, 0x10, 4, 1), + PIN_FIELD_BASE(82, 82, 2, 0x0080, 0x10, 5, 1), + PIN_FIELD_BASE(83, 83, 2, 0x0080, 0x10, 9, 1), + PIN_FIELD_BASE(84, 84, 2, 0x0080, 0x10, 11, 1), + PIN_FIELD_BASE(85, 85, 2, 0x0080, 0x10, 10, 1), + PIN_FIELD_BASE(86, 86, 2, 0x0080, 0x10, 12, 1), + PIN_FIELD_BASE(87, 87, 2, 0x0080, 0x10, 14, 1), + PIN_FIELD_BASE(88, 88, 2, 0x0080, 0x10, 13, 1), + PIN_FIELD_BASE(97, 97, 1, 0x00d0, 0x10, 1, 1), + PIN_FIELD_BASE(98, 98, 1, 0x00d0, 0x10, 0, 1), + PIN_FIELD_BASE(117, 117, 1, 0x00d0, 0x10, 2, 1), + PIN_FIELD_BASE(118, 118, 1, 0x00d0, 0x10, 3, 1), + PIN_FIELD_BASE(119, 119, 1, 0x00d0, 0x10, 4, 1), + PIN_FIELD_BASE(120, 120, 1, 0x00d0, 0x10, 5, 1), + PIN_FIELD_BASE(121, 121, 1, 0x00d0, 0x10, 6, 1), + PIN_FIELD_BASE(122, 122, 1, 0x00d0, 0x10, 7, 1), + PIN_FIELD_BASE(123, 123, 1, 0x00d0, 0x10, 8, 1), + PIN_FIELD_BASE(124, 124, 1, 0x00d0, 0x10, 9, 1), + PIN_FIELD_BASE(153, 153, 2, 0x0080, 0x10, 6, 1), + PIN_FIELD_BASE(154, 154, 2, 0x0080, 0x10, 7, 1), + PIN_FIELD_BASE(155, 155, 2, 0x0080, 0x10, 8, 1), + PIN_FIELD_BASE(172, 172, 9, 0x00b0, 0x10, 7, 1), + PIN_FIELD_BASE(173, 173, 9, 0x00b0, 0x10, 8, 1), + PIN_FIELD_BASE(174, 174, 9, 0x00b0, 0x10, 3, 1), + PIN_FIELD_BASE(175, 175, 9, 0x00b0, 0x10, 4, 1), + PIN_FIELD_BASE(176, 176, 9, 0x00b0, 0x10, 5, 1), + PIN_FIELD_BASE(177, 177, 9, 0x00b0, 0x10, 9, 1), + PIN_FIELD_BASE(178, 178, 9, 0x00b0, 0x10, 10, 1), + PIN_FIELD_BASE(179, 179, 9, 0x00b0, 0x10, 11, 1), + PIN_FIELD_BASE(180, 180, 9, 0x00b0, 0x10, 12, 1), + PIN_FIELD_BASE(181, 181, 9, 0x00b0, 0x10, 13, 1), + PIN_FIELD_BASE(182, 182, 9, 0x00b0, 0x10, 14, 1), + PIN_FIELD_BASE(183, 183, 9, 0x00b0, 0x10, 6, 1), + PIN_FIELD_BASE(184, 184, 7, 0x0080, 0x10, 10, 1), + PIN_FIELD_BASE(185, 185, 7, 0x0080, 0x10, 0, 1), + PIN_FIELD_BASE(186, 186, 7, 0x0080, 0x10, 1, 1), + PIN_FIELD_BASE(187, 187, 7, 0x0080, 0x10, 11, 1), + PIN_FIELD_BASE(188, 188, 7, 0x0080, 0x10, 2, 1), + PIN_FIELD_BASE(189, 189, 7, 0x0080, 0x10, 3, 1), + PIN_FIELD_BASE(190, 190, 7, 0x0080, 0x10, 4, 1), + PIN_FIELD_BASE(191, 191, 7, 0x0080, 0x10, 5, 1), + PIN_FIELD_BASE(192, 192, 7, 0x0080, 0x10, 6, 1), + PIN_FIELD_BASE(193, 193, 7, 0x0080, 0x10, 7, 1), + PIN_FIELD_BASE(194, 194, 7, 0x0080, 0x10, 8, 1), + PIN_FIELD_BASE(195, 195, 7, 0x0080, 0x10, 9, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_r1_range[] = { + PIN_FIELD_BASE(33, 33, 9, 0x00c0, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 9, 0x00c0, 0x10, 1, 1), + PIN_FIELD_BASE(35, 35, 9, 0x00c0, 0x10, 2, 1), + PIN_FIELD_BASE(77, 77, 2, 0x0090, 0x10, 0, 1), + PIN_FIELD_BASE(78, 78, 2, 0x0090, 0x10, 1, 1), + PIN_FIELD_BASE(79, 79, 2, 0x0090, 0x10, 2, 1), + PIN_FIELD_BASE(80, 80, 2, 0x0090, 0x10, 3, 1), + PIN_FIELD_BASE(81, 81, 2, 0x0090, 0x10, 4, 1), + PIN_FIELD_BASE(82, 82, 2, 0x0090, 0x10, 5, 1), + PIN_FIELD_BASE(83, 83, 2, 0x0090, 0x10, 9, 1), + PIN_FIELD_BASE(84, 84, 2, 0x0090, 0x10, 11, 1), + PIN_FIELD_BASE(85, 85, 2, 0x0090, 0x10, 10, 1), + PIN_FIELD_BASE(86, 86, 2, 0x0090, 0x10, 12, 1), + PIN_FIELD_BASE(87, 87, 2, 0x0090, 0x10, 14, 1), + PIN_FIELD_BASE(88, 88, 2, 0x0090, 0x10, 13, 1), + PIN_FIELD_BASE(97, 97, 1, 0x00e0, 0x10, 1, 1), + PIN_FIELD_BASE(98, 98, 1, 0x00e0, 0x10, 0, 1), + PIN_FIELD_BASE(117, 117, 1, 0x00e0, 0x10, 2, 1), + PIN_FIELD_BASE(118, 118, 1, 0x00e0, 0x10, 3, 1), + PIN_FIELD_BASE(119, 119, 1, 0x00e0, 0x10, 4, 1), + PIN_FIELD_BASE(120, 120, 1, 0x00e0, 0x10, 5, 1), + PIN_FIELD_BASE(121, 121, 1, 0x00e0, 0x10, 6, 1), + PIN_FIELD_BASE(122, 122, 1, 0x00e0, 0x10, 7, 1), + PIN_FIELD_BASE(123, 123, 1, 0x00e0, 0x10, 8, 1), + PIN_FIELD_BASE(124, 124, 1, 0x00e0, 0x10, 9, 1), + PIN_FIELD_BASE(153, 153, 2, 0x0090, 0x10, 6, 1), + PIN_FIELD_BASE(154, 154, 2, 0x0090, 0x10, 7, 1), + PIN_FIELD_BASE(155, 155, 2, 0x0090, 0x10, 8, 1), + PIN_FIELD_BASE(172, 172, 9, 0x00c0, 0x10, 7, 1), + PIN_FIELD_BASE(173, 173, 9, 0x00c0, 0x10, 8, 1), + PIN_FIELD_BASE(174, 174, 9, 0x00c0, 0x10, 3, 1), + PIN_FIELD_BASE(175, 175, 9, 0x00c0, 0x10, 4, 1), + PIN_FIELD_BASE(176, 176, 9, 0x00c0, 0x10, 5, 1), + PIN_FIELD_BASE(177, 177, 9, 0x00c0, 0x10, 9, 1), + PIN_FIELD_BASE(178, 178, 9, 0x00c0, 0x10, 10, 1), + PIN_FIELD_BASE(179, 179, 9, 0x00c0, 0x10, 11, 1), + PIN_FIELD_BASE(180, 180, 9, 0x00c0, 0x10, 12, 1), + PIN_FIELD_BASE(181, 181, 9, 0x00c0, 0x10, 13, 1), + PIN_FIELD_BASE(182, 182, 9, 0x00c0, 0x10, 14, 1), + PIN_FIELD_BASE(183, 183, 9, 0x00c0, 0x10, 6, 1), + PIN_FIELD_BASE(184, 184, 7, 0x0090, 0x10, 10, 1), + PIN_FIELD_BASE(185, 185, 7, 0x0090, 0x10, 0, 1), + PIN_FIELD_BASE(186, 186, 7, 0x0090, 0x10, 1, 1), + PIN_FIELD_BASE(187, 187, 7, 0x0090, 0x10, 11, 1), + PIN_FIELD_BASE(188, 188, 7, 0x0090, 0x10, 2, 1), + PIN_FIELD_BASE(189, 189, 7, 0x0090, 0x10, 3, 1), + PIN_FIELD_BASE(190, 190, 7, 0x0090, 0x10, 4, 1), + PIN_FIELD_BASE(191, 191, 7, 0x0090, 0x10, 5, 1), + PIN_FIELD_BASE(192, 192, 7, 0x0090, 0x10, 6, 1), + PIN_FIELD_BASE(193, 193, 7, 0x0090, 0x10, 7, 1), + PIN_FIELD_BASE(194, 194, 7, 0x0090, 0x10, 8, 1), + PIN_FIELD_BASE(195, 195, 7, 0x0090, 0x10, 9, 1), +}; + +static const struct mtk_pin_field_calc mt6878_pin_drv_range[] = { + PIN_FIELD_BASE(0, 0, 3, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(1, 1, 3, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(2, 2, 3, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(3, 3, 3, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(4, 4, 3, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(5, 5, 3, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(6, 6, 4, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(7, 7, 4, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(8, 8, 4, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(9, 9, 4, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(10, 10, 4, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(11, 11, 4, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(12, 12, 4, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(13, 13, 6, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(14, 14, 6, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(15, 15, 6, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(16, 16, 6, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(17, 17, 6, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(18, 18, 6, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(19, 19, 3, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(20, 20, 3, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(21, 21, 3, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(22, 22, 3, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(23, 23, 3, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(24, 24, 5, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(25, 25, 3, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(26, 26, 3, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(27, 27, 3, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(28, 28, 3, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(29, 29, 6, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(30, 30, 6, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(31, 31, 6, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(32, 32, 6, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(33, 33, 9, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(34, 34, 9, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(35, 35, 9, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(36, 36, 8, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(37, 37, 8, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(38, 38, 8, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(39, 39, 8, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(40, 40, 8, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(41, 41, 4, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(42, 42, 4, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(43, 43, 4, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(44, 44, 4, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(45, 45, 4, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(46, 46, 4, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(47, 47, 4, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(48, 48, 3, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(49, 49, 3, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(50, 50, 3, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(51, 51, 3, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(52, 52, 3, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(53, 53, 3, 0x0010, 0x10, 15, 3), + PIN_FIELD_BASE(54, 54, 3, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(55, 55, 3, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(56, 56, 5, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(57, 57, 5, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(58, 58, 3, 0x0020, 0x10, 6, 3), + PIN_FIELD_BASE(59, 59, 3, 0x0020, 0x10, 3, 3), + PIN_FIELD_BASE(60, 60, 8, 0x0020, 0x10, 0, 3), + PIN_FIELD_BASE(61, 61, 8, 0x0020, 0x10, 3, 3), + PIN_FIELD_BASE(62, 62, 8, 0x0020, 0x10, 9, 3), + PIN_FIELD_BASE(63, 63, 8, 0x0020, 0x10, 6, 3), + PIN_FIELD_BASE(64, 64, 8, 0x0020, 0x10, 12, 3), + PIN_FIELD_BASE(65, 65, 8, 0x0020, 0x10, 15, 3), + PIN_FIELD_BASE(66, 66, 8, 0x0020, 0x10, 21, 3), + PIN_FIELD_BASE(67, 67, 8, 0x0020, 0x10, 18, 3), + PIN_FIELD_BASE(68, 68, 5, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(69, 69, 5, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(70, 70, 5, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(71, 71, 5, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(72, 72, 5, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(73, 73, 5, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(74, 74, 5, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(75, 75, 5, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(76, 76, 5, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(77, 77, 2, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(78, 78, 2, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(79, 79, 2, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(80, 80, 2, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(81, 81, 2, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(82, 82, 2, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(83, 83, 2, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(84, 84, 2, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(85, 85, 2, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(86, 86, 2, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(87, 87, 2, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(88, 88, 2, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(89, 89, 4, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(90, 90, 4, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(91, 91, 4, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(92, 92, 8, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(93, 93, 8, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(94, 94, 8, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(95, 95, 8, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(96, 96, 8, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(97, 97, 1, 0x0020, 0x10, 18, 3), + PIN_FIELD_BASE(98, 98, 1, 0x0020, 0x10, 15, 3), + PIN_FIELD_BASE(99, 99, 1, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(100, 100, 1, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(101, 101, 1, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(102, 102, 1, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(103, 103, 1, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(104, 104, 1, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(105, 105, 1, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(106, 106, 1, 0x0010, 0x10, 15, 3), + PIN_FIELD_BASE(107, 107, 1, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(108, 108, 1, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(109, 109, 1, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(110, 110, 1, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(111, 111, 1, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(112, 112, 1, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(113, 113, 1, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(114, 114, 1, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(115, 115, 1, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(116, 116, 1, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(117, 117, 1, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(118, 118, 1, 0x0010, 0x10, 27, 3), + PIN_FIELD_BASE(119, 119, 1, 0x0020, 0x10, 0, 3), + PIN_FIELD_BASE(120, 120, 1, 0x0020, 0x10, 3, 3), + PIN_FIELD_BASE(121, 121, 1, 0x0020, 0x10, 6, 3), + PIN_FIELD_BASE(122, 122, 1, 0x0020, 0x10, 9, 3), + PIN_FIELD_BASE(123, 123, 1, 0x0020, 0x10, 12, 3), + PIN_FIELD_BASE(124, 124, 1, 0x0020, 0x10, 12, 3), + PIN_FIELD_BASE(125, 125, 8, 0x0010, 0x10, 27, 3), + PIN_FIELD_BASE(126, 126, 8, 0x0020, 0x10, 24, 3), + PIN_FIELD_BASE(127, 127, 8, 0x0020, 0x10, 27, 3), + PIN_FIELD_BASE(128, 128, 8, 0x0030, 0x10, 0, 3), + PIN_FIELD_BASE(129, 129, 8, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(130, 130, 8, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(131, 131, 6, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(132, 132, 6, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(133, 133, 8, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(134, 134, 8, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(135, 135, 6, 0x0010, 0x10, 15, 3), + PIN_FIELD_BASE(136, 136, 6, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(137, 137, 6, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(138, 138, 6, 0x0010, 0x10, 27, 3), + PIN_FIELD_BASE(139, 139, 6, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(140, 140, 6, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(141, 141, 6, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(142, 142, 6, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(143, 143, 8, 0x0010, 0x10, 6, 3), + PIN_FIELD_BASE(144, 144, 8, 0x0010, 0x10, 15, 3), + PIN_FIELD_BASE(145, 145, 5, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(146, 146, 5, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(147, 147, 3, 0x0010, 0x10, 27, 3), + PIN_FIELD_BASE(148, 148, 3, 0x0020, 0x10, 0, 3), + PIN_FIELD_BASE(149, 149, 8, 0x0010, 0x10, 18, 3), + PIN_FIELD_BASE(150, 150, 8, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(151, 151, 8, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(152, 152, 8, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(153, 153, 2, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(154, 154, 2, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(155, 155, 2, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(156, 156, 9, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(157, 157, 9, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(158, 158, 9, 0x0000, 0x10, 27, 3), + PIN_FIELD_BASE(159, 159, 9, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(160, 160, 4, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(161, 161, 4, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(162, 162, 4, 0x0010, 0x10, 21, 3), + PIN_FIELD_BASE(163, 163, 4, 0x0010, 0x10, 24, 3), + PIN_FIELD_BASE(164, 164, 4, 0x0010, 0x10, 15, 3), + PIN_FIELD_BASE(165, 165, 4, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(166, 166, 4, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(167, 167, 4, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(168, 168, 4, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(169, 169, 4, 0x0010, 0x10, 12, 3), + PIN_FIELD_BASE(170, 170, 4, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(171, 171, 4, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(172, 172, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(173, 173, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(174, 174, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(175, 175, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(176, 176, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(177, 177, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(178, 178, 9, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(179, 179, 9, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(180, 180, 9, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(181, 181, 9, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(182, 182, 9, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(183, 183, 9, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(184, 184, 7, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(185, 185, 7, 0x0000, 0x10, 0, 3), + PIN_FIELD_BASE(186, 186, 7, 0x0000, 0x10, 3, 3), + PIN_FIELD_BASE(187, 187, 7, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(188, 188, 7, 0x0000, 0x10, 6, 3), + PIN_FIELD_BASE(189, 189, 7, 0x0000, 0x10, 9, 3), + PIN_FIELD_BASE(190, 190, 7, 0x0000, 0x10, 12, 3), + PIN_FIELD_BASE(191, 191, 7, 0x0000, 0x10, 15, 3), + PIN_FIELD_BASE(192, 192, 7, 0x0000, 0x10, 18, 3), + PIN_FIELD_BASE(193, 193, 7, 0x0000, 0x10, 21, 3), + PIN_FIELD_BASE(194, 194, 7, 0x0000, 0x10, 24, 3), + PIN_FIELD_BASE(195, 195, 7, 0x0000, 0x10, 27, 3), +}; + +static const struct mtk_pin_field_calc mt6878_pin_drv_adv_range[] = { + PIN_FIELD_BASE(19, 19, 3, 0x0030, 0x10, 0, 3), + PIN_FIELD_BASE(24, 24, 5, 0x0020, 0x10, 0, 3), + PIN_FIELD_BASE(25, 25, 3, 0x0030, 0x10, 3, 3), + PIN_FIELD_BASE(26, 26, 3, 0x0030, 0x10, 6, 3), + PIN_FIELD_BASE(52, 52, 3, 0x0030, 0x10, 12, 3), + PIN_FIELD_BASE(53, 53, 3, 0x0030, 0x10, 15, 3), + PIN_FIELD_BASE(55, 55, 3, 0x0030, 0x10, 9, 3), + PIN_FIELD_BASE(60, 60, 8, 0x0050, 0x10, 12, 3), + PIN_FIELD_BASE(61, 61, 8, 0x0050, 0x10, 15, 3), + PIN_FIELD_BASE(62, 62, 8, 0x0050, 0x10, 21, 3), + PIN_FIELD_BASE(63, 63, 8, 0x0050, 0x10, 18, 3), + PIN_FIELD_BASE(64, 64, 8, 0x0050, 0x10, 24, 3), + PIN_FIELD_BASE(65, 65, 8, 0x0050, 0x10, 27, 3), + PIN_FIELD_BASE(66, 66, 8, 0x0060, 0x10, 3, 3), + PIN_FIELD_BASE(67, 67, 8, 0x0060, 0x10, 0, 3), + PIN_FIELD_BASE(92, 92, 8, 0x0040, 0x10, 0, 3), + PIN_FIELD_BASE(93, 93, 8, 0x0040, 0x10, 3, 3), + PIN_FIELD_BASE(94, 94, 8, 0x0040, 0x10, 6, 3), + PIN_FIELD_BASE(95, 95, 8, 0x0040, 0x10, 9, 3), + PIN_FIELD_BASE(96, 96, 8, 0x0040, 0x10, 12, 3), + PIN_FIELD_BASE(125, 125, 8, 0x0050, 0x10, 9, 3), + PIN_FIELD_BASE(126, 126, 8, 0x0060, 0x10, 6, 3), + PIN_FIELD_BASE(127, 127, 8, 0x0060, 0x10, 9, 3), + PIN_FIELD_BASE(128, 128, 8, 0x0060, 0x10, 12, 3), + PIN_FIELD_BASE(129, 129, 8, 0x0040, 0x10, 15, 3), + PIN_FIELD_BASE(130, 130, 8, 0x0040, 0x10, 24, 3), + PIN_FIELD_BASE(131, 131, 6, 0x0030, 0x10, 12, 3), + PIN_FIELD_BASE(132, 132, 6, 0x0030, 0x10, 21, 3), + PIN_FIELD_BASE(133, 133, 8, 0x0040, 0x10, 18, 3), + PIN_FIELD_BASE(134, 134, 8, 0x0040, 0x10, 27, 3), + PIN_FIELD_BASE(135, 135, 6, 0x0030, 0x10, 15, 3), + PIN_FIELD_BASE(136, 136, 6, 0x0030, 0x10, 24, 3), + PIN_FIELD_BASE(137, 137, 6, 0x0030, 0x10, 18, 3), + PIN_FIELD_BASE(138, 138, 6, 0x0030, 0x10, 27, 3), + PIN_FIELD_BASE(139, 139, 6, 0x0030, 0x10, 0, 3), + PIN_FIELD_BASE(140, 140, 6, 0x0030, 0x10, 6, 3), + PIN_FIELD_BASE(141, 141, 6, 0x0030, 0x10, 3, 3), + PIN_FIELD_BASE(142, 142, 6, 0x0030, 0x10, 9, 3), + PIN_FIELD_BASE(143, 143, 8, 0x0040, 0x10, 21, 3), + PIN_FIELD_BASE(144, 144, 8, 0x0050, 0x10, 0, 3), + PIN_FIELD_BASE(145, 145, 5, 0x0020, 0x10, 3, 3), + PIN_FIELD_BASE(146, 146, 5, 0x0020, 0x10, 6, 3), + PIN_FIELD_BASE(147, 147, 3, 0x0030, 0x10, 18, 3), + PIN_FIELD_BASE(148, 148, 3, 0x0030, 0x10, 21, 3), + PIN_FIELD_BASE(149, 149, 8, 0x0050, 0x10, 3, 3), + PIN_FIELD_BASE(150, 150, 8, 0x0050, 0x10, 6, 3), + PIN_FIELD_BASE(156, 156, 9, 0x0020, 0x10, 0, 5), + PIN_FIELD_BASE(157, 157, 9, 0x0020, 0x10, 5, 5), + PIN_FIELD_BASE(158, 158, 9, 0x0020, 0x10, 10, 5), + PIN_FIELD_BASE(159, 159, 9, 0x0020, 0x10, 15, 5), +}; + +static const struct mtk_pin_field_calc mt6878_pin_rsel_range[] = { + PIN_FIELD_BASE(19, 19, 3, 0x00d0, 0x10, 0, 3), + PIN_FIELD_BASE(24, 24, 5, 0x00a0, 0x10, 0, 3), + PIN_FIELD_BASE(25, 25, 3, 0x00d0, 0x10, 3, 3), + PIN_FIELD_BASE(26, 26, 3, 0x00d0, 0x10, 6, 3), + PIN_FIELD_BASE(52, 52, 3, 0x00d0, 0x10, 12, 3), + PIN_FIELD_BASE(53, 53, 3, 0x00d0, 0x10, 15, 3), + PIN_FIELD_BASE(55, 55, 3, 0x00d0, 0x10, 9, 3), + PIN_FIELD_BASE(60, 60, 8, 0x0110, 0x10, 12, 3), + PIN_FIELD_BASE(61, 61, 8, 0x0110, 0x10, 15, 3), + PIN_FIELD_BASE(62, 62, 8, 0x0110, 0x10, 21, 3), + PIN_FIELD_BASE(63, 63, 8, 0x0110, 0x10, 18, 3), + PIN_FIELD_BASE(64, 64, 8, 0x0110, 0x10, 24, 3), + PIN_FIELD_BASE(65, 65, 8, 0x0110, 0x10, 27, 3), + PIN_FIELD_BASE(66, 66, 8, 0x0120, 0x10, 3, 3), + PIN_FIELD_BASE(67, 67, 8, 0x0120, 0x10, 0, 3), + PIN_FIELD_BASE(92, 92, 8, 0x0100, 0x10, 0, 3), + PIN_FIELD_BASE(93, 93, 8, 0x0100, 0x10, 3, 3), + PIN_FIELD_BASE(94, 94, 8, 0x0100, 0x10, 6, 3), + PIN_FIELD_BASE(95, 95, 8, 0x0100, 0x10, 9, 3), + PIN_FIELD_BASE(96, 96, 8, 0x0100, 0x10, 12, 3), + PIN_FIELD_BASE(125, 125, 8, 0x0110, 0x10, 9, 3), + PIN_FIELD_BASE(126, 126, 8, 0x0120, 0x10, 6, 3), + PIN_FIELD_BASE(127, 127, 8, 0x0120, 0x10, 9, 3), + PIN_FIELD_BASE(128, 128, 8, 0x0120, 0x10, 12, 3), + PIN_FIELD_BASE(129, 129, 8, 0x0100, 0x10, 15, 3), + PIN_FIELD_BASE(130, 130, 8, 0x0100, 0x10, 24, 3), + PIN_FIELD_BASE(131, 131, 6, 0x00d0, 0x10, 12, 3), + PIN_FIELD_BASE(132, 132, 6, 0x00d0, 0x10, 21, 3), + PIN_FIELD_BASE(133, 133, 8, 0x0100, 0x10, 18, 3), + PIN_FIELD_BASE(134, 134, 8, 0x0100, 0x10, 27, 3), + PIN_FIELD_BASE(135, 135, 6, 0x00d0, 0x10, 15, 3), + PIN_FIELD_BASE(136, 136, 6, 0x00d0, 0x10, 24, 3), + PIN_FIELD_BASE(137, 137, 6, 0x00d0, 0x10, 18, 3), + PIN_FIELD_BASE(138, 138, 6, 0x00d0, 0x10, 27, 3), + PIN_FIELD_BASE(139, 139, 6, 0x00d0, 0x10, 0, 3), + PIN_FIELD_BASE(140, 140, 6, 0x00d0, 0x10, 6, 3), + PIN_FIELD_BASE(141, 141, 6, 0x00d0, 0x10, 3, 3), + PIN_FIELD_BASE(142, 142, 6, 0x00d0, 0x10, 9, 3), + PIN_FIELD_BASE(143, 143, 8, 0x0100, 0x10, 21, 3), + PIN_FIELD_BASE(144, 144, 8, 0x0110, 0x10, 0, 3), + PIN_FIELD_BASE(145, 145, 5, 0x00a0, 0x10, 3, 3), + PIN_FIELD_BASE(146, 146, 5, 0x00a0, 0x10, 6, 3), + PIN_FIELD_BASE(147, 147, 3, 0x00d0, 0x10, 18, 3), + PIN_FIELD_BASE(148, 148, 3, 0x00d0, 0x10, 21, 3), + PIN_FIELD_BASE(149, 149, 8, 0x0110, 0x10, 3, 3), + PIN_FIELD_BASE(150, 150, 8, 0x0110, 0x10, 6, 3), +}; + +static const unsigned int mt6878_pull_type[] = { + MTK_PULL_PU_PD_TYPE /* 0 */, + MTK_PULL_PU_PD_TYPE /* 1 */, + MTK_PULL_PU_PD_TYPE /* 2 */, + MTK_PULL_PU_PD_TYPE /* 3 */, + MTK_PULL_PU_PD_TYPE /* 4 */, + MTK_PULL_PU_PD_TYPE /* 5 */, + MTK_PULL_PU_PD_TYPE /* 6 */, + MTK_PULL_PU_PD_TYPE /* 7 */, + MTK_PULL_PU_PD_TYPE /* 8 */, + MTK_PULL_PU_PD_TYPE /* 9 */, + MTK_PULL_PU_PD_TYPE /* 10 */, + MTK_PULL_PU_PD_TYPE /* 11 */, + MTK_PULL_PU_PD_TYPE /* 12 */, + MTK_PULL_PU_PD_TYPE /* 13 */, + MTK_PULL_PU_PD_TYPE /* 14 */, + MTK_PULL_PU_PD_TYPE /* 15 */, + MTK_PULL_PU_PD_TYPE /* 16 */, + MTK_PULL_PU_PD_TYPE /* 17 */, + MTK_PULL_PU_PD_TYPE /* 18 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 19 */, + MTK_PULL_PU_PD_TYPE /* 20 */, + MTK_PULL_PU_PD_TYPE /* 21 */, + MTK_PULL_PU_PD_TYPE /* 22 */, + MTK_PULL_PU_PD_TYPE /* 23 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 24 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 25 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 26 */, + MTK_PULL_PU_PD_TYPE /* 27 */, + MTK_PULL_PU_PD_TYPE /* 28 */, + MTK_PULL_PU_PD_TYPE /* 29 */, + MTK_PULL_PU_PD_TYPE /* 30 */, + MTK_PULL_PU_PD_TYPE /* 31 */, + MTK_PULL_PU_PD_TYPE /* 32 */, + MTK_PULL_PUPD_R1R0_TYPE /* 33 */, + MTK_PULL_PUPD_R1R0_TYPE /* 34 */, + MTK_PULL_PUPD_R1R0_TYPE /* 35 */, + MTK_PULL_PU_PD_TYPE /* 36 */, + MTK_PULL_PU_PD_TYPE /* 37 */, + MTK_PULL_PU_PD_TYPE /* 38 */, + MTK_PULL_PU_PD_TYPE /* 39 */, + MTK_PULL_PU_PD_TYPE /* 40 */, + MTK_PULL_PU_PD_TYPE /* 41 */, + MTK_PULL_PU_PD_TYPE /* 42 */, + MTK_PULL_PU_PD_TYPE /* 43 */, + MTK_PULL_PU_PD_TYPE /* 44 */, + MTK_PULL_PU_PD_TYPE /* 45 */, + MTK_PULL_PU_PD_TYPE /* 46 */, + MTK_PULL_PU_PD_TYPE /* 47 */, + MTK_PULL_PU_PD_TYPE /* 48 */, + MTK_PULL_PU_PD_TYPE /* 49 */, + MTK_PULL_PU_PD_TYPE /* 50 */, + MTK_PULL_PU_PD_TYPE /* 51 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 52 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 53 */, + MTK_PULL_PU_PD_TYPE /* 54 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 55 */, + MTK_PULL_PU_PD_TYPE /* 56 */, + MTK_PULL_PU_PD_TYPE /* 57 */, + MTK_PULL_PU_PD_TYPE /* 58 */, + MTK_PULL_PU_PD_TYPE /* 59 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 60 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 61 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 62 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 63 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 64 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 65 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 66 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 67 */, + MTK_PULL_PU_PD_TYPE /* 68 */, + MTK_PULL_PU_PD_TYPE /* 69 */, + MTK_PULL_PU_PD_TYPE /* 70 */, + MTK_PULL_PU_PD_TYPE /* 71 */, + MTK_PULL_PU_PD_TYPE /* 72 */, + MTK_PULL_PU_PD_TYPE /* 73 */, + MTK_PULL_PU_PD_TYPE /* 74 */, + MTK_PULL_PU_PD_TYPE /* 75 */, + MTK_PULL_PU_PD_TYPE /* 76 */, + MTK_PULL_PUPD_R1R0_TYPE /* 77 */, + MTK_PULL_PUPD_R1R0_TYPE /* 78 */, + MTK_PULL_PUPD_R1R0_TYPE /* 79 */, + MTK_PULL_PUPD_R1R0_TYPE /* 80 */, + MTK_PULL_PUPD_R1R0_TYPE /* 81 */, + MTK_PULL_PUPD_R1R0_TYPE /* 82 */, + MTK_PULL_PUPD_R1R0_TYPE /* 83 */, + MTK_PULL_PUPD_R1R0_TYPE /* 84 */, + MTK_PULL_PUPD_R1R0_TYPE /* 85 */, + MTK_PULL_PUPD_R1R0_TYPE /* 86 */, + MTK_PULL_PUPD_R1R0_TYPE /* 87 */, + MTK_PULL_PUPD_R1R0_TYPE /* 88 */, + MTK_PULL_PU_PD_TYPE /* 89 */, + MTK_PULL_PU_PD_TYPE /* 90 */, + MTK_PULL_PU_PD_TYPE /* 91 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 92 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 93 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 94 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 95 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 96 */, + MTK_PULL_PUPD_R1R0_TYPE /* 97 */, + MTK_PULL_PUPD_R1R0_TYPE /* 98 */, + MTK_PULL_PU_PD_TYPE /* 99 */, + MTK_PULL_PU_PD_TYPE /* 100 */, + MTK_PULL_PU_PD_TYPE /* 101 */, + MTK_PULL_PU_PD_TYPE /* 102 */, + MTK_PULL_PU_PD_TYPE /* 103 */, + MTK_PULL_PU_PD_TYPE /* 104 */, + MTK_PULL_PU_PD_TYPE /* 105 */, + MTK_PULL_PU_PD_TYPE /* 106 */, + MTK_PULL_PU_PD_TYPE /* 107 */, + MTK_PULL_PU_PD_TYPE /* 108 */, + MTK_PULL_PU_PD_TYPE /* 109 */, + MTK_PULL_PU_PD_TYPE /* 110 */, + MTK_PULL_PU_PD_TYPE /* 111 */, + MTK_PULL_PU_PD_TYPE /* 112 */, + MTK_PULL_PU_PD_TYPE /* 113 */, + MTK_PULL_PU_PD_TYPE /* 114 */, + MTK_PULL_PU_PD_TYPE /* 115 */, + MTK_PULL_PU_PD_TYPE /* 116 */, + MTK_PULL_PUPD_R1R0_TYPE /* 117 */, + MTK_PULL_PUPD_R1R0_TYPE /* 118 */, + MTK_PULL_PUPD_R1R0_TYPE /* 119 */, + MTK_PULL_PUPD_R1R0_TYPE /* 120 */, + MTK_PULL_PUPD_R1R0_TYPE /* 121 */, + MTK_PULL_PUPD_R1R0_TYPE /* 122 */, + MTK_PULL_PUPD_R1R0_TYPE /* 123 */, + MTK_PULL_PUPD_R1R0_TYPE /* 124 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 125 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 126 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 127 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 128 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 129 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 130 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 131 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 132 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 133 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 134 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 135 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 136 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 137 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 138 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 139 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 140 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 141 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 142 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 143 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 144 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 145 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 146 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 147 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 148 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 149 */, + MTK_PULL_PU_PD_RSEL_TYPE /* 150 */, + MTK_PULL_PU_PD_TYPE /* 151 */, + MTK_PULL_PU_PD_TYPE /* 152 */, + MTK_PULL_PUPD_R1R0_TYPE /* 153 */, + MTK_PULL_PUPD_R1R0_TYPE /* 154 */, + MTK_PULL_PUPD_R1R0_TYPE /* 155 */, + MTK_PULL_PU_PD_TYPE /* 156 */, + MTK_PULL_PU_PD_TYPE /* 157 */, + MTK_PULL_PU_PD_TYPE /* 158 */, + MTK_PULL_PU_PD_TYPE /* 159 */, + MTK_PULL_PU_PD_TYPE /* 160 */, + MTK_PULL_PU_PD_TYPE /* 161 */, + MTK_PULL_PU_PD_TYPE /* 162 */, + MTK_PULL_PU_PD_TYPE /* 163 */, + MTK_PULL_PU_PD_TYPE /* 164 */, + MTK_PULL_PU_PD_TYPE /* 165 */, + MTK_PULL_PU_PD_TYPE /* 166 */, + MTK_PULL_PU_PD_TYPE /* 167 */, + MTK_PULL_PU_PD_TYPE /* 168 */, + MTK_PULL_PU_PD_TYPE /* 169 */, + MTK_PULL_PU_PD_TYPE /* 170 */, + MTK_PULL_PU_PD_TYPE /* 171 */, + MTK_PULL_PUPD_R1R0_TYPE /* 172 */, + MTK_PULL_PUPD_R1R0_TYPE /* 173 */, + MTK_PULL_PUPD_R1R0_TYPE /* 174 */, + MTK_PULL_PUPD_R1R0_TYPE /* 175 */, + MTK_PULL_PUPD_R1R0_TYPE /* 176 */, + MTK_PULL_PUPD_R1R0_TYPE /* 177 */, + MTK_PULL_PUPD_R1R0_TYPE /* 178 */, + MTK_PULL_PUPD_R1R0_TYPE /* 179 */, + MTK_PULL_PUPD_R1R0_TYPE /* 180 */, + MTK_PULL_PUPD_R1R0_TYPE /* 181 */, + MTK_PULL_PUPD_R1R0_TYPE /* 182 */, + MTK_PULL_PUPD_R1R0_TYPE /* 183 */, + MTK_PULL_PUPD_R1R0_TYPE /* 184 */, + MTK_PULL_PUPD_R1R0_TYPE /* 185 */, + MTK_PULL_PUPD_R1R0_TYPE /* 186 */, + MTK_PULL_PUPD_R1R0_TYPE /* 187 */, + MTK_PULL_PUPD_R1R0_TYPE /* 188 */, + MTK_PULL_PUPD_R1R0_TYPE /* 189 */, + MTK_PULL_PUPD_R1R0_TYPE /* 190 */, + MTK_PULL_PUPD_R1R0_TYPE /* 191 */, + MTK_PULL_PUPD_R1R0_TYPE /* 192 */, + MTK_PULL_PUPD_R1R0_TYPE /* 193 */, + MTK_PULL_PUPD_R1R0_TYPE /* 194 */, + MTK_PULL_PUPD_R1R0_TYPE /* 195 */, +}; + +static const char * const mt6878_pinctrl_register_base_names[] = { + "gpio", "iocfg_bl", "iocfg_bm", "iocfg_br", + "iocfg_bl1", "iocfg_br1", "iocfg_lm", "iocfg_lt", + "iocfg_rm", "iocfg_rt", +}; + +static const struct mtk_eint_hw mt6878_eint_hw = { + .port_mask = 31, + .ports = 1, + .ap_num = 216, + .db_cnt = 36, + .db_time = debounce_time_mt6878, +}; + +static const struct mtk_pin_reg_calc mt6878_reg_cals[PINCTRL_PIN_REG_MAX] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt6878_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt6878_pin_dir_range), + [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt6878_pin_di_range), + [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt6878_pin_do_range), + [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt6878_pin_dir_range), + [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt6878_pin_smt_range), + [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt6878_pin_ies_range), + [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt6878_pin_pu_range), + [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt6878_pin_pd_range), + [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt6878_pin_drv_range), + [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt6878_pin_pupd_range), + [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt6878_pin_r0_range), + [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt6878_pin_r1_range), + [PINCTRL_PIN_REG_DRV_ADV] = MTK_RANGE(mt6878_pin_drv_adv_range), + [PINCTRL_PIN_REG_RSEL] = MTK_RANGE(mt6878_pin_rsel_range), +}; + +static const struct mtk_pin_soc mt6878_data = { + .reg_cal = mt6878_reg_cals, + .pins = mtk_pins_mt6878, + .npins = ARRAY_SIZE(mtk_pins_mt6878), + .ngrps = ARRAY_SIZE(mtk_pins_mt6878), + .eint_pin = eint_pins_mt6878, + .eint_hw = &mt6878_eint_hw, + .nfuncs = 8, + .gpio_m = 0, + .base_names = mt6878_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt6878_pinctrl_register_base_names), + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .pull_type = mt6878_pull_type, + .adv_drive_get = mtk_pinconf_adv_drive_get, + .adv_drive_set = mtk_pinconf_adv_drive_set, +}; + +static const struct of_device_id mt6878_pinctrl_of_match[] = { + { .compatible = "mediatek,mt6878-pinctrl", .data = &mt6878_data }, + { } +}; + +static struct platform_driver mt6878_pinctrl_driver = { + .driver = { + .name = "mt6878-pinctrl", + .of_match_table = mt6878_pinctrl_of_match, + .pm = pm_sleep_ptr(&mtk_paris_pinctrl_pm_ops), + }, + .probe = mtk_paris_pinctrl_probe, +}; + +static int __init mt6878_pinctrl_init(void) +{ + return platform_driver_register(&mt6878_pinctrl_driver); +} +arch_initcall(mt6878_pinctrl_init); + +MODULE_DESCRIPTION("MediaTek MT6878 Pinctrl Driver"); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6878.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6878.h new file mode 100644 index 00000000000000..a251af00eff11b --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6878.h @@ -0,0 +1,2248 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Light Hsieh + * + * Copyright (C) 2025 Igor Belwon + */ + +#ifndef __PINCTRL_MTK_MT6878_H +#define __PINCTRL_MTK_MT6878_H + +#include "pinctrl-paris.h" + +static const struct mtk_pin_desc mtk_pins_mt6878[] = { + MTK_PIN( + 0, "GPIO0", + MTK_EINT_FUNCTION(0, 0), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "TP_GPIO0_AO"), + MTK_FUNCTION(2, "SRCLKENA1"), + MTK_FUNCTION(7, "DBG_MON_A3") + ), + MTK_PIN( + 1, "GPIO1", + MTK_EINT_FUNCTION(0, 1), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "TP_GPIO1_AO"), + MTK_FUNCTION(2, "SRCLKENA1"), + MTK_FUNCTION(3, "SRCLKENA2"), + MTK_FUNCTION(5, "IDDIG"), + MTK_FUNCTION(7, "DBG_MON_A4") + ), + MTK_PIN( + 2, "GPIO2", + MTK_EINT_FUNCTION(0, 2), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "TP_GPIO2_AO"), + MTK_FUNCTION(2, "SRCLKENAI0"), + MTK_FUNCTION(4, "SCP_DMIC_CLK"), + MTK_FUNCTION(5, "DMIC_CLK"), + MTK_FUNCTION(7, "DBG_MON_A5") + ), + MTK_PIN( + 3, "GPIO3", + MTK_EINT_FUNCTION(0, 3), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "TP_GPIO3_AO"), + MTK_FUNCTION(2, "SRCLKENAI1"), + MTK_FUNCTION(4, "SCP_DMIC_DAT"), + MTK_FUNCTION(5, "DMIC_DAT"), + MTK_FUNCTION(7, "DBG_MON_A6") + ), + MTK_PIN( + 4, "GPIO4", + MTK_EINT_FUNCTION(0, 4), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "SPI7_CLK"), + MTK_FUNCTION(2, "TP_GPIO4_AO"), + MTK_FUNCTION(3, "ANT_SEL0"), + MTK_FUNCTION(5, "DMIC1_CLK"), + MTK_FUNCTION(6, "MD_INT4"), + MTK_FUNCTION(7, "DBG_MON_A7") + ), + MTK_PIN( + 5, "GPIO5", + MTK_EINT_FUNCTION(0, 5), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "SPI7_CSB"), + MTK_FUNCTION(2, "TP_GPIO5_AO"), + MTK_FUNCTION(3, "ANT_SEL1"), + MTK_FUNCTION(5, "DMIC1_DAT"), + MTK_FUNCTION(6, "MD_INT0"), + MTK_FUNCTION(7, "DBG_MON_A8") + ), + MTK_PIN( + 6, "GPIO6", + MTK_EINT_FUNCTION(0, 6), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "SPI7_MO"), + MTK_FUNCTION(2, "TP_GPIO6_AO"), + MTK_FUNCTION(3, "ANT_SEL2"), + MTK_FUNCTION(4, "MD32_0_GPIO0"), + MTK_FUNCTION(6, "MD_INT3"), + MTK_FUNCTION(7, "DBG_MON_B0") + ), + MTK_PIN( + 7, "GPIO7", + MTK_EINT_FUNCTION(0, 7), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "SPI7_MI"), + MTK_FUNCTION(2, "TP_GPIO7_AO"), + MTK_FUNCTION(3, "ANT_SEL3"), + MTK_FUNCTION(4, "MD32_1_GPIO0") + ), + MTK_PIN( + 8, "GPIO8", + MTK_EINT_FUNCTION(0, 8), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(2, "SCP_JTAG0_TRSTN_VLP"), + MTK_FUNCTION(3, "SPM_JTAG_TRSTN_VLP"), + MTK_FUNCTION(4, "SSPM_JTAG_TRSTN_VLP"), + MTK_FUNCTION(5, "HFRP_JTAG0_TRSTN"), + MTK_FUNCTION(6, "IO_JTAG_TRSTN"), + MTK_FUNCTION(7, "CONN_BGF_MCU_TDI") + ), + MTK_PIN( + 9, "GPIO9", + MTK_EINT_FUNCTION(0, 9), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(2, "SCP_JTAG0_TCK_VLP"), + MTK_FUNCTION(3, "SPM_JTAG_TCK_VLP"), + MTK_FUNCTION(4, "SSPM_JTAG_TCK_VLP"), + MTK_FUNCTION(5, "HFRP_JTAG0_TCK"), + MTK_FUNCTION(6, "IO_JTAG_TCK"), + MTK_FUNCTION(7, "CONN_BGF_MCU_TRST_B") + ), + MTK_PIN( + 10, "GPIO10", + MTK_EINT_FUNCTION(0, 10), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(2, "SCP_JTAG0_TMS_VLP"), + MTK_FUNCTION(3, "SPM_JTAG_TMS_VLP"), + MTK_FUNCTION(4, "SSPM_JTAG_TMS_VLP"), + MTK_FUNCTION(5, "HFRP_JTAG0_TMS"), + MTK_FUNCTION(6, "IO_JTAG_TMS"), + MTK_FUNCTION(7, "CONN_BGF_MCU_TCK") + ), + MTK_PIN( + 11, "GPIO11", + MTK_EINT_FUNCTION(0, 11), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(2, "SCP_JTAG0_TDI_VLP"), + MTK_FUNCTION(3, "SPM_JTAG_TDI_VLP"), + MTK_FUNCTION(4, "SSPM_JTAG_TDI_VLP"), + MTK_FUNCTION(5, "HFRP_JTAG0_TDI"), + MTK_FUNCTION(6, "IO_JTAG_TDI"), + MTK_FUNCTION(7, "CONN_BGF_MCU_TDO") + ), + MTK_PIN( + 12, "GPIO12", + MTK_EINT_FUNCTION(0, 12), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(2, "SCP_JTAG0_TDO_VLP"), + MTK_FUNCTION(3, "SPM_JTAG_TDO_VLP"), + MTK_FUNCTION(4, "SSPM_JTAG_TDO_VLP"), + MTK_FUNCTION(5, "HFRP_JTAG0_TDO"), + MTK_FUNCTION(6, "IO_JTAG_TDO"), + MTK_FUNCTION(7, "CONN_BGF_MCU_TMS") + ), + MTK_PIN( + 13, "GPIO13", + MTK_EINT_FUNCTION(0, 13), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "MFG_EB_JTAG_TDI"), + MTK_FUNCTION(2, "CONN_WF_MCU_TDI"), + MTK_FUNCTION(3, "SCP_JTAG0_TDI_VCORE"), + MTK_FUNCTION(5, "SPM_JTAG_TDI_VCORE"), + MTK_FUNCTION(6, "MCUPM_JTAG_TDI") + ), + MTK_PIN( + 14, "GPIO14", + MTK_EINT_FUNCTION(0, 14), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "MFG_EB_JTAG_TRSTN"), + MTK_FUNCTION(2, "CONN_WF_MCU_TRST_B"), + MTK_FUNCTION(3, "SCP_JTAG0_TRSTN_VCORE"), + MTK_FUNCTION(5, "SPM_JTAG_TRSTN_VCORE"), + MTK_FUNCTION(6, "MCUPM_JTAG_TRSTN") + ), + MTK_PIN( + 15, "GPIO15", + MTK_EINT_FUNCTION(0, 15), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "MFG_EB_JTAG_TCK"), + MTK_FUNCTION(2, "CONN_WF_MCU_TCK"), + MTK_FUNCTION(3, "SCP_JTAG0_TCK_VCORE"), + MTK_FUNCTION(5, "SPM_JTAG_TCK_VCORE"), + MTK_FUNCTION(6, "MCUPM_JTAG_TCK") + ), + MTK_PIN( + 16, "GPIO16", + MTK_EINT_FUNCTION(0, 16), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "MFG_EB_JTAG_TDO"), + MTK_FUNCTION(2, "CONN_WF_MCU_TDO"), + MTK_FUNCTION(3, "SCP_JTAG0_TDO_VCORE"), + MTK_FUNCTION(5, "SPM_JTAG_TDO_VCORE"), + MTK_FUNCTION(6, "MCUPM_JTAG_TDO") + ), + MTK_PIN( + 17, "GPIO17", + MTK_EINT_FUNCTION(0, 17), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "MFG_EB_JTAG_TMS"), + MTK_FUNCTION(2, "CONN_WF_MCU_TMS"), + MTK_FUNCTION(3, "SCP_JTAG0_TMS_VCORE"), + MTK_FUNCTION(5, "SPM_JTAG_TMS_VCORE"), + MTK_FUNCTION(6, "MCUPM_JTAG_TMS") + ), + MTK_PIN( + 18, "GPIO18", + MTK_EINT_FUNCTION(0, 18), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(2, "CONN_BT_TXD"), + MTK_FUNCTION(3, "CONN_TCXOENA_REQ"), + MTK_FUNCTION(6, "GPS_L1_ELNA_EN") + ), + MTK_PIN( + 19, "GPIO19", + MTK_EINT_FUNCTION(0, 19), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "PWM_0"), + MTK_FUNCTION(3, "SDA10"), + MTK_FUNCTION(4, "MD32_0_GPIO0"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A9") + ), + MTK_PIN( + 20, "GPIO20", + MTK_EINT_FUNCTION(0, 20), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "PWM_1"), + MTK_FUNCTION(2, "SPI4_CLK"), + MTK_FUNCTION(4, "GPS_L1_ELNA_EN"), + MTK_FUNCTION(6, "DAP_SONIC_SWCK"), + MTK_FUNCTION(7, "DBG_MON_A10") + ), + MTK_PIN( + 21, "GPIO21", + MTK_EINT_FUNCTION(0, 21), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "PWM_2"), + MTK_FUNCTION(2, "SPI4_CSB"), + MTK_FUNCTION(4, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(5, "IDDIG"), + MTK_FUNCTION(6, "DAP_SONIC_SWD"), + MTK_FUNCTION(7, "DBG_MON_A11") + ), + MTK_PIN( + 22, "GPIO22", + MTK_EINT_FUNCTION(0, 22), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "PWM_3"), + MTK_FUNCTION(2, "SPI4_MO"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "VBUSVALID"), + MTK_FUNCTION(6, "DAP_MD32_SWCK"), + MTK_FUNCTION(7, "DBG_MON_A12") + ), + MTK_PIN( + 23, "GPIO23", + MTK_EINT_FUNCTION(0, 23), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(2, "SPI4_MI"), + MTK_FUNCTION(4, "MD32_1_GPIO0"), + MTK_FUNCTION(5, "USB_DRVVBUS"), + MTK_FUNCTION(6, "DAP_MD32_SWD"), + MTK_FUNCTION(7, "DBG_MON_A13") + ), + MTK_PIN( + 24, "GPIO24", + MTK_EINT_FUNCTION(0, 24), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(2, "SCL12"), + MTK_FUNCTION(3, "SCL10"), + MTK_FUNCTION(4, "CMVREF0"), + MTK_FUNCTION(5, "CONN_WIFI_TXD"), + MTK_FUNCTION(6, "CMFLASH0"), + MTK_FUNCTION(7, "DBG_MON_A14") + ), + MTK_PIN( + 25, "GPIO25", + MTK_EINT_FUNCTION(0, 25), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "SPI6_CLK"), + MTK_FUNCTION(2, "SCL11"), + MTK_FUNCTION(4, "CMVREF1"), + MTK_FUNCTION(6, "CMFLASH1"), + MTK_FUNCTION(7, "DBG_MON_A15") + ), + MTK_PIN( + 26, "GPIO26", + MTK_EINT_FUNCTION(0, 26), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "SPI6_CSB"), + MTK_FUNCTION(2, "SDA11"), + MTK_FUNCTION(3, "USB_DRVVBUS"), + MTK_FUNCTION(4, "CMVREF2"), + MTK_FUNCTION(6, "CMFLASH2"), + MTK_FUNCTION(7, "DBG_MON_A16") + ), + MTK_PIN( + 27, "GPIO27", + MTK_EINT_FUNCTION(0, 27), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "SPI6_MO"), + MTK_FUNCTION(3, "VBUSVALID"), + MTK_FUNCTION(4, "CMVREF3"), + MTK_FUNCTION(5, "DMIC1_CLK"), + MTK_FUNCTION(6, "CMFLASH3"), + MTK_FUNCTION(7, "DBG_MON_A17") + ), + MTK_PIN( + 28, "GPIO28", + MTK_EINT_FUNCTION(0, 28), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "SPI6_MI"), + MTK_FUNCTION(3, "IDDIG"), + MTK_FUNCTION(5, "DMIC1_DAT"), + MTK_FUNCTION(6, "CMFLASH0"), + MTK_FUNCTION(7, "DBG_MON_A18") + ), + MTK_PIN( + 29, "GPIO29", + MTK_EINT_FUNCTION(0, 29), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "I2SIN2_BCK"), + MTK_FUNCTION(2, "TP_UTXD1_VCORE"), + MTK_FUNCTION(3, "MD_UTXD0"), + MTK_FUNCTION(4, "SSPM_UTXD_AO_VCORE"), + MTK_FUNCTION(5, "MD32_1_TXD"), + MTK_FUNCTION(6, "CONN_BT_TXD"), + MTK_FUNCTION(7, "PTA_TXD") + ), + MTK_PIN( + 30, "GPIO30", + MTK_EINT_FUNCTION(0, 30), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "I2SIN2_LRCK"), + MTK_FUNCTION(2, "TP_URXD1_VCORE"), + MTK_FUNCTION(3, "MD_URXD0"), + MTK_FUNCTION(4, "SSPM_URXD_AO_VCORE"), + MTK_FUNCTION(5, "MD32_1_RXD"), + MTK_FUNCTION(7, "PTA_RXD") + ), + MTK_PIN( + 31, "GPIO31", + MTK_EINT_FUNCTION(0, 31), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "I2SOUT2_DO"), + MTK_FUNCTION(2, "TP_UTXD2_VCORE"), + MTK_FUNCTION(3, "MD_UTXD1"), + MTK_FUNCTION(4, "HFRP_UTXD1"), + MTK_FUNCTION(5, "MD32_0_TXD"), + MTK_FUNCTION(6, "CONN_WIFI_TXD"), + MTK_FUNCTION(7, "CONN_BGF_UART0_TXD") + ), + MTK_PIN( + 32, "GPIO32", + MTK_EINT_FUNCTION(0, 32), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "I2SIN2_DI"), + MTK_FUNCTION(2, "TP_URXD2_VCORE"), + MTK_FUNCTION(3, "MD_URXD1"), + MTK_FUNCTION(4, "HFRP_URXD1"), + MTK_FUNCTION(5, "MD32_0_RXD"), + MTK_FUNCTION(7, "CONN_BGF_UART0_RXD") + ), + MTK_PIN( + 33, "GPIO33", + MTK_EINT_FUNCTION(0, 33), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "ANT_SEL0"), + MTK_FUNCTION(3, "GPS_L1_ELNA_EN"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(5, "CONN_BPI_BUS18_ANT1"), + MTK_FUNCTION(6, "MD_UCTS0") + ), + MTK_PIN( + 34, "GPIO34", + MTK_EINT_FUNCTION(0, 34), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "ANT_SEL1"), + MTK_FUNCTION(3, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(5, "CONN_BPI_BUS19_ANT2"), + MTK_FUNCTION(6, "MD_URTS0") + ), + MTK_PIN( + 35, "GPIO35", + MTK_EINT_FUNCTION(0, 35), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "ANT_SEL2"), + MTK_FUNCTION(2, "SSPM_JTAG_TCK_VCORE"), + MTK_FUNCTION(3, "UDI_TCK"), + MTK_FUNCTION(5, "CONN_BPI_BUS20_ANT3"), + MTK_FUNCTION(6, "MD_UCTS1") + ), + MTK_PIN( + 36, "GPIO36", + MTK_EINT_FUNCTION(0, 36), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "ANT_SEL3"), + MTK_FUNCTION(2, "SSPM_JTAG_TRSTN_VCORE"), + MTK_FUNCTION(3, "UDI_NTRST"), + MTK_FUNCTION(5, "CONN_BPI_BUS21_ANT4"), + MTK_FUNCTION(6, "MD_URTS1") + ), + MTK_PIN( + 37, "GPIO37", + MTK_EINT_FUNCTION(0, 37), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "ANT_SEL4"), + MTK_FUNCTION(2, "SSPM_JTAG_TDI_VCORE"), + MTK_FUNCTION(3, "UDI_TDI"), + MTK_FUNCTION(6, "TP_UCTS1_VCORE") + ), + MTK_PIN( + 38, "GPIO38", + MTK_EINT_FUNCTION(0, 38), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(1, "ANT_SEL5"), + MTK_FUNCTION(2, "SSPM_JTAG_TMS_VCORE"), + MTK_FUNCTION(3, "UDI_TMS"), + MTK_FUNCTION(6, "TP_URTS1_VCORE") + ), + MTK_PIN( + 39, "GPIO39", + MTK_EINT_FUNCTION(0, 39), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "ANT_SEL6"), + MTK_FUNCTION(2, "SSPM_JTAG_TDO_VCORE"), + MTK_FUNCTION(3, "UDI_TDO"), + MTK_FUNCTION(5, "CLKM3") + ), + MTK_PIN( + 40, "GPIO40", + MTK_EINT_FUNCTION(0, 40), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "ANT_SEL7"), + MTK_FUNCTION(2, "PMSR_SMAP"), + MTK_FUNCTION(3, "CONN_TCXOENA_REQ"), + MTK_FUNCTION(4, "CONN_WIFI_TXD"), + MTK_FUNCTION(5, "GPS_PPS") + ), + MTK_PIN( + 41, "GPIO41", + MTK_EINT_FUNCTION(0, 41), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "I2SIN1_MCK"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(3, "GPS_PPS"), + MTK_FUNCTION(4, "HFRP_UCTS1"), + MTK_FUNCTION(5, "TP_UCTS2_VCORE"), + MTK_FUNCTION(6, "ANT_SEL8"), + MTK_FUNCTION(7, "DBG_MON_B1") + ), + MTK_PIN( + 42, "GPIO42", + MTK_EINT_FUNCTION(0, 42), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "I2SIN1_BCK"), + MTK_FUNCTION(2, "I2SIN4_BCK"), + MTK_FUNCTION(4, "HFRP_URTS1"), + MTK_FUNCTION(5, "TP_URTS2_VCORE"), + MTK_FUNCTION(6, "ANT_SEL9"), + MTK_FUNCTION(7, "DBG_MON_B2") + ), + MTK_PIN( + 43, "GPIO43", + MTK_EINT_FUNCTION(0, 43), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "I2SIN1_LRCK"), + MTK_FUNCTION(2, "I2SIN4_LRCK"), + MTK_FUNCTION(6, "ANT_SEL10"), + MTK_FUNCTION(7, "DBG_MON_B3") + ), + MTK_PIN( + 44, "GPIO44", + MTK_EINT_FUNCTION(0, 44), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "I2SOUT1_DO"), + MTK_FUNCTION(2, "I2SOUT4_DATA0"), + MTK_FUNCTION(6, "ANT_SEL11"), + MTK_FUNCTION(7, "DBG_MON_B4") + ), + MTK_PIN( + 45, "GPIO45", + MTK_EINT_FUNCTION(0, 45), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "I2SIN1_DI"), + MTK_FUNCTION(2, "I2SIN4_DATA0"), + MTK_FUNCTION(5, "AGPS_SYNC"), + MTK_FUNCTION(6, "ANT_SEL12"), + MTK_FUNCTION(7, "DBG_MON_B5") + ), + MTK_PIN( + 46, "GPIO46", + MTK_EINT_FUNCTION(0, 46), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "MD_INT1_C2K_UIM0_HOT_PLUG"), + MTK_FUNCTION(2, "MD_INT2_C2K_UIM1_HOT_PLUG"), + MTK_FUNCTION(3, "SRCLKENAI0"), + MTK_FUNCTION(5, "SSPM_UTXD_AO_VLP"), + MTK_FUNCTION(6, "MD_MCIF_UTXD0"), + MTK_FUNCTION(7, "DBG_MON_B6") + ), + MTK_PIN( + 47, "GPIO47", + MTK_EINT_FUNCTION(0, 47), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "MD_INT2_C2K_UIM1_HOT_PLUG"), + MTK_FUNCTION(2, "MD_INT1_C2K_UIM0_HOT_PLUG"), + MTK_FUNCTION(3, "SRCLKENAI1"), + MTK_FUNCTION(4, "SRCLKENA1"), + MTK_FUNCTION(5, "SSPM_URXD_AO_VLP"), + MTK_FUNCTION(6, "MD_MCIF_URXD0"), + MTK_FUNCTION(7, "DBG_MON_B7") + ), + MTK_PIN( + 48, "GPIO48", + MTK_EINT_FUNCTION(0, 48), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "UTXD0"), + MTK_FUNCTION(3, "MD_UTXD1"), + MTK_FUNCTION(4, "HFRP_UTXD1"), + MTK_FUNCTION(5, "MD32_0_TXD") + ), + MTK_PIN( + 49, "GPIO49", + MTK_EINT_FUNCTION(0, 49), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "URXD0"), + MTK_FUNCTION(3, "MD_URXD1"), + MTK_FUNCTION(4, "HFRP_URXD1"), + MTK_FUNCTION(5, "MD32_0_RXD") + ), + MTK_PIN( + 50, "GPIO50", + MTK_EINT_FUNCTION(0, 50), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "MD_UTXD0"), + MTK_FUNCTION(2, "TP_UTXD1_VLP"), + MTK_FUNCTION(3, "CONN_BGF_UART0_TXD"), + MTK_FUNCTION(4, "SSPM_UTXD_AO_VLP"), + MTK_FUNCTION(5, "MD_MCIF_UTXD0"), + MTK_FUNCTION(6, "TP_UTXD2_VLP"), + MTK_FUNCTION(7, "UTXD1") + ), + MTK_PIN( + 51, "GPIO51", + MTK_EINT_FUNCTION(0, 51), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "MD_URXD0"), + MTK_FUNCTION(2, "TP_URXD1_VLP"), + MTK_FUNCTION(3, "CONN_BGF_UART0_RXD"), + MTK_FUNCTION(4, "SSPM_URXD_AO_VLP"), + MTK_FUNCTION(5, "MD_MCIF_URXD0"), + MTK_FUNCTION(6, "TP_URXD2_VLP"), + MTK_FUNCTION(7, "URXD1") + ), + MTK_PIN( + 52, "GPIO52", + MTK_EINT_FUNCTION(0, 52), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "KPROW0"), + MTK_FUNCTION(2, "CMFLASH0"), + MTK_FUNCTION(3, "SDA12"), + MTK_FUNCTION(4, "DSI_TE1") + ), + MTK_PIN( + 53, "GPIO53", + MTK_EINT_FUNCTION(0, 53), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "KPROW1"), + MTK_FUNCTION(2, "CMFLASH1"), + MTK_FUNCTION(3, "SCL12"), + MTK_FUNCTION(4, "LCM_RST1"), + MTK_FUNCTION(6, "EXTIF0_ACT") + ), + MTK_PIN( + 54, "GPIO54", + MTK_EINT_FUNCTION(0, 54), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "KPCOL0_VLP"), + MTK_FUNCTION(7, "KPCOL0_VLP") + ), + MTK_PIN( + 55, "GPIO55", + MTK_EINT_FUNCTION(0, 55), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "KPCOL1"), + MTK_FUNCTION(3, "SDA12"), + MTK_FUNCTION(4, "DISP_PWM1"), + MTK_FUNCTION(7, "JTRSTN_SEL1_VCORE") + ), + MTK_PIN( + 56, "GPIO56", + MTK_EINT_FUNCTION(0, 56), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "SPI0_CLK"), + MTK_FUNCTION(7, "JTCK_SEL1_VCORE") + ), + MTK_PIN( + 57, "GPIO57", + MTK_EINT_FUNCTION(0, 57), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "SPI0_CSB"), + MTK_FUNCTION(7, "JTMS_SEL1_VCORE") + ), + MTK_PIN( + 58, "GPIO58", + MTK_EINT_FUNCTION(0, 58), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "SPI0_MO"), + MTK_FUNCTION(7, "JTDO_SEL1_VCORE") + ), + MTK_PIN( + 59, "GPIO59", + MTK_EINT_FUNCTION(0, 59), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "SPI0_MI"), + MTK_FUNCTION(7, "JTDI_SEL1_VCORE") + ), + MTK_PIN( + 60, "GPIO60", + MTK_EINT_FUNCTION(0, 60), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "SCP_SPI1_CK"), + MTK_FUNCTION(2, "SPI1_CLK"), + MTK_FUNCTION(4, "SCP_SCL3"), + MTK_FUNCTION(5, "TP_GPIO0_AO"), + MTK_FUNCTION(6, "UTXD0"), + MTK_FUNCTION(7, "TP_UTXD2_VLP") + ), + MTK_PIN( + 61, "GPIO61", + MTK_EINT_FUNCTION(0, 61), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "SCP_SPI1_CS"), + MTK_FUNCTION(2, "SPI1_CSB"), + MTK_FUNCTION(5, "TP_GPIO1_AO"), + MTK_FUNCTION(6, "URXD0"), + MTK_FUNCTION(7, "TP_URXD2_VLP") + ), + MTK_PIN( + 62, "GPIO62", + MTK_EINT_FUNCTION(0, 62), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "SCP_SPI1_MO"), + MTK_FUNCTION(2, "SPI1_MO"), + MTK_FUNCTION(3, "SCP_SCL3"), + MTK_FUNCTION(4, "SCP_SDA3"), + MTK_FUNCTION(5, "TP_GPIO2_AO"), + MTK_FUNCTION(7, "DBG_MON_B29") + ), + MTK_PIN( + 63, "GPIO63", + MTK_EINT_FUNCTION(0, 63), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "SCP_SPI1_MI"), + MTK_FUNCTION(2, "SPI1_MI"), + MTK_FUNCTION(3, "SCP_SDA3"), + MTK_FUNCTION(5, "TP_GPIO3_AO"), + MTK_FUNCTION(7, "DBG_MON_B30") + ), + MTK_PIN( + 64, "GPIO64", + MTK_EINT_FUNCTION(0, 64), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "SCP_SPI2_CK"), + MTK_FUNCTION(2, "SPI2_CLK"), + MTK_FUNCTION(4, "SCP_SCL2"), + MTK_FUNCTION(5, "TP_GPIO4_AO") + ), + MTK_PIN( + 65, "GPIO65", + MTK_EINT_FUNCTION(0, 65), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "SCP_SPI2_CS"), + MTK_FUNCTION(2, "SPI2_CSB"), + MTK_FUNCTION(5, "TP_GPIO5_AO"), + MTK_FUNCTION(7, "DBG_MON_B31") + ), + MTK_PIN( + 66, "GPIO66", + MTK_EINT_FUNCTION(0, 66), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "SCP_SPI2_MO"), + MTK_FUNCTION(2, "SPI2_MO"), + MTK_FUNCTION(3, "SCP_SCL2"), + MTK_FUNCTION(4, "SCP_SDA2"), + MTK_FUNCTION(5, "TP_GPIO6_AO") + ), + MTK_PIN( + 67, "GPIO67", + MTK_EINT_FUNCTION(0, 67), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "SCP_SPI2_MI"), + MTK_FUNCTION(2, "SPI2_MI"), + MTK_FUNCTION(3, "SCP_SDA2"), + MTK_FUNCTION(5, "TP_GPIO7_AO") + ), + MTK_PIN( + 68, "GPIO68", + MTK_EINT_FUNCTION(0, 68), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "SCP_SPI3_CK"), + MTK_FUNCTION(2, "SPI3_CLK"), + MTK_FUNCTION(3, "MD_INT4"), + MTK_FUNCTION(4, "SCP_SCL4"), + MTK_FUNCTION(5, "TP_GPIO8_AO"), + MTK_FUNCTION(7, "DBG_MON_A19") + ), + MTK_PIN( + 69, "GPIO69", + MTK_EINT_FUNCTION(0, 69), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "SCP_SPI3_CS"), + MTK_FUNCTION(2, "SPI3_CSB"), + MTK_FUNCTION(3, "MD_INT3"), + MTK_FUNCTION(5, "TP_GPIO9_AO"), + MTK_FUNCTION(7, "DBG_MON_A20") + ), + MTK_PIN( + 70, "GPIO70", + MTK_EINT_FUNCTION(0, 70), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO70"), + MTK_FUNCTION(1, "SCP_SPI3_MO"), + MTK_FUNCTION(2, "SPI3_MO"), + MTK_FUNCTION(3, "SCP_SCL4"), + MTK_FUNCTION(4, "SCP_SDA4"), + MTK_FUNCTION(5, "TP_GPIO10_AO"), + MTK_FUNCTION(7, "DBG_MON_A21") + ), + MTK_PIN( + 71, "GPIO71", + MTK_EINT_FUNCTION(0, 71), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO71"), + MTK_FUNCTION(1, "SCP_SPI3_MI"), + MTK_FUNCTION(2, "SPI3_MI"), + MTK_FUNCTION(3, "SCP_SDA4"), + MTK_FUNCTION(4, "MD_INT0"), + MTK_FUNCTION(5, "TP_GPIO11_AO"), + MTK_FUNCTION(7, "DBG_MON_A22") + ), + MTK_PIN( + 72, "GPIO72", + MTK_EINT_FUNCTION(0, 72), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO72"), + MTK_FUNCTION(1, "SPI5_CLK"), + MTK_FUNCTION(2, "SCP_SPI0_CK"), + MTK_FUNCTION(3, "UCTS2"), + MTK_FUNCTION(4, "MBISTREADEN_TRIGGER"), + MTK_FUNCTION(5, "TP_GPIO12_AO"), + MTK_FUNCTION(6, "EXTIF0_ACT"), + MTK_FUNCTION(7, "DAP_SONIC_SWCK") + ), + MTK_PIN( + 73, "GPIO73", + MTK_EINT_FUNCTION(0, 73), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO73"), + MTK_FUNCTION(1, "SPI5_CSB"), + MTK_FUNCTION(2, "SCP_SPI0_CS"), + MTK_FUNCTION(3, "URTS2"), + MTK_FUNCTION(4, "MBISTWRITEEN_TRIGGER"), + MTK_FUNCTION(5, "TP_GPIO13_AO"), + MTK_FUNCTION(6, "EXTIF0_PRI"), + MTK_FUNCTION(7, "DAP_SONIC_SWD") + ), + MTK_PIN( + 74, "GPIO74", + MTK_EINT_FUNCTION(0, 74), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO74"), + MTK_FUNCTION(1, "SPI5_MO"), + MTK_FUNCTION(2, "SCP_SPI0_MO"), + MTK_FUNCTION(3, "UTXD2"), + MTK_FUNCTION(4, "TP_UTXD2_VCORE"), + MTK_FUNCTION(5, "TP_GPIO14_AO"), + MTK_FUNCTION(6, "EXTIF0_GNT_B"), + MTK_FUNCTION(7, "DAP_MD32_SWCK") + ), + MTK_PIN( + 75, "GPIO75", + MTK_EINT_FUNCTION(0, 75), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "SPI5_MI"), + MTK_FUNCTION(2, "SCP_SPI0_MI"), + MTK_FUNCTION(3, "URXD2"), + MTK_FUNCTION(4, "TP_URXD2_VCORE"), + MTK_FUNCTION(5, "TP_GPIO15_AO"), + MTK_FUNCTION(7, "DAP_MD32_SWD") + ), + MTK_PIN( + 76, "GPIO76", + MTK_EINT_FUNCTION(0, 76), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "AP_GOOD"), + MTK_FUNCTION(3, "CONN_WIFI_TXD"), + MTK_FUNCTION(4, "GPS_PPS"), + MTK_FUNCTION(5, "PMSR_SMAP"), + MTK_FUNCTION(6, "AGPS_SYNC") + ), + MTK_PIN( + 77, "GPIO77", + MTK_EINT_FUNCTION(0, 77), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "MSDC1_CLK"), + MTK_FUNCTION(2, "MD1_SIM2_SCLK"), + MTK_FUNCTION(3, "UDI_TCK"), + MTK_FUNCTION(4, "CONN_DSP_JCK"), + MTK_FUNCTION(6, "TSFDC_EN"), + MTK_FUNCTION(7, "SSPM_JTAG_TCK_VCORE") + ), + MTK_PIN( + 78, "GPIO78", + MTK_EINT_FUNCTION(0, 78), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "MSDC1_CMD"), + MTK_FUNCTION(2, "CONN_WF_MCU_AICE_TMSC"), + MTK_FUNCTION(3, "UDI_TMS"), + MTK_FUNCTION(4, "CONN_DSP_JMS"), + MTK_FUNCTION(6, "TSFDC_VCO_RST"), + MTK_FUNCTION(7, "SSPM_JTAG_TMS_VCORE") + ), + MTK_PIN( + 79, "GPIO79", + MTK_EINT_FUNCTION(0, 79), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "MSDC1_DAT0"), + MTK_FUNCTION(2, "MD1_SIM2_SRST"), + MTK_FUNCTION(3, "UDI_TDI"), + MTK_FUNCTION(4, "CONN_DSP_JDI"), + MTK_FUNCTION(6, "TSFDC_TSSEL2"), + MTK_FUNCTION(7, "SSPM_JTAG_TDI_VCORE") + ), + MTK_PIN( + 80, "GPIO80", + MTK_EINT_FUNCTION(0, 80), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "MSDC1_DAT1"), + MTK_FUNCTION(2, "MD1_SIM2_SIO"), + MTK_FUNCTION(3, "UDI_TDO"), + MTK_FUNCTION(4, "CONN_DSP_JDO"), + MTK_FUNCTION(6, "TSFDC_TSSEL1"), + MTK_FUNCTION(7, "SSPM_JTAG_TDO_VCORE") + ), + MTK_PIN( + 81, "GPIO81", + MTK_EINT_FUNCTION(0, 81), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "MSDC1_DAT2"), + MTK_FUNCTION(2, "CONN_WF_MCU_AICE_TCKC"), + MTK_FUNCTION(3, "UDI_NTRST"), + MTK_FUNCTION(4, "CONN_BGF_MCU_AICE_TCKC"), + MTK_FUNCTION(5, "MIPI3_D_SDATA"), + MTK_FUNCTION(6, "TSFDC_TSSEL0"), + MTK_FUNCTION(7, "SSPM_JTAG_TRSTN_VCORE") + ), + MTK_PIN( + 82, "GPIO82", + MTK_EINT_FUNCTION(0, 82), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "MSDC1_DAT3"), + MTK_FUNCTION(3, "CONN_BGF_MCU_AICE_TMSC"), + MTK_FUNCTION(4, "CONN_DSP_JINTP"), + MTK_FUNCTION(5, "MIPI3_D_SCLK"), + MTK_FUNCTION(6, "TSFDC_RCK_SELB") + ), + MTK_PIN( + 83, "GPIO83", + MTK_EINT_FUNCTION(0, 83), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "MD1_SIM1_SCLK"), + MTK_FUNCTION(6, "TSFDC_26M") + ), + MTK_PIN( + 84, "GPIO84", + MTK_EINT_FUNCTION(0, 84), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "MD1_SIM1_SRST"), + MTK_FUNCTION(3, "SPM_JTAG_TCK_VCORE"), + MTK_FUNCTION(4, "APU_JTAG_TCK"), + MTK_FUNCTION(6, "TSFDC_SDO"), + MTK_FUNCTION(7, "CONN_DSP_L5_JCK") + ), + MTK_PIN( + 85, "GPIO85", + MTK_EINT_FUNCTION(0, 85), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "MD1_SIM1_SIO"), + MTK_FUNCTION(3, "SPM_JTAG_TRSTN_VCORE"), + MTK_FUNCTION(4, "APU_JTAG_TRST"), + MTK_FUNCTION(6, "TSFDC_FOUT"), + MTK_FUNCTION(7, "CONN_DSP_L5_JINTP") + ), + MTK_PIN( + 86, "GPIO86", + MTK_EINT_FUNCTION(0, 86), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "MD1_SIM2_SCLK"), + MTK_FUNCTION(3, "SPM_JTAG_TDI_VCORE"), + MTK_FUNCTION(4, "APU_JTAG_TDI"), + MTK_FUNCTION(6, "TSFDC_SCK"), + MTK_FUNCTION(7, "CONN_DSP_L5_JDI") + ), + MTK_PIN( + 87, "GPIO87", + MTK_EINT_FUNCTION(0, 87), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "MD1_SIM2_SRST"), + MTK_FUNCTION(3, "SPM_JTAG_TMS_VCORE"), + MTK_FUNCTION(4, "APU_JTAG_TMS"), + MTK_FUNCTION(6, "TSFDC_SDI"), + MTK_FUNCTION(7, "CONN_DSP_L5_JMS") + ), + MTK_PIN( + 88, "GPIO88", + MTK_EINT_FUNCTION(0, 88), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "MD1_SIM2_SIO"), + MTK_FUNCTION(3, "SPM_JTAG_TDO_VCORE"), + MTK_FUNCTION(4, "APU_JTAG_TDO"), + MTK_FUNCTION(6, "TSFDC_SCF"), + MTK_FUNCTION(7, "CONN_DSP_L5_JDO") + ), + MTK_PIN( + 89, "GPIO89", + MTK_EINT_FUNCTION(0, 89), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "DSI_TE"), + MTK_FUNCTION(7, "DBG_MON_B8") + ), + MTK_PIN( + 90, "GPIO90", + MTK_EINT_FUNCTION(0, 90), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "LCM_RST"), + MTK_FUNCTION(7, "DBG_MON_B9") + ), + MTK_PIN( + 91, "GPIO91", + MTK_EINT_FUNCTION(0, 91), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO91"), + MTK_FUNCTION(1, "DISP_PWM"), + MTK_FUNCTION(7, "DBG_MON_B10") + ), + MTK_PIN( + 92, "GPIO92", + MTK_EINT_FUNCTION(0, 92), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO92"), + MTK_FUNCTION(1, "CMMCLK0"), + MTK_FUNCTION(7, "DBG_MON_A23") + ), + MTK_PIN( + 93, "GPIO93", + MTK_EINT_FUNCTION(0, 93), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO93"), + MTK_FUNCTION(1, "CMMCLK1"), + MTK_FUNCTION(7, "DBG_MON_A24") + ), + MTK_PIN( + 94, "GPIO94", + MTK_EINT_FUNCTION(0, 94), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO94"), + MTK_FUNCTION(1, "CMMCLK2"), + MTK_FUNCTION(7, "DBG_MON_A25") + ), + MTK_PIN( + 95, "GPIO95", + MTK_EINT_FUNCTION(0, 95), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO95"), + MTK_FUNCTION(1, "CMMCLK3"), + MTK_FUNCTION(5, "MD32_1_TXD"), + MTK_FUNCTION(6, "PTA_TXD"), + MTK_FUNCTION(7, "DBG_MON_A26") + ), + MTK_PIN( + 96, "GPIO96", + MTK_EINT_FUNCTION(0, 96), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO96"), + MTK_FUNCTION(1, "CMMCLK4"), + MTK_FUNCTION(5, "MD32_1_RXD"), + MTK_FUNCTION(6, "PTA_RXD"), + MTK_FUNCTION(7, "DBG_MON_A27") + ), + MTK_PIN( + 97, "GPIO97", + MTK_EINT_FUNCTION(0, 97), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO97"), + MTK_FUNCTION(1, "MD_UCNT_A_TGL") + ), + MTK_PIN( + 98, "GPIO98", + MTK_EINT_FUNCTION(0, 98), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO98"), + MTK_FUNCTION(1, "DIGRF_IRQ") + ), + MTK_PIN( + 99, "GPIO99", + MTK_EINT_FUNCTION(0, 99), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO99"), + MTK_FUNCTION(1, "BPI_BUS0"), + MTK_FUNCTION(4, "MFG_TSFDC_EN"), + MTK_FUNCTION(6, "ANT_SEL0"), + MTK_FUNCTION(7, "DBG_MON_B11") + ), + MTK_PIN( + 100, "GPIO100", + MTK_EINT_FUNCTION(0, 100), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO100"), + MTK_FUNCTION(1, "BPI_BUS1"), + MTK_FUNCTION(4, "MFG_TSFDC_VCO_RST"), + MTK_FUNCTION(6, "ANT_SEL1"), + MTK_FUNCTION(7, "DBG_MON_B12") + ), + MTK_PIN( + 101, "GPIO101", + MTK_EINT_FUNCTION(0, 101), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "BPI_BUS2"), + MTK_FUNCTION(3, "DMIC1_CLK"), + MTK_FUNCTION(4, "MFG_TSFDC_TSSEL2"), + MTK_FUNCTION(6, "ANT_SEL2"), + MTK_FUNCTION(7, "DBG_MON_B13") + ), + MTK_PIN( + 102, "GPIO102", + MTK_EINT_FUNCTION(0, 102), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "BPI_BUS3"), + MTK_FUNCTION(3, "DMIC1_DAT"), + MTK_FUNCTION(4, "MFG_TSFDC_TSSEL1"), + MTK_FUNCTION(6, "ANT_SEL3"), + MTK_FUNCTION(7, "DBG_MON_B14") + ), + MTK_PIN( + 103, "GPIO103", + MTK_EINT_FUNCTION(0, 103), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "BPI_BUS4"), + MTK_FUNCTION(4, "MFG_TSFDC_TSSEL0"), + MTK_FUNCTION(6, "ANT_SEL4"), + MTK_FUNCTION(7, "DBG_MON_B15") + ), + MTK_PIN( + 104, "GPIO104", + MTK_EINT_FUNCTION(0, 104), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "BPI_BUS5"), + MTK_FUNCTION(4, "MFG_TSFDC_RCK_SELB"), + MTK_FUNCTION(6, "ANT_SEL5"), + MTK_FUNCTION(7, "DBG_MON_B16") + ), + MTK_PIN( + 105, "GPIO105", + MTK_EINT_FUNCTION(0, 105), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "BPI_BUS6"), + MTK_FUNCTION(2, "CONN_BPI_BUS6"), + MTK_FUNCTION(6, "ANT_SEL6"), + MTK_FUNCTION(7, "DBG_MON_B17") + ), + MTK_PIN( + 106, "GPIO106", + MTK_EINT_FUNCTION(0, 106), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "BPI_BUS7"), + MTK_FUNCTION(2, "CONN_BPI_BUS7"), + MTK_FUNCTION(4, "MFG_TSFDC_SDO"), + MTK_FUNCTION(5, "AUD_DAC_26M_CLK"), + MTK_FUNCTION(6, "ANT_SEL7"), + MTK_FUNCTION(7, "DBG_MON_B18") + ), + MTK_PIN( + 107, "GPIO107", + MTK_EINT_FUNCTION(0, 107), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "BPI_BUS8"), + MTK_FUNCTION(2, "CONN_BPI_BUS8"), + MTK_FUNCTION(4, "MFG_TSFDC_FOUT"), + MTK_FUNCTION(5, "I2SOUT4_DATA0"), + MTK_FUNCTION(6, "ANT_SEL8"), + MTK_FUNCTION(7, "DBG_MON_B19") + ), + MTK_PIN( + 108, "GPIO108", + MTK_EINT_FUNCTION(0, 108), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "BPI_BUS9"), + MTK_FUNCTION(2, "CONN_BPI_BUS9"), + MTK_FUNCTION(5, "I2SOUT4_DATA1"), + MTK_FUNCTION(6, "ANT_SEL9"), + MTK_FUNCTION(7, "DBG_MON_B20") + ), + MTK_PIN( + 109, "GPIO109", + MTK_EINT_FUNCTION(0, 109), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "BPI_BUS10"), + MTK_FUNCTION(2, "CONN_BPI_BUS10"), + MTK_FUNCTION(5, "I2SOUT4_DATA2"), + MTK_FUNCTION(6, "ANT_SEL10"), + MTK_FUNCTION(7, "DBG_MON_B21") + ), + MTK_PIN( + 110, "GPIO110", + MTK_EINT_FUNCTION(0, 110), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "BPI_BUS11"), + MTK_FUNCTION(2, "CONN_BPI_BUS11_OLAT0"), + MTK_FUNCTION(5, "I2SOUT4_DATA3"), + MTK_FUNCTION(6, "ANT_SEL11"), + MTK_FUNCTION(7, "DBG_MON_B22") + ), + MTK_PIN( + 111, "GPIO111", + MTK_EINT_FUNCTION(0, 111), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "BPI_BUS12"), + MTK_FUNCTION(2, "CONN_BPI_BUS12_OLAT1"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(5, "I2SIN4_BCK"), + MTK_FUNCTION(6, "ANT_SEL12"), + MTK_FUNCTION(7, "DBG_MON_B23") + ), + MTK_PIN( + 112, "GPIO112", + MTK_EINT_FUNCTION(0, 112), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "BPI_BUS13"), + MTK_FUNCTION(2, "CONN_BPI_BUS13_OLAT2"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(5, "I2SIN4_DATA0"), + MTK_FUNCTION(6, "ANT_SEL13"), + MTK_FUNCTION(7, "DBG_MON_B24") + ), + MTK_PIN( + 113, "GPIO113", + MTK_EINT_FUNCTION(0, 113), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "BPI_BUS14"), + MTK_FUNCTION(2, "CONN_BPI_BUS14_OLAT3"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(5, "I2SIN4_DATA1"), + MTK_FUNCTION(6, "ANT_SEL14"), + MTK_FUNCTION(7, "DBG_MON_B25") + ), + MTK_PIN( + 114, "GPIO114", + MTK_EINT_FUNCTION(0, 114), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "BPI_BUS15"), + MTK_FUNCTION(2, "CONN_BPI_BUS15_OLAT4"), + MTK_FUNCTION(3, "CLKM3"), + MTK_FUNCTION(5, "I2SIN4_DATA2"), + MTK_FUNCTION(6, "ANT_SEL15"), + MTK_FUNCTION(7, "DBG_MON_B26") + ), + MTK_PIN( + 115, "GPIO115", + MTK_EINT_FUNCTION(0, 115), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "BPI_BUS16"), + MTK_FUNCTION(2, "CONN_BPI_BUS16_OLAT5"), + MTK_FUNCTION(5, "I2SIN4_DATA3"), + MTK_FUNCTION(6, "ANT_SEL16"), + MTK_FUNCTION(7, "DBG_MON_B27") + ), + MTK_PIN( + 116, "GPIO116", + MTK_EINT_FUNCTION(0, 116), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "BPI_BUS17"), + MTK_FUNCTION(2, "CONN_BPI_BUS17_ANT0"), + MTK_FUNCTION(5, "I2SIN4_LRCK"), + MTK_FUNCTION(6, "ANT_SEL17"), + MTK_FUNCTION(7, "DBG_MON_B28") + ), + MTK_PIN( + 117, "GPIO117", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "MIPI0_D_SCLK"), + MTK_FUNCTION(2, "CONN_MIPI0_SCLK"), + MTK_FUNCTION(3, "BPI_BUS18"), + MTK_FUNCTION(6, "ANT_SEL18") + ), + MTK_PIN( + 118, "GPIO118", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "MIPI0_D_SDATA"), + MTK_FUNCTION(2, "CONN_MIPI0_SDATA"), + MTK_FUNCTION(3, "BPI_BUS19"), + MTK_FUNCTION(6, "ANT_SEL19") + ), + MTK_PIN( + 119, "GPIO119", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "MIPI1_D_SCLK"), + MTK_FUNCTION(2, "CONN_MIPI1_SCLK"), + MTK_FUNCTION(3, "BPI_BUS20"), + MTK_FUNCTION(6, "ANT_SEL20") + ), + MTK_PIN( + 120, "GPIO120", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "MIPI1_D_SDATA"), + MTK_FUNCTION(2, "CONN_MIPI1_SDATA"), + MTK_FUNCTION(3, "BPI_BUS21"), + MTK_FUNCTION(6, "ANT_SEL21") + ), + MTK_PIN( + 121, "GPIO121", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "MIPI2_D_SCLK"), + MTK_FUNCTION(2, "MIPI4_D_SCLK"), + MTK_FUNCTION(3, "BPI_BUS22"), + MTK_FUNCTION(6, "MD_GPS_L1_BLANK") + ), + MTK_PIN( + 122, "GPIO122", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "MIPI2_D_SDATA"), + MTK_FUNCTION(2, "MIPI4_D_SDATA"), + MTK_FUNCTION(3, "BPI_BUS23"), + MTK_FUNCTION(6, "MD_GPS_L5_BLANK") + ), + MTK_PIN( + 123, "GPIO123", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO123"), + MTK_FUNCTION(1, "MIPI_M_SCLK") + ), + MTK_PIN( + 124, "GPIO124", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO124"), + MTK_FUNCTION(1, "MIPI_M_SDATA") + ), + MTK_PIN( + 125, "GPIO125", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO125"), + MTK_FUNCTION(1, "SCL0"), + MTK_FUNCTION(2, "SCP_SCL4"), + MTK_FUNCTION(3, "TP_UTXD2_VLP"), + MTK_FUNCTION(4, "TP_UCTS1_VLP"), + MTK_FUNCTION(5, "TP_GPIO4_AO"), + MTK_FUNCTION(6, "UTXD2") + ), + MTK_PIN( + 126, "GPIO126", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO126"), + MTK_FUNCTION(1, "SDA0"), + MTK_FUNCTION(2, "SCP_SDA4"), + MTK_FUNCTION(3, "TP_URXD2_VLP"), + MTK_FUNCTION(4, "TP_URTS1_VLP"), + MTK_FUNCTION(5, "TP_GPIO5_AO"), + MTK_FUNCTION(6, "URXD2") + ), + MTK_PIN( + 127, "GPIO127", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO127"), + MTK_FUNCTION(1, "SCL1"), + MTK_FUNCTION(2, "SCP_SCL5"), + MTK_FUNCTION(3, "TP_UCTS2_VLP"), + MTK_FUNCTION(4, "TP_UTXD1_VLP"), + MTK_FUNCTION(5, "TP_GPIO6_AO"), + MTK_FUNCTION(6, "MD_MCIF_UTXD0") + ), + MTK_PIN( + 128, "GPIO128", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO128"), + MTK_FUNCTION(1, "SDA1"), + MTK_FUNCTION(2, "SCP_SDA5"), + MTK_FUNCTION(3, "TP_URTS2_VLP"), + MTK_FUNCTION(4, "TP_URXD1_VLP"), + MTK_FUNCTION(5, "TP_GPIO7_AO"), + MTK_FUNCTION(6, "MD_MCIF_URXD0") + ), + MTK_PIN( + 129, "GPIO129", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO129"), + MTK_FUNCTION(1, "SCL2") + ), + MTK_PIN( + 130, "GPIO130", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO130"), + MTK_FUNCTION(1, "SDA2") + ), + MTK_PIN( + 131, "GPIO131", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "SCL3"), + MTK_FUNCTION(3, "TP_UTXD2_VCORE"), + MTK_FUNCTION(6, "SSPM_UTXD_AO_VCORE") + ), + MTK_PIN( + 132, "GPIO132", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "SDA3"), + MTK_FUNCTION(3, "TP_URXD2_VCORE"), + MTK_FUNCTION(6, "SSPM_URXD_AO_VCORE") + ), + MTK_PIN( + 133, "GPIO133", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "SCL4") + ), + MTK_PIN( + 134, "GPIO134", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "SDA4") + ), + MTK_PIN( + 135, "GPIO135", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "SCL5") + ), + MTK_PIN( + 136, "GPIO136", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "SDA5") + ), + MTK_PIN( + 137, "GPIO137", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO137"), + MTK_FUNCTION(1, "SCL6") + ), + MTK_PIN( + 138, "GPIO138", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO138"), + MTK_FUNCTION(1, "SDA6") + ), + MTK_PIN( + 139, "GPIO139", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO139"), + MTK_FUNCTION(1, "SCL7"), + MTK_FUNCTION(3, "TP_UTXD1_VCORE"), + MTK_FUNCTION(4, "MD_UTXD0"), + MTK_FUNCTION(6, "UTXD1") + ), + MTK_PIN( + 140, "GPIO140", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO140"), + MTK_FUNCTION(1, "SDA7"), + MTK_FUNCTION(3, "TP_URXD1_VCORE"), + MTK_FUNCTION(4, "MD_URXD0"), + MTK_FUNCTION(6, "URXD1") + ), + MTK_PIN( + 141, "GPIO141", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO141"), + MTK_FUNCTION(1, "SCL8") + ), + MTK_PIN( + 142, "GPIO142", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO142"), + MTK_FUNCTION(1, "SDA8") + ), + MTK_PIN( + 143, "GPIO143", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO143"), + MTK_FUNCTION(1, "SCL9"), + MTK_FUNCTION(2, "GPS_L1_ELNA_EN"), + MTK_FUNCTION(3, "HFRP_UTXD1"), + MTK_FUNCTION(4, "CONN_BGF_MCU_AICE_TMSC"), + MTK_FUNCTION(5, "CONN_WF_MCU_AICE_TMSC"), + MTK_FUNCTION(7, "MBISTREADEN_TRIGGER") + ), + MTK_PIN( + 144, "GPIO144", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO144"), + MTK_FUNCTION(1, "SDA9"), + MTK_FUNCTION(2, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(3, "HFRP_URXD1"), + MTK_FUNCTION(4, "CONN_BGF_MCU_AICE_TCKC"), + MTK_FUNCTION(5, "CONN_WF_MCU_AICE_TCKC"), + MTK_FUNCTION(7, "MBISTWRITEEN_TRIGGER") + ), + MTK_PIN( + 145, "GPIO145", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO145"), + MTK_FUNCTION(1, "SCL10"), + MTK_FUNCTION(2, "SCP_SCL0"), + MTK_FUNCTION(5, "TP_GPIO8_AO") + ), + MTK_PIN( + 146, "GPIO146", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO146"), + MTK_FUNCTION(1, "SDA10"), + MTK_FUNCTION(2, "SCP_SDA0"), + MTK_FUNCTION(5, "TP_GPIO9_AO") + ), + MTK_PIN( + 147, "GPIO147", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "SCL11"), + MTK_FUNCTION(2, "SCP_SCL1"), + MTK_FUNCTION(3, "SCP_DMIC_CLK"), + MTK_FUNCTION(4, "DMIC_CLK"), + MTK_FUNCTION(5, "TP_GPIO10_AO"), + MTK_FUNCTION(6, "EXTIF0_PRI") + ), + MTK_PIN( + 148, "GPIO148", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "SDA11"), + MTK_FUNCTION(2, "SCP_SDA1"), + MTK_FUNCTION(3, "SCP_DMIC_DAT"), + MTK_FUNCTION(4, "DMIC_DAT"), + MTK_FUNCTION(5, "TP_GPIO11_AO"), + MTK_FUNCTION(6, "EXTIF0_GNT_B") + ), + MTK_PIN( + 149, "GPIO149", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "KPROW2"), + MTK_FUNCTION(2, "PWM_VLP"), + MTK_FUNCTION(4, "MD_INT0"), + MTK_FUNCTION(5, "TP_GPIO12_AO"), + MTK_FUNCTION(6, "SCL0"), + MTK_FUNCTION(7, "DBG_MON_A28") + ), + MTK_PIN( + 150, "GPIO150", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "KPCOL2"), + MTK_FUNCTION(2, "PWM_VLP"), + MTK_FUNCTION(3, "CMMCLK5"), + MTK_FUNCTION(4, "MD_INT3"), + MTK_FUNCTION(5, "TP_GPIO13_AO"), + MTK_FUNCTION(6, "SDA0") + ), + MTK_PIN( + 151, "GPIO151", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "SRCLKENAI0"), + MTK_FUNCTION(4, "MD_INT4"), + MTK_FUNCTION(5, "TP_GPIO14_AO"), + MTK_FUNCTION(7, "DBG_MON_A29") + ), + MTK_PIN( + 152, "GPIO152", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "SRCLKENAI1"), + MTK_FUNCTION(4, "SPMI_M_TRIG_FLAG"), + MTK_FUNCTION(5, "TP_GPIO15_AO"), + MTK_FUNCTION(7, "DBG_MON_A30") + ), + MTK_PIN( + 153, "GPIO153", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "MD1_SIM2_SCLK"), + MTK_FUNCTION(2, "DISP_PWM1"), + MTK_FUNCTION(4, "SPMI_P_TRIG_FLAG"), + MTK_FUNCTION(7, "DBG_MON_A0") + ), + MTK_PIN( + 154, "GPIO154", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "MD1_SIM2_SRST"), + MTK_FUNCTION(2, "LCM_RST1"), + MTK_FUNCTION(3, "GPS_L1_ELNA_EN"), + MTK_FUNCTION(4, "CMFLASH2"), + MTK_FUNCTION(5, "MBISTREADEN_TRIGGER"), + MTK_FUNCTION(7, "DBG_MON_A1") + ), + MTK_PIN( + 155, "GPIO155", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "MD1_SIM2_SIO"), + MTK_FUNCTION(2, "DSI_TE1"), + MTK_FUNCTION(3, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(4, "CMFLASH3"), + MTK_FUNCTION(5, "MBISTWRITEEN_TRIGGER"), + MTK_FUNCTION(7, "DBG_MON_A2") + ), + MTK_PIN( + 156, "GPIO156", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "SPMI_M_SCL") + ), + MTK_PIN( + 157, "GPIO157", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "SPMI_M_SDA") + ), + MTK_PIN( + 158, "GPIO158", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "SPMI_P_SCL") + ), + MTK_PIN( + 159, "GPIO159", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "SPMI_P_SDA") + ), + MTK_PIN( + 160, "GPIO160", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "SRCLKENA0") + ), + MTK_PIN( + 161, "GPIO161", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "SCP_VREQ_VAO") + ), + MTK_PIN( + 162, "GPIO162", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO162"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + 163, "GPIO163", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO163"), + MTK_FUNCTION(1, "WATCHDOG") + ), + MTK_PIN( + 164, "GPIO164", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO164"), + MTK_FUNCTION(1, "AUD_CLK_MOSI"), + MTK_FUNCTION(3, "AUD_CLK_MOSI") + ), + MTK_PIN( + 165, "GPIO165", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO165"), + MTK_FUNCTION(1, "AUD_SYNC_MOSI") + ), + MTK_PIN( + 166, "GPIO166", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO166"), + MTK_FUNCTION(1, "AUD_DAT_MOSI0"), + MTK_FUNCTION(3, "AUD_DAT_MOSI0") + ), + MTK_PIN( + 167, "GPIO167", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO167"), + MTK_FUNCTION(1, "AUD_DAT_MOSI1"), + MTK_FUNCTION(3, "AUD_DAT_MOSI1") + ), + MTK_PIN( + 168, "GPIO168", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO168"), + MTK_FUNCTION(1, "AUD_NLE_MOSI0"), + MTK_FUNCTION(2, "AUD_SYNC_MISO") + ), + MTK_PIN( + 169, "GPIO169", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO169"), + MTK_FUNCTION(1, "AUD_NLE_MOSI1"), + MTK_FUNCTION(2, "AUD_CLK_MISO"), + MTK_FUNCTION(3, "AUD_CLK_MISO") + ), + MTK_PIN( + 170, "GPIO170", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO170"), + MTK_FUNCTION(1, "AUD_DAT_MISO0"), + MTK_FUNCTION(2, "VOW_DAT_MISO"), + MTK_FUNCTION(3, "AUD_DAT_MISO0") + ), + MTK_PIN( + 171, "GPIO171", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO171"), + MTK_FUNCTION(1, "AUD_DAT_MISO1"), + MTK_FUNCTION(2, "VOW_CLK_MISO"), + MTK_FUNCTION(3, "AUD_DAT_MISO1") + ), + MTK_PIN( + 172, "GPIO172", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(1, "CONN_TOP_CLK"), + MTK_FUNCTION(7, "DBG_MON_A31") + ), + MTK_PIN( + 173, "GPIO173", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(1, "CONN_TOP_DATA") + ), + MTK_PIN( + 174, "GPIO174", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(1, "CONN_BT_CLK") + ), + MTK_PIN( + 175, "GPIO175", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO175"), + MTK_FUNCTION(1, "CONN_BT_DATA") + ), + MTK_PIN( + 176, "GPIO176", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(1, "CONN_HRST_B") + ), + MTK_PIN( + 177, "GPIO177", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(1, "CONN_WB_PTA") + ), + MTK_PIN( + 178, "GPIO178", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "CONN_WF_CTRL0") + ), + MTK_PIN( + 179, "GPIO179", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "CONN_WF_CTRL1") + ), + MTK_PIN( + 180, "GPIO180", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "CONN_WF_CTRL2") + ), + MTK_PIN( + 181, "GPIO181", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "CONN_WF_CTRL3"), + MTK_FUNCTION(2, "CONN_TOP_CLK_2"), + MTK_FUNCTION(3, "GPS_L1_ELNA_EN") + ), + MTK_PIN( + 182, "GPIO182", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "CONN_WF_CTRL4"), + MTK_FUNCTION(2, "CONN_TOP_DATA_2"), + MTK_FUNCTION(3, "GPS_L5_ELNA_EN") + ), + MTK_PIN( + 183, "GPIO183", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "CONN_HRST_B_2") + ), + MTK_PIN( + 184, "GPIO184", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "MSDC0_DSL"), + MTK_FUNCTION(3, "ANT_SEL13") + ), + MTK_PIN( + 185, "GPIO185", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "MSDC0_CLK"), + MTK_FUNCTION(2, "CONN_TCXOENA_REQ"), + MTK_FUNCTION(3, "ANT_SEL14") + ), + MTK_PIN( + 186, "GPIO186", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "MSDC0_CMD"), + MTK_FUNCTION(2, "GPS_L1_ELNA_EN"), + MTK_FUNCTION(3, "ANT_SEL15"), + MTK_FUNCTION(5, "I2SOUT4_DATA0") + ), + MTK_PIN( + 187, "GPIO187", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(1, "MSDC0_RSTB"), + MTK_FUNCTION(2, "GPS_L5_ELNA_EN"), + MTK_FUNCTION(3, "ANT_SEL16"), + MTK_FUNCTION(5, "I2SOUT4_DATA1") + ), + MTK_PIN( + 188, "GPIO188", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(3, "ANT_SEL17"), + MTK_FUNCTION(5, "I2SOUT4_DATA2") + ), + MTK_PIN( + 189, "GPIO189", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(3, "ANT_SEL18"), + MTK_FUNCTION(5, "I2SOUT4_DATA3") + ), + MTK_PIN( + 190, "GPIO190", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO190"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(2, "DMIC1_CLK"), + MTK_FUNCTION(3, "ANT_SEL19"), + MTK_FUNCTION(5, "I2SIN4_BCK") + ), + MTK_PIN( + 191, "GPIO191", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO191"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(2, "DMIC1_DAT"), + MTK_FUNCTION(3, "ANT_SEL20"), + MTK_FUNCTION(5, "I2SIN4_DATA0") + ), + MTK_PIN( + 192, "GPIO192", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO192"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(3, "ANT_SEL21"), + MTK_FUNCTION(4, "UFS_MPHY_SCL"), + MTK_FUNCTION(5, "I2SIN4_DATA1") + ), + MTK_PIN( + 193, "GPIO193", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO193"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(2, "USB_DRVVBUS"), + MTK_FUNCTION(4, "UFS_MPHY_SDA"), + MTK_FUNCTION(5, "I2SIN4_DATA2") + ), + MTK_PIN( + 194, "GPIO194", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO194"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(2, "VBUSVALID"), + MTK_FUNCTION(5, "I2SIN4_DATA3") + ), + MTK_PIN( + 195, "GPIO195", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO195"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(5, "I2SIN4_LRCK") + ), + MTK_PIN( + 196, "GPIO196", + MTK_EINT_FUNCTION(0, 196), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 197, "GPIO197", + MTK_EINT_FUNCTION(0, 197), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 198, "GPIO198", + MTK_EINT_FUNCTION(0, 198), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 199, "GPIO199", + MTK_EINT_FUNCTION(0, 199), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 200, "GPIO200", + MTK_EINT_FUNCTION(0, 200), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 201, "GPIO201", + MTK_EINT_FUNCTION(0, 201), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 202, "GPIO202", + MTK_EINT_FUNCTION(0, 202), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 203, "GPIO203", + MTK_EINT_FUNCTION(0, 203), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 204, "GPIO204", + MTK_EINT_FUNCTION(0, 204), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 205, "GPIO205", + MTK_EINT_FUNCTION(0, 205), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 206, "GPIO206", + MTK_EINT_FUNCTION(0, 206), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 207, "GPIO207", + MTK_EINT_FUNCTION(0, 207), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 208, "GPIO208", + MTK_EINT_FUNCTION(0, 208), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 209, "GPIO209", + MTK_EINT_FUNCTION(0, 209), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 210, "GPIO210", + MTK_EINT_FUNCTION(0, 210), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 211, "GPIO211", + MTK_EINT_FUNCTION(0, 211), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 212, "GPIO212", + MTK_EINT_FUNCTION(0, 212), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 213, "GPIO213", + MTK_EINT_FUNCTION(0, 213), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 214, "GPIO214", + MTK_EINT_FUNCTION(0, 214), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), + MTK_PIN( + 215, "GPIO215", + MTK_EINT_FUNCTION(0, 215), + DRV_GRP4, + MTK_FUNCTION(0, NULL) + ), +}; + +static struct mtk_eint_pin eint_pins_mt6878[] = { + MTK_EINT_PIN(0, 0, 0, 1), + MTK_EINT_PIN(1, 0, 1, 1), + MTK_EINT_PIN(2, 0, 2, 1), + MTK_EINT_PIN(3, 0, 3, 1), + MTK_EINT_PIN(4, 0, 4, 1), + MTK_EINT_PIN(5, 0, 5, 1), + MTK_EINT_PIN(6, 1, 0, 1), + MTK_EINT_PIN(7, 1, 1, 1), + MTK_EINT_PIN(8, 1, 2, 1), + MTK_EINT_PIN(9, 1, 3, 1), + MTK_EINT_PIN(10, 1, 4, 1), + MTK_EINT_PIN(11, 1, 5, 1), + MTK_EINT_PIN(12, 1, 6, 1), + MTK_EINT_PIN(13, 2, 0, 1), + MTK_EINT_PIN(14, 2, 1, 1), + MTK_EINT_PIN(15, 2, 2, 1), + MTK_EINT_PIN(16, 2, 3, 1), + MTK_EINT_PIN(17, 2, 4, 1), + MTK_EINT_PIN(18, 2, 5, 1), + MTK_EINT_PIN(19, 0, 6, 1), + MTK_EINT_PIN(20, 0, 7, 1), + MTK_EINT_PIN(21, 0, 8, 1), + MTK_EINT_PIN(22, 0, 9, 1), + MTK_EINT_PIN(23, 0, 10, 1), + MTK_EINT_PIN(24, 0, 11, 1), + MTK_EINT_PIN(25, 0, 12, 1), + MTK_EINT_PIN(26, 0, 13, 1), + MTK_EINT_PIN(27, 0, 14, 1), + MTK_EINT_PIN(28, 0, 15, 1), + MTK_EINT_PIN(29, 2, 6, 1), + MTK_EINT_PIN(30, 2, 7, 1), + MTK_EINT_PIN(31, 2, 8, 1), + MTK_EINT_PIN(32, 2, 9, 1), + MTK_EINT_PIN(33, 0, 16, 1), + MTK_EINT_PIN(34, 0, 17, 1), + MTK_EINT_PIN(35, 0, 18, 1), + MTK_EINT_PIN(36, 0, 19, 0), + MTK_EINT_PIN(37, 0, 20, 0), + MTK_EINT_PIN(38, 0, 21, 0), + MTK_EINT_PIN(39, 0, 22, 0), + MTK_EINT_PIN(40, 0, 23, 0), + MTK_EINT_PIN(41, 1, 7, 0), + MTK_EINT_PIN(42, 1, 8, 0), + MTK_EINT_PIN(43, 1, 9, 0), + MTK_EINT_PIN(44, 1, 10, 0), + MTK_EINT_PIN(45, 1, 11, 0), + MTK_EINT_PIN(46, 1, 12, 0), + MTK_EINT_PIN(47, 1, 13, 0), + MTK_EINT_PIN(48, 0, 24, 0), + MTK_EINT_PIN(49, 0, 25, 0), + MTK_EINT_PIN(50, 0, 26, 0), + MTK_EINT_PIN(51, 0, 27, 0), + MTK_EINT_PIN(52, 0, 28, 0), + MTK_EINT_PIN(53, 0, 29, 0), + MTK_EINT_PIN(54, 0, 30, 0), + MTK_EINT_PIN(55, 0, 31, 0), + MTK_EINT_PIN(56, 0, 32, 0), + MTK_EINT_PIN(57, 0, 33, 0), + MTK_EINT_PIN(58, 0, 34, 0), + MTK_EINT_PIN(59, 0, 35, 0), + MTK_EINT_PIN(60, 0, 36, 0), + MTK_EINT_PIN(61, 0, 37, 0), + MTK_EINT_PIN(62, 0, 38, 0), + MTK_EINT_PIN(63, 0, 39, 0), + MTK_EINT_PIN(64, 0, 40, 0), + MTK_EINT_PIN(65, 0, 41, 0), + MTK_EINT_PIN(66, 0, 42, 0), + MTK_EINT_PIN(67, 0, 43, 0), + MTK_EINT_PIN(68, 0, 44, 0), + MTK_EINT_PIN(69, 0, 45, 0), + MTK_EINT_PIN(70, 0, 46, 0), + MTK_EINT_PIN(71, 0, 47, 0), + MTK_EINT_PIN(72, 0, 48, 0), + MTK_EINT_PIN(73, 0, 49, 0), + MTK_EINT_PIN(74, 0, 50, 0), + MTK_EINT_PIN(75, 0, 51, 0), + MTK_EINT_PIN(76, 0, 52, 0), + MTK_EINT_PIN(77, 1, 14, 0), + MTK_EINT_PIN(78, 1, 15, 0), + MTK_EINT_PIN(79, 1, 16, 0), + MTK_EINT_PIN(80, 1, 17, 0), + MTK_EINT_PIN(81, 1, 18, 0), + MTK_EINT_PIN(82, 1, 19, 0), + MTK_EINT_PIN(83, 1, 20, 0), + MTK_EINT_PIN(84, 1, 21, 0), + MTK_EINT_PIN(85, 1, 22, 0), + MTK_EINT_PIN(86, 1, 23, 0), + MTK_EINT_PIN(87, 1, 24, 0), + MTK_EINT_PIN(88, 1, 25, 0), + MTK_EINT_PIN(89, 1, 26, 0), + MTK_EINT_PIN(90, 1, 27, 0), + MTK_EINT_PIN(91, 1, 28, 0), + MTK_EINT_PIN(92, 0, 53, 0), + MTK_EINT_PIN(93, 0, 54, 0), + MTK_EINT_PIN(94, 0, 55, 0), + MTK_EINT_PIN(95, 0, 56, 0), + MTK_EINT_PIN(96, 0, 57, 0), + MTK_EINT_PIN(97, 2, 10, 0), + MTK_EINT_PIN(98, 2, 11, 0), + MTK_EINT_PIN(99, 1, 29, 0), + MTK_EINT_PIN(100, 1, 30, 0), + MTK_EINT_PIN(101, 1, 31, 0), + MTK_EINT_PIN(102, 1, 32, 0), + MTK_EINT_PIN(103, 1, 33, 0), + MTK_EINT_PIN(104, 1, 34, 0), + MTK_EINT_PIN(105, 1, 35, 0), + MTK_EINT_PIN(106, 1, 36, 0), + MTK_EINT_PIN(107, 1, 37, 0), + MTK_EINT_PIN(108, 1, 38, 0), + MTK_EINT_PIN(109, 1, 39, 0), + MTK_EINT_PIN(110, 1, 40, 0), + MTK_EINT_PIN(111, 1, 41, 0), + MTK_EINT_PIN(112, 1, 42, 0), + MTK_EINT_PIN(113, 1, 43, 0), + MTK_EINT_PIN(114, 1, 44, 0), + MTK_EINT_PIN(115, 1, 45, 0), + MTK_EINT_PIN(116, 1, 46, 0), + MTK_EINT_PIN(196, 3, 0, 0), + MTK_EINT_PIN(197, 3, 1, 0), + MTK_EINT_PIN(198, 3, 2, 0), + MTK_EINT_PIN(199, 3, 3, 0), + MTK_EINT_PIN(200, 3, 4, 0), + MTK_EINT_PIN(201, 3, 5, 0), + MTK_EINT_PIN(202, 3, 6, 0), + MTK_EINT_PIN(203, 3, 7, 0), + MTK_EINT_PIN(204, 3, 8, 0), + MTK_EINT_PIN(205, 3, 9, 0), + MTK_EINT_PIN(206, 3, 10, 0), + MTK_EINT_PIN(207, 3, 11, 0), + MTK_EINT_PIN(208, 3, 12, 0), + MTK_EINT_PIN(209, 3, 13, 0), + MTK_EINT_PIN(210, 3, 14, 0), + MTK_EINT_PIN(211, 3, 15, 0), + MTK_EINT_PIN(212, 3, 16, 0), + MTK_EINT_PIN(213, 3, 17, 0), + MTK_EINT_PIN(214, 3, 18, 0), + MTK_EINT_PIN(215, 3, 19, 0), +}; + +#endif /* __PINCTRL_MTK_MT6878_H */ From a7b4825cb1346bf404fdb10cb00caf45a9900683 Mon Sep 17 00:00:00 2001 From: Bryan Brattlof Date: Fri, 12 Sep 2025 10:40:41 -0500 Subject: [PATCH 018/684] dt-bindings: pinctrl: pinctrl-single: add ti,am62l-padconf compatible Add the "ti,am62l-padconf" compatible to allow for some changes in the driver in the future when needed. Signed-off-by: Bryan Brattlof Acked-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml index f83dbf32ad1838..9135788cf62ec4 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml @@ -24,6 +24,7 @@ properties: - items: - enum: - ti,am437-padconf + - ti,am62l-padconf - ti,am654-padconf - ti,dra7-padconf - ti,omap2420-padconf From 543e3b4a54d779446d0e7aaf4adee1b7d59292fe Mon Sep 17 00:00:00 2001 From: Antony Kurniawan Soemardi Date: Sun, 14 Sep 2025 18:34:59 +0000 Subject: [PATCH 019/684] dt-bindings: pinctrl: qcom: msm8960: rename msmgpio node to tlmm Rename the GPIO controller node from "msmgpio" to "tlmm" to match the convention used by other Qualcomm SoCs. Suggested-by: Shinjo Park Signed-off-by: Antony Kurniawan Soemardi Reviewed-by: Bjorn Andersson Acked-by: Rob Herring (Arm) Reviewed-by: Dmitry Baryshkov Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml index 46618740bd312b..03a36927701420 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml @@ -107,12 +107,12 @@ examples: - | #include - msmgpio: pinctrl@800000 { + tlmm: pinctrl@800000 { compatible = "qcom,msm8960-pinctrl"; reg = <0x800000 0x4000>; #gpio-cells = <2>; gpio-controller; - gpio-ranges = <&msmgpio 0 0 152>; + gpio-ranges = <&tlmm 0 0 152>; interrupts = ; interrupt-controller; #interrupt-cells = <2>; From 37e7b536061a33c8f27030e3ffc5a717a6c319e3 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Fri, 19 Sep 2025 15:17:11 +0300 Subject: [PATCH 020/684] pinctrl: qcom: glymur: Drop unnecessary platform data from match table The platform specific configuration is already passed on to the generic msm probe. So it's useless to exist in the match table next to the compatible. So drop it from match table. Fixes: 87ebcd8baebf ("pinctrl: qcom: Add glymur pinctrl driver") Signed-off-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-glymur.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-glymur.c b/drivers/pinctrl/qcom/pinctrl-glymur.c index 9913f98e953110..9781e7fcb3a11c 100644 --- a/drivers/pinctrl/qcom/pinctrl-glymur.c +++ b/drivers/pinctrl/qcom/pinctrl-glymur.c @@ -1743,7 +1743,7 @@ static const struct msm_pinctrl_soc_data glymur_tlmm = { }; static const struct of_device_id glymur_tlmm_of_match[] = { - { .compatible = "qcom,glymur-tlmm", .data = &glymur_tlmm }, + { .compatible = "qcom,glymur-tlmm", }, { } }; From e73fda2dcb0bad6650e654556c5242b773707257 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Fri, 19 Sep 2025 15:17:12 +0300 Subject: [PATCH 021/684] pinctrl: qcom: glymur: Fix the gpio and egpio pin functions Mark the gpio/egpio as GPIO specific pin functions, othewise the pin muxing generic framework will complain about the gpio being already requested by a different owner. Fixes: 87ebcd8baebf ("pinctrl: qcom: Add glymur pinctrl driver") Signed-off-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-glymur.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-glymur.c b/drivers/pinctrl/qcom/pinctrl-glymur.c index 9781e7fcb3a11c..335005084b6bc8 100644 --- a/drivers/pinctrl/qcom/pinctrl-glymur.c +++ b/drivers/pinctrl/qcom/pinctrl-glymur.c @@ -1316,7 +1316,7 @@ static const char *const wcn_sw_ctrl_groups[] = { }; static const struct pinfunction glymur_functions[] = { - MSM_PIN_FUNCTION(gpio), + MSM_GPIO_PIN_FUNCTION(gpio), MSM_PIN_FUNCTION(resout_gpio_n), MSM_PIN_FUNCTION(aoss_cti), MSM_PIN_FUNCTION(asc_cci), @@ -1342,7 +1342,7 @@ static const struct pinfunction glymur_functions[] = { MSM_PIN_FUNCTION(edp0_hot), MSM_PIN_FUNCTION(edp0_lcd), MSM_PIN_FUNCTION(edp1_lcd), - MSM_PIN_FUNCTION(egpio), + MSM_GPIO_PIN_FUNCTION(egpio), MSM_PIN_FUNCTION(eusb_ac_en), MSM_PIN_FUNCTION(gcc_gp1), MSM_PIN_FUNCTION(gcc_gp2), From 5f345e61a50d33eaba88e89d7867826aafb8b114 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Wed, 24 Sep 2025 22:31:02 +0530 Subject: [PATCH 022/684] dt-bindings: pinctrl: qcom,pmic-gpio: Add GPIO bindings for Glymur PMICs Update the Qualcomm Technologies, Inc. PMIC GPIO binding documentation to include compatible strings for PMK8850, PMH0101, PMH0104, PMH0110 and PMCX0102 PMICs. Signed-off-by: Anjelique Melendez Signed-off-by: Jishnu Prakash Signed-off-by: Pankaj Patil Signed-off-by: Kamal Wadhwa Reviewed-by: Bartosz Golaszewski Acked-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,pmic-gpio.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml index 5e6dfcc3fe9b3c..8ae4489637f3d1 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml @@ -59,7 +59,11 @@ properties: - qcom,pmc8180-gpio - qcom,pmc8180c-gpio - qcom,pmc8380-gpio + - qcom,pmcx0102-gpio - qcom,pmd8028-gpio + - qcom,pmh0101-gpio + - qcom,pmh0104-gpio + - qcom,pmh0110-gpio - qcom,pmi632-gpio - qcom,pmi8950-gpio - qcom,pmi8994-gpio @@ -68,6 +72,7 @@ properties: - qcom,pmiv0104-gpio - qcom,pmk8350-gpio - qcom,pmk8550-gpio + - qcom,pmk8850-gpio - qcom,pmm8155au-gpio - qcom,pmm8654au-gpio - qcom,pmp8074-gpio @@ -191,6 +196,8 @@ allOf: - qcom,pm8950-gpio - qcom,pm8953-gpio - qcom,pmi632-gpio + - qcom,pmh0104-gpio + - qcom,pmk8850-gpio then: properties: gpio-line-names: @@ -303,6 +310,8 @@ allOf: compatible: contains: enum: + - qcom,pmcx0102-gpio + - qcom,pmh0110-gpio - qcom,pmi8998-gpio then: properties: @@ -318,6 +327,7 @@ allOf: compatible: contains: enum: + - qcom,pmh0101-gpio - qcom,pmih0108-gpio then: properties: @@ -481,13 +491,18 @@ $defs: - gpio1-gpio22 for pm8994 - gpio1-gpio26 for pm8998 - gpio1-gpio22 for pma8084 + - gpio1-gpio14 for pmcx0102 - gpio1-gpio4 for pmd8028 + - gpio1-gpio18 for pmh0101 + - gpio1-gpio8 for pmh0104 + - gpio1-gpio14 for pmh0110 - gpio1-gpio8 for pmi632 - gpio1-gpio2 for pmi8950 - gpio1-gpio10 for pmi8994 - gpio1-gpio18 for pmih0108 - gpio1-gpio4 for pmk8350 - gpio1-gpio6 for pmk8550 + - gpio1-gpio8 for pmk8850 - gpio1-gpio10 for pmm8155au - gpio1-gpio12 for pmm8654au - gpio1-gpio12 for pmp8074 (holes on gpio1 and gpio12) From 120b6d1a22ee46dcf35e21949ddce6fe736550f0 Mon Sep 17 00:00:00 2001 From: Anjelique Melendez Date: Wed, 24 Sep 2025 22:31:03 +0530 Subject: [PATCH 023/684] pinctrl: qcom: spmi-gpio: Add PMCX0102, PMK8850 & PMH01XX PMICs support Add support for PMCX0102, PMH0101, PMH0104, PMH0110 and PMK8850 PMIC GPIOs with adding appropriate compatible strings. Signed-off-by: Anjelique Melendez Signed-off-by: Jishnu Prakash Signed-off-by: Kamal Wadhwa Reviewed-by: Dmitry Baryshkov Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 485b68cc93f8ed..c4f7d2d7a01768 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1239,7 +1239,11 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 }, { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 }, { .compatible = "qcom,pmc8380-gpio", .data = (void *) 10 }, + { .compatible = "qcom,pmcx0102-gpio", .data = (void *)14 }, { .compatible = "qcom,pmd8028-gpio", .data = (void *) 4 }, + { .compatible = "qcom,pmh0101-gpio", .data = (void *)18 }, + { .compatible = "qcom,pmh0104-gpio", .data = (void *)8 }, + { .compatible = "qcom,pmh0110-gpio", .data = (void *)14 }, { .compatible = "qcom,pmi632-gpio", .data = (void *) 8 }, { .compatible = "qcom,pmi8950-gpio", .data = (void *) 2 }, { .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 }, @@ -1248,6 +1252,7 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pmiv0104-gpio", .data = (void *) 10 }, { .compatible = "qcom,pmk8350-gpio", .data = (void *) 4 }, { .compatible = "qcom,pmk8550-gpio", .data = (void *) 6 }, + { .compatible = "qcom,pmk8850-gpio", .data = (void *)8 }, { .compatible = "qcom,pmm8155au-gpio", .data = (void *) 10 }, { .compatible = "qcom,pmm8654au-gpio", .data = (void *) 12 }, /* pmp8074 has 12 GPIOs with holes on 1 and 12 */ From bfdccbe92e6de5a4b468343cbca3143b89df99af Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 24 Sep 2025 22:31:04 +0530 Subject: [PATCH 024/684] pinctrl: qcom: spmi-gpio: add support for {LV_VIN2, MV_VIN3}_CLK subtypes Add support for SPMI PMIC GPIO subtypes GPIO_LV_VIN2_CLK and GPIO_MV_VIN3_CLK. Signed-off-by: Subbaraman Narayanamurthy Signed-off-by: Jishnu Prakash Signed-off-by: Kamal Wadhwa Reviewed-by: Dmitry Baryshkov Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index c4f7d2d7a01768..83f940fe30b26a 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -42,6 +42,8 @@ #define PMIC_GPIO_SUBTYPE_GPIO_MV 0x11 #define PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2 0x12 #define PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3 0x13 +#define PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2_CLK 0x14 +#define PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3_CLK 0x15 #define PMIC_MPP_REG_RT_STS 0x10 #define PMIC_MPP_REG_RT_STS_VAL_MASK 0x1 @@ -852,11 +854,13 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state, pad->lv_mv_type = true; break; case PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2: + case PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2_CLK: pad->num_sources = 2; pad->have_buffer = true; pad->lv_mv_type = true; break; case PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3: + case PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3_CLK: pad->num_sources = 3; pad->have_buffer = true; pad->lv_mv_type = true; From d51093cf011cab7235f64beb92a344806db393a6 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Wed, 24 Sep 2025 17:31:59 -0500 Subject: [PATCH 025/684] dt-bindings: pinctrl: Convert Marvell Berlin pinctrl to DT schema Convert the Marvell/Synaptics Berlin pinctrl binding to DT schema format. The "reg" property was not documented for the newer SoCs. Otherwise, it's a straight-forward conversion. Signed-off-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../bindings/pinctrl/berlin,pinctrl.txt | 47 ---------- .../pinctrl/marvell,berlin2-soc-pinctrl.yaml | 86 +++++++++++++++++++ 2 files changed, 86 insertions(+), 47 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/berlin,pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,berlin2-soc-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/berlin,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/berlin,pinctrl.txt deleted file mode 100644 index 0a2d5516e1f398..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/berlin,pinctrl.txt +++ /dev/null @@ -1,47 +0,0 @@ -* Pin-controller driver for the Marvell Berlin SoCs - -Pin control registers are part of both chip controller and system -controller register sets. Pin controller nodes should be a sub-node of -either the chip controller or system controller node. The pins -controlled are organized in groups, so no actual pin information is -needed. - -A pin-controller node should contain subnodes representing the pin group -configurations, one per function. Each subnode has the group name and -the muxing function used. - -Be aware the Marvell Berlin datasheets use the keyword 'mode' for what -is called a 'function' in the pin-controller subsystem. - -Required properties: -- compatible: should be one of: - "marvell,berlin2-soc-pinctrl", - "marvell,berlin2-system-pinctrl", - "marvell,berlin2cd-soc-pinctrl", - "marvell,berlin2cd-system-pinctrl", - "marvell,berlin2q-soc-pinctrl", - "marvell,berlin2q-system-pinctrl", - "marvell,berlin4ct-avio-pinctrl", - "marvell,berlin4ct-soc-pinctrl", - "marvell,berlin4ct-system-pinctrl", - "syna,as370-soc-pinctrl" - -Required subnode-properties: -- groups: a list of strings describing the group names. -- function: a string describing the function used to mux the groups. - -Example: - -sys_pinctrl: pin-controller { - compatible = "marvell,berlin2q-system-pinctrl"; - - uart0_pmux: uart0-pmux { - groups = "GSM12"; - function = "uart0"; - }; -}; - -&uart0 { - pinctrl-0 = <&uart0_pmux>; - pinctrl-names = "default"; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,berlin2-soc-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/marvell,berlin2-soc-pinctrl.yaml new file mode 100644 index 00000000000000..6ace3bf5433bd0 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,berlin2-soc-pinctrl.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/marvell,berlin2-soc-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Berlin pin-controller driver + +maintainers: + - Antoine Tenart + - Jisheng Zhang + +description: > + Pin control registers are part of both chip controller and system controller + register sets. Pin controller nodes should be a sub-node of either the chip + controller or system controller node. The pins controlled are organized in + groups, so no actual pin information is needed. + + A pin-controller node should contain subnodes representing the pin group + configurations, one per function. Each subnode has the group name and the + muxing function used. + + Be aware the Marvell Berlin datasheets use the keyword 'mode' for what is + called a 'function' in the pin-controller subsystem. + +properties: + compatible: + items: + - enum: + - marvell,berlin2-soc-pinctrl + - marvell,berlin2-system-pinctrl + - marvell,berlin2cd-soc-pinctrl + - marvell,berlin2cd-system-pinctrl + - marvell,berlin2q-soc-pinctrl + - marvell,berlin2q-system-pinctrl + - marvell,berlin4ct-avio-pinctrl + - marvell,berlin4ct-soc-pinctrl + - marvell,berlin4ct-system-pinctrl + - syna,as370-soc-pinctrl + + reg: + maxItems: 1 + +additionalProperties: + description: Pin group configuration subnodes. + type: object + $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + groups: + description: List of pin group names. + $ref: /schemas/types.yaml#/definitions/string-array + + function: + description: Function used to mux the group. + $ref: /schemas/types.yaml#/definitions/string + + required: + - groups + - function + +allOf: + - if: + properties: + compatible: + contains: + enum: + - marvell,berlin4ct-avio-pinctrl + - marvell,berlin4ct-soc-pinctrl + - marvell,berlin4ct-system-pinctrl + - syna,as370-soc-pinctrl + then: + required: + - reg + +examples: + - | + pinctrl { + compatible = "marvell,berlin2q-system-pinctrl"; + + uart0-pmux { + groups = "GSM12"; + function = "uart0"; + }; + }; From c1c9641a04e839604612eac99c827f8f3e0c4f06 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Thu, 25 Sep 2025 17:18:50 -0500 Subject: [PATCH 026/684] dt-bindings: pinctrl: Convert marvell,armada-3710-(sb|nb)-pinctrl to DT schema Convert the marvell,armada3710-(sb|nb)-pinctrl binding to DT schema format. The binding includes the "marvell,armada-3700-xtal-clock" subnode which is simple enough to include here. Mark interrupt-controller/#interrupt-cells as required as the users have them and the h/w is either capable of interrupts or not. As this syscon has 2 register ranges, syscon-common.yaml needs to be updated to drop the restriction of 1 register entry. Signed-off-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../bindings/clock/armada3700-xtal-clock.txt | 29 --- .../bindings/mfd/syscon-common.yaml | 3 - .../pinctrl/marvell,armada-37xx-pinctrl.txt | 195 ------------------ .../marvell,armada3710-xb-pinctrl.yaml | 124 +++++++++++ 4 files changed, 124 insertions(+), 227 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt delete mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada3710-xb-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt b/Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt deleted file mode 100644 index 4c0807f28cfaa1..00000000000000 --- a/Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt +++ /dev/null @@ -1,29 +0,0 @@ -* Xtal Clock bindings for Marvell Armada 37xx SoCs - -Marvell Armada 37xx SoCs allow to determine the xtal clock frequencies by -reading the gpio latch register. - -This node must be a subnode of the node exposing the register address -of the GPIO block where the gpio latch is located. -See Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt - -Required properties: -- compatible : shall be one of the following: - "marvell,armada-3700-xtal-clock" -- #clock-cells : from common clock binding; shall be set to 0 - -Optional properties: -- clock-output-names : from common clock binding; allows overwrite default clock - output names ("xtal") - -Example: -pinctrl_nb: pinctrl-nb@13800 { - compatible = "armada3710-nb-pinctrl", "syscon", "simple-mfd"; - reg = <0x13800 0x100>, <0x13C00 0x20>; - - xtalclk: xtal-clk { - compatible = "marvell,armada-3700-xtal-clock"; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; -}; diff --git a/Documentation/devicetree/bindings/mfd/syscon-common.yaml b/Documentation/devicetree/bindings/mfd/syscon-common.yaml index 451cbad467a3c5..14a08e7bc8bdd7 100644 --- a/Documentation/devicetree/bindings/mfd/syscon-common.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon-common.yaml @@ -35,9 +35,6 @@ properties: minItems: 2 maxItems: 5 # Should be enough - reg: - maxItems: 1 - reg-io-width: description: The size (in bytes) of the IO accesses that should be performed diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt deleted file mode 100644 index ecec514b315506..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt +++ /dev/null @@ -1,195 +0,0 @@ -* Marvell Armada 37xx SoC pin and gpio controller - -Each Armada 37xx SoC come with two pin and gpio controller one for the -south bridge and the other for the north bridge. - -Inside this set of register the gpio latch allows exposing some -configuration of the SoC and especially the clock frequency of the -xtal. Hence, this node is a represent as syscon allowing sharing the -register between multiple hardware block. - -GPIO and pin controller: ------------------------- - -Main node: - -Refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the meaning -of the phrase "pin configuration node". - -Required properties for pinctrl driver: - -- compatible: "marvell,armada3710-sb-pinctrl", "syscon, "simple-mfd" - for the south bridge - "marvell,armada3710-nb-pinctrl", "syscon, "simple-mfd" - for the north bridge -- reg: The first set of register are for pinctrl/gpio and the second - set for the interrupt controller -- interrupts: list of the interrupt use by the gpio - -Available groups and functions for the North bridge: - -group: jtag - - pins 20-24 - - functions jtag, gpio - -group sdio0 - - pins 8-10 - - functions sdio, gpio - -group emmc_nb - - pins 27-35 - - functions emmc, gpio - -group pwm0 - - pin 11 (GPIO1-11) - - functions pwm, led, gpio - -group pwm1 - - pin 12 - - functions pwm, led, gpio - -group pwm2 - - pin 13 - - functions pwm, led, gpio - -group pwm3 - - pin 14 - - functions pwm, led, gpio - -group pmic1 - - pin 7 - - functions pmic, gpio - -group pmic0 - - pin 6 - - functions pmic, gpio - -group i2c2 - - pins 2-3 - - functions i2c, gpio - -group i2c1 - - pins 0-1 - - functions i2c, gpio - -group spi_cs1 - - pin 17 - - functions spi, gpio - -group spi_cs2 - - pin 18 - - functions spi, gpio - -group spi_cs3 - - pin 19 - - functions spi, gpio - -group onewire - - pin 4 - - functions onewire, gpio - -group uart1 - - pins 25-26 - - functions uart, gpio - -group spi_quad - - pins 15-16 - - functions spi, gpio - -group uart2 - - pins 9-10 and 18-19 - - functions uart, gpio - -Available groups and functions for the South bridge: - -group usb32_drvvbus0 - - pin 36 - - functions drvbus, gpio - -group usb2_drvvbus1 - - pin 37 - - functions drvbus, gpio - -group sdio_sb - - pins 60-65 - - functions sdio, gpio - -group rgmii - - pins 42-53 - - functions mii, gpio - -group pcie1 - - pins 39 - - functions pcie, gpio - -group pcie1_clkreq - - pins 40 - - functions pcie, gpio - -group pcie1_wakeup - - pins 41 - - functions pcie, gpio - -group smi - - pins 54-55 - - functions smi, gpio - -group ptp - - pins 56 - - functions ptp, gpio - -group ptp_clk - - pin 57 - - functions ptp, mii - -group ptp_trig - - pin 58 - - functions ptp, mii - -group mii_col - - pin 59 - - functions mii, mii_err - -GPIO subnode: - -Please refer to gpio.txt in this directory for details of gpio-ranges property -and the common GPIO bindings used by client devices. - -Required properties for gpio driver under the gpio subnode: -- interrupts: List of interrupt specifier for the controllers interrupt. -- gpio-controller: Marks the device node as a gpio controller. -- #gpio-cells: Should be 2. The first cell is the GPIO number and the - second cell specifies GPIO flags, as defined in - . Only the GPIO_ACTIVE_HIGH and - GPIO_ACTIVE_LOW flags are supported. -- gpio-ranges: Range of pins managed by the GPIO controller. - -Xtal Clock bindings for Marvell Armada 37xx SoCs ------------------------------------------------- - -see Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt - - -Example: -pinctrl_sb: pinctrl-sb@18800 { - compatible = "marvell,armada3710-sb-pinctrl", "syscon", "simple-mfd"; - reg = <0x18800 0x100>, <0x18C00 0x20>; - gpio { - #gpio-cells = <2>; - gpio-ranges = <&pinctrl_sb 0 0 29>; - gpio-controller; - interrupts = - , - , - , - , - ; - }; - - rgmii_pins: mii-pins { - groups = "rgmii"; - function = "mii"; - }; - -}; diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada3710-xb-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/marvell,armada3710-xb-pinctrl.yaml new file mode 100644 index 00000000000000..51bad2e8d6f1f7 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada3710-xb-pinctrl.yaml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/marvell,armada3710-xb-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Armada 37xx SoC pin and gpio controller + +maintainers: + - Gregory CLEMENT + - Marek Behún + - Miquel Raynal + +description: > + Each Armada 37xx SoC come with two pin and gpio controller one for the south + bridge and the other for the north bridge. + + Inside this set of register the gpio latch allows exposing some configuration + of the SoC and especially the clock frequency of the xtal. Hence, this node is + a represent as syscon allowing sharing the register between multiple hardware + block. + +properties: + compatible: + items: + - enum: + - marvell,armada3710-sb-pinctrl + - marvell,armada3710-nb-pinctrl + - const: syscon + - const: simple-mfd + + reg: + items: + - description: pinctrl and GPIO controller registers + - description: interrupt controller registers + + gpio: + description: GPIO controller subnode + type: object + additionalProperties: false + + properties: + '#gpio-cells': + const: 2 + + gpio-controller: true + + gpio-ranges: + description: Range of pins managed by the GPIO controller + + '#interrupt-cells': + const: 2 + + interrupt-controller: true + + interrupts: + description: List of interrupt specifiers for the GPIO controller + + required: + - '#gpio-cells' + - gpio-ranges + - gpio-controller + - '#interrupt-cells' + - interrupt-controller + - interrupts + + xtal-clk: + type: object + additionalProperties: false + + properties: + compatible: + const: marvell,armada-3700-xtal-clock + + '#clock-cells': + const: 0 + + clock-output-names: true + +patternProperties: + '-pins$': + $ref: pinmux-node.yaml# + additionalProperties: false + + properties: + groups: + enum: [ emmc_nb, i2c1, i2c2, jtag, mii_col, onewire, pcie1, + pcie1_clkreq, pcie1_wakeup, pmic0, pmic1, ptp, ptp_clk, + ptp_trig, pwm0, pwm1, pwm2, pwm3, rgmii, sdio0, sdio_sb, smi, + spi_cs1, spi_cs2, spi_cs3, spi_quad, uart1, uart2, + usb2_drvvbus1, usb32_drvvbus ] + + function: + enum: [ drvbus, emmc, gpio, i2c, jtag, led, mii, mii_err, onewire, + pcie, pmic, ptp, pwm, sdio, smi, spi, uart ] + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + + pinctrl_sb: pinctrl@18800 { + compatible = "marvell,armada3710-sb-pinctrl", "syscon", "simple-mfd"; + reg = <0x18800 0x100>, <0x18C00 0x20>; + + gpio { + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_sb 0 0 29>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts = + , + , + , + , + ; + }; + }; From e7db6f1528fd036cfade3222dac979dfbc24ddfb Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Wed, 24 Sep 2025 16:16:03 -0700 Subject: [PATCH 027/684] dt-bindings: pinctrl: describe Kaanapali TLMM The Top Level Mode Multiplexer (TLMM) in the Kaanapali SoC provide GPIO and pinctrl functionality for UFS, SDC and 217 GPIO pins. Add a DeviceTree binding to describe the Kaanapali TLMM block. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,kaanapali-tlmm.yaml | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,kaanapali-tlmm.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,kaanapali-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,kaanapali-tlmm.yaml new file mode 100644 index 00000000000000..53534a07a1f0e2 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,kaanapali-tlmm.yaml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,kaanapali-tlmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. Kaanapali TLMM block + +maintainers: + - Jingyi Wang + +description: + Top Level Mode Multiplexer pin controller in Qualcomm Kaanapali SoC. + +allOf: + - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# + +properties: + compatible: + const: qcom,kaanapali-tlmm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-reserved-ranges: + minItems: 1 + maxItems: 109 + + gpio-line-names: + maxItems: 217 + +patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/qcom-kaanapali-tlmm-state" + - patternProperties: + "-pins$": + $ref: "#/$defs/qcom-kaanapali-tlmm-state" + additionalProperties: false + +$defs: + qcom-kaanapali-tlmm-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-9]|21[0-6])$" + - enum: [ ufs_reset, sdc2_clk, sdc2_cmd, sdc2_data ] + minItems: 1 + maxItems: 36 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [ gpio, aoss_cti, atest_char, atest_usb, audio_ext_mclk0, + audio_ext_mclk1, audio_ref_clk, cam_asc_mclk2, cam_asc_mclk4, + cam_mclk, cci_async_in, cci_i2c_scl, cci_i2c_sda, cci_timer, + cmu_rng, coex_uart1_rx, coex_uart1_tx, coex_uart2_rx, + coex_uart2_tx, dbg_out_clk, ddr_bist_complete, ddr_bist_fail, + ddr_bist_start, ddr_bist_stop, ddr_pxi0, ddr_pxi1, ddr_pxi2, + ddr_pxi3, dp_hot, egpio, gcc_gp1, gcc_gp2, gcc_gp3, gnss_adc0, + gnss_adc1, i2chub0_se0, i2chub0_se1, i2chub0_se2, i2chub0_se3, + i2chub0_se4, i2s0_data0, i2s0_data1, i2s0_sck, i2s0_ws, + i2s1_data0, i2s1_data1, i2s1_sck, i2s1_ws, ibi_i3c, jitter_bist, + mdp_esync0_out, mdp_esync1_out, mdp_vsync, mdp_vsync0_out, + mdp_vsync1_out, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out, + mdp_vsync_e, nav_gpio0, nav_gpio1, nav_gpio2, nav_gpio3, + pcie0_clk_req_n, phase_flag, pll_bist_sync, pll_clk_aux, + prng_rosc0, prng_rosc1, prng_rosc2, prng_rosc3, qdss_cti, + qdss_gpio_traceclk, qdss_gpio_tracectl, qdss_gpio_tracedata, + qlink_big_enable, qlink_big_request, qlink_little_enable, + qlink_little_request, qlink_wmss, qspi0, qspi1, qspi2, qspi3, + qspi_clk, qspi_cs, qup1_se0, qup1_se1, qup1_se2, qup1_se3, + qup1_se4, qup1_se5, qup1_se6, qup1_se7, qup2_se0, qup2_se1, + qup2_se2, qup2_se3, qup2_se4, qup3_se0, qup3_se1, qup3_se2, + qup3_se3, qup3_se4, qup3_se5, qup4_se0, qup4_se1, qup4_se2, + qup4_se3, qup4_se4, sd_write_protect, sdc40, sdc41, sdc42, sdc43, + sdc4_clk, sdc4_cmd, sys_throttle, tb_trig_sdc2, tb_trig_sdc4, + tmess_prng0, tmess_prng1, tmess_prng2, tmess_prng3, tsense_pwm1, + tsense_pwm2, tsense_pwm3, tsense_pwm4, tsense_pwm5, tsense_pwm6, + tsense_pwm7, uim0_clk, uim0_data, uim0_present, uim0_reset, uim1_clk, + uim1_data, uim1_present, uim1_reset, usb0_hs, usb_phy, vfr_0, vfr_1, + vsense_trigger_mirnat, wcn_sw, wcn_sw_ctrl ] + + required: + - pins + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + tlmm: pinctrl@f100000 { + compatible = "qcom,kaanapali-tlmm"; + reg = <0x0f100000 0x300000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 218>; + interrupt-controller; + #interrupt-cells = <2>; + + qup-uart7-state { + pins = "gpio62", "gpio63"; + function = "qup1_se7"; + }; + }; +... From 35ff9c6b318af715f54dc2053b328ca7bfb2c00f Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Wed, 24 Sep 2025 16:16:04 -0700 Subject: [PATCH 028/684] pinctrl: qcom: add the tlmm driver for Kaanapali platforms Add support for Kaanapali TLMM configuration and control via the pinctrl framework. Signed-off-by: Jingyi Wang Reviewed-by: Bartosz Golaszewski Reviewed-by: Bjorn Andersson Reviewed-by: Konrad Dybcio Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/Kconfig.msm | 8 + drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-kaanapali.c | 1803 ++++++++++++++++++++++ 3 files changed, 1812 insertions(+) create mode 100644 drivers/pinctrl/qcom/pinctrl-kaanapali.c diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm index 69a5b47adedc2a..3e9e02774001b6 100644 --- a/drivers/pinctrl/qcom/Kconfig.msm +++ b/drivers/pinctrl/qcom/Kconfig.msm @@ -92,6 +92,14 @@ config PINCTRL_IPQ9574 Qualcomm Technologies Inc. IPQ9574 platform. Select this for IPQ9574. +config PINCTRL_KAANAPALI + tristate "Qualcomm Technologies Inc Kaanapali pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc Kaanapali platform. + config PINCTRL_MSM8226 tristate "Qualcomm 8226 pin controller driver" depends on ARM || COMPILE_TEST diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 567d3051e760dd..748b17a77b2cc4 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_IPQ5424) += pinctrl-ipq5424.o obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o obj-$(CONFIG_PINCTRL_IPQ6018) += pinctrl-ipq6018.o obj-$(CONFIG_PINCTRL_IPQ9574) += pinctrl-ipq9574.o +obj-$(CONFIG_PINCTRL_KAANAPALI) += pinctrl-kaanapali.o obj-$(CONFIG_PINCTRL_MSM8226) += pinctrl-msm8226.o obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o diff --git a/drivers/pinctrl/qcom/pinctrl-kaanapali.c b/drivers/pinctrl/qcom/pinctrl-kaanapali.c new file mode 100644 index 00000000000000..364e6d997337e5 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-kaanapali.c @@ -0,0 +1,1803 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include + +#include "pinctrl-msm.h" + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ + { \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 /* egpio mode */ \ + }, \ + .nfuncs = 12, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .egpio_enable = 12, \ + .egpio_present = 11, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_wakeup_present_bit = 6, \ + .intr_wakeup_enable_bit = 7, \ + .intr_target_bit = 8, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +#define UFS_RESET(pg_name, ctl, io) \ + { \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ + .ctl_reg = ctl, \ + .io_reg = io, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +static const struct pinctrl_pin_desc kaanapali_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "GPIO_146"), + PINCTRL_PIN(147, "GPIO_147"), + PINCTRL_PIN(148, "GPIO_148"), + PINCTRL_PIN(149, "GPIO_149"), + PINCTRL_PIN(150, "GPIO_150"), + PINCTRL_PIN(151, "GPIO_151"), + PINCTRL_PIN(152, "GPIO_152"), + PINCTRL_PIN(153, "GPIO_153"), + PINCTRL_PIN(154, "GPIO_154"), + PINCTRL_PIN(155, "GPIO_155"), + PINCTRL_PIN(156, "GPIO_156"), + PINCTRL_PIN(157, "GPIO_157"), + PINCTRL_PIN(158, "GPIO_158"), + PINCTRL_PIN(159, "GPIO_159"), + PINCTRL_PIN(160, "GPIO_160"), + PINCTRL_PIN(161, "GPIO_161"), + PINCTRL_PIN(162, "GPIO_162"), + PINCTRL_PIN(163, "GPIO_163"), + PINCTRL_PIN(164, "GPIO_164"), + PINCTRL_PIN(165, "GPIO_165"), + PINCTRL_PIN(166, "GPIO_166"), + PINCTRL_PIN(167, "GPIO_167"), + PINCTRL_PIN(168, "GPIO_168"), + PINCTRL_PIN(169, "GPIO_169"), + PINCTRL_PIN(170, "GPIO_170"), + PINCTRL_PIN(171, "GPIO_171"), + PINCTRL_PIN(172, "GPIO_172"), + PINCTRL_PIN(173, "GPIO_173"), + PINCTRL_PIN(174, "GPIO_174"), + PINCTRL_PIN(175, "GPIO_175"), + PINCTRL_PIN(176, "GPIO_176"), + PINCTRL_PIN(177, "GPIO_177"), + PINCTRL_PIN(178, "GPIO_178"), + PINCTRL_PIN(179, "GPIO_179"), + PINCTRL_PIN(180, "GPIO_180"), + PINCTRL_PIN(181, "GPIO_181"), + PINCTRL_PIN(182, "GPIO_182"), + PINCTRL_PIN(183, "GPIO_183"), + PINCTRL_PIN(184, "GPIO_184"), + PINCTRL_PIN(185, "GPIO_185"), + PINCTRL_PIN(186, "GPIO_186"), + PINCTRL_PIN(187, "GPIO_187"), + PINCTRL_PIN(188, "GPIO_188"), + PINCTRL_PIN(189, "GPIO_189"), + PINCTRL_PIN(190, "GPIO_190"), + PINCTRL_PIN(191, "GPIO_191"), + PINCTRL_PIN(192, "GPIO_192"), + PINCTRL_PIN(193, "GPIO_193"), + PINCTRL_PIN(194, "GPIO_194"), + PINCTRL_PIN(195, "GPIO_195"), + PINCTRL_PIN(196, "GPIO_196"), + PINCTRL_PIN(197, "GPIO_197"), + PINCTRL_PIN(198, "GPIO_198"), + PINCTRL_PIN(199, "GPIO_199"), + PINCTRL_PIN(200, "GPIO_200"), + PINCTRL_PIN(201, "GPIO_201"), + PINCTRL_PIN(202, "GPIO_202"), + PINCTRL_PIN(203, "GPIO_203"), + PINCTRL_PIN(204, "GPIO_204"), + PINCTRL_PIN(205, "GPIO_205"), + PINCTRL_PIN(206, "GPIO_206"), + PINCTRL_PIN(207, "GPIO_207"), + PINCTRL_PIN(208, "GPIO_208"), + PINCTRL_PIN(209, "GPIO_209"), + PINCTRL_PIN(210, "GPIO_210"), + PINCTRL_PIN(211, "GPIO_211"), + PINCTRL_PIN(212, "GPIO_212"), + PINCTRL_PIN(213, "GPIO_213"), + PINCTRL_PIN(214, "GPIO_214"), + PINCTRL_PIN(215, "GPIO_215"), + PINCTRL_PIN(216, "GPIO_216"), + PINCTRL_PIN(217, "UFS_RESET"), + PINCTRL_PIN(218, "SDC2_CLK"), + PINCTRL_PIN(219, "SDC2_CMD"), + PINCTRL_PIN(220, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); +DECLARE_MSM_GPIO_PINS(146); +DECLARE_MSM_GPIO_PINS(147); +DECLARE_MSM_GPIO_PINS(148); +DECLARE_MSM_GPIO_PINS(149); +DECLARE_MSM_GPIO_PINS(150); +DECLARE_MSM_GPIO_PINS(151); +DECLARE_MSM_GPIO_PINS(152); +DECLARE_MSM_GPIO_PINS(153); +DECLARE_MSM_GPIO_PINS(154); +DECLARE_MSM_GPIO_PINS(155); +DECLARE_MSM_GPIO_PINS(156); +DECLARE_MSM_GPIO_PINS(157); +DECLARE_MSM_GPIO_PINS(158); +DECLARE_MSM_GPIO_PINS(159); +DECLARE_MSM_GPIO_PINS(160); +DECLARE_MSM_GPIO_PINS(161); +DECLARE_MSM_GPIO_PINS(162); +DECLARE_MSM_GPIO_PINS(163); +DECLARE_MSM_GPIO_PINS(164); +DECLARE_MSM_GPIO_PINS(165); +DECLARE_MSM_GPIO_PINS(166); +DECLARE_MSM_GPIO_PINS(167); +DECLARE_MSM_GPIO_PINS(168); +DECLARE_MSM_GPIO_PINS(169); +DECLARE_MSM_GPIO_PINS(170); +DECLARE_MSM_GPIO_PINS(171); +DECLARE_MSM_GPIO_PINS(172); +DECLARE_MSM_GPIO_PINS(173); +DECLARE_MSM_GPIO_PINS(174); +DECLARE_MSM_GPIO_PINS(175); +DECLARE_MSM_GPIO_PINS(176); +DECLARE_MSM_GPIO_PINS(177); +DECLARE_MSM_GPIO_PINS(178); +DECLARE_MSM_GPIO_PINS(179); +DECLARE_MSM_GPIO_PINS(180); +DECLARE_MSM_GPIO_PINS(181); +DECLARE_MSM_GPIO_PINS(182); +DECLARE_MSM_GPIO_PINS(183); +DECLARE_MSM_GPIO_PINS(184); +DECLARE_MSM_GPIO_PINS(185); +DECLARE_MSM_GPIO_PINS(186); +DECLARE_MSM_GPIO_PINS(187); +DECLARE_MSM_GPIO_PINS(188); +DECLARE_MSM_GPIO_PINS(189); +DECLARE_MSM_GPIO_PINS(190); +DECLARE_MSM_GPIO_PINS(191); +DECLARE_MSM_GPIO_PINS(192); +DECLARE_MSM_GPIO_PINS(193); +DECLARE_MSM_GPIO_PINS(194); +DECLARE_MSM_GPIO_PINS(195); +DECLARE_MSM_GPIO_PINS(196); +DECLARE_MSM_GPIO_PINS(197); +DECLARE_MSM_GPIO_PINS(198); +DECLARE_MSM_GPIO_PINS(199); +DECLARE_MSM_GPIO_PINS(200); +DECLARE_MSM_GPIO_PINS(201); +DECLARE_MSM_GPIO_PINS(202); +DECLARE_MSM_GPIO_PINS(203); +DECLARE_MSM_GPIO_PINS(204); +DECLARE_MSM_GPIO_PINS(205); +DECLARE_MSM_GPIO_PINS(206); +DECLARE_MSM_GPIO_PINS(207); +DECLARE_MSM_GPIO_PINS(208); +DECLARE_MSM_GPIO_PINS(209); +DECLARE_MSM_GPIO_PINS(210); +DECLARE_MSM_GPIO_PINS(211); +DECLARE_MSM_GPIO_PINS(212); +DECLARE_MSM_GPIO_PINS(213); +DECLARE_MSM_GPIO_PINS(214); +DECLARE_MSM_GPIO_PINS(215); +DECLARE_MSM_GPIO_PINS(216); + +static const unsigned int ufs_reset_pins[] = { 217 }; +static const unsigned int sdc2_clk_pins[] = { 218 }; +static const unsigned int sdc2_cmd_pins[] = { 219 }; +static const unsigned int sdc2_data_pins[] = { 220 }; + +enum kaanapali_functions { + msm_mux_gpio, + msm_mux_aoss_cti, + msm_mux_atest_char, + msm_mux_atest_usb, + msm_mux_audio_ext_mclk0, + msm_mux_audio_ext_mclk1, + msm_mux_audio_ref_clk, + msm_mux_cam_asc_mclk2, + msm_mux_cam_asc_mclk4, + msm_mux_cam_mclk, + msm_mux_cci_async_in, + msm_mux_cci_i2c_scl, + msm_mux_cci_i2c_sda, + msm_mux_cci_timer, + msm_mux_cmu_rng, + msm_mux_coex_uart1_rx, + msm_mux_coex_uart1_tx, + msm_mux_coex_uart2_rx, + msm_mux_coex_uart2_tx, + msm_mux_dbg_out_clk, + msm_mux_ddr_bist_complete, + msm_mux_ddr_bist_fail, + msm_mux_ddr_bist_start, + msm_mux_ddr_bist_stop, + msm_mux_ddr_pxi0, + msm_mux_ddr_pxi1, + msm_mux_ddr_pxi2, + msm_mux_ddr_pxi3, + msm_mux_dp_hot, + msm_mux_egpio, + msm_mux_gcc_gp1, + msm_mux_gcc_gp2, + msm_mux_gcc_gp3, + msm_mux_gnss_adc0, + msm_mux_gnss_adc1, + msm_mux_i2chub0_se0, + msm_mux_i2chub0_se1, + msm_mux_i2chub0_se2, + msm_mux_i2chub0_se3, + msm_mux_i2chub0_se4, + msm_mux_i2s0_data0, + msm_mux_i2s0_data1, + msm_mux_i2s0_sck, + msm_mux_i2s0_ws, + msm_mux_i2s1_data0, + msm_mux_i2s1_data1, + msm_mux_i2s1_sck, + msm_mux_i2s1_ws, + msm_mux_ibi_i3c, + msm_mux_jitter_bist, + msm_mux_mdp_esync0_out, + msm_mux_mdp_esync1_out, + msm_mux_mdp_vsync, + msm_mux_mdp_vsync0_out, + msm_mux_mdp_vsync1_out, + msm_mux_mdp_vsync2_out, + msm_mux_mdp_vsync3_out, + msm_mux_mdp_vsync5_out, + msm_mux_mdp_vsync_e, + msm_mux_nav_gpio0, + msm_mux_nav_gpio1, + msm_mux_nav_gpio2, + msm_mux_nav_gpio3, + msm_mux_pcie0_clk_req_n, + msm_mux_phase_flag, + msm_mux_pll_bist_sync, + msm_mux_pll_clk_aux, + msm_mux_prng_rosc0, + msm_mux_prng_rosc1, + msm_mux_prng_rosc2, + msm_mux_prng_rosc3, + msm_mux_qdss_cti, + msm_mux_qdss_gpio_traceclk, + msm_mux_qdss_gpio_tracectl, + msm_mux_qdss_gpio_tracedata, + msm_mux_qlink_big_enable, + msm_mux_qlink_big_request, + msm_mux_qlink_little_enable, + msm_mux_qlink_little_request, + msm_mux_qlink_wmss, + msm_mux_qspi0, + msm_mux_qspi1, + msm_mux_qspi2, + msm_mux_qspi3, + msm_mux_qspi_clk, + msm_mux_qspi_cs, + msm_mux_qup1_se0, + msm_mux_qup1_se1, + msm_mux_qup1_se2, + msm_mux_qup1_se3, + msm_mux_qup1_se4, + msm_mux_qup1_se5, + msm_mux_qup1_se6, + msm_mux_qup1_se7, + msm_mux_qup2_se0, + msm_mux_qup2_se1, + msm_mux_qup2_se2, + msm_mux_qup2_se3, + msm_mux_qup2_se4, + msm_mux_qup3_se0, + msm_mux_qup3_se1, + msm_mux_qup3_se2, + msm_mux_qup3_se3, + msm_mux_qup3_se4, + msm_mux_qup3_se5, + msm_mux_qup4_se0, + msm_mux_qup4_se1, + msm_mux_qup4_se2, + msm_mux_qup4_se3, + msm_mux_qup4_se4, + msm_mux_sd_write_protect, + msm_mux_sdc40, + msm_mux_sdc41, + msm_mux_sdc42, + msm_mux_sdc43, + msm_mux_sdc4_clk, + msm_mux_sdc4_cmd, + msm_mux_sys_throttle, + msm_mux_tb_trig_sdc2, + msm_mux_tb_trig_sdc4, + msm_mux_tmess_prng0, + msm_mux_tmess_prng1, + msm_mux_tmess_prng2, + msm_mux_tmess_prng3, + msm_mux_tsense_pwm1, + msm_mux_tsense_pwm2, + msm_mux_tsense_pwm3, + msm_mux_tsense_pwm4, + msm_mux_tsense_pwm5, + msm_mux_tsense_pwm6, + msm_mux_tsense_pwm7, + msm_mux_uim0_clk, + msm_mux_uim0_data, + msm_mux_uim0_present, + msm_mux_uim0_reset, + msm_mux_uim1_clk, + msm_mux_uim1_data, + msm_mux_uim1_present, + msm_mux_uim1_reset, + msm_mux_usb0_hs, + msm_mux_usb_phy, + msm_mux_vfr_0, + msm_mux_vfr_1, + msm_mux_vsense_trigger_mirnat, + msm_mux_wcn_sw, + msm_mux_wcn_sw_ctrl, + msm_mux__, +}; + +static const char *const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", + "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", + "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", + "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", + "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", + "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", + "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", + "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", + "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59", + "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", + "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", + "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", + "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", + "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", + "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101", + "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107", + "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113", + "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119", + "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125", + "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", + "gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137", + "gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143", + "gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149", + "gpio150", "gpio151", "gpio152", "gpio153", "gpio154", "gpio155", + "gpio156", "gpio157", "gpio158", "gpio159", "gpio160", "gpio161", + "gpio162", "gpio163", "gpio164", "gpio165", "gpio166", "gpio167", + "gpio168", "gpio169", "gpio170", "gpio171", "gpio172", "gpio173", + "gpio174", "gpio175", "gpio176", "gpio177", "gpio178", "gpio179", + "gpio180", "gpio181", "gpio182", "gpio183", "gpio184", "gpio185", + "gpio186", "gpio187", "gpio188", "gpio189", "gpio190", "gpio191", + "gpio192", "gpio193", "gpio194", "gpio195", "gpio196", "gpio197", + "gpio198", "gpio199", "gpio200", "gpio201", "gpio202", "gpio203", + "gpio204", "gpio205", "gpio206", "gpio207", "gpio208", "gpio209", + "gpio210", "gpio211", "gpio212", "gpio213", "gpio214", "gpio215", + "gpio216", +}; + +static const char *const aoss_cti_groups[] = { + "gpio74", "gpio75", "gpio76", "gpio77", +}; + +static const char *const atest_char_groups[] = { + "gpio126", "gpio127", "gpio128", "gpio129", "gpio133", +}; + +static const char *const atest_usb_groups[] = { + "gpio70", "gpio71", "gpio72", "gpio73", "gpio129", +}; + +static const char *const audio_ext_mclk0_groups[] = { + "gpio121", +}; + +static const char *const audio_ext_mclk1_groups[] = { + "gpio120", +}; + +static const char *const audio_ref_clk_groups[] = { + "gpio120", +}; + +static const char *const cam_asc_mclk2_groups[] = { + "gpio91", +}; + +static const char *const cam_asc_mclk4_groups[] = { + "gpio93", +}; + +static const char *const cam_mclk_groups[] = { + "gpio89", "gpio90", "gpio92", "gpio94", "gpio95", "gpio96", +}; + +static const char *const cci_async_in_groups[] = { + "gpio10", "gpio11", "gpio15", +}; + +static const char *const cci_i2c_scl_groups[] = { + "gpio110", "gpio112", "gpio114", "gpio116", "gpio149", "gpio160", +}; + +static const char *const cci_i2c_sda_groups[] = { + "gpio107", "gpio108", "gpio109", "gpio111", "gpio113", "gpio115", +}; + +static const char *const cci_timer_groups[] = { + "gpio105", "gpio106", "gpio107", "gpio159", "gpio160", +}; + +static const char *const cmu_rng_groups[] = { + "gpio40", "gpio41", "gpio42", "gpio43", "gpio144", "gpio145", + "gpio146", "gpio147", +}; + +static const char *const coex_uart1_rx_groups[] = { + "gpio144", +}; + +static const char *const coex_uart1_tx_groups[] = { + "gpio145", +}; + +static const char *const coex_uart2_rx_groups[] = { + "gpio146", +}; + +static const char *const coex_uart2_tx_groups[] = { + "gpio147", +}; + +static const char *const dbg_out_clk_groups[] = { + "gpio42", +}; + +static const char *const ddr_bist_complete_groups[] = { + "gpio44", +}; + +static const char *const ddr_bist_fail_groups[] = { + "gpio40", +}; + +static const char *const ddr_bist_start_groups[] = { + "gpio41", +}; + +static const char *const ddr_bist_stop_groups[] = { + "gpio45", +}; + +static const char *const ddr_pxi0_groups[] = { + "gpio54", "gpio55", +}; + +static const char *const ddr_pxi1_groups[] = { + "gpio44", "gpio45", +}; + +static const char *const ddr_pxi2_groups[] = { + "gpio43", "gpio52", +}; + +static const char *const ddr_pxi3_groups[] = { + "gpio46", "gpio53", +}; + +static const char *const dp_hot_groups[] = { + "gpio47", +}; + +static const char *const egpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", + "gpio6", "gpio7", "gpio28", "gpio29", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio163", "gpio164", "gpio165", "gpio166", + "gpio167", "gpio168", "gpio169", "gpio170", "gpio171", "gpio172", + "gpio173", "gpio174", "gpio175", "gpio176", "gpio177", "gpio178", + "gpio179", "gpio180", "gpio181", "gpio182", "gpio183", "gpio184", + "gpio185", "gpio186", "gpio187", "gpio188", "gpio189", "gpio190", + "gpio191", "gpio192", "gpio193", "gpio194", "gpio195", "gpio196", + "gpio197", "gpio198", "gpio199", "gpio200", "gpio201", "gpio202", + "gpio203", "gpio204", "gpio205", "gpio206", "gpio207", "gpio208", + "gpio209", "gpio210", "gpio211", "gpio212", "gpio213", "gpio214", + "gpio215", "gpio216", +}; + +static const char *const gcc_gp1_groups[] = { + "gpio130", "gpio158", +}; + +static const char *const gcc_gp2_groups[] = { + "gpio86", "gpio131", +}; + +static const char *const gcc_gp3_groups[] = { + "gpio87", "gpio132", +}; + +static const char *const gnss_adc0_groups[] = { + "gpio40", "gpio41", +}; + +static const char *const gnss_adc1_groups[] = { + "gpio42", "gpio77", +}; + +static const char *const i2chub0_se0_groups[] = { + "gpio66", "gpio67", +}; + +static const char *const i2chub0_se1_groups[] = { + "gpio78", "gpio79", +}; + +static const char *const i2chub0_se2_groups[] = { + "gpio68", "gpio69", +}; + +static const char *const i2chub0_se3_groups[] = { + "gpio70", "gpio71", +}; + +static const char *const i2chub0_se4_groups[] = { + "gpio72", "gpio73", +}; + +static const char *const i2s0_data0_groups[] = { + "gpio123", +}; + +static const char *const i2s0_data1_groups[] = { + "gpio124", +}; + +static const char *const i2s0_sck_groups[] = { + "gpio122", +}; + +static const char *const i2s0_ws_groups[] = { + "gpio125", +}; + +static const char *const i2s1_data0_groups[] = { + "gpio118", +}; + +static const char *const i2s1_data1_groups[] = { + "gpio120", +}; + +static const char *const i2s1_sck_groups[] = { + "gpio117", +}; + +static const char *const i2s1_ws_groups[] = { + "gpio119", +}; + +static const char *const ibi_i3c_groups[] = { + "gpio0", "gpio1", "gpio4", "gpio5", "gpio8", "gpio9", + "gpio12", "gpio13", "gpio28", "gpio29", "gpio32", "gpio33", + "gpio36", "gpio37", "gpio48", "gpio49", "gpio60", "gpio61", +}; + +static const char *const jitter_bist_groups[] = { + "gpio73", +}; + +static const char *const mdp_esync0_out_groups[] = { + "gpio88", +}; + +static const char *const mdp_esync1_out_groups[] = { + "gpio100", +}; + +static const char *const mdp_vsync_groups[] = { + "gpio86", "gpio87", "gpio97", "gpio98", +}; + +static const char *const mdp_vsync0_out_groups[] = { + "gpio86", +}; + +static const char *const mdp_vsync1_out_groups[] = { + "gpio86", +}; + +static const char *const mdp_vsync2_out_groups[] = { + "gpio87", +}; + +static const char *const mdp_vsync3_out_groups[] = { + "gpio87", +}; + +static const char *const mdp_vsync5_out_groups[] = { + "gpio87", +}; + +static const char *const mdp_vsync_e_groups[] = { + "gpio88", +}; + +static const char *const nav_gpio0_groups[] = { + "gpio150", +}; + +static const char *const nav_gpio1_groups[] = { + "gpio151", +}; + +static const char *const nav_gpio2_groups[] = { + "gpio148", +}; + +static const char *const nav_gpio3_groups[] = { + "gpio150", +}; + +static const char *const pcie0_clk_req_n_groups[] = { + "gpio103", +}; + +static const char *const phase_flag_groups[] = { + "gpio117", "gpio118", "gpio119", "gpio123", "gpio124", "gpio125", + "gpio169", "gpio170", "gpio171", "gpio172", "gpio173", "gpio175", + "gpio176", "gpio179", "gpio180", "gpio181", "gpio184", "gpio185", + "gpio192", "gpio196", "gpio197", "gpio198", "gpio199", "gpio204", + "gpio206", "gpio207", "gpio208", "gpio210", "gpio211", "gpio214", + "gpio215", "gpio216", +}; + +static const char *const pll_bist_sync_groups[] = { + "gpio104", +}; + +static const char *const pll_clk_aux_groups[] = { + "gpio94", +}; + +static const char *const prng_rosc0_groups[] = { + "gpio85", +}; + +static const char *const prng_rosc1_groups[] = { + "gpio64", +}; + +static const char *const prng_rosc2_groups[] = { + "gpio65", +}; + +static const char *const prng_rosc3_groups[] = { + "gpio66", +}; + +static const char *const qdss_cti_groups[] = { + "gpio27", "gpio31", "gpio72", "gpio73", "gpio82", "gpio83", + "gpio155", "gpio158", +}; + +static const char *const qdss_gpio_traceclk_groups[] = { + "gpio128", +}; + +static const char *const qdss_gpio_tracectl_groups[] = { + "gpio127", +}; + +static const char *const qdss_gpio_tracedata_groups[] = { + "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", + "gpio62", "gpio63", "gpio68", "gpio69", "gpio126", "gpio129", + "gpio130", "gpio131", "gpio132", "gpio133", +}; + +static const char *const qlink_big_enable_groups[] = { + "gpio156", +}; + +static const char *const qlink_big_request_groups[] = { + "gpio155", +}; + +static const char *const qlink_little_enable_groups[] = { + "gpio153", +}; + +static const char *const qlink_little_request_groups[] = { + "gpio152", +}; + +static const char *const qlink_wmss_groups[] = { + "gpio154", +}; + +static const char *const qspi0_groups[] = { + "gpio80", +}; + +static const char *const qspi1_groups[] = { + "gpio147", +}; + +static const char *const qspi2_groups[] = { + "gpio81", +}; + +static const char *const qspi3_groups[] = { + "gpio82", +}; + +static const char *const qspi_clk_groups[] = { + "gpio83", +}; + +static const char *const qspi_cs_groups[] = { + "gpio146", "gpio148", +}; + +static const char *const qup1_se0_groups[] = { + "gpio80", "gpio81", "gpio82", "gpio83", +}; + +static const char *const qup1_se1_groups[] = { + "gpio74", "gpio75", "gpio76", "gpio77", +}; + +static const char *const qup1_se2_groups[] = { + "gpio40", "gpio41", "gpio42", "gpio43", "gpio130", "gpio131", "gpio132", +}; + +static const char *const qup1_se3_groups[] = { + "gpio44", "gpio45", "gpio46", "gpio47", +}; + +static const char *const qup1_se4_groups[] = { + "gpio36", "gpio37", "gpio38", "gpio39", +}; + +static const char *const qup1_se5_groups[] = { + "gpio52", "gpio53", "gpio54", "gpio55", +}; + +static const char *const qup1_se6_groups[] = { + "gpio56", "gpio57", "gpio58", "gpio59", +}; + +static const char *const qup1_se7_groups[] = { + "gpio60", "gpio61", "gpio62", "gpio63", +}; + +static const char *const qup2_se0_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", +}; + +static const char *const qup2_se1_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; + +static const char *const qup2_se2_groups[] = { + "gpio117", "gpio118", "gpio119", "gpio120", +}; + +static const char *const qup2_se3_groups[] = { + "gpio122", "gpio123", "gpio124", "gpio125", +}; + +static const char *const qup2_se4_groups[] = { + "gpio208", "gpio209", +}; + +static const char *const qup3_se0_groups[] = { + "gpio64", "gpio65", +}; + +static const char *const qup3_se1_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio15", +}; + +static const char *const qup3_se2_groups[] = { + "gpio12", "gpio13", "gpio14", "gpio15", +}; + +static const char *const qup3_se3_groups[] = { + "gpio16", "gpio17", "gpio18", "gpio19", +}; + +static const char *const qup3_se4_groups[] = { + "gpio20", "gpio21", "gpio22", "gpio23", +}; + +static const char *const qup3_se5_groups[] = { + "gpio24", "gpio25", "gpio26", "gpio27", +}; + +static const char *const qup4_se0_groups[] = { + "gpio48", "gpio49", "gpio50", "gpio51", +}; + +static const char *const qup4_se1_groups[] = { + "gpio28", "gpio29", "gpio30", "gpio31", +}; + +static const char *const qup4_se2_groups[] = { + "gpio32", "gpio33", "gpio34", "gpio35", +}; + +static const char *const qup4_se3_groups[] = { + "gpio84", "gpio121", +}; + +static const char *const qup4_se4_groups[] = { + "gpio161", "gpio162", +}; + +static const char *const sd_write_protect_groups[] = { + "gpio85", +}; + +static const char *const sdc40_groups[] = { + "gpio80", +}; + +static const char *const sdc41_groups[] = { + "gpio147", +}; + +static const char *const sdc42_groups[] = { + "gpio81", +}; + +static const char *const sdc43_groups[] = { + "gpio82", +}; + +static const char *const sdc4_clk_groups[] = { + "gpio83", +}; + +static const char *const sdc4_cmd_groups[] = { + "gpio148", +}; + +static const char *const sys_throttle_groups[] = { + "gpio99", +}; + +static const char *const tb_trig_sdc2_groups[] = { + "gpio88", +}; + +static const char *const tb_trig_sdc4_groups[] = { + "gpio146", +}; + +static const char *const tmess_prng0_groups[] = { + "gpio85", +}; + +static const char *const tmess_prng1_groups[] = { + "gpio64", +}; + +static const char *const tmess_prng2_groups[] = { + "gpio65", +}; + +static const char *const tmess_prng3_groups[] = { + "gpio66", +}; + +static const char *const tsense_pwm1_groups[] = { + "gpio87", +}; + +static const char *const tsense_pwm2_groups[] = { + "gpio10", +}; + +static const char *const tsense_pwm3_groups[] = { + "gpio97", +}; + +static const char *const tsense_pwm4_groups[] = { + "gpio99", +}; + +static const char *const tsense_pwm5_groups[] = { + "gpio105", +}; + +static const char *const tsense_pwm6_groups[] = { + "gpio106", +}; + +static const char *const tsense_pwm7_groups[] = { + "gpio159", +}; + +static const char *const uim0_clk_groups[] = { + "gpio127", +}; + +static const char *const uim0_data_groups[] = { + "gpio126", +}; + +static const char *const uim0_present_groups[] = { + "gpio129", +}; + +static const char *const uim0_reset_groups[] = { + "gpio128", +}; + +static const char *const uim1_clk_groups[] = { + "gpio37", "gpio55", "gpio71", "gpio131", +}; + +static const char *const uim1_data_groups[] = { + "gpio36", "gpio54", "gpio70", "gpio130", +}; + +static const char *const uim1_present_groups[] = { + "gpio133", +}; + +static const char *const uim1_reset_groups[] = { + "gpio39", "gpio56", "gpio72", "gpio132", +}; + +static const char *const usb0_hs_groups[] = { + "gpio79", +}; + +static const char *const usb_phy_groups[] = { + "gpio59", "gpio60", +}; + +static const char *const vfr_0_groups[] = { + "gpio146", +}; + +static const char *const vfr_1_groups[] = { + "gpio151", +}; + +static const char *const vsense_trigger_mirnat_groups[] = { + "gpio59", +}; + +static const char *const wcn_sw_groups[] = { + "gpio19", +}; + +static const char *const wcn_sw_ctrl_groups[] = { + "gpio18", +}; + +static const struct pinfunction kaanapali_functions[] = { + MSM_GPIO_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ext_mclk0), + MSM_PIN_FUNCTION(audio_ext_mclk1), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(cam_asc_mclk2), + MSM_PIN_FUNCTION(cam_asc_mclk4), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async_in), + MSM_PIN_FUNCTION(cci_i2c_scl), + MSM_PIN_FUNCTION(cci_i2c_sda), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1_rx), + MSM_PIN_FUNCTION(coex_uart1_tx), + MSM_PIN_FUNCTION(coex_uart2_rx), + MSM_PIN_FUNCTION(coex_uart2_tx), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist_complete), + MSM_PIN_FUNCTION(ddr_bist_fail), + MSM_PIN_FUNCTION(ddr_bist_start), + MSM_PIN_FUNCTION(ddr_bist_stop), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gnss_adc0), + MSM_PIN_FUNCTION(gnss_adc1), + MSM_PIN_FUNCTION(i2chub0_se0), + MSM_PIN_FUNCTION(i2chub0_se1), + MSM_PIN_FUNCTION(i2chub0_se2), + MSM_PIN_FUNCTION(i2chub0_se3), + MSM_PIN_FUNCTION(i2chub0_se4), + MSM_PIN_FUNCTION(i2s0_data0), + MSM_PIN_FUNCTION(i2s0_data1), + MSM_PIN_FUNCTION(i2s0_sck), + MSM_PIN_FUNCTION(i2s0_ws), + MSM_PIN_FUNCTION(i2s1_data0), + MSM_PIN_FUNCTION(i2s1_data1), + MSM_PIN_FUNCTION(i2s1_sck), + MSM_PIN_FUNCTION(i2s1_ws), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_esync0_out), + MSM_PIN_FUNCTION(mdp_esync1_out), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0_out), + MSM_PIN_FUNCTION(mdp_vsync1_out), + MSM_PIN_FUNCTION(mdp_vsync2_out), + MSM_PIN_FUNCTION(mdp_vsync3_out), + MSM_PIN_FUNCTION(mdp_vsync5_out), + MSM_PIN_FUNCTION(mdp_vsync_e), + MSM_PIN_FUNCTION(nav_gpio0), + MSM_PIN_FUNCTION(nav_gpio1), + MSM_PIN_FUNCTION(nav_gpio2), + MSM_PIN_FUNCTION(nav_gpio3), + MSM_PIN_FUNCTION(pcie0_clk_req_n), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist_sync), + MSM_PIN_FUNCTION(pll_clk_aux), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio_traceclk), + MSM_PIN_FUNCTION(qdss_gpio_tracectl), + MSM_PIN_FUNCTION(qdss_gpio_tracedata), + MSM_PIN_FUNCTION(qlink_big_enable), + MSM_PIN_FUNCTION(qlink_big_request), + MSM_PIN_FUNCTION(qlink_little_enable), + MSM_PIN_FUNCTION(qlink_little_request), + MSM_PIN_FUNCTION(qlink_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup1_se7), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup3_se0), + MSM_PIN_FUNCTION(qup3_se1), + MSM_PIN_FUNCTION(qup3_se2), + MSM_PIN_FUNCTION(qup3_se3), + MSM_PIN_FUNCTION(qup3_se4), + MSM_PIN_FUNCTION(qup3_se5), + MSM_PIN_FUNCTION(qup4_se0), + MSM_PIN_FUNCTION(qup4_se1), + MSM_PIN_FUNCTION(qup4_se2), + MSM_PIN_FUNCTION(qup4_se3), + MSM_PIN_FUNCTION(qup4_se4), + MSM_PIN_FUNCTION(sd_write_protect), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sys_throttle), + MSM_PIN_FUNCTION(tb_trig_sdc2), + MSM_PIN_FUNCTION(tb_trig_sdc4), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(tsense_pwm5), + MSM_PIN_FUNCTION(tsense_pwm6), + MSM_PIN_FUNCTION(tsense_pwm7), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb0_hs), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), + MSM_PIN_FUNCTION(wcn_sw), + MSM_PIN_FUNCTION(wcn_sw_ctrl), +}; + +/* Every pin is maintained as a single group, and missing or non-existing pin + * would be maintained as dummy group to synchronize pin group index with + * pin descriptor registered with pinctrl core. + * Clients would not be able to request these dummy pin groups. + */ +static const struct msm_pingroup kaanapali_groups[] = { + [0] = PINGROUP(0, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [1] = PINGROUP(1, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [2] = PINGROUP(2, qup2_se0, _, _, _, _, _, _, _, _, _, egpio), + [3] = PINGROUP(3, qup2_se0, _, _, _, _, _, _, _, _, _, egpio), + [4] = PINGROUP(4, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [5] = PINGROUP(5, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [6] = PINGROUP(6, qup2_se1, _, _, _, _, _, _, _, _, _, egpio), + [7] = PINGROUP(7, qup2_se1, _, _, _, _, _, _, _, _, _, egpio), + [8] = PINGROUP(8, qup3_se1, ibi_i3c, _, _, _, _, _, _, _, _, _), + [9] = PINGROUP(9, qup3_se1, ibi_i3c, _, _, _, _, _, _, _, _, _), + [10] = PINGROUP(10, qup3_se1, cci_async_in, _, tsense_pwm2, _, _, _, _, _, _, _), + [11] = PINGROUP(11, qup3_se1, cci_async_in, _, _, _, _, _, _, _, _, _), + [12] = PINGROUP(12, qup3_se2, ibi_i3c, qup3_se1, _, _, _, _, _, _, _, _), + [13] = PINGROUP(13, qup3_se2, ibi_i3c, qup3_se1, _, _, _, _, _, _, _, _), + [14] = PINGROUP(14, qup3_se2, _, _, _, _, _, _, _, _, _, _), + [15] = PINGROUP(15, qup3_se2, cci_async_in, qup3_se1, _, _, _, _, _, _, _, _), + [16] = PINGROUP(16, qup3_se3, _, _, _, _, _, _, _, _, _, _), + [17] = PINGROUP(17, qup3_se3, _, _, _, _, _, _, _, _, _, _), + [18] = PINGROUP(18, wcn_sw_ctrl, qup3_se3, _, _, _, _, _, _, _, _, _), + [19] = PINGROUP(19, wcn_sw, qup3_se3, _, _, _, _, _, _, _, _, _), + [20] = PINGROUP(20, qup3_se4, _, _, _, _, _, _, _, _, _, _), + [21] = PINGROUP(21, qup3_se4, _, _, _, _, _, _, _, _, _, _), + [22] = PINGROUP(22, qup3_se4, _, _, _, _, _, _, _, _, _, _), + [23] = PINGROUP(23, qup3_se4, _, _, _, _, _, _, _, _, _, _), + [24] = PINGROUP(24, qup3_se5, _, _, _, _, _, _, _, _, _, _), + [25] = PINGROUP(25, qup3_se5, _, _, _, _, _, _, _, _, _, _), + [26] = PINGROUP(26, qup3_se5, _, _, _, _, _, _, _, _, _, _), + [27] = PINGROUP(27, qup3_se5, qdss_cti, _, _, _, _, _, _, _, _, _), + [28] = PINGROUP(28, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [29] = PINGROUP(29, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [30] = PINGROUP(30, qup4_se1, _, _, _, _, _, _, _, _, _, _), + [31] = PINGROUP(31, qup4_se1, qdss_cti, _, _, _, _, _, _, _, _, _), + [32] = PINGROUP(32, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _), + [33] = PINGROUP(33, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _), + [34] = PINGROUP(34, qup4_se2, _, _, _, _, _, _, _, _, _, _), + [35] = PINGROUP(35, qup4_se2, _, _, _, _, _, _, _, _, _, _), + [36] = PINGROUP(36, qup1_se4, uim1_data, ibi_i3c, _, _, _, _, _, _, _, _), + [37] = PINGROUP(37, qup1_se4, uim1_clk, ibi_i3c, _, _, _, _, _, _, _, _), + [38] = PINGROUP(38, qup1_se4, qdss_gpio_tracedata, _, _, _, _, _, _, _, _, _), + [39] = PINGROUP(39, qup1_se4, uim1_reset, qdss_gpio_tracedata, _, _, _, _, _, _, _, _), + [40] = PINGROUP(40, qup1_se2, cmu_rng, ddr_bist_fail, _, qdss_gpio_tracedata, gnss_adc0, + _, _, _, _, _), + [41] = PINGROUP(41, qup1_se2, cmu_rng, ddr_bist_start, _, qdss_gpio_tracedata, gnss_adc0, + _, _, _, _, _), + [42] = PINGROUP(42, qup1_se2, cmu_rng, dbg_out_clk, qdss_gpio_tracedata, gnss_adc1, _, _, + _, _, _, _), + [43] = PINGROUP(43, qup1_se2, cmu_rng, _, qdss_gpio_tracedata, ddr_pxi2, _, _, _, _, _, _), + [44] = PINGROUP(44, qup1_se3, ddr_bist_complete, ddr_pxi1, _, _, _, _, _, _, _, _), + [45] = PINGROUP(45, qup1_se3, ddr_bist_stop, ddr_pxi1, _, _, _, _, _, _, _, _), + [46] = PINGROUP(46, qup1_se3, ddr_pxi3, _, _, _, _, _, _, _, _, _), + [47] = PINGROUP(47, qup1_se3, dp_hot, _, _, _, _, _, _, _, _, _), + [48] = PINGROUP(48, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [49] = PINGROUP(49, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio), + [50] = PINGROUP(50, qup4_se0, _, _, _, _, _, _, _, _, _, egpio), + [51] = PINGROUP(51, qup4_se0, _, _, _, _, _, _, _, _, _, egpio), + [52] = PINGROUP(52, qup1_se5, ddr_pxi2, _, _, _, _, _, _, _, _, _), + [53] = PINGROUP(53, qup1_se5, _, ddr_pxi3, _, _, _, _, _, _, _, _), + [54] = PINGROUP(54, qup1_se5, uim1_data, ddr_pxi0, _, _, _, _, _, _, _, _), + [55] = PINGROUP(55, qup1_se5, uim1_clk, ddr_pxi0, _, _, _, _, _, _, _, _), + [56] = PINGROUP(56, qup1_se6, uim1_reset, _, _, _, _, _, _, _, _, _), + [57] = PINGROUP(57, qup1_se6, _, _, _, _, _, _, _, _, _, _), + [58] = PINGROUP(58, qup1_se6, _, _, _, _, _, _, _, _, _, _), + [59] = PINGROUP(59, qup1_se6, usb_phy, vsense_trigger_mirnat, _, _, _, _, _, _, _, _), + [60] = PINGROUP(60, qup1_se7, usb_phy, ibi_i3c, _, _, _, _, _, _, _, _), + [61] = PINGROUP(61, qup1_se7, ibi_i3c, _, _, _, _, _, _, _, _, _), + [62] = PINGROUP(62, qup1_se7, qdss_gpio_tracedata, _, _, _, _, _, _, _, _, _), + [63] = PINGROUP(63, qup1_se7, qdss_gpio_tracedata, _, _, _, _, _, _, _, _, _), + [64] = PINGROUP(64, qup3_se0, _, prng_rosc1, tmess_prng1, _, _, _, _, _, _, _), + [65] = PINGROUP(65, qup3_se0, _, prng_rosc2, tmess_prng2, _, _, _, _, _, _, _), + [66] = PINGROUP(66, i2chub0_se0, prng_rosc3, tmess_prng3, _, _, _, _, _, _, _, _), + [67] = PINGROUP(67, i2chub0_se0, _, _, _, _, _, _, _, _, _, _), + [68] = PINGROUP(68, i2chub0_se2, qdss_gpio_tracedata, _, _, _, _, _, _, _, _, _), + [69] = PINGROUP(69, i2chub0_se2, qdss_gpio_tracedata, _, _, _, _, _, _, _, _, _), + [70] = PINGROUP(70, i2chub0_se3, uim1_data, _, atest_usb, _, _, _, _, _, _, _), + [71] = PINGROUP(71, i2chub0_se3, uim1_clk, _, atest_usb, _, _, _, _, _, _, _), + [72] = PINGROUP(72, i2chub0_se4, uim1_reset, qdss_cti, _, atest_usb, _, _, _, _, _, _), + [73] = PINGROUP(73, i2chub0_se4, qdss_cti, jitter_bist, atest_usb, _, _, _, _, _, _, _), + [74] = PINGROUP(74, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _), + [76] = PINGROUP(76, qup1_se1, aoss_cti, _, _, _, _, _, _, _, _, _), + [77] = PINGROUP(77, qup1_se1, aoss_cti, gnss_adc1, _, _, _, _, _, _, _, _), + [78] = PINGROUP(78, i2chub0_se1, _, _, _, _, _, _, _, _, _, _), + [79] = PINGROUP(79, i2chub0_se1, usb0_hs, _, _, _, _, _, _, _, _, _), + [80] = PINGROUP(80, qup1_se0, sdc40, qspi0, _, _, _, _, _, _, _, _), + [81] = PINGROUP(81, qup1_se0, sdc42, qspi2, _, _, _, _, _, _, _, _), + [82] = PINGROUP(82, qup1_se0, sdc43, qdss_cti, qspi3, _, _, _, _, _, _, _), + [83] = PINGROUP(83, qup1_se0, sdc4_clk, qdss_cti, qspi_clk, _, _, _, _, _, _, _), + [84] = PINGROUP(84, qup4_se3, _, _, _, _, _, _, _, _, _, _), + [85] = PINGROUP(85, sd_write_protect, prng_rosc0, tmess_prng0, _, _, _, _, _, _, _, _), + [86] = PINGROUP(86, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out, gcc_gp2, _, _, _, _, _, _, + _), + [87] = PINGROUP(87, mdp_vsync, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out, gcc_gp3, _, + tsense_pwm1, _, _, _, _), + [88] = PINGROUP(88, mdp_vsync_e, mdp_esync0_out, tb_trig_sdc2, _, _, _, _, _, _, _, _), + [89] = PINGROUP(89, cam_mclk, _, _, _, _, _, _, _, _, _, _), + [90] = PINGROUP(90, cam_mclk, _, _, _, _, _, _, _, _, _, _), + [91] = PINGROUP(91, cam_asc_mclk2, _, _, _, _, _, _, _, _, _, _), + [92] = PINGROUP(92, cam_mclk, _, _, _, _, _, _, _, _, _, _), + [93] = PINGROUP(93, cam_asc_mclk4, _, _, _, _, _, _, _, _, _, _), + [94] = PINGROUP(94, cam_mclk, pll_clk_aux, _, _, _, _, _, _, _, _, _), + [95] = PINGROUP(95, cam_mclk, _, _, _, _, _, _, _, _, _, _), + [96] = PINGROUP(96, cam_mclk, _, _, _, _, _, _, _, _, _, _), + [97] = PINGROUP(97, mdp_vsync, tsense_pwm3, _, _, _, _, _, _, _, _, _), + [98] = PINGROUP(98, mdp_vsync, _, _, _, _, _, _, _, _, _, _), + [99] = PINGROUP(99, sys_throttle, tsense_pwm4, _, _, _, _, _, _, _, _, _), + [100] = PINGROUP(100, mdp_esync1_out, _, _, _, _, _, _, _, _, _, _), + [101] = PINGROUP(101, _, _, _, _, _, _, _, _, _, _, _), + [102] = PINGROUP(102, _, _, _, _, _, _, _, _, _, _, _), + [103] = PINGROUP(103, pcie0_clk_req_n, _, _, _, _, _, _, _, _, _, _), + [104] = PINGROUP(104, pll_bist_sync, _, _, _, _, _, _, _, _, _, _), + [105] = PINGROUP(105, cci_timer, tsense_pwm5, _, _, _, _, _, _, _, _, _), + [106] = PINGROUP(106, cci_timer, tsense_pwm6, _, _, _, _, _, _, _, _, _), + [107] = PINGROUP(107, cci_timer, cci_i2c_sda, _, _, _, _, _, _, _, _, _), + [108] = PINGROUP(108, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _), + [109] = PINGROUP(109, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _), + [110] = PINGROUP(110, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _), + [111] = PINGROUP(111, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _), + [112] = PINGROUP(112, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _), + [113] = PINGROUP(113, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _), + [114] = PINGROUP(114, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _), + [115] = PINGROUP(115, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _), + [116] = PINGROUP(116, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _), + [117] = PINGROUP(117, i2s1_sck, qup2_se2, phase_flag, _, _, _, _, _, _, _, _), + [118] = PINGROUP(118, i2s1_data0, qup2_se2, phase_flag, _, _, _, _, _, _, _, _), + [119] = PINGROUP(119, i2s1_ws, qup2_se2, phase_flag, _, _, _, _, _, _, _, _), + [120] = PINGROUP(120, i2s1_data1, qup2_se2, audio_ext_mclk1, audio_ref_clk, _, _, _, _, _, + _, _), + [121] = PINGROUP(121, audio_ext_mclk0, qup4_se3, _, _, _, _, _, _, _, _, _), + [122] = PINGROUP(122, i2s0_sck, qup2_se3, _, _, _, _, _, _, _, _, _), + [123] = PINGROUP(123, i2s0_data0, qup2_se3, _, phase_flag, _, _, _, _, _, _, _), + [124] = PINGROUP(124, i2s0_data1, qup2_se3, _, phase_flag, _, _, _, _, _, _, _), + [125] = PINGROUP(125, i2s0_ws, qup2_se3, phase_flag, _, _, _, _, _, _, _, _), + [126] = PINGROUP(126, uim0_data, qdss_gpio_tracedata, atest_char, _, _, _, _, _, _, _, _), + [127] = PINGROUP(127, uim0_clk, qdss_gpio_tracectl, atest_char, _, _, _, _, _, _, _, _), + [128] = PINGROUP(128, uim0_reset, qdss_gpio_traceclk, atest_char, _, _, _, _, _, _, _, _), + [129] = PINGROUP(129, uim0_present, qdss_gpio_tracedata, atest_usb, atest_char, _, _, _, _, + _, _, _), + [130] = PINGROUP(130, uim1_data, qup1_se2, gcc_gp1, qdss_gpio_tracedata, _, _, _, _, _, _, + _), + [131] = PINGROUP(131, uim1_clk, qup1_se2, gcc_gp2, qdss_gpio_tracedata, _, _, _, _, _, _, + _), + [132] = PINGROUP(132, uim1_reset, qup1_se2, gcc_gp3, qdss_gpio_tracedata, _, _, _, _, _, _, + _), + [133] = PINGROUP(133, uim1_present, qdss_gpio_tracedata, atest_char, _, _, _, _, _, _, _, + _), + [134] = PINGROUP(134, _, _, _, _, _, _, _, _, _, _, _), + [135] = PINGROUP(135, _, _, _, _, _, _, _, _, _, _, _), + [136] = PINGROUP(136, _, _, _, _, _, _, _, _, _, _, _), + [137] = PINGROUP(137, _, _, _, _, _, _, _, _, _, _, _), + [138] = PINGROUP(138, _, _, _, _, _, _, _, _, _, _, _), + [139] = PINGROUP(139, _, _, _, _, _, _, _, _, _, _, _), + [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _, _, _), + [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _, _, _), + [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _, _, _), + [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _, _, _), + [144] = PINGROUP(144, coex_uart1_rx, cmu_rng, _, _, _, _, _, _, _, _, _), + [145] = PINGROUP(145, coex_uart1_tx, cmu_rng, _, _, _, _, _, _, _, _, _), + [146] = PINGROUP(146, _, vfr_0, coex_uart2_rx, cmu_rng, tb_trig_sdc4, qspi_cs, _, _, _, _, + _), + [147] = PINGROUP(147, _, coex_uart2_tx, cmu_rng, sdc41, qspi1, _, _, _, _, _, _), + [148] = PINGROUP(148, nav_gpio2, _, sdc4_cmd, qspi_cs, _, _, _, _, _, _, _), + [149] = PINGROUP(149, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _), + [150] = PINGROUP(150, nav_gpio0, nav_gpio3, _, _, _, _, _, _, _, _, _), + [151] = PINGROUP(151, nav_gpio1, vfr_1, _, _, _, _, _, _, _, _, _), + [152] = PINGROUP(152, qlink_little_request, _, _, _, _, _, _, _, _, _, _), + [153] = PINGROUP(153, qlink_little_enable, _, _, _, _, _, _, _, _, _, _), + [154] = PINGROUP(154, qlink_wmss, _, _, _, _, _, _, _, _, _, _), + [155] = PINGROUP(155, qlink_big_request, qdss_cti, _, _, _, _, _, _, _, _, _), + [156] = PINGROUP(156, qlink_big_enable, _, _, _, _, _, _, _, _, _, _), + [157] = PINGROUP(157, _, _, _, _, _, _, _, _, _, _, _), + [158] = PINGROUP(158, qdss_cti, gcc_gp1, _, _, _, _, _, _, _, _, _), + [159] = PINGROUP(159, cci_timer, tsense_pwm7, _, _, _, _, _, _, _, _, _), + [160] = PINGROUP(160, cci_timer, cci_i2c_scl, _, _, _, _, _, _, _, _, _), + [161] = PINGROUP(161, qup4_se4, _, _, _, _, _, _, _, _, _, _), + [162] = PINGROUP(162, qup4_se4, _, _, _, _, _, _, _, _, _, _), + [163] = PINGROUP(163, _, _, _, _, _, _, _, _, _, _, egpio), + [164] = PINGROUP(164, _, _, _, _, _, _, _, _, _, _, egpio), + [165] = PINGROUP(165, _, _, _, _, _, _, _, _, _, _, egpio), + [166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, egpio), + [167] = PINGROUP(167, _, _, _, _, _, _, _, _, _, _, egpio), + [168] = PINGROUP(168, _, _, _, _, _, _, _, _, _, _, egpio), + [169] = PINGROUP(169, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [170] = PINGROUP(170, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [171] = PINGROUP(171, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [172] = PINGROUP(172, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [173] = PINGROUP(173, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [174] = PINGROUP(174, _, _, _, _, _, _, _, _, _, _, egpio), + [175] = PINGROUP(175, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [176] = PINGROUP(176, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [177] = PINGROUP(177, _, _, _, _, _, _, _, _, _, _, egpio), + [178] = PINGROUP(178, _, _, _, _, _, _, _, _, _, _, egpio), + [179] = PINGROUP(179, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [180] = PINGROUP(180, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [181] = PINGROUP(181, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [182] = PINGROUP(182, _, _, _, _, _, _, _, _, _, _, egpio), + [183] = PINGROUP(183, _, _, _, _, _, _, _, _, _, _, egpio), + [184] = PINGROUP(184, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [185] = PINGROUP(185, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [186] = PINGROUP(186, _, _, _, _, _, _, _, _, _, _, egpio), + [187] = PINGROUP(187, _, _, _, _, _, _, _, _, _, _, egpio), + [188] = PINGROUP(188, _, _, _, _, _, _, _, _, _, _, egpio), + [189] = PINGROUP(189, _, _, _, _, _, _, _, _, _, _, egpio), + [190] = PINGROUP(190, _, _, _, _, _, _, _, _, _, _, egpio), + [191] = PINGROUP(191, _, _, _, _, _, _, _, _, _, _, egpio), + [192] = PINGROUP(192, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [193] = PINGROUP(193, _, _, _, _, _, _, _, _, _, _, egpio), + [194] = PINGROUP(194, _, _, _, _, _, _, _, _, _, _, egpio), + [195] = PINGROUP(195, _, _, _, _, _, _, _, _, _, _, egpio), + [196] = PINGROUP(196, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [197] = PINGROUP(197, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [198] = PINGROUP(198, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [199] = PINGROUP(199, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [200] = PINGROUP(200, _, _, _, _, _, _, _, _, _, _, egpio), + [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _, _, egpio), + [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _, _, egpio), + [203] = PINGROUP(203, _, _, _, _, _, _, _, _, _, _, egpio), + [204] = PINGROUP(204, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [205] = PINGROUP(205, _, _, _, _, _, _, _, _, _, _, egpio), + [206] = PINGROUP(206, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [207] = PINGROUP(207, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [208] = PINGROUP(208, qup2_se4, _, phase_flag, _, _, _, _, _, _, _, egpio), + [209] = PINGROUP(209, qup2_se4, _, _, _, _, _, _, _, _, _, egpio), + [210] = PINGROUP(210, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [211] = PINGROUP(211, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [212] = PINGROUP(212, _, _, _, _, _, _, _, _, _, _, egpio), + [213] = PINGROUP(213, _, _, _, _, _, _, _, _, _, _, egpio), + [214] = PINGROUP(214, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [215] = PINGROUP(215, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [216] = PINGROUP(216, phase_flag, _, _, _, _, _, _, _, _, _, egpio), + [217] = UFS_RESET(ufs_reset, 0xe8004, 0xe9000), + [218] = SDC_QDSD_PINGROUP(sdc2_clk, 0xdd000, 14, 6), + [219] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xdd000, 11, 3), + [220] = SDC_QDSD_PINGROUP(sdc2_data, 0xdd000, 9, 0), +}; + +static const struct msm_gpio_wakeirq_map kaanapali_pdc_map[] = { + { 0, 89 }, { 3, 97 }, { 4, 90 }, { 7, 91 }, { 8, 92 }, { 11, 93 }, + { 12, 101 }, { 15, 115 }, { 17, 125 }, { 18, 127 }, { 19, 96 }, { 23, 99 }, + { 24, 100 }, { 27, 102 }, { 28, 103 }, { 31, 111 }, { 32, 109 }, { 35, 85 }, + { 36, 110 }, { 39, 112 }, { 43, 113 }, { 47, 138 }, { 48, 114 }, { 51, 98 }, + { 55, 88 }, { 57, 120 }, { 59, 121 }, { 60, 122 }, { 63, 108 }, { 64, 94 }, + { 65, 107 }, { 67, 116 }, { 68, 129 }, { 69, 130 }, { 75, 135 }, { 77, 123 }, + { 78, 119 }, { 79, 131 }, { 80, 139 }, { 81, 132 }, { 84, 118 }, { 85, 133 }, + { 86, 140 }, { 87, 141 }, { 88, 142 }, { 95, 143 }, { 96, 144 }, { 97, 117 }, + { 98, 134 }, { 99, 95 }, { 101, 145 }, { 102, 146 }, { 103, 147 }, { 104, 148 }, + { 120, 149 }, { 125, 150 }, { 129, 137 }, { 133, 84 }, { 144, 151 }, { 146, 152 }, + { 151, 153 }, { 152, 154 }, { 155, 106 }, { 158, 104 }, { 162, 126 }, { 164, 155 }, + { 167, 156 }, { 169, 157 }, { 170, 158 }, { 172, 159 }, { 174, 160 }, { 175, 161 }, + { 179, 162 }, { 180, 163 }, { 183, 164 }, { 186, 165 }, { 188, 128 }, { 189, 166 }, + { 190, 105 }, { 191, 167 }, { 194, 168 }, { 195, 169 }, { 196, 170 }, { 197, 171 }, + { 199, 136 }, { 200, 86 }, { 201, 172 }, { 202, 173 }, { 203, 174 }, { 205, 124 }, + { 209, 175 }, { 213, 87 }, { 216, 176 }, +}; + +static const struct msm_pinctrl_soc_data kaanapali_tlmm = { + .pins = kaanapali_pins, + .npins = ARRAY_SIZE(kaanapali_pins), + .functions = kaanapali_functions, + .nfunctions = ARRAY_SIZE(kaanapali_functions), + .groups = kaanapali_groups, + .ngroups = ARRAY_SIZE(kaanapali_groups), + .ngpios = 218, + .wakeirq_map = kaanapali_pdc_map, + .nwakeirq_map = ARRAY_SIZE(kaanapali_pdc_map), + .egpio_func = 11, +}; + +static int kaanapali_tlmm_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &kaanapali_tlmm); +} + +static const struct of_device_id kaanapali_tlmm_of_match[] = { + { .compatible = "qcom,kaanapali-tlmm",}, + {}, +}; + +static struct platform_driver kaanapali_tlmm_driver = { + .driver = { + .name = "kaanapali-tlmm", + .of_match_table = kaanapali_tlmm_of_match, + }, + .probe = kaanapali_tlmm_probe, +}; + +static int __init kaanapali_tlmm_init(void) +{ + return platform_driver_register(&kaanapali_tlmm_driver); +} +arch_initcall(kaanapali_tlmm_init); + +static void __exit kaanapali_tlmm_exit(void) +{ + platform_driver_unregister(&kaanapali_tlmm_driver); +} +module_exit(kaanapali_tlmm_exit); + +MODULE_DESCRIPTION("QTI Kaanapali TLMM driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, kaanapali_tlmm_of_match); From f919466878611065afb0b79feb28969af766ef3f Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Tue, 7 Oct 2025 03:03:29 +0100 Subject: [PATCH 029/684] dt-bindings: pinctrl: qcom,sm6115-lpass-lpi: add QCM2290 compatible Add a compatible for the LPASS LPI pin controller on QCM2290. It seems to be compatible with sm6115 LPASS pinctrl. Cc: Konrad Dybcio Cc: Srinivas Kandagatla Acked-by: Rob Herring (Arm) Signed-off-by: Alexey Klimov Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml index f4cf2ce86fcd42..ec1cd684753ad2 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml @@ -16,7 +16,13 @@ description: properties: compatible: - const: qcom,sm6115-lpass-lpi-pinctrl + oneOf: + - enum: + - qcom,sm6115-lpass-lpi-pinctrl + - items: + - enum: + - qcom,qcm2290-lpass-lpi-pinctrl + - const: qcom,sm6115-lpass-lpi-pinctrl reg: items: From 005a325480f418447949f43ace24a09a1fad5f09 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 7 Oct 2025 15:18:50 +0200 Subject: [PATCH 030/684] pinctrl: Demote subsystem banner message There is no reason to print any "hello world" from pin control unless (maybe) if we are debugging. Drop the banner. Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index c5dbf4e9db8442..157510157d47aa 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -2416,7 +2416,7 @@ EXPORT_SYMBOL_GPL(devm_pinctrl_unregister); static int __init pinctrl_init(void) { - pr_info("initialized pinctrl subsystem\n"); + pr_debug("initialized pinctrl subsystem\n"); pinctrl_init_debugfs(); return 0; } From 44bf66122c12ef6d3382a9b84b9be1802e5f0e95 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 12 Sep 2025 12:53:08 +0300 Subject: [PATCH 031/684] pinctrl: renesas: rzg2l: Fix ISEL restore on resume Commit 1d2da79708cb ("pinctrl: renesas: rzg2l: Avoid configuring ISEL in gpio_irq_{en,dis}able*()") dropped the configuration of ISEL from struct irq_chip::{irq_enable, irq_disable} APIs and moved it to struct gpio_chip::irq::{child_to_parent_hwirq, child_irq_domain_ops::free} APIs to fix spurious IRQs. After commit 1d2da79708cb ("pinctrl: renesas: rzg2l: Avoid configuring ISEL in gpio_irq_{en,dis}able*()"), ISEL was no longer configured properly on resume. This is because the pinctrl resume code used struct irq_chip::irq_enable (called from rzg2l_gpio_irq_restore()) to reconfigure the wakeup interrupts. Some drivers (e.g. Ethernet) may also reconfigure non-wakeup interrupts on resume through their own code, eventually calling struct irq_chip::irq_enable. Fix this by adding ISEL configuration back into the struct irq_chip::irq_enable API and on resume path for wakeup interrupts. As struct irq_chip::irq_enable needs now to lock to update the ISEL, convert the struct rzg2l_pinctrl::lock to a raw spinlock and replace the locking API calls with the raw variants. Otherwise the lockdep reports invalid wait context when probing the adv7511 module on RZ/G2L: [ BUG: Invalid wait context ] 6.17.0-rc5-next-20250911-00001-gfcfac22533c9 #18 Not tainted ----------------------------- (udev-worker)/165 is trying to lock: ffff00000e3664a8 (&pctrl->lock){....}-{3:3}, at: rzg2l_gpio_irq_enable+0x38/0x78 other info that might help us debug this: context-{5:5} 3 locks held by (udev-worker)/165: #0: ffff00000e890108 (&dev->mutex){....}-{4:4}, at: __driver_attach+0x90/0x1ac #1: ffff000011c07240 (request_class){+.+.}-{4:4}, at: __setup_irq+0xb4/0x6dc #2: ffff000011c070c8 (lock_class){....}-{2:2}, at: __setup_irq+0xdc/0x6dc stack backtrace: CPU: 1 UID: 0 PID: 165 Comm: (udev-worker) Not tainted 6.17.0-rc5-next-20250911-00001-gfcfac22533c9 #18 PREEMPT Hardware name: Renesas SMARC EVK based on r9a07g044l2 (DT) Call trace: show_stack+0x18/0x24 (C) dump_stack_lvl+0x90/0xd0 dump_stack+0x18/0x24 __lock_acquire+0xa14/0x20b4 lock_acquire+0x1c8/0x354 _raw_spin_lock_irqsave+0x60/0x88 rzg2l_gpio_irq_enable+0x38/0x78 irq_enable+0x40/0x8c __irq_startup+0x78/0xa4 irq_startup+0x108/0x16c __setup_irq+0x3c0/0x6dc request_threaded_irq+0xec/0x1ac devm_request_threaded_irq+0x80/0x134 adv7511_probe+0x928/0x9a4 [adv7511] i2c_device_probe+0x22c/0x3dc really_probe+0xbc/0x2a0 __driver_probe_device+0x78/0x12c driver_probe_device+0x40/0x164 __driver_attach+0x9c/0x1ac bus_for_each_dev+0x74/0xd0 driver_attach+0x24/0x30 bus_add_driver+0xe4/0x208 driver_register+0x60/0x128 i2c_register_driver+0x48/0xd0 adv7511_init+0x5c/0x1000 [adv7511] do_one_initcall+0x64/0x30c do_init_module+0x58/0x23c load_module+0x1bcc/0x1d40 init_module_from_file+0x88/0xc4 idempotent_init_module+0x188/0x27c __arm64_sys_finit_module+0x68/0xac invoke_syscall+0x48/0x110 el0_svc_common.constprop.0+0xc0/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x4c/0x160 el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c Having ISEL configuration back into the struct irq_chip::irq_enable API should be safe with respect to spurious IRQs, as in the probe case IRQs are enabled anyway in struct gpio_chip::irq::child_to_parent_hwirq. No spurious IRQs were detected on suspend/resume, boot, ethernet link insert/remove tests (executed on RZ/G3S). Boot, ethernet link insert/remove tests were also executed successfully on RZ/G2L. Fixes: 1d2da79708cb ("pinctrl: renesas: rzg2l: Avoid configuring ISEL in gpio_irq_{en,dis}able*(") Cc: stable@vger.kernel.org Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250912095308.3603704-1-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 71 +++++++++++++++---------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index f524af6f586f4a..c360e473488c33 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -359,7 +359,7 @@ struct rzg2l_pinctrl { spinlock_t bitmap_lock; /* protect tint_slot bitmap */ unsigned int hwirq[RZG2L_TINT_MAX_INTERRUPT]; - spinlock_t lock; /* lock read/write registers */ + raw_spinlock_t lock; /* lock read/write registers */ struct mutex mutex; /* serialize adding groups and functions */ struct rzg2l_pinctrl_pin_settings *settings; @@ -543,7 +543,7 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, unsigned long flags; u32 reg; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); /* Set pin to 'Non-use (Hi-Z input protection)' */ reg = readw(pctrl->base + PM(off)); @@ -567,7 +567,7 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, pctrl->data->pwpr_pfc_lock_unlock(pctrl, true); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); }; static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, @@ -882,10 +882,10 @@ static void rzg2l_rmw_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset, addr += 4; } - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); reg = readl(addr) & ~(mask << (bit * 8)); writel(reg | (val << (bit * 8)), addr); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); } static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs, u32 caps) @@ -1121,7 +1121,7 @@ static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oe if (bit < 0) return -EINVAL; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); val = readb(pctrl->base + oen_offset); if (oen) val &= ~BIT(bit); @@ -1134,7 +1134,7 @@ static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oe writeb(val, pctrl->base + oen_offset); if (pctrl->data->hwcfg->oen_pwpr_lock) writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; } @@ -1687,14 +1687,14 @@ static int rzg2l_gpio_request(struct gpio_chip *chip, unsigned int offset) if (ret) return ret; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); /* Select GPIO mode in PMC Register */ reg8 = readb(pctrl->base + PMC(off)); reg8 &= ~BIT(bit); pctrl->data->pmc_writeb(pctrl, reg8, PMC(off)); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; } @@ -1709,7 +1709,7 @@ static void rzg2l_gpio_set_direction(struct rzg2l_pinctrl *pctrl, u32 offset, unsigned long flags; u16 reg16; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); reg16 = readw(pctrl->base + PM(off)); reg16 &= ~(PM_MASK << (bit * 2)); @@ -1717,7 +1717,7 @@ static void rzg2l_gpio_set_direction(struct rzg2l_pinctrl *pctrl, u32 offset, reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (bit * 2); writew(reg16, pctrl->base + PM(off)); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); } static int rzg2l_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) @@ -1761,7 +1761,7 @@ static int rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, unsigned long flags; u8 reg8; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); reg8 = readb(pctrl->base + P(off)); @@ -1770,7 +1770,7 @@ static int rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, else writeb(reg8 & ~BIT(bit), pctrl->base + P(off)); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; } @@ -2429,14 +2429,13 @@ static int rzg2l_gpio_get_gpioint(unsigned int virq, struct rzg2l_pinctrl *pctrl return gpioint; } -static void rzg2l_gpio_irq_endisable(struct rzg2l_pinctrl *pctrl, - unsigned int hwirq, bool enable) +static void __rzg2l_gpio_irq_endisable(struct rzg2l_pinctrl *pctrl, + unsigned int hwirq, bool enable) { const struct pinctrl_pin_desc *pin_desc = &pctrl->desc.pins[hwirq]; u64 *pin_data = pin_desc->drv_data; u32 off = RZG2L_PIN_CFG_TO_PORT_OFFSET(*pin_data); u8 bit = RZG2L_PIN_ID_TO_PIN(hwirq); - unsigned long flags; void __iomem *addr; addr = pctrl->base + ISEL(off); @@ -2445,12 +2444,20 @@ static void rzg2l_gpio_irq_endisable(struct rzg2l_pinctrl *pctrl, addr += 4; } - spin_lock_irqsave(&pctrl->lock, flags); if (enable) writel(readl(addr) | BIT(bit * 8), addr); else writel(readl(addr) & ~BIT(bit * 8), addr); - spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static void rzg2l_gpio_irq_endisable(struct rzg2l_pinctrl *pctrl, + unsigned int hwirq, bool enable) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&pctrl->lock, flags); + __rzg2l_gpio_irq_endisable(pctrl, hwirq, enable); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); } static void rzg2l_gpio_irq_disable(struct irq_data *d) @@ -2462,15 +2469,25 @@ static void rzg2l_gpio_irq_disable(struct irq_data *d) gpiochip_disable_irq(gc, hwirq); } -static void rzg2l_gpio_irq_enable(struct irq_data *d) +static void __rzg2l_gpio_irq_enable(struct irq_data *d, bool lock) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct rzg2l_pinctrl *pctrl = container_of(gc, struct rzg2l_pinctrl, gpio_chip); unsigned int hwirq = irqd_to_hwirq(d); gpiochip_enable_irq(gc, hwirq); + if (lock) + rzg2l_gpio_irq_endisable(pctrl, hwirq, true); + else + __rzg2l_gpio_irq_endisable(pctrl, hwirq, true); irq_chip_enable_parent(d); } +static void rzg2l_gpio_irq_enable(struct irq_data *d) +{ + __rzg2l_gpio_irq_enable(d, true); +} + static int rzg2l_gpio_irq_set_type(struct irq_data *d, unsigned int type) { return irq_chip_set_type_parent(d, type); @@ -2616,11 +2633,11 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl) * This has to be atomically executed to protect against a concurrent * interrupt. */ - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); ret = rzg2l_gpio_irq_set_type(data, irqd_get_trigger_type(data)); if (!ret && !irqd_irq_disabled(data)) - rzg2l_gpio_irq_enable(data); - spin_unlock_irqrestore(&pctrl->lock, flags); + __rzg2l_gpio_irq_enable(data, false); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); if (ret) dev_crit(pctrl->dev, "Failed to set IRQ type for virq=%u\n", virq); @@ -2950,7 +2967,7 @@ static int rzg2l_pinctrl_probe(struct platform_device *pdev) "failed to enable GPIO clk\n"); } - spin_lock_init(&pctrl->lock); + raw_spin_lock_init(&pctrl->lock); spin_lock_init(&pctrl->bitmap_lock); mutex_init(&pctrl->mutex); atomic_set(&pctrl->wakeup_path, 0); @@ -3093,7 +3110,7 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl) u32 nports = pctrl->data->n_port_pins / RZG2L_PINS_PER_PORT; unsigned long flags; - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); pctrl->data->pwpr_pfc_lock_unlock(pctrl, false); /* Restore port registers. */ @@ -3138,7 +3155,7 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl) } pctrl->data->pwpr_pfc_lock_unlock(pctrl, true); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); } static int rzg2l_pinctrl_suspend_noirq(struct device *dev) @@ -3187,14 +3204,14 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) writeb(cache->qspi, pctrl->base + QSPI); if (pctrl->data->hwcfg->oen_pwpr_lock) { - spin_lock_irqsave(&pctrl->lock, flags); + raw_spin_lock_irqsave(&pctrl->lock, flags); pwpr = readb(pctrl->base + regs->pwpr); writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); } writeb(cache->oen, pctrl->base + pctrl->data->hwcfg->regs.oen); if (pctrl->data->hwcfg->oen_pwpr_lock) { writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); - spin_unlock_irqrestore(&pctrl->lock, flags); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); } for (u8 i = 0; i < 2; i++) { if (regs->sd_ch) From fb8a7900dcba3764902ff9f0b3824f8818b3f4df Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 9 Sep 2025 11:42:44 +0100 Subject: [PATCH 032/684] pinctrl: renesas: rzg2l: Drop unnecessary pin configurations There is no need to reconfigure a pin if the pin's configuration values are the same as the reset values. E.g. the PS0 pin configuration for the NMI function is PMC = 1 and PFC = 0, which is the same as the reset values. Currently the code is first setting it to GPIO HI-Z state and then again reconfiguring to the NMI function, leading to spurious IRQs. Fix this by dropping unnecessary pin configuration from the driver. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250909104247.3309-1-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index c360e473488c33..efb406046f1a62 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -541,9 +541,16 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, u8 pin, u8 off, u8 func) { unsigned long flags; - u32 reg; + u32 reg, pfc; + /* Switching to GPIO is not required if reset value is same as func */ raw_spin_lock_irqsave(&pctrl->lock, flags); + reg = readb(pctrl->base + PMC(off)); + pfc = readl(pctrl->base + PFC(off)); + if ((reg & BIT(pin)) && (((pfc >> (pin * 4)) & PFC_MASK) == func)) { + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + return; + } /* Set pin to 'Non-use (Hi-Z input protection)' */ reg = readw(pctrl->base + PM(off)); @@ -557,9 +564,8 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, writeb(reg & ~BIT(pin), pctrl->base + PMC(off)); /* Select Pin function mode with PFC register */ - reg = readl(pctrl->base + PFC(off)); - reg &= ~(PFC_MASK << (pin * 4)); - writel(reg | (func << (pin * 4)), pctrl->base + PFC(off)); + pfc &= ~(PFC_MASK << (pin * 4)); + writel(pfc | (func << (pin * 4)), pctrl->base + PFC(off)); /* Switch to Peripheral pin function with PMC register */ reg = readb(pctrl->base + PMC(off)); @@ -3130,11 +3136,18 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl) pm = readw(pctrl->base + PM(off)); for_each_set_bit(pin, &pinmap, max_pin) { struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; + u32 pfc_val, pfc_mask; /* Nothing to do if PFC was not configured before. */ if (!(cache->pmc[port] & BIT(pin))) continue; + pfc_val = readl(pctrl->base + PFC(off)); + pfc_mask = PFC_MASK << (pin * 4); + /* Nothing to do if reset value of the pin is same as cached value */ + if ((cache->pfc[port] & pfc_mask) == (pfc_val & pfc_mask)) + continue; + /* Set pin to 'Non-use (Hi-Z input protection)' */ pm &= ~(PM_MASK << (pin * 2)); writew(pm, pctrl->base + PM(off)); @@ -3144,8 +3157,8 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl) writeb(pmc, pctrl->base + PMC(off)); /* Select Pin function mode. */ - pfc &= ~(PFC_MASK << (pin * 4)); - pfc |= (cache->pfc[port] & (PFC_MASK << (pin * 4))); + pfc &= ~pfc_mask; + pfc |= (cache->pfc[port] & pfc_mask); writel(pfc, pctrl->base + PFC(off)); /* Switch to Peripheral pin function. */ From fea997df95fc43521a42851721a62e7c74dcacee Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 18 Sep 2025 22:04:01 +0200 Subject: [PATCH 033/684] pinctrl: renesas: Drop duplicate newlines Remove duplicate newlines. No functional change. Signed-off-by: Marek Vasut Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250918200409.37284-1-marek.vasut+renesas@mailbox.org Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pfc-emev2.c | 1 - drivers/pinctrl/renesas/pfc-r8a73a4.c | 2 -- drivers/pinctrl/renesas/pfc-r8a7778.c | 1 - drivers/pinctrl/renesas/pfc-r8a77951.c | 1 - drivers/pinctrl/renesas/pfc-r8a7796.c | 1 - drivers/pinctrl/renesas/pfc-r8a77965.c | 1 - drivers/pinctrl/renesas/pfc-r8a77970.c | 1 - drivers/pinctrl/renesas/pfc-r8a77980.c | 1 - drivers/pinctrl/renesas/pfc-r8a77995.c | 2 -- drivers/pinctrl/renesas/pfc-r8a779f0.c | 1 - drivers/pinctrl/renesas/pfc-r8a779h0.c | 1 - drivers/pinctrl/renesas/pfc-sh7723.c | 1 - drivers/pinctrl/renesas/pfc-sh7724.c | 1 - drivers/pinctrl/renesas/pfc-sh7734.c | 1 - drivers/pinctrl/renesas/pinctrl-rza1.c | 1 - 15 files changed, 17 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-emev2.c b/drivers/pinctrl/renesas/pfc-emev2.c index 86d18b03668eac..eee23ac8707666 100644 --- a/drivers/pinctrl/renesas/pfc-emev2.c +++ b/drivers/pinctrl/renesas/pfc-emev2.c @@ -666,7 +666,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_NOFN(UART_1_0_PORT158, UART2_TX, SEL_UART_1_0_01), }; - #define EMEV_MUX_PIN(name, pin, mark) \ static const unsigned int name##_pins[] = { pin }; \ static const unsigned int name##_mux[] = { mark##_MARK } diff --git a/drivers/pinctrl/renesas/pfc-r8a73a4.c b/drivers/pinctrl/renesas/pfc-r8a73a4.c index be0a4914eab335..1b00765192f524 100644 --- a/drivers/pinctrl/renesas/pfc-r8a73a4.c +++ b/drivers/pinctrl/renesas/pfc-r8a73a4.c @@ -85,7 +85,6 @@ /* Port320 - Port329 */ \ PORT_10(320, fn, pfx##32, sfx) - enum { PINMUX_RESERVED = 0, @@ -227,7 +226,6 @@ enum { PINMUX_MARK_BEGIN, - #define F1(a) a##_MARK #define F2(a) a##_MARK #define F3(a) a##_MARK diff --git a/drivers/pinctrl/renesas/pfc-r8a7778.c b/drivers/pinctrl/renesas/pfc-r8a7778.c index db92d6d91d8ee9..4611e864ba69d7 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7778.c +++ b/drivers/pinctrl/renesas/pfc-r8a7778.c @@ -1994,7 +1994,6 @@ static const char * const scif5_groups[] = { "scif5_data_b", }; - static const char * const sdhi0_groups[] = { "sdhi0_cd", "sdhi0_ctrl", diff --git a/drivers/pinctrl/renesas/pfc-r8a77951.c b/drivers/pinctrl/renesas/pfc-r8a77951.c index a1d74f61fd8cce..4b04cb9134b658 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77951.c +++ b/drivers/pinctrl/renesas/pfc-r8a77951.c @@ -249,7 +249,6 @@ #define GPSR7_1 FM(AVS2) #define GPSR7_0 FM(AVS1) - /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */ #define IP0_3_0 FM(AVB_MDC) F_(0, 0) FM(MSIOF2_SS2_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_7_4 FM(AVB_MAGIC) F_(0, 0) FM(MSIOF2_SS1_C) FM(SCK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c index 807834f319f07d..aead3b1173c968 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7796.c +++ b/drivers/pinctrl/renesas/pfc-r8a7796.c @@ -254,7 +254,6 @@ #define GPSR7_1 FM(AVS2) #define GPSR7_0 FM(AVS1) - /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */ #define IP0_3_0 FM(AVB_MDC) F_(0, 0) FM(MSIOF2_SS2_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_7_4 FM(AVB_MAGIC) F_(0, 0) FM(MSIOF2_SS1_C) FM(SCK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77965.c b/drivers/pinctrl/renesas/pfc-r8a77965.c index e7c88a5d983f43..22640cfe9e3295 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77965.c +++ b/drivers/pinctrl/renesas/pfc-r8a77965.c @@ -254,7 +254,6 @@ #define GPSR7_1 FM(AVS2) #define GPSR7_0 FM(AVS1) - /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */ #define IP0_3_0 FM(AVB_MDC) F_(0, 0) FM(MSIOF2_SS2_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_7_4 FM(AVB_MAGIC) F_(0, 0) FM(MSIOF2_SS1_C) FM(SCK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c index e1b3e3b38ec3b8..972b14ab2359af 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77970.c +++ b/drivers/pinctrl/renesas/pfc-r8a77970.c @@ -159,7 +159,6 @@ #define GPSR5_1 FM(QSPI0_MOSI_IO0) #define GPSR5_0 FM(QSPI0_SPCLK) - /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ #define IP0_3_0 FM(DU_DR2) FM(HSCK0) F_(0, 0) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_7_4 FM(DU_DR3) FM(HRTS0_N) F_(0, 0) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c index 877134d78c7e50..53b44b24bfc671 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77980.c +++ b/drivers/pinctrl/renesas/pfc-r8a77980.c @@ -193,7 +193,6 @@ #define GPSR5_1 FM(QSPI0_MOSI_IO0) #define GPSR5_0 FM(QSPI0_SPCLK) - /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ #define IP0_3_0 FM(DU_DR2) FM(SCK4) FM(GETHER_RMII_CRS_DV) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_7_4 FM(DU_DR3) FM(RX4) FM(GETHER_RMII_RX_ER) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77995.c b/drivers/pinctrl/renesas/pfc-r8a77995.c index 298e7a07e4934e..b35c62f9a0618a 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77995.c +++ b/drivers/pinctrl/renesas/pfc-r8a77995.c @@ -427,7 +427,6 @@ FM(IP12_31_28) IP12_31_28 \ #define MOD_SEL1_27 FM(SEL_SCIF0_0) FM(SEL_SCIF0_1) #define MOD_SEL1_26 FM(SEL_SSIF4_0) FM(SEL_SSIF4_1) - #define PINMUX_MOD_SELS \ \ MOD_SEL1_31 \ @@ -2869,7 +2868,6 @@ static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = { { /* sentinel */ } }; - static int r8a77995_pin_to_pocctrl(unsigned int pin, u32 *pocctrl) { switch (pin) { diff --git a/drivers/pinctrl/renesas/pfc-r8a779f0.c b/drivers/pinctrl/renesas/pfc-r8a779f0.c index 16e722a4d18fa6..46ca28fb2d513b 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779f0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779f0.c @@ -652,7 +652,6 @@ static const unsigned int i2c5_mux[] = { SDA5_MARK, SCL5_MARK, }; - /* - INTC-EX ---------------------------------------------------------------- */ static const unsigned int intc_ex_irq0_pins[] = { /* IRQ0 */ diff --git a/drivers/pinctrl/renesas/pfc-r8a779h0.c b/drivers/pinctrl/renesas/pfc-r8a779h0.c index 48b1eef250d950..63b3725a0cf6ff 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779h0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779h0.c @@ -259,7 +259,6 @@ #define GPSR7_1 F_(AVB0_AVTP_CAPTURE, IP0SR7_7_4) #define GPSR7_0 F_(AVB0_AVTP_PPS, IP0SR7_3_0) - /* SR0 */ /* IP0SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ #define IP0SR0_3_0 F_(0, 0) FM(ERROROUTC_N_B) FM(TCLK2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-sh7723.c b/drivers/pinctrl/renesas/pfc-sh7723.c index c1abdec9bf1d60..bdf555e63c2e34 100644 --- a/drivers/pinctrl/renesas/pfc-sh7723.c +++ b/drivers/pinctrl/renesas/pfc-sh7723.c @@ -182,7 +182,6 @@ enum { PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN, PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN, - PSA15_PSA14_FN1, PSA15_PSA14_FN2, PSA13_PSA12_FN1, PSA13_PSA12_FN2, PSA11_PSA10_FN1, PSA11_PSA10_FN2, diff --git a/drivers/pinctrl/renesas/pfc-sh7724.c b/drivers/pinctrl/renesas/pfc-sh7724.c index 5148a3460cc6f0..4e8c1fae7be65b 100644 --- a/drivers/pinctrl/renesas/pfc-sh7724.c +++ b/drivers/pinctrl/renesas/pfc-sh7724.c @@ -210,7 +210,6 @@ enum { PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN, PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN, - PSA15_0, PSA15_1, PSA14_0, PSA14_1, PSA13_0, PSA13_1, diff --git a/drivers/pinctrl/renesas/pfc-sh7734.c b/drivers/pinctrl/renesas/pfc-sh7734.c index a0a5d8b94086f0..df2de853df9326 100644 --- a/drivers/pinctrl/renesas/pfc-sh7734.c +++ b/drivers/pinctrl/renesas/pfc-sh7734.c @@ -664,7 +664,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP0_31_30, LCD_DATA15_A, SEL_LCDC_0), PINMUX_IPSR_MSEL(IP0_31_30, TIOC3D_C, SEL_MTU2_CH3_1), - /* IPSR1 */ PINMUX_IPSR_GPSR(IP1_1_0, A16), PINMUX_IPSR_GPSR(IP1_1_0, ST0_PWM), diff --git a/drivers/pinctrl/renesas/pinctrl-rza1.c b/drivers/pinctrl/renesas/pinctrl-rza1.c index f24e5915cbe4b4..4c7326e3de07ce 100644 --- a/drivers/pinctrl/renesas/pinctrl-rza1.c +++ b/drivers/pinctrl/renesas/pinctrl-rza1.c @@ -526,7 +526,6 @@ static inline int rza1_pinmux_get_swio(unsigned int port, const struct rza1_swio_pin *swio_pin; unsigned int i; - for (i = 0; i < table->npins; ++i) { swio_pin = &table->pins[i]; if (swio_pin->port == port && swio_pin->pin == pin && From cea950101108b7bfffe26ec4007b8e263a4b56a8 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 21 Sep 2025 12:15:52 +0100 Subject: [PATCH 034/684] pinctrl: renesas: rzg2l: Fix PMC restore PMC restore needs unlocking the register using the PWPR register. Fixes: ede014cd1ea6422d ("pinctrl: renesas: rzg2l: Add function pointer for PMC register write") Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250921111557.103069-2-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index efb406046f1a62..6c97df26bff44b 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -3016,7 +3016,11 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen * Now cache the registers or set them in the order suggested by * HW manual (section "Operation for GPIO Function"). */ - RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + PMC(off), cache->pmc[port]); + if (suspend) + RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + PMC(off), cache->pmc[port]); + else + pctrl->data->pmc_writeb(pctrl, cache->pmc[port], PMC(off)); + if (has_iolh) { RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + IOLH(off), cache->iolh[0][port]); From 647a6b1808dbec19acaba29d512767b3d4d9cd71 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Tue, 23 Sep 2025 20:49:50 +0300 Subject: [PATCH 035/684] pinctrl: renesas: rzg2l: Remove extra semicolons Semicolons after end of function braces are unnecessary, remove them. Signed-off-by: Cosmin Tanislav Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250923174951.1136259-1-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index 6c97df26bff44b..947bce7bfc0e9a 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -574,7 +574,7 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, pctrl->data->pwpr_pfc_lock_unlock(pctrl, true); raw_spin_unlock_irqrestore(&pctrl->lock, flags); -}; +} static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, @@ -614,7 +614,7 @@ static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, } return 0; -}; +} static int rzg2l_map_add_config(struct pinctrl_map *map, const char *group_or_pin, @@ -1419,7 +1419,7 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, *config = pinconf_to_config_packed(param, arg); return 0; -}; +} static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, unsigned int _pin, @@ -1619,7 +1619,7 @@ static int rzg2l_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev, } return 0; -}; +} static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int group, @@ -1646,7 +1646,7 @@ static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, } return 0; -}; +} static const struct pinctrl_ops rzg2l_pinctrl_pctlops = { .get_groups_count = pinctrl_generic_get_group_count, From bf48f99d95dfd664ddb7c4d69b182606f5ed8605 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Sep 2025 14:47:52 +0200 Subject: [PATCH 036/684] pinctrl: renesas: Remove unneeded semicolons Semicolons after end of function braces are not needed, remove them. Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/99db8c1bfb64980b54a4b5c4988c7935609133e1.1758718027.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pinctrl-rzt2h.c | 4 ++-- drivers/pinctrl/renesas/pinctrl-rzv2m.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c index 3872638f5ebb39..4826ff91cd9060 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c +++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c @@ -144,7 +144,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl, /* Switch to Peripheral pin function with PMC register */ reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port)); rzt2h_pinctrl_writeb(pctrl, port, reg16 | BIT(pin), PMC(port)); -}; +} static int rzt2h_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, @@ -182,7 +182,7 @@ static int rzt2h_pinctrl_set_mux(struct pinctrl_dev *pctldev, } return 0; -}; +} static int rzt2h_map_add_config(struct pinctrl_map *map, const char *group_or_pin, diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c index dce68f93d2d57f..495e7f5d41280d 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzv2m.c +++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c @@ -155,7 +155,7 @@ static void rzv2m_pinctrl_set_pfc_mode(struct rzv2m_pinctrl *pctrl, /* Unmask input/output */ rzv2m_writel_we(pctrl->base + EN_MSK(port), pin, 0); rzv2m_writel_we(pctrl->base + DI_MSK(port), pin, 0); -}; +} static int rzv2m_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, @@ -186,7 +186,7 @@ static int rzv2m_pinctrl_set_mux(struct pinctrl_dev *pctldev, } return 0; -}; +} static int rzv2m_map_add_config(struct pinctrl_map *map, const char *group_or_pin, @@ -551,7 +551,7 @@ static int rzv2m_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, *config = pinconf_to_config_packed(param, arg); return 0; -}; +} static int rzv2m_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, unsigned int _pin, @@ -689,7 +689,7 @@ static int rzv2m_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev, } return 0; -}; +} static int rzv2m_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int group, @@ -716,7 +716,7 @@ static int rzv2m_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, } return 0; -}; +} static const struct pinctrl_ops rzv2m_pinctrl_pctlops = { .get_groups_count = pinctrl_generic_get_group_count, From 62abfd7bedc2b3d86d4209a4146f9d2b5ae21fab Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 18 Sep 2025 05:04:43 +0200 Subject: [PATCH 037/684] clk: renesas: cpg-mssr: Add missing 1ms delay into reset toggle callback R-Car V4H Reference Manual R19UH0186EJ0130 Rev.1.30 Apr. 21, 2025 page 583 Figure 9.3.1(a) Software Reset flow (A) as well as flow (B) / (C) indicate after reset has been asserted by writing a matching reset bit into register SRCR, it is mandatory to wait 1ms. This 1ms delay is documented on R-Car V4H and V4M, it is currently unclear whether S4 is affected as well. This patch does apply the extra delay on R-Car S4 as well. Fix the reset driver to respect the additional delay when toggling resets. Drivers which use separate reset_control_(de)assert() must assure matching delay in their driver code. Fixes: 0ab55cf18341 ("clk: renesas: cpg-mssr: Add support for R-Car V4H") Signed-off-by: Marek Vasut Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250918030552.331389-1-marek.vasut+renesas@mailbox.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index de1cf7ba45b78b..7063d896249eab 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -689,8 +689,15 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev, /* Reset module */ writel(bitmask, priv->pub.base0 + priv->reset_regs[reg]); - /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ - udelay(35); + /* + * On R-Car Gen4, delay after SRCR has been written is 1ms. + * On older SoCs, delay after SRCR has been written is 35us + * (one cycle of the RCLK clock @ ca. 32 kHz). + */ + if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) + usleep_range(1000, 2000); + else + usleep_range(35, 1000); /* Release module from reset state */ writel(bitmask, priv->pub.base0 + priv->reset_clear_regs[reg]); From b91401af6c00ffab003698bfabd4c166df30748b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 22 Sep 2025 18:20:38 +0200 Subject: [PATCH 038/684] clk: renesas: cpg-mssr: Read back reset registers to assure values latched On R-Car V4H, the PCIEC controller DBI read would generate an SError in case the controller reset is released by writing SRSTCLR register first, and immediately afterward reading some PCIEC controller DBI register. The issue triggers in rcar_gen4_pcie_additional_common_init() on dw_pcie_readl_dbi(dw, PCIE_PORT_LANE_SKEW), which on V4H is the first read after reset_control_deassert(dw->core_rsts[DW_PCIE_PWR_RST].rstc). The reset controller which contains the SRSTCLR register and the PCIEC controller which contains the DBI register share the same root access bus, but the bus then splits into separate segments before reaching each IP. Even if the SRSTCLR write access was posted on the bus before the DBI read access, it seems the DBI read access may reach the PCIEC controller before the SRSTCLR write completed, and trigger the SError. Mitigate the issue by adding a dummy SRSTCLR read, which assures the SRSTCLR write completes fully and is latched into the reset controller, before the PCIEC DBI read access can occur. Fixes: 0ab55cf18341 ("clk: renesas: cpg-mssr: Add support for R-Car V4H") Reviewed-by: Wolfram Sang Tested-by: Geert Uytterhoeven Signed-off-by: Marek Vasut Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250922162113.113223-1-marek.vasut+renesas@mailbox.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 46 ++++++++++++-------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 7063d896249eab..a0a68ec0490f7c 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -676,18 +676,32 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, #define rcdev_to_priv(x) container_of(x, struct cpg_mssr_priv, rcdev) -static int cpg_mssr_reset(struct reset_controller_dev *rcdev, - unsigned long id) +static int cpg_mssr_reset_operate(struct reset_controller_dev *rcdev, + const char *func, bool set, unsigned long id) { struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); unsigned int reg = id / 32; unsigned int bit = id % 32; + const u16 off = set ? priv->reset_regs[reg] : priv->reset_clear_regs[reg]; u32 bitmask = BIT(bit); - dev_dbg(priv->dev, "reset %u%02u\n", reg, bit); + if (func) + dev_dbg(priv->dev, "%s %u%02u\n", func, reg, bit); + + writel(bitmask, priv->pub.base0 + off); + readl(priv->pub.base0 + off); + barrier_data(priv->pub.base0 + off); + + return 0; +} + +static int cpg_mssr_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); /* Reset module */ - writel(bitmask, priv->pub.base0 + priv->reset_regs[reg]); + cpg_mssr_reset_operate(rcdev, "reset", true, id); /* * On R-Car Gen4, delay after SRCR has been written is 1ms. @@ -700,36 +714,18 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev, usleep_range(35, 1000); /* Release module from reset state */ - writel(bitmask, priv->pub.base0 + priv->reset_clear_regs[reg]); - - return 0; + return cpg_mssr_reset_operate(rcdev, NULL, false, id); } static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id) { - struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); - unsigned int reg = id / 32; - unsigned int bit = id % 32; - u32 bitmask = BIT(bit); - - dev_dbg(priv->dev, "assert %u%02u\n", reg, bit); - - writel(bitmask, priv->pub.base0 + priv->reset_regs[reg]); - return 0; + return cpg_mssr_reset_operate(rcdev, "assert", true, id); } static int cpg_mssr_deassert(struct reset_controller_dev *rcdev, unsigned long id) { - struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); - unsigned int reg = id / 32; - unsigned int bit = id % 32; - u32 bitmask = BIT(bit); - - dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit); - - writel(bitmask, priv->pub.base0 + priv->reset_clear_regs[reg]); - return 0; + return cpg_mssr_reset_operate(rcdev, "deassert", false, id); } static int cpg_mssr_status(struct reset_controller_dev *rcdev, From ba1ec92ccfe22c93afd5b20e2176e290d268381b Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Tue, 23 Sep 2025 19:05:15 +0300 Subject: [PATCH 039/684] clk: renesas: r9a09g077: Add ADC module clocks Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs have three 12-bit ADC peripherals, each with their own peripheral clock. For conversion, they use the PCLKL clock. Add their clocks to the list of module clocks. Signed-off-by: Cosmin Tanislav Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250923160524.1096720-2-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index af3ef6d58c87cd..4ec6c4ddc5f5fd 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -188,6 +188,9 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC), DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL), DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL), + DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH), + DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH), + DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM), DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM), DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM), DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM), From 06e6ea35e9886cf2f5997d3a27d49351511af18e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Sep 2025 15:03:09 +0200 Subject: [PATCH 040/684] clk: renesas: cpg-lib: Remove unneeded semicolon Semicolons after end of function braces are not needed, remove them. Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/deb1537b5f96d991332db5c8088bae705f7e17e3.1758718886.git.geert+renesas@glider.be --- drivers/clk/renesas/rcar-cpg-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c index a45f8e7e9ab676..7b271de7037a13 100644 --- a/drivers/clk/renesas/rcar-cpg-lib.c +++ b/drivers/clk/renesas/rcar-cpg-lib.c @@ -35,7 +35,7 @@ void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) val |= set; writel(val, reg); spin_unlock_irqrestore(&cpg_lock, flags); -}; +} static int cpg_simple_notifier_call(struct notifier_block *nb, unsigned long action, void *data) From c510368bce39cbaf4cb66f4acf788f5efa8692a6 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Oct 2025 23:26:52 +0200 Subject: [PATCH 041/684] dt-bindings: clock: renesas,r9a09g047-cpg: Add USB2 PHY core clocks Add definitions for USB2 PHY core clocks in the R9A09G047 CPG DT bindings header file. Signed-off-by: Tommaso Merciai Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251001212709.579080-9-tommaso.merciai.xr@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/renesas,r9a09g047-cpg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/renesas,r9a09g047-cpg.h b/include/dt-bindings/clock/renesas,r9a09g047-cpg.h index f165df8a6f5a34..dab24740de3c11 100644 --- a/include/dt-bindings/clock/renesas,r9a09g047-cpg.h +++ b/include/dt-bindings/clock/renesas,r9a09g047-cpg.h @@ -22,5 +22,7 @@ #define R9A09G047_GBETH_1_CLK_PTP_REF_I 11 #define R9A09G047_USB3_0_REF_ALT_CLK_P 12 #define R9A09G047_USB3_0_CLKCORE 13 +#define R9A09G047_USB2_0_CLK_CORE0 14 +#define R9A09G047_USB2_0_CLK_CORE1 15 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G047_CPG_H__ */ From 6a636d203cc8d29ae73116bbca8b0ea2c7a90d7f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 25 Sep 2025 11:53:24 +0200 Subject: [PATCH 042/684] clk: renesas: Use IS_ERR() for pointers that cannot be NULL The use of IS_ERR_OR_NULL() suggests that "clk" can be a NULL pointer. Hence smatch assumes so, and issues a "passing zero to 'PTR_ERR'" warning. At these checkpoints, "clk" always contains either a valid pointer, or an error pointer (none of the functions called return NULL pointers). Hence replace IS_ERR_OR_NULL() by IS_ERR(). Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202408032025.ve2JMaoV-lkp@intel.com/ Signed-off-by: Geert Uytterhoeven Reviewed-by: Lad Prabhakar Link: https://patch.msgid.link/81260328acb5c78e915ab04afad3901a31c16128.1758793709.git.geert+renesas@glider.be --- drivers/clk/renesas/renesas-cpg-mssr.c | 2 +- drivers/clk/renesas/rzg2l-cpg.c | 2 +- drivers/clk/renesas/rzv2h-cpg.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index a0a68ec0490f7c..a3d171ddaab992 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -451,7 +451,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, break; } - if (IS_ERR_OR_NULL(clk)) + if (IS_ERR(clk)) goto fail; dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 07909e80bae24e..64d1ef6e4c943c 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -1177,7 +1177,7 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, goto fail; } - if (IS_ERR_OR_NULL(clk)) + if (IS_ERR(clk)) goto fail; dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 2197d1d2453a3f..ff688dc88ba3e6 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -591,7 +591,7 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, goto fail; } - if (IS_ERR_OR_NULL(clk)) + if (IS_ERR(clk)) goto fail; dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); From e43b186df5c4635059f6213d100c9314c1570d02 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Wed, 1 Oct 2025 23:26:53 +0200 Subject: [PATCH 043/684] clk: renesas: r9a09g047: Add clock and reset entries for USB2 Add clock and reset entries for USB2. Signed-off-by: Tommaso Merciai Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251001212709.579080-10-tommaso.merciai.xr@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g047-cpg.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g047-cpg.c b/drivers/clk/renesas/r9a09g047-cpg.c index ef115f9ec0e64b..68f8b08bd16f3f 100644 --- a/drivers/clk/renesas/r9a09g047-cpg.c +++ b/drivers/clk/renesas/r9a09g047-cpg.c @@ -16,7 +16,7 @@ enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R9A09G047_USB3_0_CLKCORE, + LAST_DT_CORE_CLK = R9A09G047_USB2_0_CLK_CORE1, /* External Input Clocks */ CLK_AUDIO_EXTAL, @@ -177,6 +177,8 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { CDDIV1_DIVCTL3, dtable_1_8), DEF_FIXED("iotop_0_shclk", R9A09G047_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1), DEF_FIXED("spi_clk_spi", R9A09G047_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2), + DEF_FIXED("usb2_0_clk_core0", R9A09G047_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1), + DEF_FIXED("usb2_0_clk_core1", R9A09G047_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1), DEF_FIXED("gbeth_0_clk_ptp_ref_i", R9A09G047_GBETH_0_CLK_PTP_REF_I, CLK_PLLETH_DIV_125_FIX, 1, 1), DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G047_GBETH_1_CLK_PTP_REF_I, @@ -282,6 +284,16 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = { BUS_MSTOP(7, BIT(12))), DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16, BUS_MSTOP(7, BIT(14))), + DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19, + BUS_MSTOP(7, BIT(7))), + DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20, + BUS_MSTOP(7, BIT(8))), + DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21, + BUS_MSTOP(7, BIT(9))), + DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22, + BUS_MSTOP(7, BIT(10))), + DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23, + BUS_MSTOP(7, BIT(11))), DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_i", CLK_SMUX2_GBE0_TXCLK, 11, 8, 5, 24, BUS_MSTOP(8, BIT(5)), 1), DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_i", CLK_SMUX2_GBE0_RXCLK, 11, 9, 5, 25, @@ -359,6 +371,10 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = { DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */ DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */ + DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */ + DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */ + DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */ + DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */ DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */ From 0f537c41831aea18e54d889350e706e221beda63 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Fri, 10 Oct 2025 10:43:10 +0100 Subject: [PATCH 044/684] clk: renesas: r9a09g057: Add clock and reset entries for ISP Add entries detailing the clocks and resets for the ISP in the RZ/V2H(P) SoC. Signed-off-by: Daniel Scally Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251010-rzv2h_isp_clk-v2-1-2c8853a9af7c@ideasonboard.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g057-cpg.c | 14 ++++++++++++++ drivers/clk/renesas/rzv2h-cpg.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index 6389c4b6a5231e..c9c117c6782cb2 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -55,6 +55,7 @@ enum clk_ids { CLK_PLLVDO_CRU1, CLK_PLLVDO_CRU2, CLK_PLLVDO_CRU3, + CLK_PLLVDO_ISP, CLK_PLLETH_DIV_250_FIX, CLK_PLLETH_DIV_125_FIX, CLK_CSDIV_PLLETH_GBE0, @@ -157,6 +158,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4), DEF_DDIV(".pllvdo_cru2", CLK_PLLVDO_CRU2, CLK_PLLVDO, CDDIV4_DIVCTL1, dtable_2_4), DEF_DDIV(".pllvdo_cru3", CLK_PLLVDO_CRU3, CLK_PLLVDO, CDDIV4_DIVCTL2, dtable_2_4), + DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64), DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4), DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2), @@ -371,6 +373,14 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { BUS_MSTOP(9, BIT(7))), DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29, BUS_MSTOP(9, BIT(7))), + DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2, + BUS_MSTOP(9, BIT(8))), + DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3, + BUS_MSTOP(9, BIT(8))), + DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4, + BUS_MSTOP(9, BIT(9))), + DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5, + BUS_MSTOP(9, BIT(9))), DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16, BUS_MSTOP(3, BIT(4))), DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17, @@ -442,6 +452,10 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = { DEF_RST(12, 14, 5, 31), /* CRU_3_PRESETN */ DEF_RST(12, 15, 6, 0), /* CRU_3_ARESETN */ DEF_RST(13, 0, 6, 1), /* CRU_3_S_RESETN */ + DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */ + DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */ + DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */ + DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */ DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */ diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index 840eed25aeda72..e020d9624dfd75 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -115,6 +115,7 @@ struct fixed_mod_conf { #define CPG_SSEL1 (0x304) #define CPG_CDDIV0 (0x400) #define CPG_CDDIV1 (0x404) +#define CPG_CDDIV2 (0x408) #define CPG_CDDIV3 (0x40C) #define CPG_CDDIV4 (0x410) #define CPG_CSDIV0 (0x500) @@ -125,6 +126,7 @@ struct fixed_mod_conf { #define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5) #define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6) #define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7) +#define CDDIV2_DIVCTL3 DDIV_PACK(CPG_CDDIV2, 12, 3, 11) #define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13) #define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14) #define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15) From e1106d624cd72d7b526b2181ec9d30d431e6c559 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Oct 2025 10:30:23 +0300 Subject: [PATCH 045/684] pinctrl: tegra20: register csus_mux clock Add csus_mux for further use as the csus clock parent, similar to how the cdev1 and cdev2 muxes are utilized. Additionally, constify the cdev parent name lists to resolve checkpatch warnings. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Mikko Perttunen Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra20.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c index 737fc2000f66b9..1a1758fd7defe8 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra20.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -2222,14 +2222,18 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = { .drvtype_in_mux = false, }; -static const char *cdev1_parents[] = { +static const char * const cdev1_parents[] = { "dev1_osc_div", "pll_a_out0", "pll_m_out1", "audio", }; -static const char *cdev2_parents[] = { +static const char * const cdev2_parents[] = { "dev2_osc_div", "hclk", "pclk", "pll_p_out4", }; +static const char * const csus_parents[] = { + "pll_c_out1", "pll_p_out2", "pll_p_out3", "vi_sensor", +}; + static void tegra20_pinctrl_register_clock_muxes(struct platform_device *pdev) { struct tegra_pmx *pmx = platform_get_drvdata(pdev); @@ -2239,6 +2243,9 @@ static void tegra20_pinctrl_register_clock_muxes(struct platform_device *pdev) clk_register_mux(NULL, "cdev2_mux", cdev2_parents, 4, 0, pmx->regs[1] + 0x8, 4, 2, CLK_MUX_READ_ONLY, NULL); + + clk_register_mux(NULL, "csus_mux", csus_parents, 4, 0, + pmx->regs[1] + 0x8, 6, 2, CLK_MUX_READ_ONLY, NULL); } static int tegra20_pinctrl_probe(struct platform_device *pdev) From b7b76f607a15f16031001687e733046b5f6f5d86 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:04 -0700 Subject: [PATCH 046/684] perf parse-events: Fix legacy cache events if event is duplicated in a PMU The term list when adding an event to a PMU is expected to have the event name for the alias lookup. Also, set found_supported so that -EINVAL isn't returned. Fixes: 62593394f66a ("perf parse-events: Legacy cache names on all PMUs and lower priority") Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 28 +++++++++++++++++++++++++++- tools/perf/util/parse-events.h | 3 ++- tools/perf/util/parse-events.y | 2 +- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index da73d686f6b937..90a765016f64f3 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -475,8 +475,10 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state, int parse_events_add_cache(struct list_head *list, int *idx, const char *name, struct parse_events_state *parse_state, - struct parse_events_terms *parsed_terms) + struct parse_events_terms *parsed_terms, + void *loc_) { + YYLTYPE *loc = loc_; struct perf_pmu *pmu = NULL; bool found_supported = false; const char *config_name = get_config_name(parsed_terms); @@ -497,12 +499,36 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name, * The PMU has the event so add as not a legacy cache * event. */ + struct parse_events_terms temp_terms; + struct parse_events_term *term; + char *config = strdup(name); + + if (!config) + goto out_err; + + parse_events_terms__init(&temp_terms); + if (!parsed_terms) + parsed_terms = &temp_terms; + + if (parse_events_term__num(&term, + PARSE_EVENTS__TERM_TYPE_USER, + config, /*num=*/1, /*novalue=*/true, + loc, /*loc_val=*/NULL) < 0) { + zfree(&config); + goto out_err; + } + list_add(&term->list, &parsed_terms->terms); + ret = parse_events_add_pmu(parse_state, list, pmu, parsed_terms, first_wildcard_match, /*alternate_hw_config=*/PERF_COUNT_HW_MAX); + list_del_init(&term->list); + parse_events_term__delete(term); + parse_events_terms__exit(&temp_terms); if (ret) goto out_err; + found_supported = true; if (first_wildcard_match == NULL) first_wildcard_match = container_of(list->prev, struct evsel, core.node); diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 8f8c8e7fbcf186..8af19dec6a17da 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -237,7 +237,8 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, bool wildcard); int parse_events_add_cache(struct list_head *list, int *idx, const char *name, struct parse_events_state *parse_state, - struct parse_events_terms *parsed_terms); + struct parse_events_terms *parsed_terms, + void *loc); int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config); int parse_events_add_breakpoint(struct parse_events_state *parse_state, struct list_head *list, diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index a2361c0040d759..ced26c549c33ac 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -353,7 +353,7 @@ PE_LEGACY_CACHE opt_event_config if (!list) YYNOMEM; - err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); + err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2, &@1); parse_events_terms__delete($2); free($1); From 7c0135e4d7394832b562896241bc6dc943120f18 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:05 -0700 Subject: [PATCH 047/684] perf perf_api_probe: Avoid scanning all PMUs, try software PMU first Scan the software PMU first rather than last as it is the least likely to fail the probe. Specifying the software PMU by name was enabled by commit 9957d8c801fe ("perf jevents: Add common software event json"). For hardware events, add core PMU names when getting events to probe so that not all PMUs are scanned. For example, when legacy events support wildcards and for the event "cycles:u" on x86, we want to only scan the "cpu" PMU and not all uncore PMUs for the event too. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/perf_api_probe.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/perf_api_probe.c b/tools/perf/util/perf_api_probe.c index 1de3b69cdf4aaf..6ecf38314f01c6 100644 --- a/tools/perf/util/perf_api_probe.c +++ b/tools/perf/util/perf_api_probe.c @@ -59,10 +59,10 @@ static int perf_do_probe_api(setup_probe_fn_t fn, struct perf_cpu cpu, const cha static bool perf_probe_api(setup_probe_fn_t fn) { - const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; + struct perf_pmu *pmu; struct perf_cpu_map *cpus; struct perf_cpu cpu; - int ret, i = 0; + int ret = 0; cpus = perf_cpu_map__new_online_cpus(); if (!cpus) @@ -70,12 +70,23 @@ static bool perf_probe_api(setup_probe_fn_t fn) cpu = perf_cpu_map__cpu(cpus, 0); perf_cpu_map__put(cpus); - do { - ret = perf_do_probe_api(fn, cpu, try[i++]); - if (!ret) - return true; - } while (ret == -EAGAIN && try[i]); - + ret = perf_do_probe_api(fn, cpu, "software/cpu-clock/u"); + if (!ret) + return true; + + pmu = perf_pmus__scan_core(/*pmu=*/NULL); + if (pmu) { + const char *try[] = {"cycles", "instructions", NULL}; + char buf[256]; + int i = 0; + + while (ret == -EAGAIN && try[i]) { + snprintf(buf, sizeof(buf), "%s/%s/u", pmu->name, try[i++]); + ret = perf_do_probe_api(fn, cpu, buf); + if (!ret) + return true; + } + } return false; } From 8079c4c6b9faf2399859fe64f8559e31b336be45 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:06 -0700 Subject: [PATCH 048/684] perf stat: Avoid wildcarding PMUs for default events Without a PMU perf matches an event against any PMU with the event. Unfortunately some PMU drivers advertise a "cycles" event which is typically just a core event. To make perf's behavior consistent, just look up default events with their designated PMU types. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 133 +++++++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 39 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4314012846ba34..3c3188a57016f8 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1853,6 +1853,38 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) return 0; } +/* Add given software event to evlist without wildcarding. */ +static int parse_software_event(struct evlist *evlist, const char *event, + struct parse_events_error *err) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), "software/%s,name=%s/", event, event); + return parse_events(evlist, buf, err); +} + +/* Add legacy hardware/hardware-cache event to evlist for all core PMUs without wildcarding. */ +static int parse_hardware_event(struct evlist *evlist, const char *event, + struct parse_events_error *err) +{ + char buf[256]; + struct perf_pmu *pmu = NULL; + + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { + int ret; + + if (perf_pmus__num_core_pmus() == 1) + snprintf(buf, sizeof(buf), "%s/%s,name=%s/", pmu->name, event, event); + else + snprintf(buf, sizeof(buf), "%s/%s/", pmu->name, event); + + ret = parse_events(evlist, buf, err); + if (ret) + return ret; + } + return 0; +} + /* * Add default events, if there were no attributes specified or * if -d/--detailed, -d -d or -d -d -d is used: @@ -1976,26 +2008,31 @@ static int add_default_events(void) if (!evlist->core.nr_entries && !evsel_list->core.nr_entries) { /* No events so add defaults. */ - if (target__has_cpu(&target)) - ret = parse_events(evlist, "cpu-clock", &err); - else - ret = parse_events(evlist, "task-clock", &err); - if (ret) - goto out; - - ret = parse_events(evlist, - "context-switches," - "cpu-migrations," - "page-faults," - "instructions," - "cycles," - "stalled-cycles-frontend," - "stalled-cycles-backend," - "branches," - "branch-misses", - &err); - if (ret) - goto out; + const char *sw_events[] = { + target__has_cpu(&target) ? "cpu-clock" : "task-clock", + "context-switches", + "cpu-migrations", + "page-faults", + }; + const char *hw_events[] = { + "instructions", + "cycles", + "stalled-cycles-frontend", + "stalled-cycles-backend", + "branches", + "branch-misses", + }; + + for (size_t i = 0; i < ARRAY_SIZE(sw_events); i++) { + ret = parse_software_event(evlist, sw_events[i], &err); + if (ret) + goto out; + } + for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { + ret = parse_hardware_event(evlist, hw_events[i], &err); + if (ret) + goto out; + } /* * Add TopdownL1 metrics if they exist. To minimize @@ -2037,35 +2074,53 @@ static int add_default_events(void) * Detailed stats (-d), covering the L1 and last level data * caches: */ - ret = parse_events(evlist, - "L1-dcache-loads," - "L1-dcache-load-misses," - "LLC-loads," - "LLC-load-misses", - &err); + const char *hw_events[] = { + "L1-dcache-loads", + "L1-dcache-load-misses", + "LLC-loads", + "LLC-load-misses", + }; + + for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { + ret = parse_hardware_event(evlist, hw_events[i], &err); + if (ret) + goto out; + } } if (!ret && detailed_run >= 2) { /* * Very detailed stats (-d -d), covering the instruction cache * and the TLB caches: */ - ret = parse_events(evlist, - "L1-icache-loads," - "L1-icache-load-misses," - "dTLB-loads," - "dTLB-load-misses," - "iTLB-loads," - "iTLB-load-misses", - &err); + const char *hw_events[] = { + "L1-icache-loads", + "L1-icache-load-misses", + "dTLB-loads", + "dTLB-load-misses", + "iTLB-loads", + "iTLB-load-misses", + }; + + for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { + ret = parse_hardware_event(evlist, hw_events[i], &err); + if (ret) + goto out; + } } if (!ret && detailed_run >= 3) { /* * Very, very detailed stats (-d -d -d), adding prefetch events: */ - ret = parse_events(evlist, - "L1-dcache-prefetches," - "L1-dcache-prefetch-misses", - &err); + const char *hw_events[] = { + "L1-dcache-prefetches", + "L1-dcache-prefetch-misses", + }; + + for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { + ret = parse_hardware_event(evlist, hw_events[i], &err); + if (ret) + goto out; + } } out: if (!ret) { @@ -2074,7 +2129,7 @@ static int add_default_events(void) * Make at least one event non-skippable so fatal errors are visible. * 'cycles' always used to be default and non-skippable, so use that. */ - if (strcmp("cycles", evsel__name(evsel))) + if (!evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) evsel->skippable = true; } } From ee27476fa3004f83e82fc88d859586c99c8a81a3 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:07 -0700 Subject: [PATCH 049/684] perf record: Skip don't fail for events that don't open Whilst for many tools it is an expected behavior that failure to open a perf event is a failure, ARM decided to name PMU events the same as legacy events and then failed to rename such events on a server uncore SLC PMU. As perf's default behavior when no PMU is specified is to open the event on all PMUs that advertise/"have" the event, this yielded failures when trying to make the priority of legacy and sysfs/json events uniform - something requested by RISC-V and ARM. A legacy event user on ARM hardware may find their event opened on an uncore PMU which for perf record will fail. Arnaldo suggested skipping such events which this patch implements. Rather than have the skipping conditional on running on ARM, the skipping is done on all architectures as such a fundamental behavioral difference could lead to problems with tools built/depending on perf. An example of perf record failing to open events on x86 is: ``` $ perf record -e data_read,cycles,LLC-prefetch-read -a sleep 0.1 Error: Failure to open event 'data_read' on PMU 'uncore_imc_free_running_0' which will be removed. The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (data_read). "dmesg | grep -i perf" may provide additional information. Error: Failure to open event 'data_read' on PMU 'uncore_imc_free_running_1' which will be removed. The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (data_read). "dmesg | grep -i perf" may provide additional information. Error: Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be removed. The LLC-prefetch-read event is not supported. [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 2.188 MB perf.data (87 samples) ] $ perf report --stats Aggregated stats: TOTAL events: 17255 MMAP events: 284 ( 1.6%) COMM events: 1961 (11.4%) EXIT events: 1 ( 0.0%) FORK events: 1960 (11.4%) SAMPLE events: 87 ( 0.5%) MMAP2 events: 12836 (74.4%) KSYMBOL events: 83 ( 0.5%) BPF_EVENT events: 36 ( 0.2%) FINISHED_ROUND events: 2 ( 0.0%) ID_INDEX events: 1 ( 0.0%) THREAD_MAP events: 1 ( 0.0%) CPU_MAP events: 1 ( 0.0%) TIME_CONV events: 1 ( 0.0%) FINISHED_INIT events: 1 ( 0.0%) cycles stats: SAMPLE events: 87 ``` If all events fail to open then the perf record will fail: ``` $ perf record -e LLC-prefetch-read true Error: Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be removed. The LLC-prefetch-read event is not supported. Error: Failure to open any events for recording ``` As an evlist may have dummy events that open when all command line events fail we ignore dummy events when detecting if at least some events open. This still permits the dummy event on its own to be used as a permission check: ``` $ perf record -e dummy true [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.046 MB perf.data ] ``` but allows failure when a dummy event is implicilty inserted or when there are insufficient permissions to open it: ``` $ perf record -e LLC-prefetch-read -a true Error: Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be removed. The LLC-prefetch-read event is not supported. Error: Failure to open any events for recording ``` As the first parsed event in an evlist is marked as tracking, removing this event can remove tracking from the evlist, removing mmap events and breaking symbolization. To avoid this, if a tracking event is removed then the next event has tracking added. The issue with legacy events is that on RISC-V they want the driver to not have mappings from legacy to non-legacy config encodings for each vendor/model due to size, complexity and difficulty to update. It was reported that on ARM Apple-M? CPUs the legacy mapping in the driver was broken and the sysfs/json events should always take precedent, however, it isn't clear this is still the case. It is the case that without working around this issue a legacy event like cycles without a PMU can encode differently than when specified with a PMU - the non-PMU version favoring legacy encodings, the PMU one avoiding legacy encodings. Legacy events are also case sensitive while sysfs/json events are not. The patch removes events and then adjusts the idx value for each evsel. This is done so that the dense xyarrays used for file descriptors, etc. don't contain broken entries. On ARM it could be common following this change to see a lot of warnings for the cycles event due to many ARM PMUs advertising the cycles event (ARM inconsistently have events bus_cycles and then cycles implying CPU cycles, they also sometimes have a cpu_cycles event). As cycles is a popular event, avoid potentially spamming users with error messages on ARM when there are multiple cycles events in the evlist, the error is still shown when verbose is enabled. Prior versions without adding the tracking data and not warning for cycles on ARM was: Suggested-by: Arnaldo Carvalho de Melo Tested-by: James Clark Tested-by: Leo Yan Tested-by: Atish Patra Tested-by: Thomas Richter Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 85 ++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d76f01956e33b4..26d8da560446f1 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -983,7 +983,6 @@ static int record__config_tracking_events(struct record *rec) */ if (opts->target.initial_delay || target__has_cpu(&opts->target) || perf_pmus__num_core_pmus() > 1) { - /* * User space tasks can migrate between CPUs, so when tracing * selected CPUs, sideband for all CPUs is still needed. @@ -1388,10 +1387,27 @@ static int record__open(struct record *rec) struct perf_session *session = rec->session; struct record_opts *opts = &rec->opts; int rc = 0; + bool skipped = false; + bool removed_tracking = false; evlist__for_each_entry(evlist, pos) { + if (removed_tracking) { + /* + * Normally the head of the list has tracking enabled + * for sideband data like mmaps. If this event is + * removed, make sure to add tracking to the next + * processed event. + */ + if (!pos->tracking) { + pos->tracking = true; + evsel__config(pos, opts, &callchain_param); + } + removed_tracking = false; + } try_again: if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { + bool report_error = true; + if (evsel__fallback(pos, &opts->target, errno, msg, sizeof(msg))) { if (verbose > 0) ui__warning("%s\n", msg); @@ -1403,13 +1419,72 @@ static int record__open(struct record *rec) pos = evlist__reset_weak_group(evlist, pos, true); goto try_again; } - rc = -errno; - evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg)); - ui__error("%s\n", msg); - goto out; +#if defined(__aarch64__) || defined(__arm__) + if (strstr(evsel__name(pos), "cycles")) { + struct evsel *pos2; + /* + * Unfortunately ARM has many events named + * "cycles" on PMUs like the system-level (L3) + * cache which don't support sampling. Only + * display such failures to open when there is + * only 1 cycles event or verbose is enabled. + */ + evlist__for_each_entry(evlist, pos2) { + if (pos2 == pos) + continue; + if (strstr(evsel__name(pos2), "cycles")) { + report_error = false; + break; + } + } + } +#endif + if (report_error || verbose > 0) { + ui__error("Failure to open event '%s' on PMU '%s' which will be " + "removed.\n%s\n", + evsel__name(pos), evsel__pmu_name(pos), msg); + } + if (pos->tracking) + removed_tracking = true; + pos->skippable = true; + skipped = true; } } + if (skipped) { + struct evsel *tmp; + int idx = 0; + bool evlist_empty = true; + + /* Remove evsels that failed to open and update indices. */ + evlist__for_each_entry_safe(evlist, tmp, pos) { + if (pos->skippable) { + evlist__remove(evlist, pos); + continue; + } + + /* + * Note, dummy events may be command line parsed or + * added by the tool. We care about supporting `perf + * record -e dummy` which may be used as a permission + * check. Dummy events that are added to the command + * line and opened along with other events that fail, + * will still fail as if the dummy events were tool + * added events for the sake of code simplicity. + */ + if (!evsel__is_dummy_event(pos)) + evlist_empty = false; + } + evlist__for_each_entry(evlist, pos) { + pos->core.idx = idx++; + } + /* If list is empty then fail. */ + if (evlist_empty) { + ui__error("Failure to open any events for recording.\n"); + rc = -1; + goto out; + } + } if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) { pr_warning( "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" From 4bb55de4ff03db3e8b204c9c804cef3cad29a271 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:08 -0700 Subject: [PATCH 050/684] perf jevents: Support copying the source json files to OUTPUT The jevents command expects all json files to be organized under a single directory. When generating json files from scripts (to reduce laborious copy and paste in the json) we don't want to generate the json into the source directory if there is an OUTPUT directory specified. This change adds a GEN_JSON for this case where the GEN_JSON copies the JSON files to OUTPUT, only when OUTPUT is specified. The Makefile.perf clean code is updated to clean up this directory when present. This patch is part of: https://lore.kernel.org/lkml/20240926173554.404411-12-irogers@google.com/ which was similarly adding support for generating json in scripts for the consumption of jevents.py. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/Makefile.perf | 21 ++++++++++++++++----- tools/perf/pmu-events/Build | 18 ++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 47c906b807ef25..afeb4e4a8a318a 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1272,9 +1272,24 @@ endif # CONFIG_PERF_BPF_SKEL bpf-skel-clean: $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) $(SKEL_OUT)/vmlinux.h +pmu-events-clean: +ifeq ($(OUTPUT),) + $(call QUIET_CLEAN, pmu-events) $(RM) \ + pmu-events/pmu-events.c \ + pmu-events/metric_test.log \ + pmu-events/test-empty-pmu-events.c \ + pmu-events/empty-pmu-events.log +else # When an OUTPUT directory is present, clean up the copied pmu-events/arch directory. + $(call QUIET_CLEAN, pmu-events) $(RM) -r $(OUTPUT)pmu-events/arch \ + $(OUTPUT)pmu-events/pmu-events.c \ + $(OUTPUT)pmu-events/metric_test.log \ + $(OUTPUT)pmu-events/test-empty-pmu-events.c \ + $(OUTPUT)pmu-events/empty-pmu-events.log +endif + clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(LIBPERF)-clean \ arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean \ - tests-coresight-targets-clean + tests-coresight-targets-clean pmu-events-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive \ $(OUTPUT)perf-iostat $(LANG_BINDINGS) $(Q)find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '*.a' -delete -o \ @@ -1287,10 +1302,6 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $( $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ $(OUTPUT)util/intel-pt-decoder/inat-tables.c \ $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ - $(OUTPUT)pmu-events/pmu-events.c \ - $(OUTPUT)pmu-events/test-empty-pmu-events.c \ - $(OUTPUT)pmu-events/empty-pmu-events.log \ - $(OUTPUT)pmu-events/metric_test.log \ $(OUTPUT)$(fadvise_advice_array) \ $(OUTPUT)$(fsconfig_arrays) \ $(OUTPUT)$(fsmount_arrays) \ diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index 32f387d4890880..1503a16e662ae2 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -1,7 +1,6 @@ pmu-events-y += pmu-events.o JDIR = pmu-events/arch/$(SRCARCH) -JSON = $(shell [ -d $(JDIR) ] && \ - find $(JDIR) -name '*.json' -o -name 'mapfile.csv') +JSON = $(shell find pmu-events/arch -name *.json -o -name *.csv) JDIR_TEST = pmu-events/arch/test JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \ find $(JDIR_TEST) -name '*.json') @@ -29,13 +28,20 @@ $(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C) $(call rule_mkdir) $(Q)$(call echo-cmd,gen)cp $< $@ else +# Copy checked-in json for generation. +$(OUTPUT)pmu-events/arch/%: pmu-events/arch/% + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)cp $< $@ + +GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) + $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY) $(call rule_mkdir) $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false) -$(TEST_EMPTY_PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) +$(TEST_EMPTY_PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) $(call rule_mkdir) - $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none pmu-events/arch $@ + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none $(OUTPUT)pmu-events/arch $@ $(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C) $(call rule_mkdir) @@ -63,10 +69,10 @@ $(OUTPUT)%.pylint_log: % $(call rule_mkdir) $(Q)$(call echo-cmd,test)pylint "$<" > $@ || (cat $@ && rm $@ && false) -$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) \ +$(PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) \ $(EMPTY_PMU_EVENTS_TEST_LOG) $(PMU_EVENTS_MYPY_TEST_LOGS) $(PMU_EVENTS_PYLINT_TEST_LOGS) $(call rule_mkdir) - $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) pmu-events/arch $@ + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUTPUT)pmu-events/arch $@ endif # pmu-events.c file is generated in the OUTPUT directory so it needs a From 84bae3af20d0b6c5d23b4f7558c2eaa7d59c9157 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:09 -0700 Subject: [PATCH 051/684] perf pmu: Don't eagerly parse event terms When an event/alias is created for a PMU the terms are eagerly parsed using parse_events_terms. For a command like perf stat or perf record, the particular event/alias will be found, the terms parsed, the terms cloned for use in the event parsing, and then the terms used to configure the perf_event_attr. Events/aliases may be eagerly loaded, such as from sysfs or in perf list, in which case the aliases terms will be little or never used. To avoid redundant work, to avoid cloning, and to reduce memory overhead, hold the terms for an event as a string until they need handling as a term list. This may introduce duplicate parsing if an event is repeated in a list, but this situation is expected to be uncommon. Measuring the number of instructions before and after with a sysfs event and perf stat, there is a minor reduction in the number of instructions executed by 0.3%. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/pmu-events.c | 24 +------ tools/perf/util/parse-events.c | 3 +- tools/perf/util/parse-events.h | 1 - tools/perf/util/pmu.c | 111 ++++++++++++++++++++------------- 4 files changed, 70 insertions(+), 69 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 95fd9f671a22b5..f40a828c9861af 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -22,10 +22,6 @@ struct perf_pmu_test_event { /* used for matching against events from generated pmu-events.c */ struct pmu_event event; - /* used for matching against event aliases */ - /* extra events for aliases */ - const char *alias_str; - /* * Note: For when PublicDescription does not exist in the JSON, we * will have no long_desc in pmu_event.long_desc, but long_desc may @@ -52,7 +48,6 @@ static const struct perf_pmu_test_event bp_l1_btb_correct = { .desc = "L1 BTB Correction", .topic = "branch", }, - .alias_str = "event=0x8a", }; static const struct perf_pmu_test_event bp_l2_btb_correct = { @@ -63,7 +58,6 @@ static const struct perf_pmu_test_event bp_l2_btb_correct = { .desc = "L2 BTB Correction", .topic = "branch", }, - .alias_str = "event=0x8b", }; static const struct perf_pmu_test_event segment_reg_loads_any = { @@ -74,7 +68,6 @@ static const struct perf_pmu_test_event segment_reg_loads_any = { .desc = "Number of segment register loads", .topic = "other", }, - .alias_str = "event=0x6,period=0x30d40,umask=0x80", }; static const struct perf_pmu_test_event dispatch_blocked_any = { @@ -85,7 +78,6 @@ static const struct perf_pmu_test_event dispatch_blocked_any = { .desc = "Memory cluster signals to block micro-op dispatch for any reason", .topic = "other", }, - .alias_str = "event=0x9,period=0x30d40,umask=0x20", }; static const struct perf_pmu_test_event eist_trans = { @@ -96,7 +88,6 @@ static const struct perf_pmu_test_event eist_trans = { .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", .topic = "other", }, - .alias_str = "event=0x3a,period=0x30d40", }; static const struct perf_pmu_test_event l3_cache_rd = { @@ -108,7 +99,6 @@ static const struct perf_pmu_test_event l3_cache_rd = { .long_desc = "Attributable Level 3 cache access, read", .topic = "cache", }, - .alias_str = "event=0x40", .alias_long_desc = "Attributable Level 3 cache access, read", }; @@ -130,7 +120,6 @@ static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = { .topic = "uncore", .pmu = "hisi_sccl,ddrc", }, - .alias_str = "event=0x2", .matching_pmu = "hisi_sccl1_ddrc2", }; @@ -142,7 +131,6 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { .topic = "uncore", .pmu = "uncore_cbox", }, - .alias_str = "event=0x22,umask=0x81", .matching_pmu = "uncore_cbox_0", }; @@ -154,7 +142,6 @@ static const struct perf_pmu_test_event uncore_hyphen = { .topic = "uncore", .pmu = "uncore_cbox", }, - .alias_str = "event=0xe0", .matching_pmu = "uncore_cbox_0", }; @@ -166,7 +153,6 @@ static const struct perf_pmu_test_event uncore_two_hyph = { .topic = "uncore", .pmu = "uncore_cbox", }, - .alias_str = "event=0xc0", .matching_pmu = "uncore_cbox_0", }; @@ -178,7 +164,6 @@ static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = { .topic = "uncore", .pmu = "hisi_sccl,l3c", }, - .alias_str = "event=0x7", .matching_pmu = "hisi_sccl3_l3c7", }; @@ -190,7 +175,6 @@ static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = { .topic = "uncore", .pmu = "uncore_imc_free_running", }, - .alias_str = "event=0x12", .matching_pmu = "uncore_imc_free_running_0", }; @@ -202,7 +186,6 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = { .topic = "uncore", .pmu = "uncore_imc", }, - .alias_str = "event=0x34", .matching_pmu = "uncore_imc_0", }; @@ -226,7 +209,6 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = { .pmu = "uncore_sys_ddr_pmu", .compat = "v8", }, - .alias_str = "event=0x2b", .matching_pmu = "uncore_sys_ddr_pmu0", }; @@ -239,7 +221,6 @@ static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = { .pmu = "uncore_sys_ccn_pmu", .compat = "0x01", }, - .alias_str = "config=0x2c", .matching_pmu = "uncore_sys_ccn_pmu4", }; @@ -252,7 +233,6 @@ static const struct perf_pmu_test_event sys_cmn_pmu_hnf_cache_miss = { .pmu = "uncore_sys_cmn_pmu", .compat = "(434|436|43c|43a).*", }, - .alias_str = "eventid=0x1,type=0x5", .matching_pmu = "uncore_sys_cmn_pmu0", }; @@ -374,9 +354,9 @@ static int compare_alias_to_test_event(struct pmu_event_info *alias, return -1; } - if (!is_same(alias->str, test_event->alias_str)) { + if (!is_same(alias->str, test_event->event.event)) { pr_debug("testing aliases PMU %s: mismatched str, %s vs %s\n", - pmu_name, alias->str, test_event->alias_str); + pmu_name, alias->str, test_event->event.event); return -1; } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 90a765016f64f3..8f320d08cf1f4c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -40,6 +40,7 @@ static int get_config_terms(const struct parse_events_terms *head_config, struct list_head *head_terms); static int parse_events_terms__copy(const struct parse_events_terms *src, struct parse_events_terms *dest); +static int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); const struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = { @@ -2876,7 +2877,7 @@ void parse_events_terms__delete(struct parse_events_terms *terms) free(terms); } -int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb) +static int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb) { struct parse_events_term *term; bool first = true; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 8af19dec6a17da..ed7b7359113969 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -200,7 +200,6 @@ void parse_events_terms__delete(struct parse_events_terms *terms); void parse_events_terms__init(struct parse_events_terms *terms); void parse_events_terms__exit(struct parse_events_terms *terms); int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input); -int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); struct parse_events_modifier { u8 precise; /* Number of repeated 'p' for precision. */ diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 3d1f975e8db9fe..102fabfbf1d54c 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -67,8 +67,8 @@ struct perf_pmu_alias { * json events. */ char *topic; - /** @terms: Owned list of the original parsed parameters. */ - struct parse_events_terms terms; + /** @terms: Owned copy of the event terms. */ + char *terms; /** * @pmu_name: The name copied from the json struct pmu_event. This can * differ from the PMU name as it won't have suffixes. @@ -429,7 +429,7 @@ static void perf_pmu_free_alias(struct perf_pmu_alias *alias) zfree(&alias->long_desc); zfree(&alias->topic); zfree(&alias->pmu_name); - parse_events_terms__exit(&alias->terms); + zfree(&alias->terms); free(alias); } @@ -537,8 +537,8 @@ static int update_alias(const struct pmu_event *pe, assign_str(pe->name, "topic", &data->alias->topic, pe->topic); data->alias->per_pkg = pe->perpkg; if (pe->event) { - parse_events_terms__exit(&data->alias->terms); - ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); + zfree(&data->alias->terms); + data->alias->terms = strdup(pe->event); } if (!ret && pe->unit) { char *unit; @@ -590,7 +590,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, if (!alias) return -ENOMEM; - parse_events_terms__init(&alias->terms); alias->scale = 1.0; alias->unit[0] = '\0'; alias->per_pkg = perpkg; @@ -615,11 +614,16 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, if (ret) return ret; - ret = parse_events_terms(&alias->terms, val, val_fd); - if (ret) { - pr_err("Cannot parse alias %s: %d\n", val, ret); - free(alias); - return ret; + if (!val_fd) { + alias->terms = strdup(val); + } else { + size_t line_len; + + ret = getline(&alias->terms, &line_len, val_fd) < 0 ? -errno : 0; + if (ret) { + pr_err("Failed to read alias %s\n", name); + return ret; + } } alias->name = strdup(name); @@ -767,29 +771,21 @@ static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd) return ret; } -static int pmu_alias_terms(struct perf_pmu_alias *alias, int err_loc, struct list_head *terms) +static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms) { - struct parse_events_term *term, *cloned; - struct parse_events_terms clone_terms; - - parse_events_terms__init(&clone_terms); - list_for_each_entry(term, &alias->terms.terms, list) { - int ret = parse_events_term__clone(&cloned, term); + struct parse_events_terms alias_terms; + int ret; - if (ret) { - parse_events_terms__exit(&clone_terms); - return ret; - } - /* - * Weak terms don't override command line options, - * which we don't want for implicit terms in aliases. - */ - cloned->weak = true; - cloned->err_term = cloned->err_val = err_loc; - list_add_tail(&cloned->list, &clone_terms.terms); + parse_events_terms__init(&alias_terms); + ret = parse_events_terms(&alias_terms, alias->terms, /*input=*/NULL); + if (ret) { + pr_err("Cannot parse '%s' terms '%s': %d\n", + alias->name, alias->terms, ret); + parse_events_terms__exit(&alias_terms); + return ret; } - list_splice_init(&clone_terms.terms, terms); - parse_events_terms__exit(&clone_terms); + list_splice_init(&alias_terms.terms, terms); + parse_events_terms__exit(&alias_terms); return 0; } @@ -1813,10 +1809,10 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_ alias = pmu_find_alias(pmu, term); if (!alias) continue; - ret = pmu_alias_terms(alias, term->err_term, &term->list); + ret = pmu_alias_terms(alias, &term->list); if (ret) { parse_events_error__handle(err, term->err_term, - strdup("Failure to duplicate terms"), + strdup("Failed to parse terms"), NULL); return ret; } @@ -2036,18 +2032,37 @@ static int sub_non_neg(int a, int b) static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, const struct perf_pmu_alias *alias, bool skip_duplicate_pmus) { + struct parse_events_terms terms; struct parse_events_term *term; + int ret, used; size_t pmu_name_len = pmu_deduped_name_len(pmu, pmu->name, skip_duplicate_pmus); - int used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name); - list_for_each_entry(term, &alias->terms.terms, list) { + /* Paramemterized events have the parameters shown. */ + if (strstr(alias->terms, "=?")) { + /* No parameters. */ + snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); + return buf; + } + + parse_events_terms__init(&terms); + ret = parse_events_terms(&terms, alias->terms, /*input=*/NULL); + if (ret) { + pr_err("Failure to parse '%s' terms '%s': %d\n", + alias->name, alias->terms, ret); + parse_events_terms__exit(&terms); + snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); + return buf; + } + used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name); + + list_for_each_entry(term, &terms.terms, list) { if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) used += snprintf(buf + used, sub_non_neg(len, used), ",%s=%s", term->config, term->val.str); } - + parse_events_terms__exit(&terms); if (sub_non_neg(len, used) > 0) { buf[used] = '/'; used++; @@ -2070,7 +2085,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, .event_type_desc = "Kernel PMU event", }; int ret = 0; - struct strbuf sb; struct hashmap_entry *entry; size_t bkt; @@ -2081,7 +2095,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, if (perf_pmu__is_drm(pmu)) return drm_pmu__for_each_event(pmu, state, cb); - strbuf_init(&sb, /*hint=*/ 0); pmu_aliases_parse(pmu); pmu_add_cpu_aliases(pmu); hashmap__for_each_entry(pmu->aliases, entry, bkt) { @@ -2116,16 +2129,14 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, info.desc = event->desc; info.long_desc = event->long_desc; info.encoding_desc = buf + buf_used; - parse_events_terms__to_strbuf(&event->terms, &sb); buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, - "%.*s/%s/", (int)pmu_name_len, info.pmu_name, sb.buf) + 1; + "%.*s/%s/", (int)pmu_name_len, info.pmu_name, event->terms) + 1; + info.str = event->terms; info.topic = event->topic; - info.str = sb.buf; info.deprecated = event->deprecated; ret = cb(state, &info); if (ret) goto out; - strbuf_setlen(&sb, /*len=*/ 0); } if (pmu->selectable) { info.name = buf; @@ -2141,7 +2152,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, ret = cb(state, &info); } out: - strbuf_release(&sb); return ret; } @@ -2589,10 +2599,21 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config) hashmap__for_each_entry(pmu->aliases, entry, bkt) { struct perf_pmu_alias *event = entry->pvalue; struct perf_event_attr attr = {.config = 0,}; + struct parse_events_terms terms; + int ret; - int ret = perf_pmu__config(pmu, &attr, &event->terms, /*apply_hardcoded=*/true, - /*err=*/NULL); + parse_events_terms__init(&terms); + ret = parse_events_terms(&terms, event->terms, /*input=*/NULL); + if (ret) { + pr_debug("Failed to parse '%s' terms '%s': %d\n", + event->name, event->terms, ret); + parse_events_terms__exit(&terms); + continue; + } + ret = perf_pmu__config(pmu, &attr, &terms, /*apply_hardcoded=*/true, + /*err=*/NULL); + parse_events_terms__exit(&terms); if (ret == 0 && config == attr.config) return event->name; } From 5f68451a9356522920928391b84c6c21fd92c903 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:10 -0700 Subject: [PATCH 052/684] perf parse-events: Remove unused FILE input argument to scanner Now the events file isn't directly parsed from a FILE but stored in a string prior to parsing, remove the FILE argument to the associated scanner functions as they only ever pass NULL. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/util/intel-pt.c | 2 +- tools/perf/tests/parse-events.c | 2 +- tools/perf/tests/pmu.c | 3 +-- tools/perf/util/parse-events.c | 18 ++++++------------ tools/perf/util/parse-events.h | 3 +-- tools/perf/util/pmu.c | 6 +++--- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index add33cb5d1da8e..2d7c0dec86b073 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -72,7 +72,7 @@ static int intel_pt_parse_terms_with_default(const struct perf_pmu *pmu, int err; parse_events_terms__init(&terms); - err = parse_events_terms(&terms, str, /*input=*/ NULL); + err = parse_events_terms(&terms, str); if (err) goto out_free; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 67550cc60555dd..13c1e4c45ea203 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -2610,7 +2610,7 @@ static int test_term(const struct terms_test *t) parse_events_terms__init(&terms); - ret = parse_events_terms(&terms, t->str, /*input=*/ NULL); + ret = parse_events_terms(&terms, t->str); if (ret) { pr_debug("failed to parse terms '%s', err %d\n", t->str , ret); diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c index 4a9f8e090cf4b3..cbded2c6faa4d5 100644 --- a/tools/perf/tests/pmu.c +++ b/tools/perf/tests/pmu.c @@ -169,8 +169,7 @@ static int test__pmu_format(struct test_suite *test __maybe_unused, int subtest parse_events_terms__init(&terms); if (parse_events_terms(&terms, "krava01=15,krava02=170,krava03=1,krava11=27,krava12=1," - "krava13=2,krava21=119,krava22=11,krava23=2", - NULL)) { + "krava13=2,krava21=119,krava22=11,krava23=2")) { pr_err("Term parsing failed\n"); goto err_out; } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 8f320d08cf1f4c..e0f18e9c80002e 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1984,7 +1984,6 @@ int parse_events__set_default_name(struct list_head *list, char *name) } static int parse_events__scanner(const char *str, - FILE *input, struct parse_events_state *parse_state) { YY_BUFFER_STATE buffer; @@ -1995,10 +1994,7 @@ static int parse_events__scanner(const char *str, if (ret) return ret; - if (str) - buffer = parse_events__scan_string(str, scanner); - else - parse_events_set_in(input, scanner); + buffer = parse_events__scan_string(str, scanner); #ifdef PARSER_DEBUG parse_events_debug = 1; @@ -2006,10 +2002,8 @@ static int parse_events__scanner(const char *str, #endif ret = parse_events_parse(parse_state, scanner); - if (str) { - parse_events__flush_buffer(buffer, scanner); - parse_events__delete_buffer(buffer, scanner); - } + parse_events__flush_buffer(buffer, scanner); + parse_events__delete_buffer(buffer, scanner); parse_events_lex_destroy(scanner); return ret; } @@ -2017,7 +2011,7 @@ static int parse_events__scanner(const char *str, /* * parse event config string, return a list of event terms. */ -int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input) +int parse_events_terms(struct parse_events_terms *terms, const char *str) { struct parse_events_state parse_state = { .terms = NULL, @@ -2025,7 +2019,7 @@ int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE * }; int ret; - ret = parse_events__scanner(str, input, &parse_state); + ret = parse_events__scanner(str, &parse_state); if (!ret) list_splice(&parse_state.terms->terms, &terms->terms); @@ -2329,7 +2323,7 @@ int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filte }; int ret, ret2; - ret = parse_events__scanner(str, /*input=*/ NULL, &parse_state); + ret = parse_events__scanner(str, &parse_state); if (!ret && list_empty(&parse_state.list)) { WARN_ONCE(true, "WARNING: event parser found nothing\n"); diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ed7b7359113969..3052a48978f8b4 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -199,7 +198,7 @@ void parse_events_term__delete(struct parse_events_term *term); void parse_events_terms__delete(struct parse_events_terms *terms); void parse_events_terms__init(struct parse_events_terms *terms); void parse_events_terms__exit(struct parse_events_terms *terms); -int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input); +int parse_events_terms(struct parse_events_terms *terms, const char *str); struct parse_events_modifier { u8 precise; /* Number of repeated 'p' for precision. */ diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 102fabfbf1d54c..876e87708b03a5 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -777,7 +777,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms int ret; parse_events_terms__init(&alias_terms); - ret = parse_events_terms(&alias_terms, alias->terms, /*input=*/NULL); + ret = parse_events_terms(&alias_terms, alias->terms); if (ret) { pr_err("Cannot parse '%s' terms '%s': %d\n", alias->name, alias->terms, ret); @@ -2046,7 +2046,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, } parse_events_terms__init(&terms); - ret = parse_events_terms(&terms, alias->terms, /*input=*/NULL); + ret = parse_events_terms(&terms, alias->terms); if (ret) { pr_err("Failure to parse '%s' terms '%s': %d\n", alias->name, alias->terms, ret); @@ -2603,7 +2603,7 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config) int ret; parse_events_terms__init(&terms); - ret = parse_events_terms(&terms, event->terms, /*input=*/NULL); + ret = parse_events_terms(&terms, event->terms); if (ret) { pr_debug("Failed to parse '%s' terms '%s': %d\n", event->name, event->terms, ret); From 7f20b3dd93f6a10cd742c091f047464185b09eed Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:11 -0700 Subject: [PATCH 053/684] perf pmu: Use fd rather than FILE from new_alias The FILE argument was necessary for the scanner but now that functionality is not being used we can switch to just using io__getline which should cut down on stdio buffer usage. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 876e87708b03a5..7992bd923515a2 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -563,7 +563,7 @@ static int update_alias(const struct pmu_event *pe, } static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, - const char *desc, const char *val, FILE *val_fd, + const char *desc, const char *val, int val_fd, const struct pmu_event *pe, enum event_source src) { struct perf_pmu_alias *alias, *old_alias; @@ -614,12 +614,15 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, if (ret) return ret; - if (!val_fd) { + if (val_fd < 0) { alias->terms = strdup(val); } else { + char buf[256]; + struct io io; size_t line_len; - ret = getline(&alias->terms, &line_len, val_fd) < 0 ? -errno : 0; + io__init(&io, val_fd, buf, sizeof(buf)); + ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0; if (ret) { pr_err("Failed to read alias %s\n", name); return ret; @@ -698,7 +701,6 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd) while ((evt_ent = io_dir__readdir(&event_dir))) { char *name = evt_ent->d_name; int fd; - FILE *file; if (!strcmp(name, ".") || !strcmp(name, "..")) continue; @@ -714,17 +716,12 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd) pr_debug("Cannot open %s\n", name); continue; } - file = fdopen(fd, "r"); - if (!file) { - close(fd); - continue; - } if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, - /*val=*/ NULL, file, /*pe=*/ NULL, + /*val=*/ NULL, fd, /*pe=*/ NULL, EVENT_SRC_SYSFS) < 0) pr_debug("Cannot set up %s\n", name); - fclose(file); + close(fd); } pmu->sysfs_aliases_loaded = true; @@ -1041,7 +1038,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, { struct perf_pmu *pmu = vdata; - perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, + perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ -1, pe, EVENT_SRC_CPU_JSON); return 0; } @@ -1090,7 +1087,7 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, pe->name, pe->desc, pe->event, - /*val_fd=*/ NULL, + /*val_fd=*/ -1, pe, EVENT_SRC_SYS_JSON); } From 70424bb5ff5772635e86c6bcfaa9622bc222e1e6 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:12 -0700 Subject: [PATCH 054/684] perf pmu: Factor term parsing into a perf_event_attr into a helper Factor existing functionality in perf_pmu__name_from_config into a helper that will be used in later patches. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 7992bd923515a2..2c3e539851c480 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1763,6 +1763,24 @@ static int check_info_data(struct perf_pmu *pmu, return 0; } +static int perf_pmu__parse_terms_to_attr(struct perf_pmu *pmu, const char *terms_str, + struct perf_event_attr *attr) +{ + struct parse_events_terms terms; + int ret; + + parse_events_terms__init(&terms); + ret = parse_events_terms(&terms, terms_str); + if (ret) { + pr_debug("Failed to parse terms '%s': %d\n", terms_str, ret); + parse_events_terms__exit(&terms); + return ret; + } + ret = perf_pmu__config(pmu, attr, &terms, /*apply_hardcoded=*/true, /*err=*/NULL); + parse_events_terms__exit(&terms); + return ret; +} + /* * Find alias in the terms list and replace it with the terms * defined for the alias @@ -2596,21 +2614,8 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config) hashmap__for_each_entry(pmu->aliases, entry, bkt) { struct perf_pmu_alias *event = entry->pvalue; struct perf_event_attr attr = {.config = 0,}; - struct parse_events_terms terms; - int ret; + int ret = perf_pmu__parse_terms_to_attr(pmu, event->terms, &attr); - parse_events_terms__init(&terms); - ret = parse_events_terms(&terms, event->terms); - if (ret) { - pr_debug("Failed to parse '%s' terms '%s': %d\n", - event->name, event->terms, ret); - parse_events_terms__exit(&terms); - continue; - } - ret = perf_pmu__config(pmu, &attr, &terms, /*apply_hardcoded=*/true, - /*err=*/NULL); - - parse_events_terms__exit(&terms); if (ret == 0 && config == attr.config) return event->name; } From abcff00014b8ddb3cab87079f7c91ee9fa973eb5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:13 -0700 Subject: [PATCH 055/684] perf parse-events: Add terms for legacy hardware and cache config values Add the PMU terms legacy-hardware-config and legacy-cache-config. These terms are similar to the config term in that their values are assigned to the perf_event_attr config value. They differ in that the PMU type is switched to be either PERF_TYPE_HARDWARE or PERF_TYPE_HW_CACHE, and the PMU type is moved into the extended type information of the config value. This will allow later patches to add legacy events to json. An example use of the terms is in the following: ``` $ perf stat -vv -e 'cpu/legacy-hardware-config=1/,cpu/legacy-cache-config=0x10001/' true Using CPUID GenuineIntel-6-8D-1 Attempt to add: cpu/legacy-hardware-config=0x1/ ..after resolving event: cpu/legacy-hardware-config=0x1/ Attempt to add: cpu/legacy-cache-config=0x10001/ ..after resolving event: cpu/legacy-cache-config=0x10001/ Control descriptor is not initialized ------------------------------------------------------------ perf_event_attr: type 0 (PERF_TYPE_HARDWARE) size 136 config 0x1 (PERF_COUNT_HW_INSTRUCTIONS) sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 enable_on_exec 1 ------------------------------------------------------------ sys_perf_event_open: pid 994937 cpu -1 group_fd -1 flags 0x8 = 3 ------------------------------------------------------------ perf_event_attr: type 3 (PERF_TYPE_HW_CACHE) size 136 config 0x10001 (PERF_COUNT_HW_CACHE_RESULT_MISS | PERF_COUNT_HW_CACHE_OP_READ | PERF_COUNT_HW_CACHE_L1I) sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 enable_on_exec 1 ------------------------------------------------------------ sys_perf_event_open: pid 994937 cpu -1 group_fd -1 flags 0x8 = 4 cpu/legacy-hardware-config=1/: -1: 1364046 414756 414756 cpu/legacy-cache-config=0x10001/: -1: 57453 414756 414756 cpu/legacy-hardware-config=1/: 1364046 414756 414756 cpu/legacy-cache-config=0x10001/: 57453 414756 414756 Performance counter stats for 'true': 1,364,046 cpu/legacy-hardware-config=1/ 57,453 cpu/legacy-cache-config=0x10001/ 0.001988593 seconds time elapsed 0.002194000 seconds user 0.000000000 seconds sys ``` Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 70 ++++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.h | 4 +- tools/perf/util/parse-events.l | 2 + tools/perf/util/pmu.c | 30 +++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e0f18e9c80002e..4e003abe90f0d1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -868,6 +868,8 @@ const char *parse_events__term_type_str(enum parse_events__term_type term_type) [PARSE_EVENTS__TERM_TYPE_RAW] = "raw", [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE] = "legacy-cache", [PARSE_EVENTS__TERM_TYPE_HARDWARE] = "hardware", + [PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG] = "legacy-hardware-config", + [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG] = "legacy-cache-config", [PARSE_EVENTS__TERM_TYPE_CPU] = "cpu", [PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV] = "ratio-to-prev", }; @@ -921,6 +923,8 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV: + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: default: if (!err) return false; @@ -1093,6 +1097,8 @@ do { \ case PARSE_EVENTS__TERM_TYPE_USER: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: case PARSE_EVENTS__TERM_TYPE_HARDWARE: + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: default: parse_events_error__handle(parse_state->error, term->err_term, strdup(parse_events__term_type_str(term->type_term)), @@ -1115,10 +1121,68 @@ do { \ #undef CHECK_TYPE_VAL } +static bool check_pmu_is_core(__u32 type, const struct parse_events_term *term, + struct parse_events_error *err) +{ + struct perf_pmu *pmu = NULL; + + /* Avoid loading all PMUs with perf_pmus__find_by_type, just scan the core ones. */ + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { + if (pmu->type == type) + return true; + } + parse_events_error__handle(err, term->err_val, + strdup("needs a core PMU"), + NULL); + return false; +} + static int config_term_pmu(struct perf_event_attr *attr, struct parse_events_term *term, struct parse_events_state *parse_state) { + if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG) { + if (check_type_val(term, parse_state->error, PARSE_EVENTS__TERM_TYPE_NUM)) + return -EINVAL; + if (term->val.num >= PERF_COUNT_HW_MAX) { + parse_events_error__handle(parse_state->error, term->err_val, + strdup("too big"), + NULL); + return -EINVAL; + } + if (!check_pmu_is_core(attr->type, term, parse_state->error)) + return -EINVAL; + attr->config = term->val.num; + if (perf_pmus__supports_extended_type()) + attr->config |= (__u64)attr->type << PERF_PMU_TYPE_SHIFT; + attr->type = PERF_TYPE_HARDWARE; + return 0; + } + if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG) { + int cache_type, cache_op, cache_result; + + if (check_type_val(term, parse_state->error, PARSE_EVENTS__TERM_TYPE_NUM)) + return -EINVAL; + cache_type = term->val.num & 0xFF; + cache_op = (term->val.num >> 8) & 0xFF; + cache_result = (term->val.num >> 16) & 0xFF; + if ((term->val.num & ~0xFFFFFF) || + cache_type >= PERF_COUNT_HW_CACHE_MAX || + cache_op >= PERF_COUNT_HW_CACHE_OP_MAX || + cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) { + parse_events_error__handle(parse_state->error, term->err_val, + strdup("too big"), + NULL); + return -EINVAL; + } + if (!check_pmu_is_core(attr->type, term, parse_state->error)) + return -EINVAL; + attr->config = term->val.num; + if (perf_pmus__supports_extended_type()) + attr->config |= (__u64)attr->type << PERF_PMU_TYPE_SHIFT; + attr->type = PERF_TYPE_HW_CACHE; + return 0; + } if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); @@ -1205,6 +1269,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr, case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: @@ -1348,6 +1414,8 @@ do { \ case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_METRIC_ID: case PARSE_EVENTS__TERM_TYPE_RAW: @@ -1386,6 +1454,8 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 3052a48978f8b4..ad782da63c83e8 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -83,7 +83,9 @@ enum parse_events__term_type { PARSE_EVENTS__TERM_TYPE_HARDWARE, PARSE_EVENTS__TERM_TYPE_CPU, PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV, -#define __PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV + 1) + PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG, + PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG, +#define __PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG + 1) }; struct parse_events_term { diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index d65eb32124c8e2..5c8924a9dbfcaa 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -332,6 +332,8 @@ aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZ metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); } cpu { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CPU); } ratio-to-prev { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV); } +legacy-hardware-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG); } +legacy-cache-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG); } cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); } stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 2c3e539851c480..e25a4201f9ade4 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1532,6 +1532,34 @@ static int pmu_config_term(const struct perf_pmu *pmu, assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); pmu_format_value(bits, term->val.num, &attr->config3, zero); break; + case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + assert(term->val.num < PERF_COUNT_HW_MAX); + assert(pmu->is_core); + attr->config = term->val.num; + if (perf_pmus__supports_extended_type()) + attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; + attr->type = PERF_TYPE_HARDWARE; + break; + case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: { +#ifndef NDEBUG + int cache_type = term->val.num & 0xFF; + int cache_op = (term->val.num >> 8) & 0xFF; + int cache_result = (term->val.num >> 16) & 0xFF; + + assert(cache_type < PERF_COUNT_HW_CACHE_MAX); + assert(cache_op < PERF_COUNT_HW_CACHE_OP_MAX); + assert(cache_result < PERF_COUNT_HW_CACHE_RESULT_MAX); +#endif + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + assert((term->val.num & ~0xFFFFFF) == 0); + assert(pmu->is_core); + attr->config = term->val.num; + if (perf_pmus__supports_extended_type()) + attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; + attr->type = PERF_TYPE_HW_CACHE; + break; + } case PARSE_EVENTS__TERM_TYPE_USER: /* Not hardcoded. */ return -EINVAL; case PARSE_EVENTS__TERM_TYPE_NAME ... PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV: @@ -1923,6 +1951,8 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call "config1=0..0xffffffffffffffff", "config2=0..0xffffffffffffffff", "config3=0..0xffffffffffffffff", + "legacy-hardware-config=0..9,", + "legacy-cache-config=0..0xffffff,", "name=string", "period=number", "freq=number", From 903151c81c630ab7bcc37435755f6f9698e628f7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:14 -0700 Subject: [PATCH 056/684] perf jevents: Add legacy json terms and default_core event table helper Add json LegacyConfigCode and LegacyCacheCode values that translate to legacy-hardware-config and legacy-cache-config event terms respectively. Add perf_pmu__default_core_events_table as a means to find a default_core event table that will later contain legacy events. In situations like hypervisors it is more likely that tables will be NULL. Rather than testing in the calling PMU code, early exit in the pmu-event.c routines. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/empty-pmu-events.c | 26 +++++++++++++++++++ tools/perf/pmu-events/jevents.py | 32 ++++++++++++++++++++++++ tools/perf/pmu-events/pmu-events.h | 1 + 3 files changed, 59 insertions(+) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 041c598b16d831..2393b3a7a4c92b 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -461,6 +461,8 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -482,6 +484,8 @@ int pmu_events_table__find_event(const struct pmu_events_table *table, pmu_event_iter_fn fn, void *data) { + if (!table) + return PMU_EVENTS__NOT_FOUND; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -502,6 +506,8 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table, { size_t count = 0; + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -580,6 +586,8 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], fn, data); @@ -596,6 +604,8 @@ int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -707,6 +717,22 @@ const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) return NULL; } +const struct pmu_events_table *perf_pmu__default_core_events_table(void) +{ + int i = 0; + + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; + + if (!map->arch) + break; + + if (!strcmp(map->cpuid, "common")) + return &map->event_table; + } + return NULL; +} + const struct pmu_metrics_table *pmu_metrics_table__find(void) { struct perf_cpu cpu = {-1}; diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 168c044dd7cc32..1f3917cbff8770 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -325,6 +325,8 @@ def canonicalize_value(val: str) -> str: eventcode |= int(jd['ExtSel']) << 8 configcode = int(jd['ConfigCode'], 0) if 'ConfigCode' in jd else None eventidcode = int(jd['EventidCode'], 0) if 'EventidCode' in jd else None + legacy_hw_config = int(jd['LegacyConfigCode'], 0) if 'LegacyConfigCode' in jd else None + legacy_cache_config = int(jd['LegacyCacheCode'], 0) if 'LegacyCacheCode' in jd else None self.name = jd['EventName'].lower() if 'EventName' in jd else None self.topic = '' self.compat = jd.get('Compat') @@ -370,6 +372,10 @@ def canonicalize_value(val: str) -> str: event = f'config={llx(configcode)}' elif eventidcode is not None: event = f'eventid={llx(eventidcode)}' + elif legacy_hw_config is not None: + event = f'legacy-hardware-config={llx(legacy_hw_config)}' + elif legacy_cache_config is not None: + event = f'legacy-cache-config={llx(legacy_cache_config)}' else: event = f'event={llx(eventcode)}' event_fields = [ @@ -951,6 +957,8 @@ def print_system_mapping_table() -> None: pmu_event_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -972,6 +980,8 @@ def print_system_mapping_table() -> None: pmu_event_iter_fn fn, void *data) { + if (!table) + return PMU_EVENTS__NOT_FOUND; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -992,6 +1002,8 @@ def print_system_mapping_table() -> None: { size_t count = 0; + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -1070,6 +1082,8 @@ def print_system_mapping_table() -> None: pmu_metric_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], fn, data); @@ -1086,6 +1100,8 @@ def print_system_mapping_table() -> None: pmu_metric_iter_fn fn, void *data) { + if (!table) + return 0; for (size_t i = 0; i < table->num_pmus; i++) { const struct pmu_table_entry *table_pmu = &table->pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; @@ -1197,6 +1213,22 @@ def print_system_mapping_table() -> None: return NULL; } +const struct pmu_events_table *perf_pmu__default_core_events_table(void) +{ + int i = 0; + + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; + + if (!map->arch) + break; + + if (!strcmp(map->cpuid, "common")) + return &map->event_table; + } + return NULL; +} + const struct pmu_metrics_table *pmu_metrics_table__find(void) { struct perf_cpu cpu = {-1}; diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index ea022ea550874c..e0535380c0b29d 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -125,6 +125,7 @@ int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, void *data); const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu); +const struct pmu_events_table *perf_pmu__default_core_events_table(void); const struct pmu_metrics_table *pmu_metrics_table__find(void); const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid); const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid); From 249a4c6d0165b2ad32f97e6b929718178c70b00e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:15 -0700 Subject: [PATCH 057/684] perf pmu: Add and use legacy_terms in alias information Add support to finding/adding events from the default_core event table. If an event already exists from sysfs/json then the default_core configuration is saved in the legacy_terms string. Lazily use the legacy_terms string to set a legacy hardware or cache event as deprecated if the core PMU doesn't support it. Use the legacy terms string to set the alternate_hw_config, avoiding the value needing to be passed from the parse_events parser. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.c | 137 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 20 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index e25a4201f9ade4..667be41abcd768 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -69,6 +69,11 @@ struct perf_pmu_alias { char *topic; /** @terms: Owned copy of the event terms. */ char *terms; + /** + * @legacy_terms: If the event aliases a legacy event, holds a copy + * ofthe legacy event string. + */ + char *legacy_terms; /** * @pmu_name: The name copied from the json struct pmu_event. This can * differ from the PMU name as it won't have suffixes. @@ -101,6 +106,12 @@ struct perf_pmu_alias { * default. */ bool deprecated; + /** + * @legacy_deprecated_checked: Legacy events may not be supported by the + * PMU need to be checked. If they aren't supported they are marked + * deprecated. + */ + bool legacy_deprecated_checked; /** @from_sysfs: Was the alias from sysfs or a json event? */ bool from_sysfs; /** @info_loaded: Have the scale, unit and other values been read from disk? */ @@ -430,6 +441,7 @@ static void perf_pmu_free_alias(struct perf_pmu_alias *alias) zfree(&alias->topic); zfree(&alias->pmu_name); zfree(&alias->terms); + zfree(&alias->legacy_terms); free(alias); } @@ -522,6 +534,7 @@ static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias) struct update_alias_data { struct perf_pmu *pmu; struct perf_pmu_alias *alias; + bool legacy; }; static int update_alias(const struct pmu_event *pe, @@ -537,8 +550,13 @@ static int update_alias(const struct pmu_event *pe, assign_str(pe->name, "topic", &data->alias->topic, pe->topic); data->alias->per_pkg = pe->perpkg; if (pe->event) { - zfree(&data->alias->terms); - data->alias->terms = strdup(pe->event); + if (data->legacy) { + zfree(&data->alias->legacy_terms); + data->alias->legacy_terms = strdup(pe->event); + } else { + zfree(&data->alias->terms); + data->alias->terms = strdup(pe->event); + } } if (!ret && pe->unit) { char *unit; @@ -628,7 +646,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, return ret; } } - alias->name = strdup(name); alias->desc = desc ? strdup(desc) : NULL; alias->long_desc = long_desc ? strdup(long_desc) : NULL; @@ -645,15 +662,29 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, default: case EVENT_SRC_SYSFS: alias->from_sysfs = true; - if (pmu->events_table) { + if (pmu->events_table || pmu->is_core) { /* Update an event from sysfs with json data. */ struct update_alias_data data = { .pmu = pmu, .alias = alias, + .legacy = false, }; - if (pmu_events_table__find_event(pmu->events_table, pmu, name, - update_alias, &data) == 0) + if ((pmu_events_table__find_event(pmu->events_table, pmu, name, + update_alias, &data) == 0)) { + /* + * Override sysfs encodings with json encodings + * specific to the cpuid. + */ pmu->cpu_common_json_aliases++; + } + if (pmu->is_core) { + /* Add in legacy encodings. */ + data.legacy = true; + if (pmu_events_table__find_event( + perf_pmu__default_core_events_table(), + pmu, name, update_alias, &data) == 0) + pmu->cpu_common_json_aliases++; + } } pmu->sysfs_aliases++; break; @@ -1054,13 +1085,16 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_tab static void pmu_add_cpu_aliases(struct perf_pmu *pmu) { - if (!pmu->events_table) + if (!pmu->events_table && !pmu->is_core) return; if (pmu->cpu_aliases_added) return; pmu_add_cpu_aliases_table(pmu, pmu->events_table); + if (pmu->is_core) + pmu_add_cpu_aliases_table(pmu, perf_pmu__default_core_events_table()); + pmu->cpu_aliases_added = true; } @@ -1738,10 +1772,14 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, return alias; /* Alias doesn't exist, try to get it from the json events. */ - if (pmu->events_table && - pmu_events_table__find_event(pmu->events_table, pmu, name, - pmu_add_cpu_aliases_map_callback, - pmu) == 0) { + if ((pmu_events_table__find_event(pmu->events_table, pmu, name, + pmu_add_cpu_aliases_map_callback, + pmu) == 0) || + (pmu->is_core && + pmu_events_table__find_event(perf_pmu__default_core_events_table(), + pmu, name, + pmu_add_cpu_aliases_map_callback, + pmu) == 0)) { alias = perf_pmu__find_alias(pmu, name, /*load=*/ false); } return alias; @@ -1865,6 +1903,20 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_ if (ret) return ret; + if (alias->legacy_terms) { + struct perf_event_attr attr = {.config = 0,}; + + ret = perf_pmu__parse_terms_to_attr(pmu, alias->legacy_terms, &attr); + if (ret) { + parse_events_error__handle(err, term->err_term, + strdup("Error evaluating legacy terms"), + NULL); + return ret; + } + if (attr.type == PERF_TYPE_HARDWARE) + *alternate_hw_config = attr.config & PERF_HW_EVENT_MASK; + } + if (alias->per_pkg) info->per_pkg = true; @@ -2034,9 +2086,13 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) return drm_pmu__have_event(pmu, name); if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) return true; - if (pmu->cpu_aliases_added || !pmu->events_table) + if (pmu->cpu_aliases_added || (!pmu->events_table && !pmu->is_core)) return false; - return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0; + if (pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0) + return true; + return pmu->is_core && + pmu_events_table__find_event(perf_pmu__default_core_events_table(), + pmu, name, NULL, NULL) == 0; } size_t perf_pmu__num_events(struct perf_pmu *pmu) @@ -2053,13 +2109,18 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu) pmu_aliases_parse(pmu); nr = pmu->sysfs_aliases + pmu->sys_json_aliases; - if (pmu->cpu_aliases_added) - nr += pmu->cpu_json_aliases; - else if (pmu->events_table) - nr += pmu_events_table__num_events(pmu->events_table, pmu) - - pmu->cpu_common_json_aliases; - else + if (pmu->cpu_aliases_added) { + nr += pmu->cpu_json_aliases; + } else if (pmu->events_table || pmu->is_core) { + nr += pmu_events_table__num_events(pmu->events_table, pmu); + if (pmu->is_core) { + nr += pmu_events_table__num_events( + perf_pmu__default_core_events_table(), pmu); + } + nr -= pmu->cpu_common_json_aliases; + } else { assert(pmu->cpu_json_aliases == 0 && pmu->cpu_common_json_aliases == 0); + } if (perf_pmu__is_tool(pmu)) nr -= tool_pmu__num_skip_events(); @@ -2121,6 +2182,42 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, return buf; } +static bool perf_pmu_alias__check_deprecated(struct perf_pmu *pmu, struct perf_pmu_alias *alias) +{ + struct perf_event_attr attr = {.config = 0,}; + const char *check_terms; + bool has_legacy_config; + + if (alias->legacy_deprecated_checked) + return alias->deprecated; + + alias->legacy_deprecated_checked = true; + if (alias->deprecated) + return true; + + check_terms = alias->terms; + has_legacy_config = + strstr(check_terms, "legacy-hardware-config=") != NULL || + strstr(check_terms, "legacy-cache-config=") != NULL; + if (!has_legacy_config && alias->legacy_terms) { + check_terms = alias->legacy_terms; + has_legacy_config = + strstr(check_terms, "legacy-hardware-config=") != NULL || + strstr(check_terms, "legacy-cache-config=") != NULL; + } + if (!has_legacy_config) + return false; + + if (perf_pmu__parse_terms_to_attr(pmu, check_terms, &attr) != 0) { + /* Parsing failed, set as deprecated. */ + alias->deprecated = true; + } else if (attr.type < PERF_TYPE_MAX) { + /* Flag unsupported legacy events as deprecated. */ + alias->deprecated = !is_event_supported(attr.type, attr.config); + } + return alias->deprecated; +} + int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, void *state, pmu_event_callback cb) { @@ -2178,7 +2275,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, "%.*s/%s/", (int)pmu_name_len, info.pmu_name, event->terms) + 1; info.str = event->terms; info.topic = event->topic; - info.deprecated = event->deprecated; + info.deprecated = perf_pmu_alias__check_deprecated(pmu, event); ret = cb(state, &info); if (ret) goto out; From 0012e0fa221bf9cc54aa6a0e94d848653dc781bb Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:16 -0700 Subject: [PATCH 058/684] perf jevents: Add legacy-hardware and legacy-cache json The legacy-hardware.json is added containing hardware events similarly to the software.json file. A difference is that for the software PMU the name is known and matches sysfs. In the legacy-hardware.json no Unit/PMU is specified for the events meaning default_core is used and the events will appear for all core PMUs. There are potentially 1216 legacy cache events, rather than list them in a json file add a make_legacy_cache.py helper to generate them. By using json for legacy hardware and cache events: descriptions of the events can be added; events can be marked as deprecated, such as those misleadingly named l2 (deprecated is also used to mark all events that weren't previously displayed in perf list); and the name lookup becomes case insensitive. The C string encoding all the perf events and metrics is increased in size by 123,499 bytes which will increase the perf binary size. Later changes will remove hard coded event parsing for legacy hardware and cache events, turning parsing overhead into a binary search during event lookup. That event descriptions are based off of those in perf_event_open man page, credit to Vince Weaver . Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/Build | 8 +- .../arch/common/common/legacy-hardware.json | 72 + tools/perf/pmu-events/empty-pmu-events.c | 2745 ++++++++++++++++- tools/perf/pmu-events/make_legacy_cache.py | 129 + 4 files changed, 2814 insertions(+), 140 deletions(-) create mode 100644 tools/perf/pmu-events/arch/common/common/legacy-hardware.json create mode 100755 tools/perf/pmu-events/make_legacy_cache.py diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index 1503a16e662ae2..4ebf37c1497893 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -12,6 +12,8 @@ PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log +LEGACY_CACHE_PY = pmu-events/make_legacy_cache.py +LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json ifeq ($(JEVENTS_ARCH),) JEVENTS_ARCH=$(SRCARCH) @@ -33,7 +35,11 @@ $(OUTPUT)pmu-events/arch/%: pmu-events/arch/% $(call rule_mkdir) $(Q)$(call echo-cmd,gen)cp $< $@ -GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) +$(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(PYTHON) $(LEGACY_CACHE_PY) > $@ + +GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) $(LEGACY_CACHE_JSON) $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY) $(call rule_mkdir) diff --git a/tools/perf/pmu-events/arch/common/common/legacy-hardware.json b/tools/perf/pmu-events/arch/common/common/legacy-hardware.json new file mode 100644 index 00000000000000..71700647f19b18 --- /dev/null +++ b/tools/perf/pmu-events/arch/common/common/legacy-hardware.json @@ -0,0 +1,72 @@ +[ + { + "EventName": "cpu-cycles", + "BriefDescription": "Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles].", + "LegacyConfigCode": "0" + }, + { + "EventName": "cycles", + "BriefDescription": "Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles].", + "LegacyConfigCode": "0" + }, + { + "EventName": "instructions", + "BriefDescription": "Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts.", + "LegacyConfigCode": "1" + }, + { + "EventName": "cache-references", + "BriefDescription": "Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU.", + "LegacyConfigCode": "2" + }, + { + "EventName": "cache-misses", + "BriefDescription": "Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates.", + "LegacyConfigCode": "3" + }, + { + "EventName": "branches", + "BriefDescription": "Retired branch instructions [This event is an alias of branch-instructions].", + "LegacyConfigCode": "4" + }, + { + "EventName": "branch-instructions", + "BriefDescription": "Retired branch instructions [This event is an alias of branches].", + "LegacyConfigCode": "4" + }, + { + "EventName": "branch-misses", + "BriefDescription": "Mispredicted branch instructions.", + "LegacyConfigCode": "5" + }, + { + "EventName": "bus-cycles", + "BriefDescription": "Bus cycles, which can be different from total cycles.", + "LegacyConfigCode": "6" + }, + { + "EventName": "stalled-cycles-frontend", + "BriefDescription": "Stalled cycles during issue [This event is an alias of idle-cycles-frontend].", + "LegacyConfigCode": "7" + }, + { + "EventName": "idle-cycles-frontend", + "BriefDescription": "Stalled cycles during issue [This event is an alias of stalled-cycles-fronted].", + "LegacyConfigCode": "7" + }, + { + "EventName": "stalled-cycles-backend", + "BriefDescription": "Stalled cycles during retirement [This event is an alias of idle-cycles-backend].", + "LegacyConfigCode": "8" + }, + { + "EventName": "idle-cycles-backend", + "BriefDescription": "Stalled cycles during retirement [This event is an alias of stalled-cycles-backend].", + "LegacyConfigCode": "8" + }, + { + "EventName": "ref-cycles", + "BriefDescription": "Total cycles; not affected by CPU frequency scaling.", + "LegacyConfigCode": "9" + } +] diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 2393b3a7a4c92b..336e3924ce84f7 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -19,147 +19,2614 @@ struct pmu_table_entry { }; static const char *const big_c_string = -/* offset=0 */ "software\000" -/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000" -/* offset=87 */ "task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000" -/* offset=167 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=262 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=357 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" -/* offset=458 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" -/* offset=559 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=691 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=823 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" -/* offset=932 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" -/* offset=1035 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" -/* offset=1127 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" -/* offset=1254 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" -/* offset=1334 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" -/* offset=1436 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" -/* offset=1539 */ "tool\000" -/* offset=1544 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" -/* offset=1620 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" -/* offset=1690 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" -/* offset=1758 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" -/* offset=1834 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" -/* offset=1979 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" -/* offset=2082 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" -/* offset=2199 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" -/* offset=2275 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" -/* offset=2361 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" -/* offset=2471 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" -/* offset=2578 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" -/* offset=2677 */ "default_core\000" -/* offset=2690 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" -/* offset=2752 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" -/* offset=2814 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" -/* offset=2912 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" -/* offset=3014 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" -/* offset=3147 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" -/* offset=3265 */ "hisi_sccl,ddrc\000" -/* offset=3280 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" -/* offset=3350 */ "uncore_cbox\000" -/* offset=3362 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" -/* offset=3516 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" -/* offset=3570 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" -/* offset=3628 */ "hisi_sccl,l3c\000" -/* offset=3642 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" -/* offset=3710 */ "uncore_imc_free_running\000" -/* offset=3734 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" -/* offset=3814 */ "uncore_imc\000" -/* offset=3825 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" -/* offset=3890 */ "uncore_sys_ddr_pmu\000" -/* offset=3909 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" -/* offset=3985 */ "uncore_sys_ccn_pmu\000" -/* offset=4004 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" -/* offset=4081 */ "uncore_sys_cmn_pmu\000" -/* offset=4100 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=4243 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" -/* offset=4265 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" -/* offset=4328 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" -/* offset=4494 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=4558 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=4625 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" -/* offset=4696 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" -/* offset=4790 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" -/* offset=4924 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" -/* offset=4988 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=5056 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=5126 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" -/* offset=5148 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" -/* offset=5170 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" -/* offset=5190 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" +/* offset=0 */ "default_core\000" +/* offset=13 */ "l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=99 */ "l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=190 */ "l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=286 */ "l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=387 */ "l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=482 */ "l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=580 */ "l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00000\000\000\000\000\000" +/* offset=682 */ "l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=782 */ "l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00000\000\000\000\000\000" +/* offset=874 */ "l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=971 */ "l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1073 */ "l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1169 */ "l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1268 */ "l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=1371 */ "l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=1472 */ "l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1563 */ "l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1659 */ "l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1760 */ "l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1855 */ "l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1953 */ "l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=2055 */ "l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=2155 */ "l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2252 */ "l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2354 */ "l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2461 */ "l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2562 */ "l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2666 */ "l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00000\000\000\000\000\000" +/* offset=2770 */ "l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=2872 */ "l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00000\000\000\000\000\000" +/* offset=2970 */ "l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3073 */ "l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3181 */ "l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3283 */ "l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3388 */ "l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=3493 */ "l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=3596 */ "l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3693 */ "l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3795 */ "l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3902 */ "l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=4003 */ "l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=4107 */ "l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=4211 */ "l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=4313 */ "l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4416 */ "l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4524 */ "l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4637 */ "l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4744 */ "l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4854 */ "l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00000\000\000\000\000\000" +/* offset=4964 */ "l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5072 */ "l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00000\000\000\000\000\000" +/* offset=5177 */ "l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5287 */ "l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5402 */ "l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5511 */ "l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5623 */ "l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5735 */ "l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5845 */ "l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5956 */ "l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6072 */ "l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6193 */ "l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6308 */ "l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6426 */ "l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=6544 */ "l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=6660 */ "l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6771 */ "l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6887 */ "l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7008 */ "l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7123 */ "l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7241 */ "l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=7359 */ "l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=7475 */ "l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7566 */ "l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7662 */ "l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7752 */ "l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7845 */ "l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=7942 */ "l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8037 */ "l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8118 */ "l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8204 */ "l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8295 */ "l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8391 */ "l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8481 */ "l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8574 */ "l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8671 */ "l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8766 */ "l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8853 */ "l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8945 */ "l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9042 */ "l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9133 */ "l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9227 */ "l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9325 */ "l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9421 */ "l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9507 */ "l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9598 */ "l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9694 */ "l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9784 */ "l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9877 */ "l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9974 */ "l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=10069 */ "l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10161 */ "l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10258 */ "l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10360 */ "l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10456 */ "l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10555 */ "l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=10654 */ "l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=10751 */ "l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10844 */ "l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10942 */ "l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11045 */ "l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11142 */ "l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11242 */ "l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=11342 */ "l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=11440 */ "l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11532 */ "l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11629 */ "l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11731 */ "l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11827 */ "l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11926 */ "l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=12025 */ "l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=12122 */ "l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12220 */ "l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12323 */ "l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12431 */ "l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12533 */ "l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12638 */ "l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=12743 */ "l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=12846 */ "l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12946 */ "l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13051 */ "l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13161 */ "l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13265 */ "l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13372 */ "l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=13479 */ "l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=13584 */ "l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13690 */ "l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13801 */ "l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13917 */ "l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14027 */ "l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14140 */ "l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=14253 */ "l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=14364 */ "l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14470 */ "l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14581 */ "l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14697 */ "l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14807 */ "l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14920 */ "l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=15033 */ "l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=15144 */ "l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15230 */ "l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15321 */ "l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15406 */ "l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15494 */ "l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=15586 */ "l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=15676 */ "l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15756 */ "l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15841 */ "l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15931 */ "l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16026 */ "l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16115 */ "l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16207 */ "l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16303 */ "l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16397 */ "l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16483 */ "l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16574 */ "l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16670 */ "l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16760 */ "l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16853 */ "l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16950 */ "l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17045 */ "l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17130 */ "l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17220 */ "l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17315 */ "l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17404 */ "l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17496 */ "l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17592 */ "l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17686 */ "l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17777 */ "l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17873 */ "l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17974 */ "l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18069 */ "l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18167 */ "l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18265 */ "l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18361 */ "l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18453 */ "l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18550 */ "l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18652 */ "l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18748 */ "l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18847 */ "l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18946 */ "l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19043 */ "l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19134 */ "l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19230 */ "l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19331 */ "l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19426 */ "l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19524 */ "l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19622 */ "l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19718 */ "l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=19815 */ "l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=19917 */ "l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20024 */ "l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20125 */ "l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20229 */ "l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=20333 */ "l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=20435 */ "l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20534 */ "l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20638 */ "l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20747 */ "l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20850 */ "l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20956 */ "l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21062 */ "l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21166 */ "l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21271 */ "l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21381 */ "l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21496 */ "l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21605 */ "l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21717 */ "l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21829 */ "l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21939 */ "l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22044 */ "l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22154 */ "l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22269 */ "l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22378 */ "l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22490 */ "l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=22602 */ "l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=22712 */ "l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22797 */ "l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22887 */ "l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22971 */ "l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23058 */ "l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23149 */ "l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23238 */ "l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23322 */ "l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23411 */ "l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23505 */ "l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23604 */ "l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23697 */ "l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23793 */ "l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23893 */ "l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23991 */ "l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24081 */ "l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24176 */ "l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24276 */ "l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24370 */ "l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24467 */ "l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=24568 */ "l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=24667 */ "l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24756 */ "l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24850 */ "l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24949 */ "l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=25042 */ "l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=25138 */ "l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=25238 */ "l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=25336 */ "l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25431 */ "l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25531 */ "l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25636 */ "l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25735 */ "l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25837 */ "l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=25939 */ "l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26039 */ "l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26135 */ "l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26236 */ "l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26342 */ "l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26442 */ "l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26545 */ "l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26648 */ "l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26749 */ "l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26844 */ "l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26944 */ "l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27049 */ "l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27148 */ "l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27250 */ "l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=27352 */ "l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=27452 */ "l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27553 */ "l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27659 */ "l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27770 */ "l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27875 */ "l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27983 */ "l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28091 */ "l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28197 */ "l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28300 */ "l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28408 */ "l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28521 */ "l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28628 */ "l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28738 */ "l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28848 */ "l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28956 */ "l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29065 */ "l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29179 */ "l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29298 */ "l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29411 */ "l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29527 */ "l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=29643 */ "l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=29757 */ "l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29866 */ "l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29980 */ "l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30099 */ "l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30212 */ "l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30328 */ "l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=30444 */ "l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=30558 */ "l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30647 */ "l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30741 */ "l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30829 */ "l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30920 */ "l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=31015 */ "l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=31108 */ "l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31201 */ "l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31299 */ "l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31402 */ "l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31510 */ "l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31612 */ "l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31717 */ "l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00000\000\000\000\000\000" +/* offset=31826 */ "l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=31933 */ "l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00000\000\000\000\000\000" +/* offset=32032 */ "l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32136 */ "l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32245 */ "l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32348 */ "l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32454 */ "l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=32564 */ "l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=32672 */ "l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32770 */ "l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32873 */ "l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32981 */ "l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=33083 */ "l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=33188 */ "l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=33297 */ "l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=33404 */ "l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33514 */ "l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33629 */ "l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33749 */ "l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33863 */ "l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33980 */ "l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00000\000\000\000\000\000" +/* offset=34097 */ "l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=34212 */ "l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00000\000\000\000\000\000" +/* offset=34324 */ "l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34441 */ "l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34563 */ "l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34679 */ "l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34798 */ "l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=34917 */ "l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35034 */ "l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35152 */ "l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35275 */ "l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35403 */ "l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35525 */ "l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35650 */ "l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35775 */ "l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35898 */ "l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36016 */ "l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36139 */ "l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36267 */ "l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36389 */ "l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36514 */ "l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=36639 */ "l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=36762 */ "l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=36860 */ "l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=36963 */ "l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37060 */ "l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37160 */ "l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=37264 */ "l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=37366 */ "l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37454 */ "l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37547 */ "l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37645 */ "l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37748 */ "l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37845 */ "l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37945 */ "l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38049 */ "l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38151 */ "l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38245 */ "l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38344 */ "l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38448 */ "l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38546 */ "l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38647 */ "l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38752 */ "l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38855 */ "l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38948 */ "l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39046 */ "l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39149 */ "l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39246 */ "l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39346 */ "l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=39450 */ "l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=39552 */ "l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39657 */ "l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39767 */ "l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39882 */ "l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39991 */ "l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40103 */ "l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=40215 */ "l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=40325 */ "l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40432 */ "l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40544 */ "l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40661 */ "l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40772 */ "l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40886 */ "l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41000 */ "l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41112 */ "l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41225 */ "l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41343 */ "l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41466 */ "l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41583 */ "l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41703 */ "l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41823 */ "l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41941 */ "l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42054 */ "l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42172 */ "l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42295 */ "l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42412 */ "l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42532 */ "l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=42652 */ "l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=42770 */ "l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=42863 */ "l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=42961 */ "l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43053 */ "l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43148 */ "l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=43247 */ "l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=43344 */ "l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43431 */ "l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43523 */ "l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43620 */ "l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43722 */ "l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43818 */ "l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43917 */ "l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44020 */ "l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44121 */ "l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44214 */ "l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44312 */ "l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44415 */ "l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44512 */ "l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44612 */ "l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44716 */ "l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44818 */ "l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44910 */ "l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45007 */ "l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45109 */ "l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45205 */ "l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45304 */ "l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=45407 */ "l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=45508 */ "l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45612 */ "l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45721 */ "l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45835 */ "l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45943 */ "l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46054 */ "l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46165 */ "l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46274 */ "l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46380 */ "l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46491 */ "l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46607 */ "l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46717 */ "l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46830 */ "l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46943 */ "l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47054 */ "l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47166 */ "l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47283 */ "l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47405 */ "l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47521 */ "l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47640 */ "l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47759 */ "l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47876 */ "l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47988 */ "l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48105 */ "l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48227 */ "l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48343 */ "l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48462 */ "l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=48581 */ "l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=48698 */ "l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48790 */ "l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48887 */ "l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48978 */ "l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49072 */ "l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=49170 */ "l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=49266 */ "l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49364 */ "l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49467 */ "l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49575 */ "l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49688 */ "l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49795 */ "l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49905 */ "l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50019 */ "l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50131 */ "l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50235 */ "l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50344 */ "l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50458 */ "l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50566 */ "l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50677 */ "l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50792 */ "l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50905 */ "l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51008 */ "l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51116 */ "l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51229 */ "l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51336 */ "l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51446 */ "l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=51560 */ "l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=51672 */ "l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=51787 */ "l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=51907 */ "l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52032 */ "l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52151 */ "l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52273 */ "l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=52395 */ "l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=52515 */ "l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52632 */ "l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52754 */ "l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52881 */ "l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53002 */ "l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53126 */ "l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=53250 */ "l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=53372 */ "l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53495 */ "l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53623 */ "l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53756 */ "l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53883 */ "l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54013 */ "l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=54143 */ "l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=54271 */ "l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54394 */ "l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54522 */ "l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54655 */ "l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54782 */ "l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54912 */ "l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=55042 */ "l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=55170 */ "l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55273 */ "l1-instruction-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55381 */ "l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55483 */ "l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55588 */ "l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=55697 */ "l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=55804 */ "llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=55882 */ "llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=55965 */ "llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56053 */ "llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56146 */ "llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56233 */ "llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56323 */ "llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00000\000\000\000\000\000" +/* offset=56417 */ "llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=56509 */ "llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00000\000\000\000\000\000" +/* offset=56593 */ "llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56682 */ "llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56776 */ "llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56864 */ "llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56955 */ "llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57050 */ "llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57143 */ "llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57226 */ "llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57314 */ "llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57407 */ "llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57494 */ "llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57584 */ "llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57678 */ "llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57770 */ "llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=57859 */ "llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=57953 */ "llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58052 */ "llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58145 */ "llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58241 */ "llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00000\000\000\000\000\000" +/* offset=58337 */ "llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=58431 */ "llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00000\000\000\000\000\000" +/* offset=58521 */ "llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58616 */ "llc-stores-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58716 */ "llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58810 */ "llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58907 */ "llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59004 */ "llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59099 */ "llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59188 */ "llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59282 */ "llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59381 */ "llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59474 */ "llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59570 */ "llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59666 */ "llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59760 */ "llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=59855 */ "llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=59955 */ "llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60060 */ "llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60159 */ "llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60261 */ "llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00000\000\000\000\000\000" +/* offset=60363 */ "llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=60463 */ "llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00000\000\000\000\000\000" +/* offset=60560 */ "llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60662 */ "llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60769 */ "llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60870 */ "llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60974 */ "llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61078 */ "llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61180 */ "llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61283 */ "llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61391 */ "llc-speculative-read-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61504 */ "llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61611 */ "llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61721 */ "llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61831 */ "llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61939 */ "llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62042 */ "llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62150 */ "llc-speculative-load-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62263 */ "llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62370 */ "llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62480 */ "llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=62590 */ "llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=62698 */ "llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62781 */ "llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62869 */ "llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62951 */ "llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63036 */ "llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63125 */ "llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63212 */ "l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63309 */ "l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63411 */ "l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63518 */ "l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63630 */ "l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63736 */ "l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63845 */ "l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63958 */ "l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64069 */ "l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64172 */ "l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64280 */ "l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64393 */ "l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64500 */ "l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64610 */ "l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64724 */ "l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64836 */ "l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64938 */ "l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65045 */ "l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65157 */ "l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65263 */ "l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65372 */ "l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=65485 */ "l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=65596 */ "l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65704 */ "l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65817 */ "l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65935 */ "l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66047 */ "l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66162 */ "l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=66277 */ "l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=66390 */ "l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66499 */ "l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66613 */ "l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66732 */ "l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66845 */ "l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66961 */ "l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67077 */ "l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67191 */ "l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67299 */ "l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67412 */ "l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67530 */ "l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67642 */ "l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67757 */ "l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67872 */ "l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67985 */ "l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68099 */ "l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68218 */ "l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68342 */ "l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68460 */ "l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68581 */ "l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=68702 */ "l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=68821 */ "l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68937 */ "l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69058 */ "l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69184 */ "l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69304 */ "l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69427 */ "l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=69550 */ "l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=69671 */ "l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69793 */ "l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69920 */ "l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70052 */ "l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70178 */ "l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70307 */ "l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=70436 */ "l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=70563 */ "l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70685 */ "l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70812 */ "l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70944 */ "l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=71070 */ "l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=71199 */ "l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=71328 */ "l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=71455 */ "l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71557 */ "l2-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71664 */ "l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71765 */ "l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71869 */ "l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=71977 */ "l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=72083 */ "dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72154 */ "dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72230 */ "dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72311 */ "dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72397 */ "dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72477 */ "dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72560 */ "dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00000\000\000\000\000\000" +/* offset=72647 */ "dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=72732 */ "dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00000\000\000\000\000\000" +/* offset=72809 */ "dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72891 */ "dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72978 */ "dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73059 */ "dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73143 */ "dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73231 */ "dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73317 */ "dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73393 */ "dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73474 */ "dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73560 */ "dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73640 */ "dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73723 */ "dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73810 */ "dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73895 */ "dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=73977 */ "dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74064 */ "dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74156 */ "dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74242 */ "dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74331 */ "dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00000\000\000\000\000\000" +/* offset=74420 */ "dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=74507 */ "dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00000\000\000\000\000\000" +/* offset=74590 */ "dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74678 */ "dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74771 */ "dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74858 */ "dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74948 */ "dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75038 */ "dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75126 */ "dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75208 */ "dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75295 */ "dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75387 */ "dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75473 */ "dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75562 */ "dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75651 */ "dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75738 */ "dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=75826 */ "dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=75919 */ "dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76017 */ "dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76109 */ "dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76204 */ "dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00000\000\000\000\000\000" +/* offset=76299 */ "dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=76392 */ "dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00000\000\000\000\000\000" +/* offset=76482 */ "dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76577 */ "dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76677 */ "dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76771 */ "dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76868 */ "dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=76965 */ "dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77060 */ "dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77156 */ "dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77257 */ "dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77363 */ "dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77463 */ "dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77566 */ "dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77669 */ "dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77770 */ "dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77866 */ "dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77967 */ "dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78073 */ "dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78173 */ "dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78276 */ "dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=78379 */ "dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=78480 */ "dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78556 */ "dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78637 */ "dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78712 */ "dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78790 */ "dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=78872 */ "dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=78952 */ "d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79024 */ "d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79101 */ "d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79183 */ "d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79270 */ "d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79351 */ "d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79435 */ "d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=79523 */ "d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=79609 */ "d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79687 */ "d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79770 */ "d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79858 */ "d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79940 */ "d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80025 */ "d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80114 */ "d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80201 */ "d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80278 */ "d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80360 */ "d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80447 */ "d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80528 */ "d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80612 */ "d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80700 */ "d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80786 */ "d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=80869 */ "d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=80957 */ "d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81050 */ "d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81137 */ "d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81227 */ "d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81317 */ "d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81405 */ "d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81489 */ "d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81578 */ "d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81672 */ "d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81760 */ "d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81851 */ "d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81942 */ "d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82031 */ "d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82114 */ "d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82202 */ "d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82295 */ "d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82382 */ "d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82472 */ "d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82562 */ "d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82650 */ "d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82739 */ "d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82833 */ "d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82932 */ "d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83025 */ "d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83121 */ "d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83217 */ "d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83311 */ "d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83402 */ "d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83498 */ "d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83599 */ "d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83694 */ "d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83792 */ "d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83890 */ "d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83986 */ "d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84083 */ "d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84185 */ "d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84292 */ "d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84393 */ "d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84497 */ "d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=84601 */ "d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=84703 */ "d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84800 */ "d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84902 */ "d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85009 */ "d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85110 */ "d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85214 */ "d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=85318 */ "d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=85420 */ "d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85497 */ "d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85579 */ "d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85655 */ "d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85734 */ "d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=85817 */ "d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=85898 */ "data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85973 */ "data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86053 */ "data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86138 */ "data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86228 */ "data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86312 */ "data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86399 */ "data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=86490 */ "data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=86579 */ "data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86660 */ "data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86746 */ "data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86837 */ "data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86922 */ "data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87010 */ "data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87102 */ "data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87192 */ "data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87272 */ "data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87357 */ "data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87447 */ "data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87531 */ "data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87618 */ "data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87709 */ "data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87798 */ "data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=87884 */ "data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=87975 */ "data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88071 */ "data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88161 */ "data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88254 */ "data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88347 */ "data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88438 */ "data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88525 */ "data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88617 */ "data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88714 */ "data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88805 */ "data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88899 */ "data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88993 */ "data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89085 */ "data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89171 */ "data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89262 */ "data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89358 */ "data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89448 */ "data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89541 */ "data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89634 */ "data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89725 */ "data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=89817 */ "data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=89914 */ "data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90016 */ "data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90112 */ "data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90211 */ "data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=90310 */ "data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=90407 */ "data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90501 */ "data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90600 */ "data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90704 */ "data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90802 */ "data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90903 */ "data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91004 */ "data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91103 */ "data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91203 */ "data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91308 */ "data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91418 */ "data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91522 */ "data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91629 */ "data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91736 */ "data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91841 */ "data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91941 */ "data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92046 */ "data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92156 */ "data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92260 */ "data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92367 */ "data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=92474 */ "data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=92579 */ "data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92659 */ "data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92744 */ "data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92823 */ "data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92905 */ "data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=92991 */ "data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=93075 */ "itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93153 */ "itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93236 */ "itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93324 */ "itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93417 */ "itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93504 */ "itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93594 */ "itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00000\000\000\000\000\000" +/* offset=93688 */ "itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=93780 */ "itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00000\000\000\000\000\000" +/* offset=93864 */ "itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93953 */ "itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94047 */ "itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94135 */ "itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94226 */ "itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94321 */ "itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94414 */ "itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94497 */ "itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94585 */ "itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94678 */ "itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94765 */ "itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94855 */ "itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94949 */ "itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95041 */ "itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95124 */ "itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95212 */ "itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95294 */ "itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95379 */ "itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95468 */ "itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95555 */ "i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95634 */ "i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95718 */ "i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95807 */ "i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95901 */ "i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95989 */ "i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96080 */ "i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96175 */ "i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96268 */ "i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96353 */ "i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96443 */ "i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96538 */ "i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96627 */ "i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96719 */ "i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96815 */ "i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96909 */ "i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96993 */ "i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97082 */ "i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97176 */ "i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97264 */ "i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97355 */ "i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97450 */ "i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97543 */ "i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97627 */ "i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97716 */ "i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97799 */ "i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97885 */ "i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97975 */ "i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98063 */ "instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98152 */ "instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98246 */ "instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98345 */ "instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98449 */ "instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98547 */ "instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98648 */ "instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98753 */ "instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98856 */ "instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98951 */ "instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99051 */ "instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99156 */ "instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99255 */ "instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99357 */ "instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=99463 */ "instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=99567 */ "instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99661 */ "instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99760 */ "instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99864 */ "instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99962 */ "instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100063 */ "instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100168 */ "instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100271 */ "instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100365 */ "instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100464 */ "instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100557 */ "instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100653 */ "instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100753 */ "instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100851 */ "branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=100938 */ "branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101030 */ "branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101127 */ "branch-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101229 */ "branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101325 */ "branch-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101424 */ "branch-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00000\000\000\000\000\000" +/* offset=101527 */ "branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=101628 */ "branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00000\000\000\000\000\000" +/* offset=101721 */ "branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101819 */ "branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101922 */ "branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102019 */ "branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102119 */ "branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102223 */ "branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102325 */ "branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102417 */ "branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102514 */ "branch-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102616 */ "branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102712 */ "branch-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102811 */ "branch-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102914 */ "branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=103015 */ "branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103107 */ "branch-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103204 */ "branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103295 */ "branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103389 */ "branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=103485 */ "branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103579 */ "branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103678 */ "branches-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103782 */ "branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103880 */ "branches-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103981 */ "branches-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104086 */ "branches-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104189 */ "branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104284 */ "branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104384 */ "branches-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104489 */ "branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104588 */ "branches-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104690 */ "branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104796 */ "branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104900 */ "branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104994 */ "branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105093 */ "branches-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105197 */ "branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105295 */ "branches-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105396 */ "branches-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=105501 */ "branches-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=105604 */ "branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105698 */ "branches-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105797 */ "branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105890 */ "branches-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105986 */ "branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106086 */ "branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106184 */ "bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106268 */ "bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106357 */ "bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106451 */ "bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106550 */ "bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106643 */ "bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106739 */ "bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106839 */ "bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106937 */ "bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107027 */ "bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107122 */ "bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107222 */ "bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107316 */ "bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107413 */ "bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=107514 */ "bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=107613 */ "bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107702 */ "bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107796 */ "bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107895 */ "bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107988 */ "bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108084 */ "bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108184 */ "bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108282 */ "bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108371 */ "bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108465 */ "bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108553 */ "bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108644 */ "bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108739 */ "bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108832 */ "btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108916 */ "btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109005 */ "btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109099 */ "btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109198 */ "btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109291 */ "btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109387 */ "btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=109487 */ "btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=109585 */ "btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109675 */ "btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109770 */ "btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109870 */ "btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109964 */ "btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110061 */ "btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110162 */ "btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110261 */ "btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110350 */ "btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110444 */ "btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110543 */ "btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110636 */ "btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110732 */ "btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110832 */ "btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110930 */ "btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111019 */ "btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111113 */ "btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111201 */ "btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111292 */ "btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=111387 */ "btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=111480 */ "bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111564 */ "bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111653 */ "bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111747 */ "bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111846 */ "bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111939 */ "bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112035 */ "bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112135 */ "bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112233 */ "bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112323 */ "bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112418 */ "bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112518 */ "bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112612 */ "bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112709 */ "bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112810 */ "bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112909 */ "bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112998 */ "bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113092 */ "bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113191 */ "bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113284 */ "bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113380 */ "bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=113480 */ "bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=113578 */ "bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113667 */ "bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113761 */ "bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113849 */ "bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113940 */ "bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=114035 */ "bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=114128 */ "node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114203 */ "node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114283 */ "node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114368 */ "node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114458 */ "node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114542 */ "node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114629 */ "node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00000\000\000\000\000\000" +/* offset=114720 */ "node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=114809 */ "node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00000\000\000\000\000\000" +/* offset=114890 */ "node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114976 */ "node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115067 */ "node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115152 */ "node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115240 */ "node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115332 */ "node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115422 */ "node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115502 */ "node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115587 */ "node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115677 */ "node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115761 */ "node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115848 */ "node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115939 */ "node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=116028 */ "node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116114 */ "node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116205 */ "node-store-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116301 */ "node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116391 */ "node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116484 */ "node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00000\000\000\000\000\000" +/* offset=116577 */ "node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=116668 */ "node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00000\000\000\000\000\000" +/* offset=116755 */ "node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116847 */ "node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116944 */ "node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117035 */ "node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117129 */ "node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117223 */ "node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117315 */ "node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117401 */ "node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117492 */ "node-write-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117588 */ "node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117678 */ "node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117771 */ "node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117864 */ "node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117955 */ "node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118047 */ "node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118144 */ "node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118246 */ "node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118342 */ "node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118441 */ "node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00000\000\000\000\000\000" +/* offset=118540 */ "node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=118637 */ "node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00000\000\000\000\000\000" +/* offset=118731 */ "node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118830 */ "node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118934 */ "node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119032 */ "node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119133 */ "node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119234 */ "node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119333 */ "node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119433 */ "node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119538 */ "node-speculative-read-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119648 */ "node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119752 */ "node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119859 */ "node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119966 */ "node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120071 */ "node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120171 */ "node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120276 */ "node-speculative-load-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120386 */ "node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120490 */ "node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120597 */ "node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120704 */ "node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120809 */ "node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=120889 */ "node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=120974 */ "node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=121053 */ "node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=121135 */ "node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=121221 */ "node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=121305 */ "cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" +/* offset=121467 */ "cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" +/* offset=121629 */ "instructions\000legacy hardware\000Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts\000legacy-hardware-config=1\000\00000\000\000\000\000\000" +/* offset=121805 */ "cache-references\000legacy hardware\000Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU\000legacy-hardware-config=2\000\00000\000\000\000\000\000" +/* offset=122075 */ "cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates\000legacy-hardware-config=3\000\00000\000\000\000\000\000" +/* offset=122318 */ "branches\000legacy hardware\000Retired branch instructions [This event is an alias of branch-instructions]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" +/* offset=122452 */ "branch-instructions\000legacy hardware\000Retired branch instructions [This event is an alias of branches]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" +/* offset=122586 */ "branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-hardware-config=5\000\00000\000\000\000\000\000" +/* offset=122682 */ "bus-cycles\000legacy hardware\000Bus cycles, which can be different from total cycles\000legacy-hardware-config=6\000\00000\000\000\000\000\000" +/* offset=122795 */ "stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" +/* offset=122945 */ "idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of stalled-cycles-fronted]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" +/* offset=123094 */ "stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of idle-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" +/* offset=123247 */ "idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" +/* offset=123400 */ "ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000" +/* offset=123512 */ "software\000" +/* offset=123521 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000" +/* offset=123599 */ "task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000" +/* offset=123679 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123774 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123869 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" +/* offset=123970 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" +/* offset=124071 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124203 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124335 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" +/* offset=124444 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" +/* offset=124547 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" +/* offset=124639 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" +/* offset=124766 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" +/* offset=124846 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" +/* offset=124948 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" +/* offset=125051 */ "tool\000" +/* offset=125056 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" +/* offset=125132 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" +/* offset=125202 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" +/* offset=125270 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" +/* offset=125346 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" +/* offset=125491 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" +/* offset=125594 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" +/* offset=125711 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" +/* offset=125787 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" +/* offset=125873 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" +/* offset=125983 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" +/* offset=126090 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" +/* offset=126189 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" +/* offset=126251 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" +/* offset=126313 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" +/* offset=126411 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" +/* offset=126513 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" +/* offset=126646 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" +/* offset=126764 */ "hisi_sccl,ddrc\000" +/* offset=126779 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" +/* offset=126849 */ "uncore_cbox\000" +/* offset=126861 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" +/* offset=127015 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" +/* offset=127069 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" +/* offset=127127 */ "hisi_sccl,l3c\000" +/* offset=127141 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" +/* offset=127209 */ "uncore_imc_free_running\000" +/* offset=127233 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" +/* offset=127313 */ "uncore_imc\000" +/* offset=127324 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" +/* offset=127389 */ "uncore_sys_ddr_pmu\000" +/* offset=127408 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" +/* offset=127484 */ "uncore_sys_ccn_pmu\000" +/* offset=127503 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" +/* offset=127580 */ "uncore_sys_cmn_pmu\000" +/* offset=127599 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" +/* offset=127742 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" +/* offset=127764 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" +/* offset=127827 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" +/* offset=127993 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=128057 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=128124 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" +/* offset=128195 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" +/* offset=128289 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" +/* offset=128423 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" +/* offset=128487 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=128555 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=128625 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" +/* offset=128647 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" +/* offset=128669 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" +/* offset=128689 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" ; +static const struct compact_pmu_event pmu_events__common_default_core[] = { +{ 111480 }, /* bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113849 }, /* bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111564 }, /* bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111939 }, /* bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112135 }, /* bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 112035 }, /* bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 111846 }, /* bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111747 }, /* bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111653 }, /* bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112233 }, /* bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112612 }, /* bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112810 }, /* bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 112709 }, /* bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 112518 }, /* bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112418 }, /* bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112323 }, /* bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 114035 }, /* bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 113940 }, /* bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 113761 }, /* bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112909 }, /* bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113284 }, /* bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113480 }, /* bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 113380 }, /* bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 113191 }, /* bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113092 }, /* bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 112998 }, /* bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113667 }, /* bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 113578 }, /* bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106184 }, /* bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108553 }, /* bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106268 }, /* bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106643 }, /* bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106839 }, /* bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 106739 }, /* bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 106550 }, /* bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106451 }, /* bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106357 }, /* bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106937 }, /* bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107316 }, /* bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107514 }, /* bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 107413 }, /* bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 107222 }, /* bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107122 }, /* bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107027 }, /* bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108739 }, /* bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 108644 }, /* bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 108465 }, /* bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107613 }, /* bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107988 }, /* bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108184 }, /* bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 108084 }, /* bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 107895 }, /* bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107796 }, /* bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 107702 }, /* bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108371 }, /* bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108282 }, /* bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 100851 }, /* branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103295 }, /* branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 122452 }, /* branch-instructions\000legacy hardware\000Retired branch instructions [This event is an alias of branches]\000legacy-hardware-config=4\000\00000\000\000\000\000\000 */ +{ 100938 }, /* branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101325 }, /* branch-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101527 }, /* branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 101424 }, /* branch-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00000\000\000\000\000\000 */ +{ 101229 }, /* branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101127 }, /* branch-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101030 }, /* branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101628 }, /* branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00000\000\000\000\000\000 */ +{ 102019 }, /* branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102223 }, /* branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 102119 }, /* branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 101922 }, /* branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101819 }, /* branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 101721 }, /* branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103389 }, /* branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 122586 }, /* branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-hardware-config=5\000\00000\000\000\000\000\000 */ +{ 103204 }, /* branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102325 }, /* branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102712 }, /* branch-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102914 }, /* branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 102811 }, /* branch-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 102616 }, /* branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102514 }, /* branch-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 102417 }, /* branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103107 }, /* branch-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103015 }, /* branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 122318 }, /* branches\000legacy hardware\000Retired branch instructions [This event is an alias of branch-instructions]\000legacy-hardware-config=4\000\00000\000\000\000\000\000 */ +{ 105890 }, /* branches-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103485 }, /* branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103880 }, /* branches-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104086 }, /* branches-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 103981 }, /* branches-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 103782 }, /* branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103678 }, /* branches-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 103579 }, /* branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104189 }, /* branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104588 }, /* branches-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104796 }, /* branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 104690 }, /* branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 104489 }, /* branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104384 }, /* branches-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104284 }, /* branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 106086 }, /* branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 105986 }, /* branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 105797 }, /* branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104900 }, /* branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 105295 }, /* branches-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 105501 }, /* branches-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 105396 }, /* branches-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 105197 }, /* branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 105093 }, /* branches-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 104994 }, /* branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 105698 }, /* branches-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 105604 }, /* branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108832 }, /* btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111201 }, /* btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 108916 }, /* btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109291 }, /* btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109487 }, /* btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 109387 }, /* btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 109198 }, /* btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109099 }, /* btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109005 }, /* btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109585 }, /* btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109964 }, /* btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110162 }, /* btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 110061 }, /* btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 109870 }, /* btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109770 }, /* btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 109675 }, /* btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111387 }, /* btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 111292 }, /* btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 111113 }, /* btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110261 }, /* btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110636 }, /* btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110832 }, /* btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 110732 }, /* btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ +{ 110543 }, /* btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110444 }, /* btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110350 }, /* btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 111019 }, /* btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 110930 }, /* btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ +{ 122682 }, /* bus-cycles\000legacy hardware\000Bus cycles, which can be different from total cycles\000legacy-hardware-config=6\000\00000\000\000\000\000\000 */ +{ 122075 }, /* cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates\000legacy-hardware-config=3\000\00000\000\000\000\000\000 */ +{ 121805 }, /* cache-references\000legacy hardware\000Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU\000legacy-hardware-config=2\000\00000\000\000\000\000\000 */ +{ 121305 }, /* cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000 */ +{ 121467 }, /* cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000 */ +{ 78952 }, /* d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 85655 }, /* d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79024 }, /* d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79351 }, /* d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79523 }, /* d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 79435 }, /* d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 79270 }, /* d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79183 }, /* d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79101 }, /* d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79609 }, /* d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79940 }, /* d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 80114 }, /* d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 80025 }, /* d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 79858 }, /* d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79770 }, /* d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 79687 }, /* d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 85817 }, /* d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 85734 }, /* d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 85579 }, /* d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 82650 }, /* d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83025 }, /* d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83217 }, /* d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 83121 }, /* d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 82932 }, /* d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 82833 }, /* d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 82739 }, /* d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83311 }, /* d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83694 }, /* d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83890 }, /* d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 83792 }, /* d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 83599 }, /* d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83498 }, /* d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83402 }, /* d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 80201 }, /* d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 80528 }, /* d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 80700 }, /* d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 80612 }, /* d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 80447 }, /* d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 80360 }, /* d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 80278 }, /* d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 85497 }, /* d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 85420 }, /* d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 84703 }, /* d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 85110 }, /* d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 85318 }, /* d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 85214 }, /* d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 85009 }, /* d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84902 }, /* d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84800 }, /* d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 83986 }, /* d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84393 }, /* d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84601 }, /* d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 84497 }, /* d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 84292 }, /* d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84185 }, /* d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 84083 }, /* d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 80786 }, /* d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81137 }, /* d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81317 }, /* d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 81227 }, /* d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 81050 }, /* d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 80957 }, /* d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 80869 }, /* d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81405 }, /* d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81760 }, /* d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81942 }, /* d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 81851 }, /* d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 81672 }, /* d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81578 }, /* d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 81489 }, /* d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 82031 }, /* d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 82382 }, /* d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 82562 }, /* d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 82472 }, /* d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 82295 }, /* d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 82202 }, /* d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 82114 }, /* d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 85898 }, /* data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 92823 }, /* data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 85973 }, /* data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86312 }, /* data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86490 }, /* data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 86399 }, /* data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 86228 }, /* data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86138 }, /* data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86053 }, /* data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86579 }, /* data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86922 }, /* data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 87102 }, /* data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 87010 }, /* data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 86837 }, /* data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86746 }, /* data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 86660 }, /* data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 92991 }, /* data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 92905 }, /* data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 92744 }, /* data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 89725 }, /* data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90112 }, /* data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90310 }, /* data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 90211 }, /* data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 90016 }, /* data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 89914 }, /* data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 89817 }, /* data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90407 }, /* data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90802 }, /* data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91004 }, /* data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 90903 }, /* data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 90704 }, /* data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90600 }, /* data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 90501 }, /* data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 87192 }, /* data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 87531 }, /* data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 87709 }, /* data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 87618 }, /* data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 87447 }, /* data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 87357 }, /* data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 87272 }, /* data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 92659 }, /* data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 92579 }, /* data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 91841 }, /* data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 92260 }, /* data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 92474 }, /* data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 92367 }, /* data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 92156 }, /* data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 92046 }, /* data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91941 }, /* data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91103 }, /* data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91522 }, /* data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91736 }, /* data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 91629 }, /* data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 91418 }, /* data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91308 }, /* data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 91203 }, /* data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 87798 }, /* data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88161 }, /* data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88347 }, /* data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 88254 }, /* data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 88071 }, /* data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 87975 }, /* data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 87884 }, /* data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88438 }, /* data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88805 }, /* data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88993 }, /* data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 88899 }, /* data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 88714 }, /* data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88617 }, /* data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 88525 }, /* data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 89085 }, /* data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 89448 }, /* data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 89634 }, /* data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 89541 }, /* data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 89358 }, /* data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 89262 }, /* data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 89171 }, /* data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 72083 }, /* dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 78712 }, /* dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72154 }, /* dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72477 }, /* dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72647 }, /* dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 72560 }, /* dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00000\000\000\000\000\000 */ +{ 72397 }, /* dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72311 }, /* dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72230 }, /* dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72732 }, /* dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00000\000\000\000\000\000 */ +{ 73059 }, /* dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 73231 }, /* dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 73143 }, /* dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 72978 }, /* dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72891 }, /* dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 72809 }, /* dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 78872 }, /* dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 78790 }, /* dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 78637 }, /* dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 75738 }, /* dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76109 }, /* dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76299 }, /* dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 76204 }, /* dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00000\000\000\000\000\000 */ +{ 76017 }, /* dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 75919 }, /* dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 75826 }, /* dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76392 }, /* dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00000\000\000\000\000\000 */ +{ 76771 }, /* dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76965 }, /* dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 76868 }, /* dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 76677 }, /* dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76577 }, /* dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 76482 }, /* dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 73317 }, /* dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 73640 }, /* dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 73810 }, /* dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 73723 }, /* dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ +{ 73560 }, /* dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 73474 }, /* dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 73393 }, /* dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 78556 }, /* dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 78480 }, /* dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ +{ 77770 }, /* dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 78173 }, /* dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 78379 }, /* dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 78276 }, /* dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 78073 }, /* dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77967 }, /* dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77866 }, /* dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77060 }, /* dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77463 }, /* dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77669 }, /* dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 77566 }, /* dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ +{ 77363 }, /* dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77257 }, /* dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 77156 }, /* dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ +{ 73895 }, /* dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74242 }, /* dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74420 }, /* dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 74331 }, /* dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00000\000\000\000\000\000 */ +{ 74156 }, /* dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74064 }, /* dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 73977 }, /* dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74507 }, /* dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00000\000\000\000\000\000 */ +{ 74858 }, /* dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75038 }, /* dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 74948 }, /* dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 74771 }, /* dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74678 }, /* dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 74590 }, /* dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75126 }, /* dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75473 }, /* dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75651 }, /* dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 75562 }, /* dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ +{ 75387 }, /* dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75295 }, /* dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 75208 }, /* dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ +{ 95555 }, /* i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97799 }, /* i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95634 }, /* i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95989 }, /* i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96175 }, /* i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 96080 }, /* i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 95901 }, /* i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95807 }, /* i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95718 }, /* i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96268 }, /* i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96627 }, /* i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96815 }, /* i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 96719 }, /* i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 96538 }, /* i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96443 }, /* i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96353 }, /* i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97975 }, /* i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 97885 }, /* i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 97716 }, /* i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96909 }, /* i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97264 }, /* i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97450 }, /* i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 97355 }, /* i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 97176 }, /* i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97082 }, /* i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 96993 }, /* i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97627 }, /* i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 97543 }, /* i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 123247 }, /* idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000 */ +{ 122945 }, /* idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of stalled-cycles-fronted]\000legacy-hardware-config=7\000\00000\000\000\000\000\000 */ +{ 98063 }, /* instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 100557 }, /* instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98152 }, /* instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98547 }, /* instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98753 }, /* instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 98648 }, /* instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 98449 }, /* instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98345 }, /* instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98246 }, /* instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98856 }, /* instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99255 }, /* instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99463 }, /* instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 99357 }, /* instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 99156 }, /* instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99051 }, /* instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 98951 }, /* instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 100753 }, /* instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 100653 }, /* instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 100464 }, /* instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99567 }, /* instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99962 }, /* instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 100168 }, /* instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 100063 }, /* instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 99864 }, /* instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99760 }, /* instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 99661 }, /* instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 100365 }, /* instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 100271 }, /* instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 121629 }, /* instructions\000legacy hardware\000Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts\000legacy-hardware-config=1\000\00000\000\000\000\000\000 */ +{ 93075 }, /* itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95294 }, /* itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93153 }, /* itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93504 }, /* itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93688 }, /* itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 93594 }, /* itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00000\000\000\000\000\000 */ +{ 93417 }, /* itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93324 }, /* itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93236 }, /* itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93780 }, /* itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00000\000\000\000\000\000 */ +{ 94135 }, /* itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94321 }, /* itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 94226 }, /* itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 94047 }, /* itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93953 }, /* itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 93864 }, /* itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95468 }, /* itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 95379 }, /* itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 95212 }, /* itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94414 }, /* itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94765 }, /* itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94949 }, /* itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 94855 }, /* itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ +{ 94678 }, /* itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94585 }, /* itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 94497 }, /* itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95124 }, /* itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 95041 }, /* itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ +{ 8037 }, /* l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15406 }, /* l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8118 }, /* l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8481 }, /* l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8671 }, /* l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 8574 }, /* l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 8391 }, /* l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8295 }, /* l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8204 }, /* l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8766 }, /* l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9133 }, /* l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9325 }, /* l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 9227 }, /* l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 9042 }, /* l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8945 }, /* l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 8853 }, /* l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15586 }, /* l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 15494 }, /* l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 15321 }, /* l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 12122 }, /* l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12533 }, /* l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12743 }, /* l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 12638 }, /* l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 12431 }, /* l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12323 }, /* l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12220 }, /* l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12846 }, /* l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13265 }, /* l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13479 }, /* l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 13372 }, /* l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 13161 }, /* l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13051 }, /* l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 12946 }, /* l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 9421 }, /* l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9784 }, /* l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9974 }, /* l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 9877 }, /* l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 9694 }, /* l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9598 }, /* l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 9507 }, /* l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15230 }, /* l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15144 }, /* l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 14364 }, /* l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 14807 }, /* l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 15033 }, /* l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 14920 }, /* l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 14697 }, /* l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 14581 }, /* l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 14470 }, /* l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13584 }, /* l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 14027 }, /* l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 14253 }, /* l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 14140 }, /* l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 13917 }, /* l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13801 }, /* l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 13690 }, /* l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 10069 }, /* l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10456 }, /* l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10654 }, /* l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 10555 }, /* l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 10360 }, /* l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10258 }, /* l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10161 }, /* l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10751 }, /* l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11142 }, /* l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11342 }, /* l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 11242 }, /* l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 11045 }, /* l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10942 }, /* l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 10844 }, /* l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11440 }, /* l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11827 }, /* l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 12025 }, /* l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 11926 }, /* l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 11731 }, /* l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11629 }, /* l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 11532 }, /* l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 23238 }, /* l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 30829 }, /* l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23322 }, /* l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23697 }, /* l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23893 }, /* l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 23793 }, /* l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 23604 }, /* l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23505 }, /* l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23411 }, /* l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23991 }, /* l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24370 }, /* l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24568 }, /* l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 24467 }, /* l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 24276 }, /* l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24176 }, /* l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24081 }, /* l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 31015 }, /* l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 30920 }, /* l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 30741 }, /* l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 27452 }, /* l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 27875 }, /* l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28091 }, /* l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 27983 }, /* l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 27770 }, /* l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 27659 }, /* l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 27553 }, /* l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28197 }, /* l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28628 }, /* l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28848 }, /* l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 28738 }, /* l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 28521 }, /* l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28408 }, /* l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28300 }, /* l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 24667 }, /* l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 25042 }, /* l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 25238 }, /* l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 25138 }, /* l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 24949 }, /* l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24850 }, /* l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 24756 }, /* l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 30647 }, /* l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 30558 }, /* l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 29757 }, /* l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 30212 }, /* l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 30444 }, /* l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 30328 }, /* l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 30099 }, /* l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29980 }, /* l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29866 }, /* l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 28956 }, /* l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29411 }, /* l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29643 }, /* l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 29527 }, /* l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 29298 }, /* l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29179 }, /* l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 29065 }, /* l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 25336 }, /* l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 25735 }, /* l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 25939 }, /* l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 25837 }, /* l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 25636 }, /* l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 25531 }, /* l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 25431 }, /* l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26039 }, /* l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26442 }, /* l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26648 }, /* l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 26545 }, /* l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 26342 }, /* l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26236 }, /* l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26135 }, /* l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26749 }, /* l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 27148 }, /* l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 27352 }, /* l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 27250 }, /* l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 27049 }, /* l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26944 }, /* l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 26844 }, /* l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 13 }, /* l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 7752 }, /* l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 99 }, /* l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 482 }, /* l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 682 }, /* l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 580 }, /* l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00000\000\000\000\000\000 */ +{ 387 }, /* l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 286 }, /* l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 190 }, /* l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 782 }, /* l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00000\000\000\000\000\000 */ +{ 1169 }, /* l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 1371 }, /* l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 1268 }, /* l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 1073 }, /* l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 971 }, /* l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 874 }, /* l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 7942 }, /* l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 7845 }, /* l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 7662 }, /* l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 4313 }, /* l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 4744 }, /* l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 4964 }, /* l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 4854 }, /* l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00000\000\000\000\000\000 */ +{ 4637 }, /* l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 4524 }, /* l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 4416 }, /* l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5072 }, /* l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00000\000\000\000\000\000 */ +{ 5511 }, /* l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5735 }, /* l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 5623 }, /* l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 5402 }, /* l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5287 }, /* l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5177 }, /* l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 1472 }, /* l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 1855 }, /* l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 2055 }, /* l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 1953 }, /* l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 1760 }, /* l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 1659 }, /* l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 1563 }, /* l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 7566 }, /* l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 7475 }, /* l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 6660 }, /* l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 7123 }, /* l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 7359 }, /* l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 7241 }, /* l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 7008 }, /* l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 6887 }, /* l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 6771 }, /* l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5845 }, /* l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 6308 }, /* l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 6544 }, /* l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 6426 }, /* l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 6193 }, /* l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 6072 }, /* l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 5956 }, /* l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 2155 }, /* l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2562 }, /* l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2770 }, /* l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 2666 }, /* l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00000\000\000\000\000\000 */ +{ 2461 }, /* l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2354 }, /* l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2252 }, /* l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2872 }, /* l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00000\000\000\000\000\000 */ +{ 3283 }, /* l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 3493 }, /* l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 3388 }, /* l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 3181 }, /* l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 3073 }, /* l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 2970 }, /* l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 3596 }, /* l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 4003 }, /* l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 4211 }, /* l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 4107 }, /* l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 3902 }, /* l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 3795 }, /* l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 3693 }, /* l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 37366 }, /* l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43053 }, /* l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37454 }, /* l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37845 }, /* l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38049 }, /* l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 37945 }, /* l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 37748 }, /* l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37645 }, /* l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37547 }, /* l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38151 }, /* l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38546 }, /* l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38752 }, /* l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 38647 }, /* l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 38448 }, /* l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38344 }, /* l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38245 }, /* l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43247 }, /* l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 43148 }, /* l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 42961 }, /* l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 39552 }, /* l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 39991 }, /* l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 40215 }, /* l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 40103 }, /* l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 39882 }, /* l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 39767 }, /* l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 39657 }, /* l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 40325 }, /* l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 40772 }, /* l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41000 }, /* l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 40886 }, /* l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 40661 }, /* l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 40544 }, /* l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 40432 }, /* l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 38855 }, /* l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 39246 }, /* l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 39450 }, /* l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 39346 }, /* l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 39149 }, /* l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 39046 }, /* l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 38948 }, /* l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 42863 }, /* l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 42770 }, /* l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 41941 }, /* l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 42412 }, /* l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 42652 }, /* l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 42532 }, /* l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 42295 }, /* l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 42172 }, /* l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 42054 }, /* l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41112 }, /* l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41583 }, /* l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41823 }, /* l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 41703 }, /* l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 41466 }, /* l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41343 }, /* l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 41225 }, /* l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 31108 }, /* l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37060 }, /* l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31201 }, /* l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31612 }, /* l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31826 }, /* l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 31717 }, /* l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00000\000\000\000\000\000 */ +{ 31510 }, /* l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31402 }, /* l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31299 }, /* l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 31933 }, /* l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00000\000\000\000\000\000 */ +{ 32348 }, /* l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 32564 }, /* l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 32454 }, /* l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 32245 }, /* l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 32136 }, /* l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 32032 }, /* l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 37264 }, /* l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 37160 }, /* l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 36963 }, /* l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 33404 }, /* l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 33863 }, /* l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 34097 }, /* l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 33980 }, /* l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00000\000\000\000\000\000 */ +{ 33749 }, /* l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 33629 }, /* l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 33514 }, /* l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 34212 }, /* l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00000\000\000\000\000\000 */ +{ 34679 }, /* l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 34917 }, /* l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 34798 }, /* l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 34563 }, /* l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 34441 }, /* l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 34324 }, /* l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 32672 }, /* l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 33083 }, /* l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 33297 }, /* l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 33188 }, /* l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 32981 }, /* l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 32873 }, /* l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 32770 }, /* l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 36860 }, /* l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 36762 }, /* l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 35898 }, /* l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 36389 }, /* l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 36639 }, /* l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 36514 }, /* l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 36267 }, /* l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 36139 }, /* l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 36016 }, /* l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 35034 }, /* l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 35525 }, /* l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 35775 }, /* l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 35650 }, /* l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 35403 }, /* l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 35275 }, /* l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 35152 }, /* l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 49266 }, /* l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 55483 }, /* l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 49364 }, /* l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 49795 }, /* l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50019 }, /* l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 49905 }, /* l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 49688 }, /* l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 49575 }, /* l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 49467 }, /* l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50131 }, /* l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50566 }, /* l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50792 }, /* l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 50677 }, /* l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 50458 }, /* l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50344 }, /* l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 50235 }, /* l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 55697 }, /* l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 55588 }, /* l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 55381 }, /* l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 51672 }, /* l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 52151 }, /* l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 52395 }, /* l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 52273 }, /* l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 52032 }, /* l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 51907 }, /* l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 51787 }, /* l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 52515 }, /* l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53002 }, /* l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53250 }, /* l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 53126 }, /* l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 52881 }, /* l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 52754 }, /* l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 52632 }, /* l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 50905 }, /* l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 51336 }, /* l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 51560 }, /* l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 51446 }, /* l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 51229 }, /* l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 51116 }, /* l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 51008 }, /* l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 55273 }, /* l1-instruction-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 55170 }, /* l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 54271 }, /* l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 54782 }, /* l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 55042 }, /* l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 54912 }, /* l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 54655 }, /* l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 54522 }, /* l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 54394 }, /* l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53372 }, /* l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53883 }, /* l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 54143 }, /* l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 54013 }, /* l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 53756 }, /* l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53623 }, /* l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 53495 }, /* l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 15676 }, /* l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 22971 }, /* l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15756 }, /* l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16115 }, /* l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16303 }, /* l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 16207 }, /* l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 16026 }, /* l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15931 }, /* l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 15841 }, /* l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16397 }, /* l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16760 }, /* l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16950 }, /* l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 16853 }, /* l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 16670 }, /* l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16574 }, /* l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 16483 }, /* l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 23149 }, /* l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 23058 }, /* l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 22887 }, /* l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 19718 }, /* l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20125 }, /* l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20333 }, /* l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 20229 }, /* l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 20024 }, /* l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 19917 }, /* l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 19815 }, /* l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20435 }, /* l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20850 }, /* l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21062 }, /* l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 20956 }, /* l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 20747 }, /* l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20638 }, /* l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 20534 }, /* l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 17045 }, /* l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 17404 }, /* l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 17592 }, /* l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 17496 }, /* l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ +{ 17315 }, /* l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 17220 }, /* l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 17130 }, /* l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 22797 }, /* l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 22712 }, /* l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ +{ 21939 }, /* l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 22378 }, /* l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 22602 }, /* l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 22490 }, /* l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 22269 }, /* l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 22154 }, /* l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 22044 }, /* l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21166 }, /* l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21605 }, /* l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21829 }, /* l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 21717 }, /* l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ +{ 21496 }, /* l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21381 }, /* l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 21271 }, /* l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ +{ 17686 }, /* l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18069 }, /* l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18265 }, /* l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 18167 }, /* l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 17974 }, /* l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 17873 }, /* l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 17777 }, /* l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18361 }, /* l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18748 }, /* l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18946 }, /* l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 18847 }, /* l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 18652 }, /* l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18550 }, /* l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 18453 }, /* l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 19043 }, /* l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 19426 }, /* l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 19622 }, /* l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 19524 }, /* l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ +{ 19331 }, /* l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 19230 }, /* l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 19134 }, /* l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ +{ 43344 }, /* l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 48978 }, /* l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43431 }, /* l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43818 }, /* l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44020 }, /* l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 43917 }, /* l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 43722 }, /* l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43620 }, /* l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 43523 }, /* l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44121 }, /* l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44512 }, /* l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44716 }, /* l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 44612 }, /* l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 44415 }, /* l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44312 }, /* l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44214 }, /* l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 49170 }, /* l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 49072 }, /* l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 48887 }, /* l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 45508 }, /* l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 45943 }, /* l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46165 }, /* l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 46054 }, /* l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 45835 }, /* l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 45721 }, /* l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 45612 }, /* l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46274 }, /* l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46717 }, /* l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46943 }, /* l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 46830 }, /* l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 46607 }, /* l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46491 }, /* l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 46380 }, /* l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 44818 }, /* l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 45205 }, /* l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 45407 }, /* l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 45304 }, /* l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ +{ 45109 }, /* l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 45007 }, /* l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 44910 }, /* l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 48790 }, /* l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 48698 }, /* l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ +{ 47876 }, /* l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 48343 }, /* l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 48581 }, /* l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 48462 }, /* l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 48227 }, /* l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 48105 }, /* l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47988 }, /* l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47054 }, /* l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47521 }, /* l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47759 }, /* l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 47640 }, /* l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ +{ 47405 }, /* l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47283 }, /* l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 47166 }, /* l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ +{ 63212 }, /* l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 71765 }, /* l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63309 }, /* l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63736 }, /* l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63958 }, /* l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 63845 }, /* l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 63630 }, /* l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63518 }, /* l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63411 }, /* l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64069 }, /* l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64500 }, /* l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64724 }, /* l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 64610 }, /* l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 64393 }, /* l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64280 }, /* l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64172 }, /* l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 71977 }, /* l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 71869 }, /* l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 71664 }, /* l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 67985 }, /* l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68460 }, /* l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68702 }, /* l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 68581 }, /* l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 68342 }, /* l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68218 }, /* l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68099 }, /* l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68821 }, /* l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69304 }, /* l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69550 }, /* l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 69427 }, /* l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 69184 }, /* l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69058 }, /* l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 68937 }, /* l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 64836 }, /* l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 65263 }, /* l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 65485 }, /* l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 65372 }, /* l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 65157 }, /* l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 65045 }, /* l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 64938 }, /* l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 71557 }, /* l2-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 71455 }, /* l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 70563 }, /* l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 71070 }, /* l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 71328 }, /* l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 71199 }, /* l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 70944 }, /* l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 70812 }, /* l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 70685 }, /* l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69671 }, /* l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 70178 }, /* l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 70436 }, /* l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 70307 }, /* l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 70052 }, /* l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69920 }, /* l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 69793 }, /* l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 65596 }, /* l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66047 }, /* l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66277 }, /* l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 66162 }, /* l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 65935 }, /* l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 65817 }, /* l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 65704 }, /* l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66390 }, /* l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66845 }, /* l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67077 }, /* l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 66961 }, /* l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 66732 }, /* l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66613 }, /* l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 66499 }, /* l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67191 }, /* l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67642 }, /* l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67872 }, /* l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 67757 }, /* l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 67530 }, /* l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67412 }, /* l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 67299 }, /* l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 55804 }, /* llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 62951 }, /* llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 55882 }, /* llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56233 }, /* llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56417 }, /* llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 56323 }, /* llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00000\000\000\000\000\000 */ +{ 56146 }, /* llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56053 }, /* llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 55965 }, /* llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56509 }, /* llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00000\000\000\000\000\000 */ +{ 56864 }, /* llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 57050 }, /* llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 56955 }, /* llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 56776 }, /* llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56682 }, /* llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 56593 }, /* llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 63125 }, /* llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 63036 }, /* llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 62869 }, /* llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 59760 }, /* llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 60159 }, /* llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 60363 }, /* llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 60261 }, /* llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00000\000\000\000\000\000 */ +{ 60060 }, /* llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 59955 }, /* llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 59855 }, /* llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 60463 }, /* llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00000\000\000\000\000\000 */ +{ 60870 }, /* llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61078 }, /* llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 60974 }, /* llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 60769 }, /* llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 60662 }, /* llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 60560 }, /* llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 57143 }, /* llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 57494 }, /* llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 57678 }, /* llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 57584 }, /* llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ +{ 57407 }, /* llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 57314 }, /* llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 57226 }, /* llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 62781 }, /* llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 62698 }, /* llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ +{ 61939 }, /* llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 62370 }, /* llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 62590 }, /* llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 62480 }, /* llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 62263 }, /* llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 62150 }, /* llc-speculative-load-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 62042 }, /* llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61180 }, /* llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61611 }, /* llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61831 }, /* llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 61721 }, /* llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ +{ 61504 }, /* llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61391 }, /* llc-speculative-read-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 61283 }, /* llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ +{ 57770 }, /* llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 58145 }, /* llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 58337 }, /* llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 58241 }, /* llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00000\000\000\000\000\000 */ +{ 58052 }, /* llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 57953 }, /* llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 57859 }, /* llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 58431 }, /* llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00000\000\000\000\000\000 */ +{ 58810 }, /* llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59004 }, /* llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 58907 }, /* llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 58716 }, /* llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 58616 }, /* llc-stores-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 58521 }, /* llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59099 }, /* llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59474 }, /* llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59666 }, /* llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 59570 }, /* llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ +{ 59381 }, /* llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59282 }, /* llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 59188 }, /* llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ +{ 114128 }, /* node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 121053 }, /* node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114203 }, /* node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114542 }, /* node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114720 }, /* node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 114629 }, /* node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00000\000\000\000\000\000 */ +{ 114458 }, /* node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114368 }, /* node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114283 }, /* node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114809 }, /* node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00000\000\000\000\000\000 */ +{ 115152 }, /* node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 115332 }, /* node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 115240 }, /* node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 115067 }, /* node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114976 }, /* node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 114890 }, /* node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 121221 }, /* node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 121135 }, /* node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 120974 }, /* node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 117955 }, /* node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118342 }, /* node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118540 }, /* node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 118441 }, /* node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00000\000\000\000\000\000 */ +{ 118246 }, /* node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118144 }, /* node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118047 }, /* node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118637 }, /* node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00000\000\000\000\000\000 */ +{ 119032 }, /* node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119234 }, /* node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 119133 }, /* node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 118934 }, /* node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118830 }, /* node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 118731 }, /* node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 115422 }, /* node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 115761 }, /* node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 115939 }, /* node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 115848 }, /* node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ +{ 115677 }, /* node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 115587 }, /* node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 115502 }, /* node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 120889 }, /* node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 120809 }, /* node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ +{ 120071 }, /* node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 120490 }, /* node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 120704 }, /* node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 120597 }, /* node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 120386 }, /* node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 120276 }, /* node-speculative-load-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 120171 }, /* node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119333 }, /* node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119752 }, /* node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119966 }, /* node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 119859 }, /* node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ +{ 119648 }, /* node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119538 }, /* node-speculative-read-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 119433 }, /* node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ +{ 116028 }, /* node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116391 }, /* node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116577 }, /* node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ +{ 116484 }, /* node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00000\000\000\000\000\000 */ +{ 116301 }, /* node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116205 }, /* node-store-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116114 }, /* node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116668 }, /* node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00000\000\000\000\000\000 */ +{ 117035 }, /* node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117223 }, /* node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ +{ 117129 }, /* node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ +{ 116944 }, /* node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116847 }, /* node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 116755 }, /* node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117315 }, /* node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117678 }, /* node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117864 }, /* node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ +{ 117771 }, /* node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ +{ 117588 }, /* node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117492 }, /* node-write-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 117401 }, /* node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ +{ 123400 }, /* ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000 */ +{ 123094 }, /* stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of idle-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000 */ +{ 122795 }, /* stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000 */ +}; static const struct compact_pmu_event pmu_events__common_software[] = { -{ 1035 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */ -{ 1334 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */ -{ 1436 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */ -{ 357 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */ -{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */ -{ 559 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 458 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */ -{ 1254 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */ -{ 1127 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */ -{ 167 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 932 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */ -{ 691 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 823 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */ -{ 262 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 87 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */ +{ 124547 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */ +{ 124846 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */ +{ 124948 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */ +{ 123869 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */ +{ 123521 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */ +{ 124071 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */ +{ 123970 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */ +{ 124766 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */ +{ 124639 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */ +{ 123679 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */ +{ 124444 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */ +{ 124203 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */ +{ 124335 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */ +{ 123774 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */ +{ 123599 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__common_tool[] = { -{ 1544 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ -{ 1758 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ -{ 1834 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ -{ 1979 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ -{ 2082 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ -{ 2199 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ -{ 2275 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ -{ 2361 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ -{ 2471 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ -{ 1690 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ -{ 2578 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ -{ 1620 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ +{ 125056 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ +{ 125270 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ +{ 125346 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ +{ 125491 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ +{ 125594 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ +{ 125711 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ +{ 125787 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ +{ 125873 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ +{ 125983 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ +{ 125202 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ +{ 126090 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ +{ 125132 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ }; const struct pmu_table_entry pmu_events__common[] = { +{ + .entries = pmu_events__common_default_core, + .num_entries = ARRAY_SIZE(pmu_events__common_default_core), + .pmu_name = { 0 /* default_core\000 */ }, +}, { .entries = pmu_events__common_software, .num_entries = ARRAY_SIZE(pmu_events__common_software), - .pmu_name = { 0 /* software\000 */ }, + .pmu_name = { 123512 /* software\000 */ }, }, { .entries = pmu_events__common_tool, .num_entries = ARRAY_SIZE(pmu_events__common_tool), - .pmu_name = { 1539 /* tool\000 */ }, + .pmu_name = { 125051 /* tool\000 */ }, }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { -{ 2690 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ -{ 2752 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ -{ 3014 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ -{ 3147 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ -{ 2814 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ -{ 2912 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ +{ 126189 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ +{ 126251 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ +{ 126513 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ +{ 126646 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ +{ 126313 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ +{ 126411 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { -{ 3280 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ +{ 126779 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { -{ 3642 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ +{ 127141 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { -{ 3516 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ -{ 3570 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ -{ 3362 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ +{ 127015 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ +{ 127069 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ +{ 126861 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { -{ 3825 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ +{ 127324 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { -{ 3734 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ +{ 127233 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ }; @@ -167,51 +2634,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = { { .entries = pmu_events__test_soc_cpu_default_core, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), - .pmu_name = { 2677 /* default_core\000 */ }, + .pmu_name = { 0 /* default_core\000 */ }, }, { .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), - .pmu_name = { 3265 /* hisi_sccl,ddrc\000 */ }, + .pmu_name = { 126764 /* hisi_sccl,ddrc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), - .pmu_name = { 3628 /* hisi_sccl,l3c\000 */ }, + .pmu_name = { 127127 /* hisi_sccl,l3c\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_cbox, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), - .pmu_name = { 3350 /* uncore_cbox\000 */ }, + .pmu_name = { 126849 /* uncore_cbox\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), - .pmu_name = { 3814 /* uncore_imc\000 */ }, + .pmu_name = { 127313 /* uncore_imc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), - .pmu_name = { 3710 /* uncore_imc_free_running\000 */ }, + .pmu_name = { 127209 /* uncore_imc_free_running\000 */ }, }, }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 4243 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ -{ 4924 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ -{ 4696 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ -{ 4790 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ -{ 4988 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 5056 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 4328 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ -{ 4265 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ -{ 5190 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ -{ 5126 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ -{ 5148 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ -{ 5170 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ -{ 4625 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ -{ 4494 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ -{ 4558 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 127742 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ +{ 128423 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ +{ 128195 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ +{ 128289 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ +{ 128487 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 128555 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 127827 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ +{ 127764 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ +{ 128689 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ +{ 128625 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ +{ 128647 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ +{ 128669 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ +{ 128124 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ +{ 127993 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 128057 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ }; @@ -219,18 +2686,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { { .entries = pmu_metrics__test_soc_cpu_default_core, .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), - .pmu_name = { 2677 /* default_core\000 */ }, + .pmu_name = { 0 /* default_core\000 */ }, }, }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { -{ 4004 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ +{ 127503 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { -{ 4100 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ +{ 127599 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { -{ 3909 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ +{ 127408 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ }; @@ -238,17 +2705,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = { { .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), - .pmu_name = { 3985 /* uncore_sys_ccn_pmu\000 */ }, + .pmu_name = { 127484 /* uncore_sys_ccn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), - .pmu_name = { 4081 /* uncore_sys_cmn_pmu\000 */ }, + .pmu_name = { 127580 /* uncore_sys_cmn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), - .pmu_name = { 3890 /* uncore_sys_ddr_pmu\000 */ }, + .pmu_name = { 127389 /* uncore_sys_ddr_pmu\000 */ }, }, }; diff --git a/tools/perf/pmu-events/make_legacy_cache.py b/tools/perf/pmu-events/make_legacy_cache.py new file mode 100755 index 00000000000000..28a1ff804f8661 --- /dev/null +++ b/tools/perf/pmu-events/make_legacy_cache.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +import json + +hw_cache_id = [ + (0, # PERF_COUNT_HW_CACHE_L1D + ["L1-dcache", "l1-d", "l1d", "L1-data",], + [0, 1, 2,], # read, write, prefetch + "Level 1 data cache", + ), + (1, # PERF_COUNT_HW_CACHE_L1I + ["L1-icache", "l1-i", "l1i", "L1-instruction",], + [0, 2,], # read, prefetch + "Level 1 instruction cache", + ), + (2, # PERF_COUNT_HW_CACHE_LL + ["LLC", "L2"], + [0, 1, 2,], # read, write, prefetch + "Last level cache", + ), + (3, # PERF_COUNT_HW_CACHE_DTLB + ["dTLB", "d-tlb", "Data-TLB",], + [0, 1, 2,], # read, write, prefetch + "Data TLB", + ), + (4, # PERF_COUNT_HW_CACHE_ITLB + ["iTLB", "i-tlb", "Instruction-TLB",], + [0,], # read + "Instruction TLB", + ), + (5, # PERF_COUNT_HW_CACHE_BPU + ["branch", "branches", "bpu", "btb", "bpc",], + [0,], # read + "Branch prediction unit", + ), + (6, # PERF_COUNT_HW_CACHE_NODE + ["node",], + [0, 1, 2,], # read, write, prefetch + "Local memory", + ), +] + +hw_cache_op = [ + (0, # PERF_COUNT_HW_CACHE_OP_READ + ["load", "loads", "read",], + "read"), + (1, # PERF_COUNT_HW_CACHE_OP_WRITE + ["store", "stores", "write",], + "write"), + (2, # PERF_COUNT_HW_CACHE_OP_PREFETCH + ["prefetch", "prefetches", "speculative-read", "speculative-load",], + "prefetch"), +] + +hw_cache_result = [ + (0, # PERF_COUNT_HW_CACHE_RESULT_ACCESS + ["refs", "Reference", "ops", "access",], + "accesses"), + (1, # PERF_COUNT_HW_CACHE_RESULT_MISS + ["misses", "miss",], + "misses"), +] + +events = [] +def add_event(name: str, + cache_id: int, cache_op: int, cache_result: int, + desc: str, + deprecated: bool) -> None: + # Avoid conflicts with PERF_TYPE_HARDWARE events which are higher priority. + if name in ["branch-misses", "branches"]: + return + + # Tweak and deprecate L2 named events. + if name.startswith("L2"): + desc = desc.replace("Last level cache", "Level 2 (or higher) last level cache") + deprecated = True + + event = { + "EventName": name, + "BriefDescription": desc, + "LegacyCacheCode": f"0x{cache_id | (cache_op << 8) | (cache_result << 16):06x}", + } + + # Deprecate events with the name starting L2 as it is actively + # confusing as on many machines it actually means the L3 cache. + if deprecated: + event["Deprecated"] = "1" + events.append(event) + +for (cache_id, names, ops, cache_desc) in hw_cache_id: + for name in names: + add_event(name, + cache_id, + 0, # PERF_COUNT_HW_CACHE_OP_READ + 0, # PERF_COUNT_HW_CACHE_RESULT_ACCESS + f"{cache_desc} read accesses.", + deprecated=True) + + for (op, op_names, op_desc) in hw_cache_op: + if op not in ops: + continue + for op_name in op_names: + deprecated = (names[0] != name or op_names[1] != op_name) + add_event(f"{name}-{op_name}", + cache_id, + op, + 0, # PERF_COUNT_HW_CACHE_RESULT_ACCESS + f"{cache_desc} {op_desc} accesses.", + deprecated) + + for (result, result_names, result_desc) in hw_cache_result: + for result_name in result_names: + deprecated = ((names[0] != name or op_names[0] != op_name) or + (result == 0) or (result_names[0] != result_name)) + add_event(f"{name}-{op_name}-{result_name}", + cache_id, op, result, + f"{cache_desc} {op_desc} {result_desc}.", + deprecated) + + for (result, result_names, result_desc) in hw_cache_result: + for result_name in result_names: + add_event(f"{name}-{result_name}", + cache_id, + 0, # PERF_COUNT_HW_CACHE_OP_READ + result, + f"{cache_desc} read {result_desc}.", + deprecated=True) + +print(json.dumps(events, indent=2)) From b12b5b531a64a3f3f0dd7969f5bf83647e00c700 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:17 -0700 Subject: [PATCH 059/684] perf print-events: Remove print_hwcache_events Now legacy cache events are in json there's no need for a specific printing routine. To support the previous filtered version use an event glob of "legacy cache" which matches the topic of the json events. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/builtin-list.c | 16 +++++++--- tools/perf/util/print-events.c | 55 ---------------------------------- tools/perf/util/print-events.h | 1 - 3 files changed, 12 insertions(+), 60 deletions(-) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index caf42276bd0f5e..b6720ef3adf668 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -652,9 +652,18 @@ int cmd_list(int argc, const char **argv) } default_ps.pmu_glob = old_pmu_glob; } else if (strcmp(argv[i], "cache") == 0 || - strcmp(argv[i], "hwcache") == 0) - print_hwcache_events(&print_cb, ps); - else if (strcmp(argv[i], "pmu") == 0) { + strcmp(argv[i], "hwcache") == 0) { + char *old_event_glob = default_ps.event_glob; + + default_ps.event_glob = strdup("legacy cache"); + if (!default_ps.event_glob) { + ret = -1; + goto out; + } + perf_pmus__print_pmu_events(&print_cb, ps); + zfree(&default_ps.event_glob); + default_ps.event_glob = old_event_glob; + } else if (strcmp(argv[i], "pmu") == 0) { default_ps.exclude_abi = true; perf_pmus__print_pmu_events(&print_cb, ps); default_ps.exclude_abi = false; @@ -707,7 +716,6 @@ int cmd_list(int argc, const char **argv) default_ps.event_glob = s; print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, event_symbols_hw, PERF_COUNT_HW_MAX); - print_hwcache_events(&print_cb, ps); perf_pmus__print_pmu_events(&print_cb, ps); print_sdt_events(&print_cb, ps); default_ps.metrics = true; diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index 4153124a9948ee..91a5d9c7882ba4 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -186,59 +186,6 @@ bool is_event_supported(u8 type, u64 config) return ret; } -int print_hwcache_events(const struct print_callbacks *print_cb, void *print_state) -{ - struct perf_pmu *pmu = NULL; - const char *event_type_descriptor = event_type_descriptors[PERF_TYPE_HW_CACHE]; - - /* - * Only print core PMUs, skipping uncore for performance and - * PERF_TYPE_SOFTWARE that can succeed in opening legacy cache evenst. - */ - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { - if (pmu->is_uncore || pmu->type == PERF_TYPE_SOFTWARE) - continue; - - for (int type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (int op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { - /* skip invalid cache type */ - if (!evsel__is_cache_op_valid(type, op)) - continue; - - for (int res = 0; res < PERF_COUNT_HW_CACHE_RESULT_MAX; res++) { - char name[64]; - char alias_name[128]; - __u64 config; - int ret; - - __evsel__hw_cache_type_op_res_name(type, op, res, - name, sizeof(name)); - - ret = parse_events__decode_legacy_cache(name, pmu->type, - &config); - if (ret || !is_event_supported(PERF_TYPE_HW_CACHE, config)) - continue; - snprintf(alias_name, sizeof(alias_name), "%s/%s/", - pmu->name, name); - print_cb->print_event(print_state, - "cache", - pmu->name, - pmu->type, - name, - alias_name, - /*scale_unit=*/NULL, - /*deprecated=*/false, - event_type_descriptor, - /*desc=*/NULL, - /*long_desc=*/NULL, - /*encoding_desc=*/NULL); - } - } - } - } - return 0; -} - void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, unsigned int type, const struct event_symbol *syms, unsigned int max) @@ -434,8 +381,6 @@ void print_events(const struct print_callbacks *print_cb, void *print_state) print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE, event_symbols_hw, PERF_COUNT_HW_MAX); - print_hwcache_events(print_cb, print_state); - perf_pmus__print_pmu_events(print_cb, print_state); print_cb->print_event(print_state, diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h index d6ba384f0c6659..44e5dbd914004c 100644 --- a/tools/perf/util/print-events.h +++ b/tools/perf/util/print-events.h @@ -32,7 +32,6 @@ struct print_callbacks { /** Print all events, the default when no options are specified. */ void print_events(const struct print_callbacks *print_cb, void *print_state); -int print_hwcache_events(const struct print_callbacks *print_cb, void *print_state); void print_sdt_events(const struct print_callbacks *print_cb, void *print_state); void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, unsigned int type, const struct event_symbol *syms, From 50062baa536bcac03804cf04579c71b9351e829c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:18 -0700 Subject: [PATCH 060/684] perf print-events: Remove print_symbol_events Now legacy hardware events are in json there's no need for a specific printing routine that previously served for both hardware and software events. The associated event_symbols_hw is also removed. To support the previous filtered version use an event glob of "legacy hardware" which matches the topic of the json events. Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/builtin-list.c | 18 +++++++---- tools/perf/util/parse-events.c | 43 ------------------------- tools/perf/util/parse-events.h | 1 - tools/perf/util/print-events.c | 57 ---------------------------------- tools/perf/util/print-events.h | 3 -- 5 files changed, 12 insertions(+), 110 deletions(-) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index b6720ef3adf668..16400366f8276a 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -633,10 +633,18 @@ int cmd_list(int argc, const char **argv) zfree(&default_ps.pmu_glob); default_ps.pmu_glob = old_pmu_glob; } else if (strcmp(argv[i], "hw") == 0 || - strcmp(argv[i], "hardware") == 0) - print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX); - else if (strcmp(argv[i], "sw") == 0 || + strcmp(argv[i], "hardware") == 0) { + char *old_event_glob = default_ps.event_glob; + + default_ps.event_glob = strdup("legacy hardware"); + if (!default_ps.event_glob) { + ret = -1; + goto out; + } + perf_pmus__print_pmu_events(&print_cb, ps); + zfree(&default_ps.event_glob); + default_ps.event_glob = old_event_glob; + } else if (strcmp(argv[i], "sw") == 0 || strcmp(argv[i], "software") == 0) { char *old_pmu_glob = default_ps.pmu_glob; static const char * const sw_globs[] = { "software", "tool" }; @@ -714,8 +722,6 @@ int cmd_list(int argc, const char **argv) continue; } default_ps.event_glob = s; - print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX); perf_pmus__print_pmu_events(&print_cb, ps); print_sdt_events(&print_cb, ps); default_ps.metrics = true; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4e003abe90f0d1..5fd910bf42f5cc 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -42,49 +42,6 @@ static int parse_events_terms__copy(const struct parse_events_terms *src, struct parse_events_terms *dest); static int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); -const struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = { - .symbol = "cpu-cycles", - .alias = "cycles", - }, - [PERF_COUNT_HW_INSTRUCTIONS] = { - .symbol = "instructions", - .alias = "", - }, - [PERF_COUNT_HW_CACHE_REFERENCES] = { - .symbol = "cache-references", - .alias = "", - }, - [PERF_COUNT_HW_CACHE_MISSES] = { - .symbol = "cache-misses", - .alias = "", - }, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { - .symbol = "branch-instructions", - .alias = "branches", - }, - [PERF_COUNT_HW_BRANCH_MISSES] = { - .symbol = "branch-misses", - .alias = "", - }, - [PERF_COUNT_HW_BUS_CYCLES] = { - .symbol = "bus-cycles", - .alias = "", - }, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { - .symbol = "stalled-cycles-frontend", - .alias = "idle-cycles-frontend", - }, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { - .symbol = "stalled-cycles-backend", - .alias = "idle-cycles-backend", - }, - [PERF_COUNT_HW_REF_CPU_CYCLES] = { - .symbol = "ref-cycles", - .alias = "", - }, -}; - static const char *const event_types[] = { [PERF_TYPE_HARDWARE] = "hardware", [PERF_TYPE_SOFTWARE] = "software", diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ad782da63c83e8..61402c021d5121 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -266,7 +266,6 @@ struct event_symbol { const char *symbol; const char *alias; }; -extern const struct event_symbol event_symbols_hw[]; char *parse_events_formats_error_string(char *additional_terms); diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index 91a5d9c7882ba4..8f3ed83853a9e4 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -186,60 +186,6 @@ bool is_event_supported(u8 type, u64 config) return ret; } -void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, - unsigned int type, const struct event_symbol *syms, - unsigned int max) -{ - struct strlist *evt_name_list = strlist__new(NULL, NULL); - struct str_node *nd; - - if (!evt_name_list) { - pr_debug("Failed to allocate new strlist for symbol events\n"); - return; - } - for (unsigned int i = 0; i < max; i++) { - /* - * New attr.config still not supported here, the latest - * example was PERF_COUNT_SW_CGROUP_SWITCHES - */ - if (syms[i].symbol == NULL) - continue; - - if (!is_event_supported(type, i)) - continue; - - if (strlen(syms[i].alias)) { - char name[MAX_NAME_LEN]; - - snprintf(name, MAX_NAME_LEN, "%s OR %s", syms[i].symbol, syms[i].alias); - strlist__add(evt_name_list, name); - } else - strlist__add(evt_name_list, syms[i].symbol); - } - - strlist__for_each_entry(nd, evt_name_list) { - char *alias = strstr(nd->s, " OR "); - - if (alias) { - *alias = '\0'; - alias += 4; - } - print_cb->print_event(print_state, - /*topic=*/NULL, - /*pmu_name=*/NULL, - type, - nd->s, - alias, - /*scale_unit=*/NULL, - /*deprecated=*/false, - event_type_descriptors[type], - /*desc=*/NULL, - /*long_desc=*/NULL, - /*encoding_desc=*/NULL); - } - strlist__delete(evt_name_list); -} - /** struct mep - RB-tree node for building printing information. */ struct mep { /** nd - RB-tree element. */ @@ -378,9 +324,6 @@ void metricgroup__print(const struct print_callbacks *print_cb, void *print_stat */ void print_events(const struct print_callbacks *print_cb, void *print_state) { - print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX); - perf_pmus__print_pmu_events(print_cb, print_state); print_cb->print_event(print_state, diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h index 44e5dbd914004c..eabba5d4a1fd1c 100644 --- a/tools/perf/util/print-events.h +++ b/tools/perf/util/print-events.h @@ -33,9 +33,6 @@ struct print_callbacks { /** Print all events, the default when no options are specified. */ void print_events(const struct print_callbacks *print_cb, void *print_state); void print_sdt_events(const struct print_callbacks *print_cb, void *print_state); -void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, - unsigned int type, const struct event_symbol *syms, - unsigned int max); void metricgroup__print(const struct print_callbacks *print_cb, void *print_state); bool is_event_supported(u8 type, u64 config); From b1c5efbfd92eb84d6d10cccc6b4edee491f20de1 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:19 -0700 Subject: [PATCH 061/684] perf parse-events: Remove hard coded legacy hardware and cache parsing Now that legacy hardware and cache events are in json, having the lexer match the specific event is no longer necessary and generic PMU parsing can take place. Because of this remove the specific term parsing, event adding, and passing of alternate_hw_config which was now always PERF_COUNT_HW_MAX. This mirrors a similar change for software events in commit 6e9fa4131abb ("perf parse-events: Remove non-json software events"). With no hard coded legacy hardware or cache events the wild card, case insensitivity, etc. is consistent for events. This does, however, mean events like cycles will wild card against all PMUs. A change does the same was originally posted and merged from: https://lore.kernel.org/r/20240416061533.921723-10-irogers@google.com and reverted by Linus in commit 4f1b067359ac ("Revert "perf parse-events: Prefer sysfs/JSON hardware events over legacy"") due to his dislike for the cycles behavior on ARM. Earlier patches in this series make perf record event opening failures non-fatal and hide the cycles event's failure to open on ARM in perf record, so it is expected the behavior will now be transparent in perf record. perf stat with a cycles event will wildcard open the event on all PMUs. As cycles is a "default event", the perf stat behavior for default events was updated to only open them on core/software PMUs. The change to support legacy events with PMUs was done to clean up Intel's hybrid PMU implementation. Having sysfs/json events with increased priority to legacy was requested by Mark Rutland to fix Apple-M PMU issues wrt broken legacy events on that PMU. It was requested that RISC-V be able to add events to the perf tool json so the PMU driver didn't need to map legacy events to config encodings: https://lore.kernel.org/lkml/20240217005738.3744121-1-atishp@rivosinc.com/ A previous series of patches decreasing legacy hardware event priorities was posted in: https://lore.kernel.org/lkml/20250416045117.876775-1-irogers@google.com/ Namhyung Kim mentioned that hardware and software events can be implemented similarly: https://lore.kernel.org/lkml/aIJmJns2lopxf3EK@google.com/ Tested-by: Thomas Richter Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 190 ++------------------------------- tools/perf/util/parse-events.h | 14 +-- tools/perf/util/parse-events.l | 52 --------- tools/perf/util/parse-events.y | 114 +------------------- tools/perf/util/pmu.c | 9 +- 5 files changed, 17 insertions(+), 362 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5fd910bf42f5cc..3aec86aebdc6bc 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -429,110 +429,7 @@ bool parse_events__filter_pmu(const struct parse_events_state *parse_state, static int parse_events_add_pmu(struct parse_events_state *parse_state, struct list_head *list, struct perf_pmu *pmu, const struct parse_events_terms *const_parsed_terms, - struct evsel *first_wildcard_match, u64 alternate_hw_config); - -int parse_events_add_cache(struct list_head *list, int *idx, const char *name, - struct parse_events_state *parse_state, - struct parse_events_terms *parsed_terms, - void *loc_) -{ - YYLTYPE *loc = loc_; - struct perf_pmu *pmu = NULL; - bool found_supported = false; - const char *config_name = get_config_name(parsed_terms); - const char *metric_id = get_config_metric_id(parsed_terms); - struct perf_cpu_map *cpus = get_config_cpu(parsed_terms, parse_state->fake_pmu); - int ret = 0; - struct evsel *first_wildcard_match = NULL; - - while ((pmu = perf_pmus__scan_for_event(pmu, name)) != NULL) { - LIST_HEAD(config_terms); - struct perf_event_attr attr; - - if (parse_events__filter_pmu(parse_state, pmu)) - continue; - - if (perf_pmu__have_event(pmu, name)) { - /* - * The PMU has the event so add as not a legacy cache - * event. - */ - struct parse_events_terms temp_terms; - struct parse_events_term *term; - char *config = strdup(name); - - if (!config) - goto out_err; - - parse_events_terms__init(&temp_terms); - if (!parsed_terms) - parsed_terms = &temp_terms; - - if (parse_events_term__num(&term, - PARSE_EVENTS__TERM_TYPE_USER, - config, /*num=*/1, /*novalue=*/true, - loc, /*loc_val=*/NULL) < 0) { - zfree(&config); - goto out_err; - } - list_add(&term->list, &parsed_terms->terms); - - ret = parse_events_add_pmu(parse_state, list, pmu, - parsed_terms, - first_wildcard_match, - /*alternate_hw_config=*/PERF_COUNT_HW_MAX); - list_del_init(&term->list); - parse_events_term__delete(term); - parse_events_terms__exit(&temp_terms); - if (ret) - goto out_err; - found_supported = true; - if (first_wildcard_match == NULL) - first_wildcard_match = - container_of(list->prev, struct evsel, core.node); - continue; - } - - if (!pmu->is_core) { - /* Legacy cache events are only supported by core PMUs. */ - continue; - } - - memset(&attr, 0, sizeof(attr)); - attr.type = PERF_TYPE_HW_CACHE; - - ret = parse_events__decode_legacy_cache(name, pmu->type, &attr.config); - if (ret) - return ret; - - found_supported = true; - - if (parsed_terms) { - if (config_attr(&attr, parsed_terms, parse_state, config_term_common)) { - ret = -EINVAL; - goto out_err; - } - if (get_config_terms(parsed_terms, &config_terms)) { - ret = -ENOMEM; - goto out_err; - } - } - - if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name, - metric_id, pmu, &config_terms, first_wildcard_match, - cpus, /*alternate_hw_config=*/PERF_COUNT_HW_MAX) == NULL) - ret = -ENOMEM; - - if (first_wildcard_match == NULL) - first_wildcard_match = container_of(list->prev, struct evsel, core.node); - free_config_terms(&config_terms); - if (ret) - goto out_err; - } -out_err: - perf_cpu_map__put(cpus); - return found_supported ? 0 : -EINVAL; -} + struct evsel *first_wildcard_match); static void tracepoint_error(struct parse_events_error *e, int err, const char *sys, const char *name, int column) @@ -823,8 +720,6 @@ const char *parse_events__term_type_str(enum parse_events__term_type term_type) [PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size", [PARSE_EVENTS__TERM_TYPE_METRIC_ID] = "metric-id", [PARSE_EVENTS__TERM_TYPE_RAW] = "raw", - [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE] = "legacy-cache", - [PARSE_EVENTS__TERM_TYPE_HARDWARE] = "hardware", [PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG] = "legacy-hardware-config", [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG] = "legacy-cache-config", [PARSE_EVENTS__TERM_TYPE_CPU] = "cpu", @@ -877,8 +772,6 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er case PARSE_EVENTS__TERM_TYPE_AUX_ACTION: case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: case PARSE_EVENTS__TERM_TYPE_RAW: - case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: - case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV: case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: @@ -1052,8 +945,6 @@ do { \ break; case PARSE_EVENTS__TERM_TYPE_DRV_CFG: case PARSE_EVENTS__TERM_TYPE_USER: - case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: - case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: default: @@ -1140,59 +1031,6 @@ static int config_term_pmu(struct perf_event_attr *attr, attr->type = PERF_TYPE_HW_CACHE; return 0; } - if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { - struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); - - if (!pmu) { - char *err_str; - - if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0) - parse_events_error__handle(parse_state->error, term->err_term, - err_str, /*help=*/NULL); - return -EINVAL; - } - /* - * Rewrite the PMU event to a legacy cache one unless the PMU - * doesn't support legacy cache events or the event is present - * within the PMU. - */ - if (perf_pmu__supports_legacy_cache(pmu) && - !perf_pmu__have_event(pmu, term->config)) { - attr->type = PERF_TYPE_HW_CACHE; - return parse_events__decode_legacy_cache(term->config, pmu->type, - &attr->config); - } else { - term->type_term = PARSE_EVENTS__TERM_TYPE_USER; - term->no_value = true; - } - } - if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) { - struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); - - if (!pmu) { - char *err_str; - - if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0) - parse_events_error__handle(parse_state->error, term->err_term, - err_str, /*help=*/NULL); - return -EINVAL; - } - /* - * If the PMU has a sysfs or json event prefer it over - * legacy. ARM requires this. - */ - if (perf_pmu__have_event(pmu, term->config)) { - term->type_term = PARSE_EVENTS__TERM_TYPE_USER; - term->no_value = true; - term->alternate_hw_config = true; - } else { - attr->type = PERF_TYPE_HARDWARE; - attr->config = term->val.num; - if (perf_pmus__supports_extended_type()) - attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; - } - return 0; - } if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) { /* @@ -1237,8 +1075,6 @@ static int config_term_tracepoint(struct perf_event_attr *attr, case PARSE_EVENTS__TERM_TYPE_PERCORE: case PARSE_EVENTS__TERM_TYPE_METRIC_ID: case PARSE_EVENTS__TERM_TYPE_RAW: - case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: - case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_CPU: case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV: default: @@ -1376,8 +1212,6 @@ do { \ case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_METRIC_ID: case PARSE_EVENTS__TERM_TYPE_RAW: - case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: - case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_CPU: default: break; @@ -1433,8 +1267,6 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: case PARSE_EVENTS__TERM_TYPE_METRIC_ID: case PARSE_EVENTS__TERM_TYPE_RAW: - case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: - case PARSE_EVENTS__TERM_TYPE_HARDWARE: case PARSE_EVENTS__TERM_TYPE_CPU: case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV: default: @@ -1559,8 +1391,9 @@ static bool config_term_percore(struct list_head *config_terms) static int parse_events_add_pmu(struct parse_events_state *parse_state, struct list_head *list, struct perf_pmu *pmu, const struct parse_events_terms *const_parsed_terms, - struct evsel *first_wildcard_match, u64 alternate_hw_config) + struct evsel *first_wildcard_match) { + u64 alternate_hw_config = PERF_COUNT_HW_MAX; struct perf_event_attr attr; struct perf_pmu_info info; struct evsel *evsel; @@ -1693,7 +1526,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state, } int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - const char *event_name, u64 hw_config, + const char *event_name, const struct parse_events_terms *const_parsed_terms, struct list_head **listp, void *loc_) { @@ -1745,7 +1578,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, continue; if (!parse_events_add_pmu(parse_state, list, pmu, - &parsed_terms, first_wildcard_match, hw_config)) { + &parsed_terms, first_wildcard_match)) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); @@ -1760,7 +1593,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, if (parse_state->fake_pmu) { if (!parse_events_add_pmu(parse_state, list, perf_pmus__fake_pmu(), &parsed_terms, - first_wildcard_match, hw_config)) { + first_wildcard_match)) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); @@ -1802,15 +1635,13 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state /* Attempt to add to list assuming event_or_pmu is a PMU name. */ pmu = perf_pmus__find(event_or_pmu); if (pmu && !parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms, - first_wildcard_match, - /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) + first_wildcard_match)) return 0; if (parse_state->fake_pmu) { if (!parse_events_add_pmu(parse_state, *listp, perf_pmus__fake_pmu(), const_parsed_terms, - first_wildcard_match, - /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) + first_wildcard_match)) return 0; } @@ -1823,8 +1654,7 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state if (!parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms, - first_wildcard_match, - /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) { + first_wildcard_match)) { ok++; parse_state->wild_card_pmus = true; } @@ -1838,7 +1668,7 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state /* Failure to add, assume event_or_pmu is an event name. */ zfree(listp); - if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX, + if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc)) return 0; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 61402c021d5121..1012b441e9cd4d 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -79,8 +79,6 @@ enum parse_events__term_type { PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE, PARSE_EVENTS__TERM_TYPE_METRIC_ID, PARSE_EVENTS__TERM_TYPE_RAW, - PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, - PARSE_EVENTS__TERM_TYPE_HARDWARE, PARSE_EVENTS__TERM_TYPE_CPU, PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV, PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG, @@ -133,12 +131,6 @@ struct parse_events_term { * value is assumed to be 1. An event name also has no value. */ bool no_value; - /** - * @alternate_hw_config: config is the event name but num is an - * alternate PERF_TYPE_HARDWARE config value which is often nice for the - * sake of quick matching. - */ - bool alternate_hw_config; }; struct parse_events_error { @@ -235,10 +227,6 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, u32 type, u64 config, const struct parse_events_terms *head_config, bool wildcard); -int parse_events_add_cache(struct list_head *list, int *idx, const char *name, - struct parse_events_state *parse_state, - struct parse_events_terms *parsed_terms, - void *loc); int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config); int parse_events_add_breakpoint(struct parse_events_state *parse_state, struct list_head *list, @@ -250,7 +238,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, struct perf_pmu *pmu); int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - const char *event_name, u64 hw_config, + const char *event_name, const struct parse_events_terms *const_parsed_terms, struct list_head **listp, void *loc); diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 5c8924a9dbfcaa..8e0ea441e57f12 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -73,11 +73,6 @@ static int quoted_str(yyscan_t scanner, int token) return token; } -static int lc_str(yyscan_t scanner, const struct parse_events_state *state) -{ - return str(scanner, state->match_legacy_cache_terms ? PE_LEGACY_CACHE : PE_NAME); -} - /* * This function is called when the parser gets two kind of input: * @@ -115,14 +110,6 @@ do { \ yyless(0); \ } while (0) -static int sym(yyscan_t scanner, int config) -{ - YYSTYPE *yylval = parse_events_get_lval(scanner); - - yylval->num = config; - return PE_VALUE_SYM_HW; -} - static int term(yyscan_t scanner, enum parse_events__term_type type) { YYSTYPE *yylval = parse_events_get_lval(scanner); @@ -131,16 +118,6 @@ static int term(yyscan_t scanner, enum parse_events__term_type type) return PE_TERM; } -static int hw_term(yyscan_t scanner, int config) -{ - YYSTYPE *yylval = parse_events_get_lval(scanner); - char *text = parse_events_get_text(scanner); - - yylval->hardware_term.str = strdup(text); - yylval->hardware_term.num = PERF_TYPE_HARDWARE + config; - return PE_TERM_HW; -} - static void modifiers_error(struct parse_events_state *parse_state, yyscan_t scanner, int pos, char mod_char, const char *mod_name) { @@ -251,8 +228,6 @@ drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? */ modifier_event [ukhpPGHSDIWebRX]{1,17} modifier_bp [rwx]{1,3} -lc_type (L1-dcache|l1-d|l1d|L1-data|L1-icache|l1-i|l1i|L1-instruction|LLC|L2|dTLB|d-tlb|Data-TLB|iTLB|i-tlb|Instruction-TLB|branch|branches|bpu|btb|bpc|node) -lc_op_result (load|loads|read|store|stores|write|prefetch|prefetches|speculative-read|speculative-load|refs|Reference|ops|access|misses|miss) digit [0-9] non_digit [^0-9] @@ -334,23 +309,10 @@ cpu { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CPU); } ratio-to-prev { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV); } legacy-hardware-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG); } legacy-cache-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG); } -cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); } -stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } -stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } -instructions { return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); } -cache-references { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); } -cache-misses { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); } -branch-instructions|branches { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } -branch-misses { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); } -bus-cycles { return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); } -ref-cycles { return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); } r{num_raw_hex} { return str(yyscanner, PE_RAW); } r0x{num_raw_hex} { return str(yyscanner, PE_RAW); } , { return ','; } "/" { BEGIN(INITIAL); return '/'; } -{lc_type} { return lc_str(yyscanner, _parse_state); } -{lc_type}-{lc_op_result} { return lc_str(yyscanner, _parse_state); } -{lc_type}-{lc_op_result}-{lc_op_result} { return lc_str(yyscanner, _parse_state); } {num_dec} { return value(_parse_state, yyscanner, 10); } {num_hex} { return value(_parse_state, yyscanner, 16); } {term_name} { return str(yyscanner, PE_NAME); } @@ -389,20 +351,6 @@ r0x{num_raw_hex} { return str(yyscanner, PE_RAW); } <> { BEGIN(INITIAL); } } -cpu-cycles|cycles { return sym(yyscanner, PERF_COUNT_HW_CPU_CYCLES); } -stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } -stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } -instructions { return sym(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); } -cache-references { return sym(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); } -cache-misses { return sym(yyscanner, PERF_COUNT_HW_CACHE_MISSES); } -branch-instructions|branches { return sym(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } -branch-misses { return sym(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); } -bus-cycles { return sym(yyscanner, PERF_COUNT_HW_BUS_CYCLES); } -ref-cycles { return sym(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); } - -{lc_type} { return str(yyscanner, PE_LEGACY_CACHE); } -{lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); } -{lc_type}-{lc_op_result}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); } mem: { BEGIN(mem); return PE_PREFIX_MEM; } r{num_raw_hex} { return str(yyscanner, PE_RAW); } {num_dec} { return value(_parse_state, yyscanner, 10); } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index ced26c549c33ac..c194de5ec1ec7c 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -55,22 +55,18 @@ static void free_list_evsel(struct list_head* list_evsel) %} %token PE_START_EVENTS PE_START_TERMS -%token PE_VALUE PE_VALUE_SYM_HW PE_TERM +%token PE_VALUE PE_TERM %token PE_EVENT_NAME %token PE_RAW PE_NAME %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH -%token PE_LEGACY_CACHE %token PE_PREFIX_MEM %token PE_ERROR %token PE_DRV_CFG_TERM -%token PE_TERM_HW %type PE_VALUE -%type PE_VALUE_SYM_HW %type PE_MODIFIER_EVENT %type PE_TERM %type PE_RAW %type PE_NAME -%type PE_LEGACY_CACHE %type PE_MODIFIER_BP %type PE_EVENT_NAME %type PE_DRV_CFG_TERM @@ -83,8 +79,6 @@ static void free_list_evsel(struct list_head* list_evsel) %type opt_pmu_config %destructor { parse_events_terms__delete ($$); } %type event_pmu -%type event_legacy_symbol -%type event_legacy_cache %type event_legacy_mem %type event_legacy_tracepoint %type event_legacy_numeric @@ -100,8 +94,6 @@ static void free_list_evsel(struct list_head* list_evsel) %destructor { free_list_evsel ($$); } %type tracepoint_name %destructor { free ($$.sys); free ($$.event); } -%type PE_TERM_HW -%destructor { free ($$.str); } %union { @@ -116,10 +108,6 @@ static void free_list_evsel(struct list_head* list_evsel) char *sys; char *event; } tracepoint_name; - struct hardware_term { - char *str; - u64 num; - } hardware_term; } %% @@ -262,8 +250,6 @@ PE_EVENT_NAME event_def event_def event_def: event_pmu | - event_legacy_symbol | - event_legacy_cache sep_dc | event_legacy_mem sep_dc | event_legacy_tracepoint sep_dc | event_legacy_numeric sep_dc | @@ -288,7 +274,7 @@ PE_NAME sep_dc struct list_head *list; int err; - err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1); + err = parse_events_multi_pmu_add(_parse_state, $1, /*const_parsed_terms*/NULL, &list, &@1); if (err < 0) { struct parse_events_state *parse_state = _parse_state; struct parse_events_error *error = parse_state->error; @@ -304,66 +290,6 @@ PE_NAME sep_dc $$ = list; } -event_legacy_symbol: -PE_VALUE_SYM_HW '/' event_config '/' -{ - struct list_head *list; - int err; - - list = alloc_list(); - if (!list) - YYNOMEM; - err = parse_events_add_numeric(_parse_state, list, - PERF_TYPE_HARDWARE, $1, - $3, - /*wildcard=*/true); - parse_events_terms__delete($3); - if (err) { - free_list_evsel(list); - PE_ABORT(err); - } - $$ = list; -} -| -PE_VALUE_SYM_HW sep_slash_slash_dc -{ - struct list_head *list; - int err; - - list = alloc_list(); - if (!list) - YYNOMEM; - err = parse_events_add_numeric(_parse_state, list, - PERF_TYPE_HARDWARE, $1, - /*head_config=*/NULL, - /*wildcard=*/true); - if (err) - PE_ABORT(err); - $$ = list; -} - -event_legacy_cache: -PE_LEGACY_CACHE opt_event_config -{ - struct parse_events_state *parse_state = _parse_state; - struct list_head *list; - int err; - - list = alloc_list(); - if (!list) - YYNOMEM; - - err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2, &@1); - - parse_events_terms__delete($2); - free($1); - if (err) { - free_list_evsel(list); - PE_ABORT(err); - } - $$ = list; -} - event_legacy_mem: PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config { @@ -582,12 +508,7 @@ event_term $$ = head; } -name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE -| -PE_TERM_HW -{ - $$ = $1.str; -} +name_or_raw: PE_RAW | PE_NAME event_term: PE_RAW @@ -629,19 +550,6 @@ name_or_raw '=' PE_VALUE $$ = term; } | -PE_LEGACY_CACHE -{ - struct parse_events_term *term; - int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, - $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); - - if (err) { - free($1); - PE_ABORT(err); - } - $$ = term; -} -| PE_NAME { struct parse_events_term *term; @@ -655,20 +563,6 @@ PE_NAME $$ = term; } | -PE_TERM_HW -{ - struct parse_events_term *term; - int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, - $1.str, $1.num & 255, /*novalue=*/false, - &@1, /*loc_val=*/NULL); - - if (err) { - free($1.str); - PE_ABORT(err); - } - $$ = term; -} -| PE_TERM '=' name_or_raw { struct parse_events_term *term; @@ -737,8 +631,6 @@ PE_DRV_CFG_TERM sep_dc: ':' | -sep_slash_slash_dc: '/' '/' | ':' | - %% void parse_events_error(YYLTYPE *loc, void *_parse_state, diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 667be41abcd768..d597263fab4f7e 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1920,9 +1920,6 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_ if (alias->per_pkg) info->per_pkg = true; - if (term->alternate_hw_config) - *alternate_hw_config = term->val.num; - info->retirement_latency_mean = alias->retirement_latency_mean; info->retirement_latency_min = alias->retirement_latency_min; info->retirement_latency_max = alias->retirement_latency_max; @@ -2030,10 +2027,10 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call /* * max-events and driver-config are missing above as are the internal - * types user, metric-id, raw, legacy cache and hardware. Assert against - * the enum parse_events__term_type so they are kept in sync. + * types user, metric-id, and raw. Assert against the enum + * parse_events__term_type so they are kept in sync. */ - _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6, + _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 4, "perf_pmu__for_each_format()'s terms must be kept in sync with enum parse_events__term_type"); list_for_each_entry(format, &pmu->format, list) { perf_pmu_format__load(pmu, format); From 3d3056a10504fab881bdba952b9b37bc09502c2c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:20 -0700 Subject: [PATCH 062/684] perf record: Use evlist__new_default when no events specified Rather than distributing the code doing similar things to evlist__new_default, use the one implementation so that paranoia and wildcard scanning can be optimized. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 26d8da560446f1..cb52aea9607d46 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -4341,9 +4341,13 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0) { - err = parse_event(rec->evlist, "cycles:P"); - if (err) + struct evlist *def_evlist = evlist__new_default(); + + if (!def_evlist) goto out; + + evlist__splice_list_tail(rec->evlist, &def_evlist->core.entries); + evlist__delete(def_evlist); } if (rec->opts.target.tid && !rec->opts.no_inherit_set) From 468071acfc05135b9e24ed0beb535ac5c6cff945 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:21 -0700 Subject: [PATCH 063/684] perf top: Use evlist__new_default when no events specified Rather than distributing the code doing similar things to evlist__new_default, use the one implementation so that paranoia and wildcard scanning can be optimized. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/builtin-top.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a11f629c7d76a2..710604c4f6f6cb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1695,11 +1695,13 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; if (!top.evlist->core.nr_entries) { - bool can_profile_kernel = perf_event_paranoid_check(1); - int err = parse_event(top.evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); + struct evlist *def_evlist = evlist__new_default(); - if (err) + if (!def_evlist) goto out_delete_evlist; + + evlist__splice_list_tail(top.evlist, &def_evlist->core.entries); + evlist__delete(def_evlist); } status = evswitch__init(&top.evswitch, top.evlist, stderr); From 5bf6291113d2aaa559455a04ecc2c5e6396d05a0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:22 -0700 Subject: [PATCH 064/684] perf evlist: Avoid scanning all PMUs for evlist__new_default Rather than wildcard matching the cycles event specify only the core PMUs. This avoids potentially loading unnecessary uncore PMUs. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/evlist.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 80d8387e6b97bc..e8217efdda5323 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -101,16 +101,24 @@ struct evlist *evlist__new_default(void) { struct evlist *evlist = evlist__new(); bool can_profile_kernel; - int err; + struct perf_pmu *pmu = NULL; if (!evlist) return NULL; can_profile_kernel = perf_event_paranoid_check(1); - err = parse_event(evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); - if (err) { - evlist__delete(evlist); - return NULL; + + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { + char buf[256]; + int err; + + snprintf(buf, sizeof(buf), "%s/cycles/%s", pmu->name, + can_profile_kernel ? "P" : "Pu"); + err = parse_event(evlist, buf); + if (err) { + evlist__delete(evlist); + return NULL; + } } if (evlist->core.nr_entries > 1) { From 787bd5781785472ef9296ce66d6f917a19a422a4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:23 -0700 Subject: [PATCH 065/684] perf evsel: Improvements to __evsel__match Ensure both the perf_event_attr and alternate_hw_config are checked in the match. Don't mask the config if the perf_event_attr isn't a HARDWARE or HW_CACHE event. Add common early exit cases. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 56ebefd075f2e3..ad11cbfcbff1c7 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1940,16 +1940,19 @@ bool __evsel__match(const struct evsel *evsel, u32 type, u64 config) u32 e_type = evsel->core.attr.type; u64 e_config = evsel->core.attr.config; - if (e_type != type) { - return type == PERF_TYPE_HARDWARE && evsel->pmu && evsel->pmu->is_core && - evsel->alternate_hw_config == config; - } - - if ((type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) && - perf_pmus__supports_extended_type()) + if (e_type == type && e_config == config) + return true; + if (type != PERF_TYPE_HARDWARE && type != PERF_TYPE_HW_CACHE) + return false; + if ((e_type == PERF_TYPE_HARDWARE || e_type == PERF_TYPE_HW_CACHE) && + perf_pmus__supports_extended_type()) e_config &= PERF_HW_EVENT_MASK; - - return e_config == config; + if (e_type == type && e_config == config) + return true; + if (type == PERF_TYPE_HARDWARE && evsel->pmu && evsel->pmu->is_core && + evsel->alternate_hw_config == config) + return true; + return false; } int evsel__read_counter(struct evsel *evsel, int cpu_map_idx, int thread) From ecfcc6a825dfacdb4f3cf38fe4b463396fa0d029 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:24 -0700 Subject: [PATCH 066/684] perf test parse-events: Use evsel__match for legacy events Switch from the test's assert_hw/test_config to the common evsel__match code that appropriately handles events with both legacy and sysfs/json encoding. For tests asserting that a config value matches that placed in the perf_event_attr just directly compare the config values. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 299 ++++++++------------------------ 1 file changed, 74 insertions(+), 225 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 13c1e4c45ea203..f6cd994f75cf30 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -155,60 +155,38 @@ static int test__checkevent_numeric(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 1)); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); return TEST_OK; } -static int assert_hw(struct perf_evsel *evsel, enum perf_hw_id id, const char *name) -{ - struct perf_pmu *pmu; - - if (evsel->attr.type == PERF_TYPE_HARDWARE) { - TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, id)); - return 0; - } - pmu = perf_pmus__find_by_type(evsel->attr.type); - - TEST_ASSERT_VAL("unexpected PMU type", pmu); - TEST_ASSERT_VAL("PMU missing event", perf_pmu__have_event(pmu, name)); - return 0; -} - static int test__checkevent_symbolic_name(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); - perf_evlist__for_each_evsel(&evlist->core, evsel) { - int ret = assert_hw(evsel, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - - if (ret) - return ret; - } + evlist__for_each_entry(evlist, evsel) + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); return TEST_OK; } static int test__checkevent_symbolic_name_config(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); - perf_evlist__for_each_evsel(&evlist->core, evsel) { - int ret = assert_hw(evsel, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - - if (ret) - return ret; + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); /* * The period value gets configured within evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); - TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1); - TEST_ASSERT_VAL("wrong config2", 1 == evsel->attr.config2); + TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); + TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1); + TEST_ASSERT_VAL("wrong config2", 1 == evsel->core.attr.config2); } return TEST_OK; } @@ -218,8 +196,7 @@ static int test__checkevent_symbolic_alias(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_SW_PAGE_FAULTS)); + TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)); return TEST_OK; } @@ -242,7 +219,7 @@ static int test__checkevent_breakpoint(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 == @@ -256,7 +233,7 @@ static int test__checkevent_breakpoint_x(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_X == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", default_breakpoint_len() == evsel->core.attr.bp_len); @@ -270,7 +247,7 @@ static int test__checkevent_breakpoint_r(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_R == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", @@ -285,7 +262,7 @@ static int test__checkevent_breakpoint_w(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", @@ -300,7 +277,7 @@ static int test__checkevent_breakpoint_rw(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", @@ -633,7 +610,7 @@ static int test__checkevent_list(struct evlist *evlist) /* r1 */ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT != evsel->core.attr.type); while (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { - TEST_ASSERT_VAL("wrong config", test_config(evsel, 1)); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1); TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2); TEST_ASSERT_VAL("wrong config3", 0 == evsel->core.attr.config3); @@ -657,7 +634,7 @@ static int test__checkevent_list(struct evlist *evlist) /* 1:1:hp */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 1)); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -673,14 +650,14 @@ static int test__checkevent_pmu_name(struct evlist *evlist) /* cpu/config=1,name=krava/u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 1)); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "krava")); /* cpu/config=2/u" */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 2)); + TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "cpu/config=2/u")); return TEST_OK; @@ -693,7 +670,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) /* cpu/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 1)); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. @@ -705,7 +682,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) /* cpu/config=2,call-graph=no,time=0,period=2000/ */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 2)); + TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. @@ -855,7 +832,7 @@ static int test__checkterms_simple(struct parse_events_terms *terms) static int test__group1(struct evlist *evlist) { - struct evsel *evsel, *leader; + struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries == (num_core_entries() * 2)); @@ -863,14 +840,9 @@ static int test__group1(struct evlist *evlist) evlist__nr_groups(evlist) == num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* instructions:k */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -884,10 +856,7 @@ static int test__group1(struct evlist *evlist) /* cycles:upp */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -914,13 +883,9 @@ static int test__group2(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of groups", 1 == evlist__nr_groups(evlist)); evlist__for_each_entry(evlist, evsel) { - int ret; - - if (evsel->core.attr.type == PERF_TYPE_SOFTWARE) { + if (evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)) { /* faults + :ku modifier */ leader = evsel; - TEST_ASSERT_VAL("wrong config", - test_config(evsel, PERF_COUNT_SW_PAGE_FAULTS)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -933,8 +898,7 @@ static int test__group2(struct evlist *evlist) TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); continue; } - if (evsel->core.attr.type == PERF_TYPE_HARDWARE && - test_config(evsel, PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) { + if (evsel__match(evsel, HARDWARE, HW_BRANCH_INSTRUCTIONS)) { /* branches + :u modifier */ TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); @@ -948,10 +912,7 @@ static int test__group2(struct evlist *evlist) continue; } /* cycles:k */ - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -967,7 +928,6 @@ static int test__group2(struct evlist *evlist) static int test__group3(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *group1_leader = NULL, *group2_leader = NULL; - int ret; TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus() + 2)); @@ -998,8 +958,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); continue; } - if (evsel->core.attr.type == PERF_TYPE_HARDWARE && - test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)) { + if (evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { if (evsel->core.attr.exclude_user) { /* group1 cycles:kppp */ TEST_ASSERT_VAL("wrong exclude_user", @@ -1042,7 +1001,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) } if (evsel->core.attr.type == 1) { /* group2 1:3 + G modifier */ - TEST_ASSERT_VAL("wrong config", test_config(evsel, 3)); + TEST_ASSERT_VAL("wrong config", 3 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1055,10 +1014,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) continue; } /* instructions:u */ - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1073,7 +1029,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) static int test__group4(struct evlist *evlist __maybe_unused) { - struct evsel *evsel, *leader; + struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries == (num_core_entries() * 2)); @@ -1081,14 +1037,9 @@ static int test__group4(struct evlist *evlist __maybe_unused) num_core_entries() == evlist__nr_groups(evlist)); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles:u + p */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1103,10 +1054,7 @@ static int test__group4(struct evlist *evlist __maybe_unused) /* instructions:kp + p */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1123,7 +1071,6 @@ static int test__group4(struct evlist *evlist __maybe_unused) static int test__group5(struct evlist *evlist __maybe_unused) { struct evsel *evsel = NULL, *leader; - int ret; TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries == (5 * num_core_entries())); @@ -1133,10 +1080,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(); i++) { /* cycles + G */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1151,10 +1095,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) /* instructions + G */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1168,10 +1109,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(); i++) { /* cycles:G */ evsel = leader = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1186,10 +1124,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) /* instructions:G */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1202,10 +1137,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(); i++) { /* cycles */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1227,14 +1159,9 @@ static int test__group_gh1(struct evlist *evlist) evlist__nr_groups(evlist) == num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles + :H group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1248,10 +1175,7 @@ static int test__group_gh1(struct evlist *evlist) /* cache-misses:G + :H group modifier */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1274,14 +1198,9 @@ static int test__group_gh2(struct evlist *evlist) evlist__nr_groups(evlist) == num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles + :G group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1295,10 +1214,7 @@ static int test__group_gh2(struct evlist *evlist) /* cache-misses:H + :G group modifier */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1321,14 +1237,9 @@ static int test__group_gh3(struct evlist *evlist) evlist__nr_groups(evlist) == num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles:G + :u group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1342,10 +1253,7 @@ static int test__group_gh3(struct evlist *evlist) /* cache-misses:H + :u group modifier */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1368,14 +1276,9 @@ static int test__group_gh4(struct evlist *evlist) evlist__nr_groups(evlist) == num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles:G + :uG group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1389,10 +1292,7 @@ static int test__group_gh4(struct evlist *evlist) /* cache-misses:H + :uG group modifier */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1413,14 +1313,9 @@ static int test__leader_sample1(struct evlist *evlist) evlist->core.nr_entries == (3 * num_core_entries())); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1433,10 +1328,7 @@ static int test__leader_sample1(struct evlist *evlist) /* cache-misses - not sampling */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1448,10 +1340,8 @@ static int test__leader_sample1(struct evlist *evlist) /* branch-misses - not sampling */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); @@ -1473,14 +1363,9 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) evlist->core.nr_entries == (2 * num_core_entries())); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* instructions - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1493,10 +1378,8 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) /* branch-misses - not sampling */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1536,14 +1419,9 @@ static int test__pinned_group(struct evlist *evlist) evlist->core.nr_entries == (3 * num_core_entries())); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); /* TODO: The group modifier is not copied to the split group leader. */ @@ -1552,18 +1430,13 @@ static int test__pinned_group(struct evlist *evlist) /* cache-misses - can not be pinned, but will go on with the leader */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); /* branch-misses - ditto */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); } return TEST_OK; @@ -1590,14 +1463,9 @@ static int test__exclusive_group(struct evlist *evlist) evlist->core.nr_entries == 3 * num_core_entries()); for (int i = 0; i < num_core_entries(); i++) { - int ret; - /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); /* TODO: The group modifier is not copied to the split group leader. */ @@ -1606,18 +1474,13 @@ static int test__exclusive_group(struct evlist *evlist) /* cache-misses - can not be pinned, but will go on with the leader */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); /* branch-misses - ditto */ evsel = evsel__next(evsel); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); - if (ret) - return ret; - + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); } return TEST_OK; @@ -1628,7 +1491,7 @@ static int test__checkevent_breakpoint_len(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 == @@ -1643,7 +1506,7 @@ static int test__checkevent_breakpoint_len_w(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0)); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 == @@ -1671,8 +1534,7 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries == 1 + num_core_entries()); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_SW_TASK_CLOCK)); + TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)); return TEST_OK; } @@ -1751,7 +1613,6 @@ static bool test__acr_valid(void) static int test__ratio_to_prev(struct evlist *evlist) { struct evsel *evsel; - int ret; TEST_ASSERT_VAL("wrong number of entries", 2 * perf_pmus__num_core_pmus() == evlist->core.nr_entries); @@ -1764,16 +1625,16 @@ static int test__ratio_to_prev(struct evlist *evlist) TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); } else { TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2); TEST_ASSERT_VAL("wrong leader", !evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 0); TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); + TEST_ASSERT_VAL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); } - if (ret) - return ret; /* * The period value gets configured within evlist__config, * while this test executes only parse events method. @@ -1799,18 +1660,15 @@ static int test__checkevent_raw_pmu(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 0x1a)); + TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config); return TEST_OK; } static int test__sym_event_slash(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - - if (ret) - return ret; + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); return TEST_OK; } @@ -1818,11 +1676,8 @@ static int test__sym_event_slash(struct evlist *evlist) static int test__sym_event_dc(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - - if (ret) - return ret; + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); return TEST_OK; } @@ -1830,11 +1685,8 @@ static int test__sym_event_dc(struct evlist *evlist) static int test__term_equal_term(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - - if (ret) - return ret; + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "name") == 0); return TEST_OK; } @@ -1842,11 +1694,8 @@ static int test__term_equal_term(struct evlist *evlist) static int test__term_equal_legacy(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); - - if (ret) - return ret; + TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "l1d") == 0); return TEST_OK; } From 2e6dc3b9334cd0d404591009b3d9957edcf2f6cf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:25 -0700 Subject: [PATCH 067/684] perf test parse-events: Without a PMU use cpu-cycles rather than cycles Without a PMU perf matches an event against any PMU with the event. Unfortunately some PMU drivers advertise a "cycles" event which is typically just a core event. Switch to using "cpu-cycles" which is an indentical legacy event but avoids the multiple PMU confusion introduced by the PMU drivers. Note, on x86 cpu-cycles is also a sysfs event but cycles isn't. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 61 ++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index f6cd994f75cf30..23f3e265e2a144 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -585,9 +585,10 @@ static int test__checkevent_pmu(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", test_config(evsel, 10)); TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1); TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2); @@ -646,17 +647,18 @@ static int test__checkevent_list(struct evlist *evlist) static int test__checkevent_pmu_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); /* cpu/config=1,name=krava/u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "krava")); /* cpu/config=2/u" */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "cpu/config=2/u")); @@ -666,10 +668,11 @@ static int test__checkevent_pmu_name(struct evlist *evlist) static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); /* cpu/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured within evlist__config, @@ -681,7 +684,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) /* cpu/config=2,call-graph=no,time=0,period=2000/ */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured within evlist__config, @@ -697,12 +700,14 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) static int test__checkevent_pmu_events(struct evlist *evlist) { struct evsel *evsel; + struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); TEST_ASSERT_VAL("wrong number of entries", 1 <= evlist->core.nr_entries); evlist__for_each_entry(evlist, evsel) { - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type || - strcmp(evsel->pmu->name, "cpu")); + TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type || + !strncmp(evsel__name(evsel), evsel->pmu->name, + strlen(evsel->pmu->name))); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1650,7 +1655,7 @@ static int test__checkevent_complex_name(struct evlist *evlist) TEST_ASSERT_VAL("wrong complex name parsing", evsel__name_is(evsel, - "COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks")); + "COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks")); return TEST_OK; } @@ -1787,7 +1792,7 @@ static const struct evlist_test test__events[] = { /* 4 */ }, { - .name = "cycles/period=100000,config2/", + .name = "cpu-cycles/period=100000,config2/", .check = test__checkevent_symbolic_name_config, /* 5 */ }, @@ -1902,27 +1907,27 @@ static const struct evlist_test test__events[] = { /* 7 */ }, { - .name = "{instructions:k,cycles:upp}", + .name = "{instructions:k,cpu-cycles:upp}", .check = test__group1, /* 8 */ }, { - .name = "{faults:k,branches}:u,cycles:k", + .name = "{faults:k,branches}:u,cpu-cycles:k", .check = test__group2, /* 9 */ }, { - .name = "group1{syscalls:sys_enter_openat:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u", + .name = "group1{syscalls:sys_enter_openat:H,cpu-cycles:kppp},group2{cpu-cycles,1:3}:G,instructions:u", .check = test__group3, /* 0 */ }, { - .name = "{cycles:u,instructions:kp}:p", + .name = "{cpu-cycles:u,instructions:kp}:p", .check = test__group4, /* 1 */ }, { - .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles", + .name = "{cpu-cycles,instructions}:G,{cpu-cycles:G,instructions:G},cpu-cycles", .check = test__group5, /* 2 */ }, @@ -1932,27 +1937,27 @@ static const struct evlist_test test__events[] = { /* 3 */ }, { - .name = "{cycles,cache-misses:G}:H", + .name = "{cpu-cycles,cache-misses:G}:H", .check = test__group_gh1, /* 4 */ }, { - .name = "{cycles,cache-misses:H}:G", + .name = "{cpu-cycles,cache-misses:H}:G", .check = test__group_gh2, /* 5 */ }, { - .name = "{cycles:G,cache-misses:H}:u", + .name = "{cpu-cycles:G,cache-misses:H}:u", .check = test__group_gh3, /* 6 */ }, { - .name = "{cycles:G,cache-misses:H}:uG", + .name = "{cpu-cycles:G,cache-misses:H}:uG", .check = test__group_gh4, /* 7 */ }, { - .name = "{cycles,cache-misses,branch-misses}:S", + .name = "{cpu-cycles,cache-misses,branch-misses}:S", .check = test__leader_sample1, /* 8 */ }, @@ -1967,7 +1972,7 @@ static const struct evlist_test test__events[] = { /* 0 */ }, { - .name = "{cycles,cache-misses,branch-misses}:D", + .name = "{cpu-cycles,cache-misses,branch-misses}:D", .check = test__pinned_group, /* 1 */ }, @@ -2005,7 +2010,7 @@ static const struct evlist_test test__events[] = { /* 6 */ }, { - .name = "task-clock:P,cycles", + .name = "task-clock:P,cpu-cycles", .check = test__checkevent_precise_max_modifier, /* 7 */ }, @@ -2036,17 +2041,17 @@ static const struct evlist_test test__events[] = { /* 2 */ }, { - .name = "cycles/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks'/Duk", + .name = "cpu-cycles/name='COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks'/Duk", .check = test__checkevent_complex_name, /* 3 */ }, { - .name = "cycles//u", + .name = "cpu-cycles//u", .check = test__sym_event_slash, /* 4 */ }, { - .name = "cycles:k", + .name = "cpu-cycles:k", .check = test__sym_event_dc, /* 5 */ }, @@ -2056,17 +2061,17 @@ static const struct evlist_test test__events[] = { /* 6 */ }, { - .name = "{cycles,cache-misses,branch-misses}:e", + .name = "{cpu-cycles,cache-misses,branch-misses}:e", .check = test__exclusive_group, /* 7 */ }, { - .name = "cycles/name=name/", + .name = "cpu-cycles/name=name/", .check = test__term_equal_term, /* 8 */ }, { - .name = "cycles/name=l1d/", + .name = "cpu-cycles/name=l1d/", .check = test__term_equal_legacy, /* 9 */ }, @@ -2174,7 +2179,7 @@ static const struct evlist_test test__events_pmu[] = { /* 2 */ }, { - .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", + .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", .valid = test__pmu_cpu_event_valid, .check = test__checkevent_complex_name, /* 3 */ From d47c65eea8acd13a32a8d0caa3bae9a611b09ac8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:26 -0700 Subject: [PATCH 068/684] perf test parse-events: Remove cpu PMU requirement In the event parse string, switch "cpu" to "default_core" and then rewrite this to the first core PMU name prior to parsing. This enables testing with a PMU on hybrid x86 and other systems that don't use "cpu" for the core PMU name. The name "default_core" is already used by jevents. Update test expectations to match. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 230 +++++++++++++++----------------- 1 file changed, 110 insertions(+), 120 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 23f3e265e2a144..5dd2f03e952d7a 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -20,17 +20,24 @@ #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) -static int num_core_entries(void) +static int num_core_entries(struct evlist *evlist) { /* - * If the kernel supports extended type, expect events to be - * opened once for each core PMU type. Otherwise fall back to the legacy - * behavior of opening only one event even though there are multiple - * PMUs + * Returns number of core PMUs if the evlist has >1 core PMU, otherwise + * returns 1. The number of core PMUs is needed as wild carding can + * open an event for each core PMU. If the events were opened with a + * specified PMU then wild carding won't happen. */ - if (perf_pmus__supports_extended_type()) - return perf_pmus__num_core_pmus(); + struct perf_pmu *core_pmu = NULL; + struct evsel *evsel; + evlist__for_each_entry(evlist, evsel) { + if (!evsel->pmu->is_core) + continue; + if (core_pmu != evsel->pmu && core_pmu != NULL) + return perf_pmus__num_core_pmus(); + core_pmu = evsel->pmu; + } return 1; } @@ -345,7 +352,7 @@ static int test__checkevent_symbolic_name_modifier(struct evlist *evlist) struct perf_evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == num_core_entries()); + evlist->core.nr_entries == num_core_entries(evlist)); perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); @@ -648,19 +655,21 @@ static int test__checkevent_pmu_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); + char buf[256]; - /* cpu/config=1,name=krava/u */ + /* default_core/config=1,name=krava/u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "krava")); - /* cpu/config=2/u" */ + /* default_core/config=2/u" */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "cpu/config=2/u")); + snprintf(buf, sizeof(buf), "%s/config=2/u", core_pmu->name); + TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, buf)); return TEST_OK; } @@ -670,7 +679,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); - /* cpu/config=1,call-graph=fp,time,period=100000/ */ + /* default_core/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); @@ -682,7 +691,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel)); TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type)); - /* cpu/config=2,call-graph=no,time=0,period=2000/ */ + /* default_core/config=2,call-graph=no,time=0,period=2000/ */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); @@ -740,7 +749,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); } - /* cpu/pmu-event/u*/ + /* default_core/pmu-event/u*/ evsel = evsel__next(evsel); TEST_ASSERT_VAL("wrong type", evsel__find_pmu(evsel)->is_core); TEST_ASSERT_VAL("wrong exclude_user", @@ -840,11 +849,11 @@ static int test__group1(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (num_core_entries() * 2)); + evlist->core.nr_entries == (num_core_entries(evlist) * 2)); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries()); + evlist__nr_groups(evlist) == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions:k */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); @@ -880,7 +889,7 @@ static int test__group2(struct evlist *evlist) struct evsel *evsel, *leader = NULL; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries() + 1)); + evlist->core.nr_entries == (2 * num_core_entries(evlist) + 1)); /* * TODO: Currently the software event won't be grouped with the hardware * event except for 1 PMU. @@ -1037,11 +1046,11 @@ static int test__group4(struct evlist *evlist __maybe_unused) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (num_core_entries() * 2)); + evlist->core.nr_entries == (num_core_entries(evlist) * 2)); TEST_ASSERT_VAL("wrong number of groups", - num_core_entries() == evlist__nr_groups(evlist)); + num_core_entries(evlist) == evlist__nr_groups(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:u + p */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1078,11 +1087,11 @@ static int test__group5(struct evlist *evlist __maybe_unused) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (5 * num_core_entries())); + evlist->core.nr_entries == (5 * num_core_entries(evlist))); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == (2 * num_core_entries())); + evlist__nr_groups(evlist) == (2 * num_core_entries(evlist))); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + G */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1111,7 +1120,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); } - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G */ evsel = leader = evsel__next(evsel); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1139,7 +1148,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); } - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles */ evsel = evsel__next(evsel); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1159,11 +1168,11 @@ static int test__group_gh1(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries())); + evlist->core.nr_entries == (2 * num_core_entries(evlist))); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries()); + evlist__nr_groups(evlist) == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :H group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1198,11 +1207,11 @@ static int test__group_gh2(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries())); + evlist->core.nr_entries == (2 * num_core_entries(evlist))); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries()); + evlist__nr_groups(evlist) == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :G group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1237,11 +1246,11 @@ static int test__group_gh3(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries())); + evlist->core.nr_entries == (2 * num_core_entries(evlist))); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries()); + evlist__nr_groups(evlist) == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :u group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1276,11 +1285,11 @@ static int test__group_gh4(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries())); + evlist->core.nr_entries == (2 * num_core_entries(evlist))); TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries()); + evlist__nr_groups(evlist) == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :uG group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1315,9 +1324,9 @@ static int test__leader_sample1(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (3 * num_core_entries())); + evlist->core.nr_entries == (3 * num_core_entries(evlist))); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1365,9 +1374,9 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries())); + evlist->core.nr_entries == (2 * num_core_entries(evlist))); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); @@ -1403,9 +1412,9 @@ static int test__checkevent_pinned_modifier(struct evlist *evlist) struct evsel *evsel = NULL; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == num_core_entries()); + evlist->core.nr_entries == num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); @@ -1421,9 +1430,9 @@ static int test__pinned_group(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (3 * num_core_entries())); + evlist->core.nr_entries == (3 * num_core_entries(evlist))); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1465,9 +1474,9 @@ static int test__exclusive_group(struct evlist *evlist) struct evsel *evsel = NULL, *leader; TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == 3 * num_core_entries()); + evlist->core.nr_entries == 3 * num_core_entries(evlist)); - for (int i = 0; i < num_core_entries(); i++) { + for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -1538,7 +1547,7 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == 1 + num_core_entries()); + evlist->core.nr_entries == 1 + num_core_entries(evlist)); TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)); return TEST_OK; } @@ -1575,14 +1584,9 @@ static int test__checkevent_config_cache(struct evlist *evlist) return test__checkevent_genhw(evlist); } -static bool test__pmu_cpu_valid(void) +static bool test__pmu_default_core_event_valid(void) { - return !!perf_pmus__find("cpu"); -} - -static bool test__pmu_cpu_event_valid(void) -{ - struct perf_pmu *pmu = perf_pmus__find("cpu"); + struct perf_pmu *pmu = perf_pmus__find_core_pmu(); if (!pmu) return false; @@ -2161,26 +2165,23 @@ static const struct evlist_test test__events[] = { static const struct evlist_test test__events_pmu[] = { { - .name = "cpu/config=10,config1=1,config2=3,period=1000/u", - .valid = test__pmu_cpu_valid, + .name = "default_core/config=10,config1=1,config2=3,period=1000/u", .check = test__checkevent_pmu, /* 0 */ }, { - .name = "cpu/config=1,name=krava/u,cpu/config=2/u", - .valid = test__pmu_cpu_valid, + .name = "default_core/config=1,name=krava/u,default_core/config=2/u", .check = test__checkevent_pmu_name, /* 1 */ }, { - .name = "cpu/config=1,call-graph=fp,time,period=100000/,cpu/config=2,call-graph=no,time=0,period=2000/", - .valid = test__pmu_cpu_valid, + .name = "default_core/config=1,call-graph=fp,time,period=100000/,default_core/config=2,call-graph=no,time=0,period=2000/", .check = test__checkevent_pmu_partial_time_callgraph, /* 2 */ }, { - .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", - .valid = test__pmu_cpu_event_valid, + .name = "default_core/name='COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", + .valid = test__pmu_default_core_event_valid, .check = test__checkevent_complex_name, /* 3 */ }, @@ -2195,158 +2196,132 @@ static const struct evlist_test test__events_pmu[] = { /* 5 */ }, { - .name = "cpu/L1-dcache-load-miss/", - .valid = test__pmu_cpu_valid, + .name = "default_core/L1-dcache-load-miss/", .check = test__checkevent_genhw, /* 6 */ }, { - .name = "cpu/L1-dcache-load-miss/kp", - .valid = test__pmu_cpu_valid, + .name = "default_core/L1-dcache-load-miss/kp", .check = test__checkevent_genhw_modifier, /* 7 */ }, { - .name = "cpu/L1-dcache-misses,name=cachepmu/", - .valid = test__pmu_cpu_valid, + .name = "default_core/L1-dcache-misses,name=cachepmu/", .check = test__checkevent_config_cache, /* 8 */ }, { - .name = "cpu/instructions/", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/", .check = test__checkevent_symbolic_name, /* 9 */ }, { - .name = "cpu/cycles,period=100000,config2/", - .valid = test__pmu_cpu_valid, + .name = "default_core/cycles,period=100000,config2/", .check = test__checkevent_symbolic_name_config, /* 0 */ }, { - .name = "cpu/instructions/h", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/h", .check = test__checkevent_symbolic_name_modifier, /* 1 */ }, { - .name = "cpu/instructions/G", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/G", .check = test__checkevent_exclude_host_modifier, /* 2 */ }, { - .name = "cpu/instructions/H", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/H", .check = test__checkevent_exclude_guest_modifier, /* 3 */ }, { - .name = "{cpu/instructions/k,cpu/cycles/upp}", - .valid = test__pmu_cpu_valid, + .name = "{default_core/instructions/k,default_core/cycles/upp}", .check = test__group1, /* 4 */ }, { - .name = "{cpu/cycles/u,cpu/instructions/kp}:p", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/u,default_core/instructions/kp}:p", .check = test__group4, /* 5 */ }, { - .name = "{cpu/cycles/,cpu/cache-misses/G}:H", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/,default_core/cache-misses/G}:H", .check = test__group_gh1, /* 6 */ }, { - .name = "{cpu/cycles/,cpu/cache-misses/H}:G", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/,default_core/cache-misses/H}:G", .check = test__group_gh2, /* 7 */ }, { - .name = "{cpu/cycles/G,cpu/cache-misses/H}:u", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/G,default_core/cache-misses/H}:u", .check = test__group_gh3, /* 8 */ }, { - .name = "{cpu/cycles/G,cpu/cache-misses/H}:uG", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/G,default_core/cache-misses/H}:uG", .check = test__group_gh4, /* 9 */ }, { - .name = "{cpu/cycles/,cpu/cache-misses/,cpu/branch-misses/}:S", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/,default_core/cache-misses/,default_core/branch-misses/}:S", .check = test__leader_sample1, /* 0 */ }, { - .name = "{cpu/instructions/,cpu/branch-misses/}:Su", - .valid = test__pmu_cpu_valid, + .name = "{default_core/instructions/,default_core/branch-misses/}:Su", .check = test__leader_sample2, /* 1 */ }, { - .name = "cpu/instructions/uDp", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/uDp", .check = test__checkevent_pinned_modifier, /* 2 */ }, { - .name = "{cpu/cycles/,cpu/cache-misses/,cpu/branch-misses/}:D", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/,default_core/cache-misses/,default_core/branch-misses/}:D", .check = test__pinned_group, /* 3 */ }, { - .name = "cpu/instructions/I", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/I", .check = test__checkevent_exclude_idle_modifier, /* 4 */ }, { - .name = "cpu/instructions/kIG", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/kIG", .check = test__checkevent_exclude_idle_modifier_1, /* 5 */ }, { - .name = "cpu/cycles/u", - .valid = test__pmu_cpu_valid, + .name = "default_core/cycles/u", .check = test__sym_event_slash, /* 6 */ }, { - .name = "cpu/cycles/k", - .valid = test__pmu_cpu_valid, + .name = "default_core/cycles/k", .check = test__sym_event_dc, /* 7 */ }, { - .name = "cpu/instructions/uep", - .valid = test__pmu_cpu_valid, + .name = "default_core/instructions/uep", .check = test__checkevent_exclusive_modifier, /* 8 */ }, { - .name = "{cpu/cycles/,cpu/cache-misses/,cpu/branch-misses/}:e", - .valid = test__pmu_cpu_valid, + .name = "{default_core/cycles/,default_core/cache-misses/,default_core/branch-misses/}:e", .check = test__exclusive_group, /* 9 */ }, { - .name = "cpu/cycles,name=name/", - .valid = test__pmu_cpu_valid, + .name = "default_core/cycles,name=name/", .check = test__term_equal_term, /* 0 */ }, { - .name = "cpu/cycles,name=l1d/", - .valid = test__pmu_cpu_valid, + .name = "default_core/cycles,name=l1d/", .check = test__term_equal_legacy, /* 1 */ }, @@ -2436,15 +2411,30 @@ static int combine_test_results(int existing, int latest) static int test_events(const struct evlist_test *events, int cnt) { int ret = TEST_OK; + struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); for (int i = 0; i < cnt; i++) { - const struct evlist_test *e = &events[i]; + struct evlist_test e = events[i]; int test_ret; + const char *pos = e.name; + char buf[1024], *buf_pos = buf, *end; + + while ((end = strstr(pos, "default_core"))) { + size_t len = end - pos; + + strncpy(buf_pos, pos, len); + pos = end + 12; + buf_pos += len; + strcpy(buf_pos, core_pmu->name); + buf_pos += strlen(core_pmu->name); + } + strcpy(buf_pos, pos); - pr_debug("running test %d '%s'\n", i, e->name); - test_ret = test_event(e); + e.name = buf; + pr_debug("running test %d '%s'\n", i, e.name); + test_ret = test_event(&e); if (test_ret != TEST_OK) { - pr_debug("Event test failure: test %d '%s'", i, e->name); + pr_debug("Event test failure: test %d '%s'", i, e.name); ret = combine_test_results(ret, test_ret); } } From 4bebf7ff3e6a13bb0d3378e143efb86cd73d0c76 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:27 -0700 Subject: [PATCH 069/684] perf test: Switch cycles event to cpu-cycles Without a PMU perf matches an event against any PMU with the event. Unfortunately some PMU drivers advertise a "cycles" event which is typically just a core event. As tests assume a core event, switch to use "cpu-cycles" that avoids the overloaded "cycles" event on troublesome PMUs and is so far not overloaded. Note, on x86 this changes a legacy event into a sysfs one. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/perf-time-to-tsc.c | 4 ++-- tools/perf/tests/switch-tracking.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 1acb12b1a2eb31..5927d1ea20e223 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -704,7 +704,7 @@ static int do_test_code_reading(bool try_kcore) struct map *map; bool have_vmlinux, have_kcore; struct dso *dso; - const char *events[] = { "cycles", "cycles:u", "cpu-clock", "cpu-clock:u", NULL }; + const char *events[] = { "cpu-cycles", "cpu-cycles:u", "cpu-clock", "cpu-clock:u", NULL }; int evidx = 0; struct perf_env host_env; diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index eafb49eb0b56b7..729cc9cc1cb77f 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -90,7 +90,7 @@ static int test__keep_tracking(struct test_suite *test __maybe_unused, int subte perf_evlist__set_maps(&evlist->core, cpus, threads); CHECK__(parse_event(evlist, "dummy:u")); - CHECK__(parse_event(evlist, "cycles:u")); + CHECK__(parse_event(evlist, "cpu-cycles:u")); evlist__config(evlist, &opts, NULL); diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c index d4437410c99f45..cca41bd37ae3c2 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/tests/perf-time-to-tsc.c @@ -101,11 +101,11 @@ static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int su perf_evlist__set_maps(&evlist->core, cpus, threads); - CHECK__(parse_event(evlist, "cycles:u")); + CHECK__(parse_event(evlist, "cpu-cycles:u")); evlist__config(evlist, &opts, NULL); - /* For hybrid "cycles:u", it creates two events */ + /* For hybrid "cpu-cycles:u", it creates two events */ evlist__for_each_entry(evlist, evsel) { evsel->core.attr.comm = 1; evsel->core.attr.disabled = 1; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 5be294014d3b5a..15791fcb76b2f0 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -332,7 +332,7 @@ static int process_events(struct evlist *evlist, static int test__switch_tracking(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { const char *sched_switch = "sched:sched_switch"; - const char *cycles = "cycles:u"; + const char *cycles = "cpu-cycles:u"; struct switch_tracking switch_tracking = { .tids = NULL, }; struct record_opts opts = { .mmap_pages = UINT_MAX, From 8f9f6d7117c9d24217530eae068e367e8947d74e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:28 -0700 Subject: [PATCH 070/684] perf test: Clean up test_..config helpers Just have a single test_hw_config helper that strips extended type information in the case of hardware and hardware cache events. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 5dd2f03e952d7a..b6ba0e632454e0 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -41,22 +41,7 @@ static int num_core_entries(struct evlist *evlist) return 1; } -static bool test_config(const struct evsel *evsel, __u64 expected_config) -{ - __u32 type = evsel->core.attr.type; - __u64 config = evsel->core.attr.config; - - if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) { - /* - * HARDWARE and HW_CACHE events encode the PMU's extended type - * in the top 32-bits. Mask in order to ignore. - */ - config &= PERF_HW_EVENT_MASK; - } - return config == expected_config; -} - -static bool test_perf_config(const struct perf_evsel *evsel, __u64 expected_config) +static bool test_hw_config(const struct perf_evsel *evsel, __u64 expected_config) { return (evsel->attr.config & PERF_HW_EVENT_MASK) == expected_config; } @@ -129,7 +114,7 @@ static int test__checkevent_raw(struct evlist *evlist) struct perf_pmu *pmu __maybe_unused = NULL; bool type_matched = false; - TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 0x1a)); + TEST_ASSERT_VAL("wrong config", test_hw_config(evsel, 0x1a)); TEST_ASSERT_VAL("event not parsed as raw type", evsel->attr.type == PERF_TYPE_RAW); #if defined(__aarch64__) @@ -215,7 +200,7 @@ static int test__checkevent_genhw(struct evlist *evlist) perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 1 << 16)); + TEST_ASSERT_VAL("wrong config", test_hw_config(evsel, 1 << 16)); } return TEST_OK; } @@ -596,7 +581,7 @@ static int test__checkevent_pmu(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_config(evsel, 10)); + TEST_ASSERT_VAL("wrong config", test_hw_config(&evsel->core, 10)); TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1); TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2); TEST_ASSERT_VAL("wrong config3", 0 == evsel->core.attr.config3); From c4b34fe0021ffc5b6eab8411a6b9d0cefed89b35 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:29 -0700 Subject: [PATCH 071/684] perf test parse-events: Add evlist test helper Add TEST_ASSERT_EVLIST to dump the failing evlist in the event of a failure. Add the macro to a number of tests not currently checking the evlist length. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 236 ++++++++++++++++++++++---------- 1 file changed, 165 insertions(+), 71 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index b6ba0e632454e0..20c91acea88a6f 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -7,6 +7,7 @@ #include "debug.h" #include "pmu.h" #include "pmus.h" +#include "strbuf.h" #include #include #include "fncache.h" @@ -20,6 +21,22 @@ #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) +static bool check_evlist(const char *test, int line, bool cond, struct evlist *evlist) +{ + struct strbuf sb = STRBUF_INIT; + + if (cond) + return true; + + evlist__format_evsels(evlist, &sb, 2048); + pr_debug("FAILED %s:%d: %s\nFor evlist: %s\n", __FILE__, line, test, sb.buf); + strbuf_release(&sb); + return false; +} +#define TEST_ASSERT_EVLIST(test, cond, evlist) \ + if (!check_evlist(test, __LINE__, cond, evlist)) \ + return TEST_FAIL + static int num_core_entries(struct evlist *evlist) { /* @@ -76,8 +93,8 @@ static int test__checkevent_tracepoint(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist__nr_groups(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); + TEST_ASSERT_EVLIST("wrong number of groups", 0 == evlist__nr_groups(evlist), evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong sample_type", PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); @@ -89,8 +106,8 @@ static int test__checkevent_tracepoint_multi(struct evlist *evlist) { struct evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1); - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist__nr_groups(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries > 1, evlist); + TEST_ASSERT_EVLIST("wrong number of groups", 0 == evlist__nr_groups(evlist), evlist); evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("wrong type", @@ -108,7 +125,7 @@ static int test__checkevent_raw(struct evlist *evlist) struct perf_evsel *evsel; bool raw_type_match = false; - TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); perf_evlist__for_each_evsel(&evlist->core, evsel) { struct perf_pmu *pmu __maybe_unused = NULL; @@ -145,7 +162,7 @@ static int test__checkevent_numeric(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); return TEST_OK; @@ -156,7 +173,7 @@ static int test__checkevent_symbolic_name(struct evlist *evlist) { struct evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); evlist__for_each_entry(evlist, evsel) TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); @@ -168,7 +185,7 @@ static int test__checkevent_symbolic_name_config(struct evlist *evlist) { struct evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); @@ -187,7 +204,7 @@ static int test__checkevent_symbolic_alias(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)); return TEST_OK; } @@ -196,7 +213,7 @@ static int test__checkevent_genhw(struct evlist *evlist) { struct perf_evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); @@ -209,7 +226,7 @@ static int test__checkevent_breakpoint(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == @@ -223,7 +240,7 @@ static int test__checkevent_breakpoint_x(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", @@ -236,7 +253,7 @@ static int test__checkevent_breakpoint_r(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); @@ -251,7 +268,7 @@ static int test__checkevent_breakpoint_w(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); @@ -266,7 +283,7 @@ static int test__checkevent_breakpoint_rw(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); @@ -281,6 +298,7 @@ static int test__checkevent_tracepoint_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -294,7 +312,7 @@ test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) { struct perf_evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1); + TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries > 1, evlist); perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); @@ -310,6 +328,8 @@ static int test__checkevent_raw_modifier(struct evlist *evlist) { struct perf_evsel *evsel; + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); + perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -323,6 +343,8 @@ static int test__checkevent_numeric_modifier(struct evlist *evlist) { struct perf_evsel *evsel; + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); + perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -336,8 +358,9 @@ static int test__checkevent_symbolic_name_modifier(struct evlist *evlist) { struct perf_evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); @@ -352,6 +375,10 @@ static int test__checkevent_exclude_host_modifier(struct evlist *evlist) { struct perf_evsel *evsel; + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); + perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); @@ -363,6 +390,10 @@ static int test__checkevent_exclude_guest_modifier(struct evlist *evlist) { struct perf_evsel *evsel; + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); + perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); @@ -374,6 +405,7 @@ static int test__checkevent_symbolic_alias_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -386,6 +418,10 @@ static int test__checkevent_genhw_modifier(struct evlist *evlist) { struct perf_evsel *evsel; + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); + perf_evlist__for_each_entry(&evlist->core, evsel) { TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -399,6 +435,10 @@ static int test__checkevent_exclude_idle_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); + TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); @@ -414,6 +454,10 @@ static int test__checkevent_exclude_idle_modifier_1(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); + TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); @@ -643,7 +687,7 @@ static int test__checkevent_pmu_name(struct evlist *evlist) char buf[256]; /* default_core/config=1,name=krava/u */ - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 2 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "krava")); @@ -665,7 +709,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); /* default_core/config=1,call-graph=fp,time,period=100000/ */ - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 2 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); /* @@ -696,7 +740,7 @@ static int test__checkevent_pmu_events(struct evlist *evlist) struct evsel *evsel; struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); - TEST_ASSERT_VAL("wrong number of entries", 1 <= evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 <= evlist->core.nr_entries, evlist); evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type || @@ -721,7 +765,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) * The wild card event will be opened at least once, but it may be * opened on each core PMU. */ - TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries >= 2); + TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries >= 2, evlist); for (int i = 0; i < evlist->core.nr_entries - 1; i++) { evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); /* pmu-event:u */ @@ -833,10 +877,12 @@ static int test__group1(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (num_core_entries(evlist) * 2)); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (num_core_entries(evlist) * 2), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions:k */ @@ -873,13 +919,14 @@ static int test__group2(struct evlist *evlist) { struct evsel *evsel, *leader = NULL; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist) + 1)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist) + 1), + evlist); /* * TODO: Currently the software event won't be grouped with the hardware * event except for 1 PMU. */ - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist__nr_groups(evlist)); + TEST_ASSERT_EVLIST("wrong number of groups", 1 == evlist__nr_groups(evlist), evlist); evlist__for_each_entry(evlist, evsel) { if (evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)) { @@ -928,14 +975,15 @@ static int test__group3(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *group1_leader = NULL, *group2_leader = NULL; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus() + 2)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus() + 2), + evlist); /* * Currently the software event won't be grouped with the hardware event * except for 1 PMU. This means there are always just 2 groups * regardless of the number of core PMUs. */ - TEST_ASSERT_VAL("wrong number of groups", 2 == evlist__nr_groups(evlist)); + TEST_ASSERT_EVLIST("wrong number of groups", 2 == evlist__nr_groups(evlist), evlist); evlist__for_each_entry(evlist, evsel) { if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { @@ -1030,10 +1078,12 @@ static int test__group4(struct evlist *evlist __maybe_unused) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (num_core_entries(evlist) * 2)); - TEST_ASSERT_VAL("wrong number of groups", - num_core_entries(evlist) == evlist__nr_groups(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (num_core_entries(evlist) * 2), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + num_core_entries(evlist) == evlist__nr_groups(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:u + p */ @@ -1071,10 +1121,12 @@ static int test__group5(struct evlist *evlist __maybe_unused) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (5 * num_core_entries(evlist))); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == (2 * num_core_entries(evlist))); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (5 * num_core_entries(evlist)), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == (2 * num_core_entries(evlist)), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + G */ @@ -1152,10 +1204,12 @@ static int test__group_gh1(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist))); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist)), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :H group modifier */ @@ -1191,10 +1245,12 @@ static int test__group_gh2(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist))); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist)), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :G group modifier */ @@ -1230,10 +1286,12 @@ static int test__group_gh3(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist))); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist)), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :u group modifier */ @@ -1269,10 +1327,12 @@ static int test__group_gh4(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist))); - TEST_ASSERT_VAL("wrong number of groups", - evlist__nr_groups(evlist) == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist)), + evlist); + TEST_ASSERT_EVLIST("wrong number of groups", + evlist__nr_groups(evlist) == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :uG group modifier */ @@ -1308,8 +1368,9 @@ static int test__leader_sample1(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (3 * num_core_entries(evlist))); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (3 * num_core_entries(evlist)), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - sampling group leader */ @@ -1358,8 +1419,9 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (2 * num_core_entries(evlist))); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (2 * num_core_entries(evlist)), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions - sampling group leader */ @@ -1396,8 +1458,9 @@ static int test__checkevent_pinned_modifier(struct evlist *evlist) { struct evsel *evsel = NULL; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); @@ -1414,8 +1477,9 @@ static int test__pinned_group(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == (3 * num_core_entries(evlist))); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == (3 * num_core_entries(evlist)), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ @@ -1445,6 +1509,9 @@ static int test__checkevent_exclusive_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1458,8 +1525,9 @@ static int test__exclusive_group(struct evlist *evlist) { struct evsel *evsel = NULL, *leader; - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == 3 * num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == 3 * num_core_entries(evlist), + evlist); for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ @@ -1488,7 +1556,7 @@ static int test__checkevent_breakpoint_len(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == @@ -1503,7 +1571,7 @@ static int test__checkevent_breakpoint_len_w(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == @@ -1519,6 +1587,7 @@ test__checkevent_breakpoint_len_rw_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); @@ -1531,8 +1600,9 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", - evlist->core.nr_entries == 1 + num_core_entries(evlist)); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == 1 + num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)); return TEST_OK; } @@ -1541,6 +1611,9 @@ static int test__checkevent_config_symbol(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "insn")); return TEST_OK; } @@ -1549,6 +1622,7 @@ static int test__checkevent_config_raw(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "rawpmu")); return TEST_OK; } @@ -1557,6 +1631,7 @@ static int test__checkevent_config_num(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "numpmu")); return TEST_OK; } @@ -1565,6 +1640,9 @@ static int test__checkevent_config_cache(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "cachepmu")); return test__checkevent_genhw(evlist); } @@ -1588,6 +1666,7 @@ static int test__intel_pt(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "intel_pt//u")); return TEST_OK; } @@ -1642,6 +1721,9 @@ static int test__checkevent_complex_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("wrong complex name parsing", evsel__name_is(evsel, "COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks")); @@ -1652,7 +1734,7 @@ static int test__checkevent_raw_pmu(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); + TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config); return TEST_OK; @@ -1662,6 +1744,9 @@ static int test__sym_event_slash(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); return TEST_OK; @@ -1671,6 +1756,9 @@ static int test__sym_event_dc(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); return TEST_OK; @@ -1680,6 +1768,9 @@ static int test__term_equal_term(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "name") == 0); return TEST_OK; @@ -1689,6 +1780,9 @@ static int test__term_equal_legacy(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); + TEST_ASSERT_EVLIST("wrong number of entries", + evlist->core.nr_entries == num_core_entries(evlist), + evlist); TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "l1d") == 0); return TEST_OK; From b4a63b0e73709bb8eb1a5ed10599fb2256f7ba5f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 5 Oct 2025 11:24:30 -0700 Subject: [PATCH 072/684] perf test parse-events: Add evsel test helper Add TEST_ASSERT_EVSEL to dump the failing evsel in the event of a failure. Signed-off-by: Ian Rogers Tested-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 1380 +++++++++++++++++-------------- 1 file changed, 742 insertions(+), 638 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 20c91acea88a6f..e4cdb517c10e6f 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "parse-events.h" #include "evsel.h" +#include "evsel_fprintf.h" #include "evlist.h" #include #include "tests.h" @@ -37,6 +38,21 @@ static bool check_evlist(const char *test, int line, bool cond, struct evlist *e if (!check_evlist(test, __LINE__, cond, evlist)) \ return TEST_FAIL +static bool check_evsel(const char *test, int line, bool cond, struct evsel *evsel) +{ + struct perf_attr_details details = { .verbose = true, }; + + if (cond) + return true; + + pr_debug("FAILED %s:%d: %s\nFor evsel: ", __FILE__, line, test); + evsel__fprintf(evsel, &details, debug_file()); + return false; +} +#define TEST_ASSERT_EVSEL(test, cond, evsel) \ + if (!check_evsel(test, __LINE__, cond, evsel)) \ + return TEST_FAIL + static int num_core_entries(struct evlist *evlist) { /* @@ -58,9 +74,9 @@ static int num_core_entries(struct evlist *evlist) return 1; } -static bool test_hw_config(const struct perf_evsel *evsel, __u64 expected_config) +static bool test_hw_config(const struct evsel *evsel, __u64 expected_config) { - return (evsel->attr.config & PERF_HW_EVENT_MASK) == expected_config; + return (evsel->core.attr.config & PERF_HW_EVENT_MASK) == expected_config; } #if defined(__s390x__) @@ -95,10 +111,10 @@ static int test__checkevent_tracepoint(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); TEST_ASSERT_EVLIST("wrong number of groups", 0 == evlist__nr_groups(evlist), evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong sample_type", + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type, evsel); + TEST_ASSERT_EVSEL("wrong sample_period", 1 == evsel->core.attr.sample_period, evsel); return TEST_OK; } @@ -110,30 +126,34 @@ static int test__checkevent_tracepoint_multi(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of groups", 0 == evlist__nr_groups(evlist), evlist); evlist__for_each_entry(evlist, evsel) { - TEST_ASSERT_VAL("wrong type", - PERF_TYPE_TRACEPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", - 1 == evsel->core.attr.sample_period); + TEST_ASSERT_EVSEL("wrong type", + PERF_TYPE_TRACEPOINT == evsel->core.attr.type, + evsel); + TEST_ASSERT_EVSEL("wrong sample_type", + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type, + evsel); + TEST_ASSERT_EVSEL("wrong sample_period", + 1 == evsel->core.attr.sample_period, + evsel); } return TEST_OK; } static int test__checkevent_raw(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; bool raw_type_match = false; TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); - perf_evlist__for_each_evsel(&evlist->core, evsel) { + evlist__for_each_entry(evlist, evsel) { struct perf_pmu *pmu __maybe_unused = NULL; bool type_matched = false; - TEST_ASSERT_VAL("wrong config", test_hw_config(evsel, 0x1a)); - TEST_ASSERT_VAL("event not parsed as raw type", - evsel->attr.type == PERF_TYPE_RAW); + TEST_ASSERT_EVSEL("wrong config", test_hw_config(evsel, 0x1a), evsel); + TEST_ASSERT_EVSEL("event not parsed as raw type", + evsel->core.attr.type == PERF_TYPE_RAW, + evsel); #if defined(__aarch64__) /* * Arm doesn't have a real raw type PMU in sysfs, so raw events @@ -144,15 +164,15 @@ static int test__checkevent_raw(struct evlist *evlist) type_matched = raw_type_match = true; #else while ((pmu = perf_pmus__scan(pmu)) != NULL) { - if (pmu->type == evsel->attr.type) { - TEST_ASSERT_VAL("PMU type expected once", !type_matched); + if (pmu->type == evsel->core.attr.type) { + TEST_ASSERT_EVSEL("PMU type expected once", !type_matched, evsel); type_matched = true; if (pmu->type == PERF_TYPE_RAW) raw_type_match = true; } } #endif - TEST_ASSERT_VAL("No PMU found for type", type_matched); + TEST_ASSERT_EVSEL("No PMU found for type", type_matched, evsel); } TEST_ASSERT_VAL("Raw PMU not matched", raw_type_match); return TEST_OK; @@ -163,8 +183,8 @@ static int test__checkevent_numeric(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); + TEST_ASSERT_EVSEL("wrong type", 1 == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 1 == evsel->core.attr.config, evsel); return TEST_OK; } @@ -175,9 +195,11 @@ static int test__checkevent_symbolic_name(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); - evlist__for_each_entry(evlist, evsel) - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + } return TEST_OK; } @@ -188,14 +210,16 @@ static int test__checkevent_symbolic_name_config(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); evlist__for_each_entry(evlist, evsel) { - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); /* * The period value gets configured within evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); - TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1); - TEST_ASSERT_VAL("wrong config2", 1 == evsel->core.attr.config2); + TEST_ASSERT_EVSEL("wrong period", 0 == evsel->core.attr.sample_period, evsel); + TEST_ASSERT_EVSEL("wrong config1", 0 == evsel->core.attr.config1, evsel); + TEST_ASSERT_EVSEL("wrong config2", 1 == evsel->core.attr.config2, evsel); } return TEST_OK; } @@ -205,19 +229,20 @@ static int test__checkevent_symbolic_alias(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)); + TEST_ASSERT_EVSEL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS), + evsel); return TEST_OK; } static int test__checkevent_genhw(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", 0 != evlist->core.nr_entries, evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", test_hw_config(evsel, 1 << 16)); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", test_hw_config(evsel, 1 << 16), evsel); } return TEST_OK; } @@ -227,12 +252,12 @@ static int test__checkevent_breakpoint(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == - evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 == - evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", + (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == evsel->core.attr.bp_type, + evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -241,11 +266,11 @@ static int test__checkevent_breakpoint_x(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_X == evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", default_breakpoint_len() == evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", HW_BREAKPOINT_X == evsel->core.attr.bp_type, evsel); + TEST_ASSERT_EVSEL("wrong bp_len", default_breakpoint_len() == evsel->core.attr.bp_len, + evsel); return TEST_OK; } @@ -254,13 +279,10 @@ static int test__checkevent_breakpoint_r(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_R == evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", HW_BREAKPOINT_R == evsel->core.attr.bp_type, evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -269,13 +291,10 @@ static int test__checkevent_breakpoint_w(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_W == evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", HW_BREAKPOINT_W == evsel->core.attr.bp_type, evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -284,13 +303,12 @@ static int test__checkevent_breakpoint_rw(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", - (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", + (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->core.attr.bp_type, + evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -299,10 +317,10 @@ static int test__checkevent_tracepoint_modifier(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); return test__checkevent_tracepoint(evlist); } @@ -310,15 +328,15 @@ static int test__checkevent_tracepoint_modifier(struct evlist *evlist) static int test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries > 1, evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); } return test__checkevent_tracepoint_multi(evlist); @@ -326,77 +344,77 @@ test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) static int test__checkevent_raw_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); } return test__checkevent_raw(evlist); } static int test__checkevent_numeric_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); } return test__checkevent_numeric(evlist); } static int test__checkevent_symbolic_name_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); } return test__checkevent_symbolic_name(evlist); } static int test__checkevent_exclude_host_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); } return test__checkevent_symbolic_name(evlist); } static int test__checkevent_exclude_guest_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude guest", evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); } return test__checkevent_symbolic_name(evlist); } @@ -406,27 +424,27 @@ static int test__checkevent_symbolic_alias_modifier(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); return test__checkevent_symbolic_alias(evlist); } static int test__checkevent_genhw_modifier(struct evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - perf_evlist__for_each_entry(&evlist->core, evsel) { - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + evlist__for_each_entry(evlist, evsel) { + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); } return test__checkevent_genhw(evlist); } @@ -439,13 +457,13 @@ static int test__checkevent_exclude_idle_modifier(struct evlist *evlist) evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong exclude idle", evsel->core.attr.exclude_idle, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); return test__checkevent_symbolic_name(evlist); } @@ -458,13 +476,13 @@ static int test__checkevent_exclude_idle_modifier_1(struct evlist *evlist) evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong exclude idle", evsel->core.attr.exclude_idle, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); return test__checkevent_symbolic_name(evlist); } @@ -474,11 +492,11 @@ static int test__checkevent_breakpoint_modifier(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "mem:0:u")); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "mem:0:u"), evsel); return test__checkevent_breakpoint(evlist); } @@ -487,11 +505,11 @@ static int test__checkevent_breakpoint_x_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "mem:0:x:k")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "mem:0:x:k"), evsel); return test__checkevent_breakpoint_x(evlist); } @@ -500,11 +518,11 @@ static int test__checkevent_breakpoint_r_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "mem:0:r:hp")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "mem:0:r:hp"), evsel); return test__checkevent_breakpoint_r(evlist); } @@ -513,11 +531,11 @@ static int test__checkevent_breakpoint_w_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "mem:0:w:up")); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "mem:0:w:up"), evsel); return test__checkevent_breakpoint_w(evlist); } @@ -526,11 +544,11 @@ static int test__checkevent_breakpoint_rw_modifier(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "mem:0:rw:kp")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "mem:0:rw:kp"), evsel); return test__checkevent_breakpoint_rw(evlist); } @@ -539,11 +557,11 @@ static int test__checkevent_breakpoint_modifier_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint")); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint"), evsel); return test__checkevent_breakpoint(evlist); } @@ -552,11 +570,11 @@ static int test__checkevent_breakpoint_x_modifier_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint"), evsel); return test__checkevent_breakpoint_x(evlist); } @@ -565,11 +583,11 @@ static int test__checkevent_breakpoint_r_modifier_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint"), evsel); return test__checkevent_breakpoint_r(evlist); } @@ -578,11 +596,11 @@ static int test__checkevent_breakpoint_w_modifier_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint")); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint"), evsel); return test__checkevent_breakpoint_w(evlist); } @@ -591,11 +609,11 @@ static int test__checkevent_breakpoint_rw_modifier_name(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint")); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint"), evsel); return test__checkevent_breakpoint_rw(evlist); } @@ -604,15 +622,15 @@ static int test__checkevent_breakpoint_2_events(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); + TEST_ASSERT_EVSEL("wrong number of entries", 2 == evlist->core.nr_entries, evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint1")); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint1"), evsel); evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "breakpoint2")); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "breakpoint2"), evsel); return TEST_OK; } @@ -623,17 +641,17 @@ static int test__checkevent_pmu(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); struct perf_pmu *core_pmu = perf_pmus__find_core_pmu(); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", test_hw_config(&evsel->core, 10)); - TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1); - TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2); - TEST_ASSERT_VAL("wrong config3", 0 == evsel->core.attr.config3); + TEST_ASSERT_EVSEL("wrong number of entries", 1 == evlist->core.nr_entries, evsel); + TEST_ASSERT_EVSEL("wrong type", core_pmu->type == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", test_hw_config(evsel, 10), evsel); + TEST_ASSERT_EVSEL("wrong config1", 1 == evsel->core.attr.config1, evsel); + TEST_ASSERT_EVSEL("wrong config2", 3 == evsel->core.attr.config2, evsel); + TEST_ASSERT_EVSEL("wrong config3", 0 == evsel->core.attr.config3, evsel); /* * The period value gets configured within evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); + TEST_ASSERT_EVSEL("wrong period", 0 == evsel->core.attr.sample_period, evsel); return TEST_OK; } @@ -642,40 +660,40 @@ static int test__checkevent_list(struct evlist *evlist) { struct evsel *evsel = evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 3 <= evlist->core.nr_entries); + TEST_ASSERT_EVSEL("wrong number of entries", 3 <= evlist->core.nr_entries, evsel); /* r1 */ - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT != evsel->core.attr.type); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_TRACEPOINT != evsel->core.attr.type, evsel); while (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { - TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1); - TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2); - TEST_ASSERT_VAL("wrong config3", 0 == evsel->core.attr.config3); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong config", 1 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong config1", 0 == evsel->core.attr.config1, evsel); + TEST_ASSERT_EVSEL("wrong config2", 0 == evsel->core.attr.config2, evsel); + TEST_ASSERT_EVSEL("wrong config3", 0 == evsel->core.attr.config3, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); evsel = evsel__next(evsel); } /* syscalls:sys_enter_openat:k */ - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong sample_type", PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type, + evsel); + TEST_ASSERT_EVSEL("wrong sample_period", 1 == evsel->core.attr.sample_period, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); /* 1:1:hp */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong type", 1 == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 1 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); return TEST_OK; } @@ -688,17 +706,17 @@ static int test__checkevent_pmu_name(struct evlist *evlist) /* default_core/config=1,name=krava/u */ TEST_ASSERT_EVLIST("wrong number of entries", 2 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, "krava")); + TEST_ASSERT_EVSEL("wrong type", core_pmu->type == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 1 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, "krava"), evsel); /* default_core/config=2/u" */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); + TEST_ASSERT_EVSEL("wrong number of entries", 2 == evlist->core.nr_entries, evsel); + TEST_ASSERT_EVSEL("wrong type", core_pmu->type == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 2 == evsel->core.attr.config, evsel); snprintf(buf, sizeof(buf), "%s/config=2/u", core_pmu->name); - TEST_ASSERT_VAL("wrong name", evsel__name_is(evsel, buf)); + TEST_ASSERT_EVSEL("wrong name", evsel__name_is(evsel, buf), evsel); return TEST_OK; } @@ -710,27 +728,27 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) /* default_core/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_EVLIST("wrong number of entries", 2 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); + TEST_ASSERT_EVSEL("wrong type", core_pmu->type == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 1 == evsel->core.attr.config, evsel); /* * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); - TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel)); - TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type)); + TEST_ASSERT_EVSEL("wrong period", 0 == evsel->core.attr.sample_period, evsel); + TEST_ASSERT_EVSEL("wrong callgraph", !evsel__has_callchain(evsel), evsel); + TEST_ASSERT_EVSEL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type), evsel); /* default_core/config=2,call-graph=no,time=0,period=2000/ */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); + TEST_ASSERT_EVSEL("wrong type", core_pmu->type == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 2 == evsel->core.attr.config, evsel); /* * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); - TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel)); - TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type)); + TEST_ASSERT_EVSEL("wrong period", 0 == evsel->core.attr.sample_period, evsel); + TEST_ASSERT_EVSEL("wrong callgraph", !evsel__has_callchain(evsel), evsel); + TEST_ASSERT_EVSEL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type), evsel); return TEST_OK; } @@ -743,15 +761,17 @@ static int test__checkevent_pmu_events(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", 1 <= evlist->core.nr_entries, evlist); evlist__for_each_entry(evlist, evsel) { - TEST_ASSERT_VAL("wrong type", core_pmu->type == evsel->core.attr.type || - !strncmp(evsel__name(evsel), evsel->pmu->name, - strlen(evsel->pmu->name))); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); - TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("wrong type", + core_pmu->type == evsel->core.attr.type || + !strncmp(evsel__name(evsel), evsel->pmu->name, + strlen(evsel->pmu->name)), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong pinned", !evsel->core.attr.pinned, evsel); + TEST_ASSERT_EVSEL("wrong exclusive", !evsel->core.attr.exclusive, evsel); } return TEST_OK; } @@ -769,26 +789,22 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) for (int i = 0; i < evlist->core.nr_entries - 1; i++) { evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); /* pmu-event:u */ - TEST_ASSERT_VAL("wrong exclude_user", - !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); - TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong pinned", !evsel->core.attr.pinned, evsel); + TEST_ASSERT_EVSEL("wrong exclusive", !evsel->core.attr.exclusive, evsel); } /* default_core/pmu-event/u*/ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", evsel__find_pmu(evsel)->is_core); - TEST_ASSERT_VAL("wrong exclude_user", - !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); - TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.pinned); + TEST_ASSERT_EVSEL("wrong type", evsel__find_pmu(evsel)->is_core, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong pinned", !evsel->core.attr.pinned, evsel); + TEST_ASSERT_EVSEL("wrong exclusive", !evsel->core.attr.pinned, evsel); return TEST_OK; } @@ -887,30 +903,33 @@ static int test__group1(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions:k */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); /* cycles:upp */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip == 2, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } return TEST_OK; } @@ -932,41 +951,53 @@ static int test__group2(struct evlist *evlist) if (evsel__match(evsel, SOFTWARE, SW_PAGE_FAULTS)) { /* faults + :ku modifier */ leader = evsel; - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, + evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, + evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, + evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); continue; } if (evsel__match(evsel, HARDWARE, HW_BRANCH_INSTRUCTIONS)) { /* branches + :u modifier */ - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - if (evsel__has_leader(evsel, leader)) - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, + evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, + evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + if (evsel__has_leader(evsel, leader)) { + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, + evsel); + } + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); continue; } /* cycles:k */ - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } return TEST_OK; } @@ -989,87 +1020,110 @@ static int test__group3(struct evlist *evlist __maybe_unused) if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { /* group1 syscalls:sys_enter_openat:H */ group1_leader = evsel; - TEST_ASSERT_VAL("wrong sample_type", - evsel->core.attr.sample_type == PERF_TP_SAMPLE_TYPE); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong group name", !strcmp(evsel->group_name, "group1")); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong sample_type", + evsel->core.attr.sample_type == PERF_TP_SAMPLE_TYPE, + evsel); + TEST_ASSERT_EVSEL("wrong sample_period", + 1 == evsel->core.attr.sample_period, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", evsel->core.attr.exclude_guest, + evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, + evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong group name", !strcmp(evsel->group_name, "group1"), + evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, + evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); continue; } if (evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { if (evsel->core.attr.exclude_user) { /* group1 cycles:kppp */ - TEST_ASSERT_VAL("wrong exclude_user", - evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", - !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", - !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", - !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", - evsel->core.attr.precise_ip == 3); + TEST_ASSERT_EVSEL("wrong exclude_user", + evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", + !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, + evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", + !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", + !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", + evsel->core.attr.precise_ip == 3, evsel); if (evsel__has_leader(evsel, group1_leader)) { - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong group_idx", - evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, + evsel); + TEST_ASSERT_EVSEL("wrong group_idx", + evsel__group_idx(evsel) == 1, + evsel); } - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } else { /* group2 cycles + G modifier */ group2_leader = evsel; - TEST_ASSERT_VAL("wrong exclude_kernel", - !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", - !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", - !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", - evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); + TEST_ASSERT_EVSEL("wrong exclude_kernel", + !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", + !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", + !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", + evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, + evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), + evsel); if (evsel->core.nr_members == 2) { - TEST_ASSERT_VAL("wrong group_idx", - evsel__group_idx(evsel) == 0); + TEST_ASSERT_EVSEL("wrong group_idx", + evsel__group_idx(evsel) == 0, + evsel); } - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } continue; } if (evsel->core.attr.type == 1) { /* group2 1:3 + G modifier */ - TEST_ASSERT_VAL("wrong config", 3 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - if (evsel__has_leader(evsel, group2_leader)) - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("wrong config", 3 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, + evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, + evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, + evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + if (evsel__has_leader(evsel, group2_leader)) { + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, + evsel); + } + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); continue; } /* instructions:u */ - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } return TEST_OK; } @@ -1088,31 +1142,35 @@ static int test__group4(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:u + p */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 1); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip == 1, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); /* instructions:kp + p */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip == 2, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } return TEST_OK; } @@ -1131,71 +1189,81 @@ static int test__group5(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + G */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); /* instructions + G */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); } for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G */ evsel = leader = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); + TEST_ASSERT_EVSEL("wrong sample_read", !evsel->sample_read, evsel); /* instructions:G */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); } for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); } return TEST_OK; } @@ -1214,29 +1282,33 @@ static int test__group_gh1(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :H group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); /* cache-misses:G + :H group modifier */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); } return TEST_OK; } @@ -1255,29 +1327,33 @@ static int test__group_gh2(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles + :G group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); /* cache-misses:H + :G group modifier */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); } return TEST_OK; } @@ -1296,29 +1372,33 @@ static int test__group_gh3(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :u group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); /* cache-misses:H + :u group modifier */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); } return TEST_OK; } @@ -1337,29 +1417,33 @@ static int test__group_gh4(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles:G + :uG group modifier */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__is_group_leader(evsel), evsel); + TEST_ASSERT_EVSEL("wrong core.nr_members", evsel->core.nr_members == 2, evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 0, evsel); /* cache-misses:H + :uG group modifier */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong group_idx", evsel__group_idx(evsel) == 1, evsel); } return TEST_OK; } @@ -1375,42 +1459,47 @@ static int test__leader_sample1(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", evsel->sample_read, evsel); /* cache-misses - not sampling */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", evsel->sample_read, evsel); /* branch-misses - not sampling */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", evsel->sample_read, evsel); } return TEST_OK; } @@ -1426,30 +1515,33 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) for (int i = 0; i < num_core_entries(evlist); i++) { /* instructions - sampling group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", evsel->sample_read, evsel); /* branch-misses - not sampling */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); - TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong exclude guest", !evsel->core.attr.exclude_guest, evsel); + TEST_ASSERT_EVSEL("wrong exclude host", !evsel->core.attr.exclude_host, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); + TEST_ASSERT_EVSEL("wrong sample_read", evsel->sample_read, evsel); } return TEST_OK; } @@ -1464,11 +1556,11 @@ static int test__checkevent_pinned_modifier(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong pinned", evsel->core.attr.pinned, evsel); } return test__checkevent_symbolic_name(evlist); } @@ -1484,23 +1576,28 @@ static int test__pinned_group(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); /* TODO: The group modifier is not copied to the split group leader. */ if (perf_pmus__num_core_pmus() == 1) - TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned); + TEST_ASSERT_EVSEL("wrong pinned", evsel->core.attr.pinned, evsel); /* cache-misses - can not be pinned, but will go on with the leader */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong pinned", !evsel->core.attr.pinned, evsel); /* branch-misses - ditto */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); - TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong pinned", !evsel->core.attr.pinned, evsel); } return TEST_OK; } @@ -1512,11 +1609,11 @@ static int test__checkevent_exclusive_modifier(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); - TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", evsel->core.attr.precise_ip, evsel); + TEST_ASSERT_EVSEL("wrong exclusive", evsel->core.attr.exclusive, evsel); return test__checkevent_symbolic_name(evlist); } @@ -1532,23 +1629,28 @@ static int test__exclusive_group(struct evlist *evlist) for (int i = 0; i < num_core_entries(evlist); i++) { /* cycles - group leader */ evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); + TEST_ASSERT_EVSEL("wrong group name", !evsel->group_name, evsel); + TEST_ASSERT_EVSEL("wrong leader", evsel__has_leader(evsel, leader), evsel); /* TODO: The group modifier is not copied to the split group leader. */ if (perf_pmus__num_core_pmus() == 1) - TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("wrong exclusive", evsel->core.attr.exclusive, evsel); /* cache-misses - can not be pinned, but will go on with the leader */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)); - TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CACHE_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclusive", !evsel->core.attr.exclusive, evsel); /* branch-misses - ditto */ evsel = evsel__next(evsel); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)); - TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES), + evsel); + TEST_ASSERT_EVSEL("wrong exclusive", !evsel->core.attr.exclusive, evsel); } return TEST_OK; } @@ -1557,12 +1659,12 @@ static int test__checkevent_breakpoint_len(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == - evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 == - evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", + (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == evsel->core.attr.bp_type, + evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_1 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -1572,12 +1674,10 @@ static int test__checkevent_breakpoint_len_w(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); - TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == - evsel->core.attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 == - evsel->core.attr.bp_len); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0 == evsel->core.attr.config, evsel); + TEST_ASSERT_EVSEL("wrong bp_type", HW_BREAKPOINT_W == evsel->core.attr.bp_type, evsel); + TEST_ASSERT_EVSEL("wrong bp_len", HW_BREAKPOINT_LEN_2 == evsel->core.attr.bp_len, evsel); return TEST_OK; } @@ -1588,10 +1688,10 @@ test__checkevent_breakpoint_len_rw_modifier(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); + TEST_ASSERT_EVSEL("wrong exclude_hv", evsel->core.attr.exclude_hv, evsel); + TEST_ASSERT_EVSEL("wrong precise_ip", !evsel->core.attr.precise_ip, evsel); return test__checkevent_breakpoint_rw(evlist); } @@ -1603,7 +1703,7 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == 1 + num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)); + TEST_ASSERT_EVSEL("wrong type/config", evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK), evsel); return TEST_OK; } @@ -1614,7 +1714,7 @@ static int test__checkevent_config_symbol(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "insn")); + TEST_ASSERT_EVSEL("wrong name setting", evsel__name_is(evsel, "insn"), evsel); return TEST_OK; } @@ -1623,7 +1723,7 @@ static int test__checkevent_config_raw(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "rawpmu")); + TEST_ASSERT_EVSEL("wrong name setting", evsel__name_is(evsel, "rawpmu"), evsel); return TEST_OK; } @@ -1632,7 +1732,7 @@ static int test__checkevent_config_num(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "numpmu")); + TEST_ASSERT_EVSEL("wrong name setting", evsel__name_is(evsel, "numpmu"), evsel); return TEST_OK; } @@ -1643,7 +1743,7 @@ static int test__checkevent_config_cache(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "cachepmu")); + TEST_ASSERT_EVSEL("wrong name setting", evsel__name_is(evsel, "cachepmu"), evsel); return test__checkevent_genhw(evlist); } @@ -1667,7 +1767,7 @@ static int test__intel_pt(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong name setting", evsel__name_is(evsel, "intel_pt//u")); + TEST_ASSERT_EVSEL("wrong name setting", evsel__name_is(evsel, "intel_pt//u"), evsel); return TEST_OK; } @@ -1698,15 +1798,17 @@ static int test__ratio_to_prev(struct evlist *evlist) TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 0); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), + evsel); } else { TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2); TEST_ASSERT_VAL("wrong leader", !evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 0); TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); - TEST_ASSERT_VAL("unexpected event", - evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)); + TEST_ASSERT_EVSEL("unexpected event", + evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS), + evsel); } /* * The period value gets configured within evlist__config, @@ -1724,9 +1826,10 @@ static int test__checkevent_complex_name(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("wrong complex name parsing", - evsel__name_is(evsel, - "COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks")); + TEST_ASSERT_EVSEL("wrong complex name parsing", + evsel__name_is(evsel, + "COMPLEX_CYCLES_NAME:orig=cpu-cycles,desc=chip-clock-ticks"), + evsel); return TEST_OK; } @@ -1735,8 +1838,8 @@ static int test__checkevent_raw_pmu(struct evlist *evlist) struct evsel *evsel = evlist__first(evlist); TEST_ASSERT_EVLIST("wrong number of entries", 1 == evlist->core.nr_entries, evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); - TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config); + TEST_ASSERT_EVSEL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type, evsel); + TEST_ASSERT_EVSEL("wrong config", 0x1a == evsel->core.attr.config, evsel); return TEST_OK; } @@ -1747,8 +1850,8 @@ static int test__sym_event_slash(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), evsel); + TEST_ASSERT_EVSEL("wrong exclude_kernel", evsel->core.attr.exclude_kernel, evsel); return TEST_OK; } @@ -1759,8 +1862,8 @@ static int test__sym_event_dc(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), evsel); + TEST_ASSERT_EVSEL("wrong exclude_user", evsel->core.attr.exclude_user, evsel); return TEST_OK; } @@ -1771,8 +1874,8 @@ static int test__term_equal_term(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "name") == 0); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), evsel); + TEST_ASSERT_EVSEL("wrong name setting", strcmp(evsel->name, "name") == 0, evsel); return TEST_OK; } @@ -1783,8 +1886,8 @@ static int test__term_equal_legacy(struct evlist *evlist) TEST_ASSERT_EVLIST("wrong number of entries", evlist->core.nr_entries == num_core_entries(evlist), evlist); - TEST_ASSERT_VAL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)); - TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "l1d") == 0); + TEST_ASSERT_EVSEL("unexpected event", evsel__match(evsel, HARDWARE, HW_CPU_CYCLES), evsel); + TEST_ASSERT_EVSEL("wrong name setting", strcmp(evsel->name, "l1d") == 0, evsel); return TEST_OK; } @@ -2754,8 +2857,9 @@ static int test__checkevent_pmu_events_alias(struct evlist *evlist) struct evsel *evsel1 = evlist__first(evlist); struct evsel *evsel2 = evlist__last(evlist); - TEST_ASSERT_VAL("wrong type", evsel1->core.attr.type == evsel2->core.attr.type); - TEST_ASSERT_VAL("wrong config", evsel1->core.attr.config == evsel2->core.attr.config); + TEST_ASSERT_EVSEL("wrong type", evsel1->core.attr.type == evsel2->core.attr.type, evsel1); + TEST_ASSERT_EVSEL("wrong config", evsel1->core.attr.config == evsel2->core.attr.config, + evsel1); return TEST_OK; } From b46d155e0db3b98a531431357247e15dc357a797 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Sep 2025 17:30:08 +0200 Subject: [PATCH 073/684] dmaengine: sh: usb-dmac: Convert to NOIRQ_SYSTEM_SLEEP/RUNTIME_PM_OPS() Convert the Renesas USB-DMA Controller driver from SET_NOIRQ_SYSTEM_SLEEP_PM_OPS() and SET_RUNTIME_PM_OPS() to NOIRQ_SYSTEM_SLEEP_PM_OPS(), RUNTIME_PM_OPS(), and pm_ptr(). This lets us drop the check for CONFIG_PM, and reduces kernel size in case CONFIG_PM is disabled, while increasing build coverage. Signed-off-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/sh/usb-dmac.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c index 7e2b6c97fa2f97..b42e5a66fd9575 100644 --- a/drivers/dma/sh/usb-dmac.c +++ b/drivers/dma/sh/usb-dmac.c @@ -670,7 +670,6 @@ static struct dma_chan *usb_dmac_of_xlate(struct of_phandle_args *dma_spec, * Power management */ -#ifdef CONFIG_PM static int usb_dmac_runtime_suspend(struct device *dev) { struct usb_dmac *dmac = dev_get_drvdata(dev); @@ -691,13 +690,11 @@ static int usb_dmac_runtime_resume(struct device *dev) return usb_dmac_init(dmac); } -#endif /* CONFIG_PM */ static const struct dev_pm_ops usb_dmac_pm = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(usb_dmac_runtime_suspend, usb_dmac_runtime_resume, - NULL) + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + RUNTIME_PM_OPS(usb_dmac_runtime_suspend, usb_dmac_runtime_resume, NULL) }; /* ----------------------------------------------------------------------------- @@ -894,7 +891,7 @@ MODULE_DEVICE_TABLE(of, usb_dmac_of_ids); static struct platform_driver usb_dmac_driver = { .driver = { - .pm = &usb_dmac_pm, + .pm = pm_ptr(&usb_dmac_pm), .name = "usb-dmac", .of_match_table = usb_dmac_of_ids, }, From 75396f5b9534780add6a32aaa9b005911bc98dd2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Sep 2025 17:28:37 +0200 Subject: [PATCH 074/684] dmaengine: nbpfaxi: Convert to RUNTIME_PM_OPS() Convert the Renesas Type-AXI NBPF DMA driver from SET_RUNTIME_PM_OPS() to RUNTIME_PM_OPS(), and pm_ptr(). This lets us drop the check for CONFIG_PM, and reduces kernel size in case CONFIG_PM is disabled, while increasing build coverage. Signed-off-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/nbpfaxi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index 765462303de098..334425faac00bf 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -1500,7 +1500,6 @@ static const struct platform_device_id nbpf_ids[] = { }; MODULE_DEVICE_TABLE(platform, nbpf_ids); -#ifdef CONFIG_PM static int nbpf_runtime_suspend(struct device *dev) { struct nbpf_device *nbpf = dev_get_drvdata(dev); @@ -1513,17 +1512,16 @@ static int nbpf_runtime_resume(struct device *dev) struct nbpf_device *nbpf = dev_get_drvdata(dev); return clk_prepare_enable(nbpf->clk); } -#endif static const struct dev_pm_ops nbpf_pm_ops = { - SET_RUNTIME_PM_OPS(nbpf_runtime_suspend, nbpf_runtime_resume, NULL) + RUNTIME_PM_OPS(nbpf_runtime_suspend, nbpf_runtime_resume, NULL) }; static struct platform_driver nbpf_driver = { .driver = { .name = "dma-nbpf", .of_match_table = nbpf_match, - .pm = &nbpf_pm_ops, + .pm = pm_ptr(&nbpf_pm_ops), }, .id_table = nbpf_ids, .probe = nbpf_probe, From b78c6286acd7ef93ddb064b5ad08b993eab33482 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Sep 2025 17:25:09 +0200 Subject: [PATCH 075/684] dmaengine: rcar-dmac: Remove dummy Runtime PM callback Since commit 63d00be69348fda4 ("PM: runtime: Allow unassigned ->runtime_suspend|resume callbacks"), unassigned .runtime_{suspend,resume}() callbacks are treated the same as dummy callbacks that just return zero. Signed-off-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 0c45ce8c74aa2d..0b8fb830ce8ce6 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1729,11 +1729,6 @@ static struct dma_chan *rcar_dmac_of_xlate(struct of_phandle_args *dma_spec, */ #ifdef CONFIG_PM -static int rcar_dmac_runtime_suspend(struct device *dev) -{ - return 0; -} - static int rcar_dmac_runtime_resume(struct device *dev) { struct rcar_dmac *dmac = dev_get_drvdata(dev); @@ -1750,8 +1745,7 @@ static const struct dev_pm_ops rcar_dmac_pm = { */ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(rcar_dmac_runtime_suspend, rcar_dmac_runtime_resume, - NULL) + SET_RUNTIME_PM_OPS(NULL, rcar_dmac_runtime_resume, NULL) }; /* ----------------------------------------------------------------------------- From c3c328d2383fa7f68ec93574152924cd8f5fe82c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Sep 2025 17:25:10 +0200 Subject: [PATCH 076/684] dmaengine: rcar-dmac: Convert to NOIRQ_SYSTEM_SLEEP/RUNTIME_PM_OPS() Convert the Renesas R-Car DMA Controller driver from SET_NOIRQ_SYSTEM_SLEEP_PM_OPS() and SET_RUNTIME_PM_OPS() to NOIRQ_SYSTEM_SLEEP_PM_OPS(), RUNTIME_PM_OPS(), and pm_ptr(). This lets us drop the check for CONFIG_PM, and reduces kernel size in case CONFIG_PM is disabled, while increasing build coverage. Signed-off-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 0b8fb830ce8ce6..475a347cae1b6a 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1728,14 +1728,12 @@ static struct dma_chan *rcar_dmac_of_xlate(struct of_phandle_args *dma_spec, * Power management */ -#ifdef CONFIG_PM static int rcar_dmac_runtime_resume(struct device *dev) { struct rcar_dmac *dmac = dev_get_drvdata(dev); return rcar_dmac_init(dmac); } -#endif static const struct dev_pm_ops rcar_dmac_pm = { /* @@ -1743,9 +1741,9 @@ static const struct dev_pm_ops rcar_dmac_pm = { * - Wait for the current transfer to complete and stop the device, * - Resume transfers, if any. */ - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(NULL, rcar_dmac_runtime_resume, NULL) + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + RUNTIME_PM_OPS(NULL, rcar_dmac_runtime_resume, NULL) }; /* ----------------------------------------------------------------------------- @@ -2030,7 +2028,7 @@ MODULE_DEVICE_TABLE(of, rcar_dmac_of_ids); static struct platform_driver rcar_dmac_driver = { .driver = { - .pm = &rcar_dmac_pm, + .pm = pm_ptr(&rcar_dmac_pm), .name = "rcar-dmac", .of_match_table = rcar_dmac_of_ids, }, From bc2c39600212979b6fc836113bde1b707c02f442 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 2 Oct 2025 13:47:35 +0100 Subject: [PATCH 077/684] dmaengine: sh: Kconfig: Drop ARCH_R7S72100/ARCH_RZG2L dependency The RZ DMA controller is used across multiple Renesas SoCs, not only RZ/A1 (R7S72100) and RZ/G2L. Limiting the build to these SoCs prevents enabling the driver on newer platforms such as RZ/V2H(P) and RZ/V2N. Replace the ARCH_R7S72100 || ARCH_RZG2L dependency with ARCH_RENESAS so the driver can be built for all Renesas SoCs. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/sh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig index 8184d475a49a18..a16c7e83bd14ac 100644 --- a/drivers/dma/sh/Kconfig +++ b/drivers/dma/sh/Kconfig @@ -50,7 +50,7 @@ config RENESAS_USB_DMAC config RZ_DMAC tristate "Renesas RZ DMA Controller" - depends on ARCH_R7S72100 || ARCH_RZG2L || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA select DMA_VIRTUAL_CHANNELS help From f80ea8566917c4bb680911db839a170873e5d17c Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Tue, 30 Sep 2025 18:22:26 -0700 Subject: [PATCH 078/684] dmaengine: idxd: drain ATS translations when disabling WQ There's an errata[1], for the Disable WQ command that it does not guaranteee that address translations are drained. If WQ configuration is updated, pending address translations can use an updated WQ configuration, resulting an invalid translation response that is cached in the device translation cache. Replace the Disable WQ command with a Drain WQ command followed by a Reset WQ command, this guarantees that all ATS translations are drained from the device before changing WQ configuration. [1] https://cdrdv2.intel.com/v1/dl/getcontent/843306 ("Intel DSA May Cause Invalid Translation Caching") Signed-off-by: Nikhil Rao Signed-off-by: Fenghua Yu Signed-off-by: Vinicius Costa Gomes Reviewed-by: Dave Jiang Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 5cf419fe6b4645..c2cdf41b6e5764 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -16,6 +16,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, u32 *status); static void idxd_device_wqs_clear_state(struct idxd_device *idxd); static void idxd_wq_disable_cleanup(struct idxd_wq *wq); +static int idxd_wq_config_write(struct idxd_wq *wq); /* Interrupt control bits */ void idxd_unmask_error_interrupts(struct idxd_device *idxd) @@ -215,14 +216,28 @@ int idxd_wq_disable(struct idxd_wq *wq, bool reset_config) return 0; } + /* + * Disable WQ does not drain address translations, if WQ attributes are + * changed before translations are drained, pending translations can + * be issued using updated WQ attibutes, resulting in invalid + * translations being cached in the device translation cache. + * + * To make sure pending translations are drained before WQ + * attributes are changed, we use a WQ Drain followed by WQ Reset and + * then restore the WQ configuration. + */ + idxd_wq_drain(wq); + operand = BIT(wq->id % 16) | ((wq->id / 16) << 16); - idxd_cmd_exec(idxd, IDXD_CMD_DISABLE_WQ, operand, &status); + idxd_cmd_exec(idxd, IDXD_CMD_RESET_WQ, operand, &status); if (status != IDXD_CMDSTS_SUCCESS) { - dev_dbg(dev, "WQ disable failed: %#x\n", status); + dev_dbg(dev, "WQ reset failed: %#x\n", status); return -ENXIO; } + idxd_wq_config_write(wq); + if (reset_config) idxd_wq_disable_cleanup(wq); clear_bit(wq->id, idxd->wq_enable_map); From 4e8331317e73902e8b2663352c8766227e633901 Mon Sep 17 00:00:00 2001 From: Jyothi Kumar Seerapu Date: Thu, 25 Sep 2025 17:30:34 +0530 Subject: [PATCH 079/684] dmaengine: qcom: gpi: Add GPI Block event interrupt support GSI hardware generates an interrupt for each transfer completion. For multiple messages within a single transfer, this results in N interrupts for N messages, leading to significant software interrupt latency. To mitigate this latency, utilize Block Event Interrupt (BEI) mechanism. Enabling BEI instructs the GSI hardware to prevent interrupt generation and BEI is disabled when an interrupt is necessary. Large I2C transfer can be divided into chunks of messages internally. Interrupts are not expected for the messages for which BEI bit set, only the last message triggers an interrupt, indicating the completion of N messages. This BEI mechanism enhances overall transfer efficiency. Signed-off-by: Jyothi Kumar Seerapu Reviewed-by: Dmitry Baryshkov Signed-off-by: Vinod Koul --- drivers/dma/qcom/gpi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 8e87738086b25a..66bfea1f156d1e 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1619,7 +1619,8 @@ gpi_peripheral_config(struct dma_chan *chan, struct dma_slave_config *config) } static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, - struct scatterlist *sgl, enum dma_transfer_direction direction) + struct scatterlist *sgl, enum dma_transfer_direction direction, + unsigned long flags) { struct gpi_i2c_config *i2c = chan->config; struct device *dev = chan->gpii->gpi_dev->dev; @@ -1684,6 +1685,9 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, tre->dword[3] = u32_encode_bits(TRE_TYPE_DMA, TRE_FLAGS_TYPE); tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOT); + + if (!(flags & DMA_PREP_INTERRUPT)) + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI); } for (i = 0; i < tre_idx; i++) @@ -1827,6 +1831,9 @@ gpi_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; } + if (!(flags & DMA_PREP_INTERRUPT) && (nr - nr_tre < 2)) + return NULL; + gpi_desc = kzalloc(sizeof(*gpi_desc), GFP_NOWAIT); if (!gpi_desc) return NULL; @@ -1835,7 +1842,7 @@ gpi_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (gchan->protocol == QCOM_GPI_SPI) { i = gpi_create_spi_tre(gchan, gpi_desc, sgl, direction); } else if (gchan->protocol == QCOM_GPI_I2C) { - i = gpi_create_i2c_tre(gchan, gpi_desc, sgl, direction); + i = gpi_create_i2c_tre(gchan, gpi_desc, sgl, direction, flags); } else { dev_err(dev, "invalid peripheral: %d\n", gchan->protocol); kfree(gpi_desc); From 398035178503bf662281bbffb4bebce1460a4bc5 Mon Sep 17 00:00:00 2001 From: Jyothi Kumar Seerapu Date: Thu, 25 Sep 2025 17:30:35 +0530 Subject: [PATCH 080/684] i2c: i2c-qcom-geni: Add Block event interrupt support The I2C driver gets an interrupt upon transfer completion. When handling multiple messages in a single transfer, this results in N interrupts for N messages, leading to significant software interrupt latency. To mitigate this latency, utilize Block Event Interrupt (BEI) mechanism. Enabling BEI instructs the hardware to prevent interrupt generation and BEI is disabled when an interrupt is necessary. Large I2C transfer can be divided into chunks of messages internally. Interrupts are not expected for the messages for which BEI bit set, only the last message triggers an interrupt, indicating the completion of N messages. This BEI mechanism enhances overall transfer efficiency. BEI optimizations are currently implemented for I2C write transfers only, as there is no use case for multiple I2C read messages in a single transfer at this time. Signed-off-by: Jyothi Kumar Seerapu Reviewed-by: Dmitry Baryshkov Acked-by: Andi Shyti Reviewed-by: Mukesh Savaliya Acked-by: Mukesh Savaliya Signed-off-by: Vinod Koul --- drivers/i2c/busses/i2c-qcom-geni.c | 248 ++++++++++++++++++++++++++--- 1 file changed, 224 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 95a577764d5c01..962780d76e0727 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -77,6 +77,25 @@ enum geni_i2c_err_code { #define XFER_TIMEOUT HZ #define RST_TIMEOUT HZ +#define QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC 2 + +/** + * struct geni_i2c_gpi_multi_desc_xfer - Structure for multi transfer support + * + * @msg_idx_cnt: Current message index being processed in the transfer + * @unmap_msg_cnt: Number of messages that have been unmapped + * @irq_cnt: Number of transfer completion interrupts received + * @dma_buf: Array of virtual addresses for DMA-safe buffers + * @dma_addr: Array of DMA addresses corresponding to the buffers + */ +struct geni_i2c_gpi_multi_desc_xfer { + u32 msg_idx_cnt; + u32 unmap_msg_cnt; + u32 irq_cnt; + void **dma_buf; + dma_addr_t *dma_addr; +}; + struct geni_i2c_dev { struct geni_se se; u32 tx_wm; @@ -99,6 +118,9 @@ struct geni_i2c_dev { struct dma_chan *rx_c; bool gpi_mode; bool abort_done; + bool is_tx_multi_desc_xfer; + u32 num_msgs; + struct geni_i2c_gpi_multi_desc_xfer i2c_multi_desc_config; }; struct geni_i2c_desc { @@ -499,6 +521,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result) { struct geni_i2c_dev *gi2c = cb; + struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer; if (result->result != DMA_TRANS_NOERROR) { dev_err(gi2c->se.dev, "DMA txn failed:%d\n", result->result); @@ -507,6 +530,11 @@ static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result) dev_dbg(gi2c->se.dev, "DMA xfer has pending: %d\n", result->residue); } + if (gi2c->is_tx_multi_desc_xfer) { + tx_multi_xfer = &gi2c->i2c_multi_desc_config; + tx_multi_xfer->irq_cnt++; + } + complete(&gi2c->done); } @@ -525,7 +553,72 @@ static void geni_i2c_gpi_unmap(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, } } -static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, +/** + * geni_i2c_gpi_multi_desc_unmap() - Unmaps DMA buffers post multi message TX transfers + * @gi2c: I2C dev handle + * @msgs: Array of I2C messages + * @peripheral: Pointer to gpi_i2c_config + */ +static void geni_i2c_gpi_multi_desc_unmap(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], + struct gpi_i2c_config *peripheral) +{ + u32 msg_xfer_cnt, wr_idx = 0; + struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer = &gi2c->i2c_multi_desc_config; + + msg_xfer_cnt = gi2c->err ? tx_multi_xfer->msg_idx_cnt : tx_multi_xfer->irq_cnt; + + /* Unmap the processed DMA buffers based on the received interrupt count */ + for (; tx_multi_xfer->unmap_msg_cnt < msg_xfer_cnt; tx_multi_xfer->unmap_msg_cnt++) { + wr_idx = tx_multi_xfer->unmap_msg_cnt; + geni_i2c_gpi_unmap(gi2c, &msgs[wr_idx], + tx_multi_xfer->dma_buf[wr_idx], + tx_multi_xfer->dma_addr[wr_idx], + NULL, 0); + + if (tx_multi_xfer->unmap_msg_cnt == gi2c->num_msgs - 1) { + kfree(tx_multi_xfer->dma_buf); + kfree(tx_multi_xfer->dma_addr); + break; + } + } +} + +/** + * geni_i2c_gpi_multi_xfer_timeout_handler() - Handles multi message transfer timeout + * @dev: Pointer to the corresponding dev node + * @multi_xfer: Pointer to the geni_i2c_gpi_multi_desc_xfer + * @transfer_timeout_msecs: Timeout value in milliseconds + * @transfer_comp: Completion object of the transfer + * + * This function waits for the completion of each processed transfer messages + * based on the interrupts generated upon transfer completion. + * + * Return: On success returns 0, -ETIMEDOUT on timeout. + */ +static int geni_i2c_gpi_multi_xfer_timeout_handler(struct device *dev, + struct geni_i2c_gpi_multi_desc_xfer *multi_xfer, + u32 transfer_timeout_msecs, + struct completion *transfer_comp) +{ + int i; + u32 time_left; + + for (i = 0; i < multi_xfer->msg_idx_cnt - 1; i++) { + reinit_completion(transfer_comp); + + if (multi_xfer->msg_idx_cnt != multi_xfer->irq_cnt) { + time_left = wait_for_completion_timeout(transfer_comp, + transfer_timeout_msecs); + if (!time_left) { + dev_err(dev, "%s: Transfer timeout\n", __func__); + return -ETIMEDOUT; + } + } + } + return 0; +} + +static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], struct dma_slave_config *config, dma_addr_t *dma_addr_p, void **buf, unsigned int op, struct dma_chan *dma_chan) { @@ -537,26 +630,45 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, enum dma_transfer_direction dma_dirn; struct dma_async_tx_descriptor *desc; int ret; + struct geni_i2c_gpi_multi_desc_xfer *gi2c_gpi_xfer; + dma_cookie_t cookie; + u32 msg_idx; peripheral = config->peripheral_config; + gi2c_gpi_xfer = &gi2c->i2c_multi_desc_config; + msg_idx = gi2c_gpi_xfer->msg_idx_cnt; - dma_buf = i2c_get_dma_safe_msg_buf(msg, 1); - if (!dma_buf) - return -ENOMEM; + dma_buf = i2c_get_dma_safe_msg_buf(&msgs[msg_idx], 1); + if (!dma_buf) { + ret = -ENOMEM; + goto out; + } if (op == I2C_WRITE) map_dirn = DMA_TO_DEVICE; else map_dirn = DMA_FROM_DEVICE; - addr = dma_map_single(gi2c->se.dev->parent, dma_buf, msg->len, map_dirn); + addr = dma_map_single(gi2c->se.dev->parent, dma_buf, + msgs[msg_idx].len, map_dirn); if (dma_mapping_error(gi2c->se.dev->parent, addr)) { - i2c_put_dma_safe_msg_buf(dma_buf, msg, false); - return -ENOMEM; + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false); + ret = -ENOMEM; + goto out; + } + + if (gi2c->is_tx_multi_desc_xfer) { + flags = DMA_CTRL_ACK; + + /* BEI bit to be cleared for last TRE */ + if (msg_idx == gi2c->num_msgs - 1) + flags |= DMA_PREP_INTERRUPT; + } else { + flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; } /* set the length as message for rx txn */ - peripheral->rx_len = msg->len; + peripheral->rx_len = msgs[msg_idx].len; peripheral->op = op; ret = dmaengine_slave_config(dma_chan, config); @@ -567,14 +679,21 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, peripheral->set_config = 0; peripheral->multi_msg = true; - flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; if (op == I2C_WRITE) dma_dirn = DMA_MEM_TO_DEV; else dma_dirn = DMA_DEV_TO_MEM; - desc = dmaengine_prep_slave_single(dma_chan, addr, msg->len, dma_dirn, flags); + desc = dmaengine_prep_slave_single(dma_chan, addr, msgs[msg_idx].len, + dma_dirn, flags); + if (!desc && !(flags & DMA_PREP_INTERRUPT)) { + /* Retry with interrupt if not enough TREs */ + flags |= DMA_PREP_INTERRUPT; + desc = dmaengine_prep_slave_single(dma_chan, addr, msgs[msg_idx].len, + dma_dirn, flags); + } + if (!desc) { dev_err(gi2c->se.dev, "prep_slave_sg failed\n"); ret = -EIO; @@ -584,15 +703,48 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, desc->callback_result = i2c_gpi_cb_result; desc->callback_param = gi2c; - dmaengine_submit(desc); - *buf = dma_buf; - *dma_addr_p = addr; + if (!((msgs[msg_idx].flags & I2C_M_RD) && op == I2C_WRITE)) + gi2c_gpi_xfer->msg_idx_cnt++; + cookie = dmaengine_submit(desc); + if (dma_submit_error(cookie)) { + dev_err(gi2c->se.dev, + "%s: dmaengine_submit failed (%d)\n", __func__, cookie); + ret = -EINVAL; + goto err_config; + } + + if (gi2c->is_tx_multi_desc_xfer) { + gi2c_gpi_xfer->dma_buf[msg_idx] = dma_buf; + gi2c_gpi_xfer->dma_addr[msg_idx] = addr; + + dma_async_issue_pending(gi2c->tx_c); + + if ((msg_idx == (gi2c->num_msgs - 1)) || flags & DMA_PREP_INTERRUPT) { + ret = geni_i2c_gpi_multi_xfer_timeout_handler(gi2c->se.dev, gi2c_gpi_xfer, + XFER_TIMEOUT, &gi2c->done); + if (ret) { + dev_err(gi2c->se.dev, + "I2C multi write msg transfer timeout: %d\n", + ret); + gi2c->err = ret; + return ret; + } + } + } else { + /* Non multi descriptor message transfer */ + *buf = dma_buf; + *dma_addr_p = addr; + } return 0; err_config: - dma_unmap_single(gi2c->se.dev->parent, addr, msg->len, map_dirn); - i2c_put_dma_safe_msg_buf(dma_buf, msg, false); + dma_unmap_single(gi2c->se.dev->parent, addr, + msgs[msg_idx].len, map_dirn); + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false); + +out: + gi2c->err = ret; return ret; } @@ -604,6 +756,7 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i unsigned long time_left; dma_addr_t tx_addr, rx_addr; void *tx_buf = NULL, *rx_buf = NULL; + struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer; const struct geni_i2c_clk_fld *itr = gi2c->clk_fld; config.peripheral_config = &peripheral; @@ -617,6 +770,41 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i peripheral.set_config = 1; peripheral.multi_msg = false; + gi2c->num_msgs = num; + gi2c->is_tx_multi_desc_xfer = false; + + tx_multi_xfer = &gi2c->i2c_multi_desc_config; + memset(tx_multi_xfer, 0, sizeof(struct geni_i2c_gpi_multi_desc_xfer)); + + /* + * If number of write messages are two and higher then + * configure hardware for multi descriptor transfers with BEI. + */ + if (num >= QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC) { + gi2c->is_tx_multi_desc_xfer = true; + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) { + /* + * Multi descriptor transfer with BEI + * support is enabled for write transfers. + * TODO: Add BEI optimization support for + * read transfers later. + */ + gi2c->is_tx_multi_desc_xfer = false; + break; + } + } + } + + if (gi2c->is_tx_multi_desc_xfer) { + tx_multi_xfer->dma_buf = kcalloc(num, sizeof(void *), GFP_KERNEL); + tx_multi_xfer->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_KERNEL); + if (!tx_multi_xfer->dma_buf || !tx_multi_xfer->dma_addr) { + ret = -ENOMEM; + goto err; + } + } + for (i = 0; i < num; i++) { gi2c->cur = &msgs[i]; gi2c->err = 0; @@ -627,14 +815,16 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i peripheral.stretch = 1; peripheral.addr = msgs[i].addr; + if (i > 0 && (!(msgs[i].flags & I2C_M_RD))) + peripheral.multi_msg = false; - ret = geni_i2c_gpi(gi2c, &msgs[i], &config, + ret = geni_i2c_gpi(gi2c, msgs, &config, &tx_addr, &tx_buf, I2C_WRITE, gi2c->tx_c); if (ret) goto err; if (msgs[i].flags & I2C_M_RD) { - ret = geni_i2c_gpi(gi2c, &msgs[i], &config, + ret = geni_i2c_gpi(gi2c, msgs, &config, &rx_addr, &rx_buf, I2C_READ, gi2c->rx_c); if (ret) goto err; @@ -642,18 +832,24 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i dma_async_issue_pending(gi2c->rx_c); } - dma_async_issue_pending(gi2c->tx_c); - - time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); - if (!time_left) - gi2c->err = -ETIMEDOUT; + if (!gi2c->is_tx_multi_desc_xfer) { + dma_async_issue_pending(gi2c->tx_c); + time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); + if (!time_left) { + dev_err(gi2c->se.dev, "%s:I2C timeout\n", __func__); + gi2c->err = -ETIMEDOUT; + } + } if (gi2c->err) { ret = gi2c->err; goto err; } - geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr); + if (!gi2c->is_tx_multi_desc_xfer) + geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr); + else if (tx_multi_xfer->unmap_msg_cnt != tx_multi_xfer->irq_cnt) + geni_i2c_gpi_multi_desc_unmap(gi2c, msgs, &peripheral); } return num; @@ -662,7 +858,11 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i dev_err(gi2c->se.dev, "GPI transfer failed: %d\n", ret); dmaengine_terminate_sync(gi2c->rx_c); dmaengine_terminate_sync(gi2c->tx_c); - geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr); + if (gi2c->is_tx_multi_desc_xfer) + geni_i2c_gpi_multi_desc_unmap(gi2c, msgs, &peripheral); + else + geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr); + return ret; } From 8abe970efea56f44773713cf91032cd2fd4d8c01 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 3 Oct 2025 20:14:39 +0200 Subject: [PATCH 081/684] clk: qcom: gcc-x1e80100: Add missing USB4 clocks/resets Currently, some of the USB4 clocks/resets are described, but not all of the back-end muxes are present. Configuring them properly is necessary for proper operation of the hardware. Add all the resets & muxes and wire up any unaccounted USB4 clock paths. Fixes: 161b7c401f4b ("clk: qcom: Add Global Clock controller (GCC) driver for X1E80100") Reviewed-by: Bryan O'Donoghue Signed-off-by: Konrad Dybcio Reviewed-by: Taniya Das Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251003-topic-hamoa_gcc_usb4-v2-2-61d27a14ee65@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-x1e80100.c | 698 +++++++++++++++++++++++++++++++- 1 file changed, 681 insertions(+), 17 deletions(-) diff --git a/drivers/clk/qcom/gcc-x1e80100.c b/drivers/clk/qcom/gcc-x1e80100.c index 301fc9fc32d8e6..8804ad5d70be0b 100644 --- a/drivers/clk/qcom/gcc-x1e80100.c +++ b/drivers/clk/qcom/gcc-x1e80100.c @@ -32,6 +32,33 @@ enum { DT_USB3_PHY_0_WRAPPER_GCC_USB30_PIPE, DT_USB3_PHY_1_WRAPPER_GCC_USB30_PIPE, DT_USB3_PHY_2_WRAPPER_GCC_USB30_PIPE, + DT_GCC_USB4_0_PHY_DP0_GMUX_CLK_SRC, + DT_GCC_USB4_0_PHY_DP1_GMUX_CLK_SRC, + DT_GCC_USB4_0_PHY_PCIE_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_0_PHY_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_0_PHY_SYS_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_DP0_GMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_DP1_GMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_2_PHY_DP0_GMUX_CLK_SRC, + DT_GCC_USB4_2_PHY_DP1_GMUX_CLK_SRC, + DT_GCC_USB4_2_PHY_PCIE_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_2_PHY_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_2_PHY_SYS_PIPEGMUX_CLK_SRC, + DT_QUSB4PHY_0_GCC_USB4_RX0_CLK, + DT_QUSB4PHY_0_GCC_USB4_RX1_CLK, + DT_QUSB4PHY_1_GCC_USB4_RX0_CLK, + DT_QUSB4PHY_1_GCC_USB4_RX1_CLK, + DT_QUSB4PHY_2_GCC_USB4_RX0_CLK, + DT_QUSB4PHY_2_GCC_USB4_RX1_CLK, + DT_USB4_0_PHY_GCC_USB4_PCIE_PIPE_CLK, + DT_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, + DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + DT_USB4_2_PHY_GCC_USB4_PCIE_PIPE_CLK, + DT_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK, }; enum { @@ -42,10 +69,40 @@ enum { P_GCC_GPLL7_OUT_MAIN, P_GCC_GPLL8_OUT_MAIN, P_GCC_GPLL9_OUT_MAIN, + P_GCC_USB3_PRIM_PHY_PIPE_CLK_SRC, + P_GCC_USB3_SEC_PHY_PIPE_CLK_SRC, + P_GCC_USB3_TERT_PHY_PIPE_CLK_SRC, + P_GCC_USB4_0_PHY_DP0_GMUX_CLK_SRC, + P_GCC_USB4_0_PHY_DP1_GMUX_CLK_SRC, + P_GCC_USB4_0_PHY_PCIE_PIPEGMUX_CLK_SRC, + P_GCC_USB4_0_PHY_PIPEGMUX_CLK_SRC, + P_GCC_USB4_0_PHY_SYS_PIPEGMUX_CLK_SRC, + P_GCC_USB4_1_PHY_DP0_GMUX_CLK_SRC, + P_GCC_USB4_1_PHY_DP1_GMUX_CLK_SRC, + P_GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC, + P_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, + P_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, + P_GCC_USB4_2_PHY_DP0_GMUX_CLK_SRC, + P_GCC_USB4_2_PHY_DP1_GMUX_CLK_SRC, + P_GCC_USB4_2_PHY_PCIE_PIPEGMUX_CLK_SRC, + P_GCC_USB4_2_PHY_PIPEGMUX_CLK_SRC, + P_GCC_USB4_2_PHY_SYS_PIPEGMUX_CLK_SRC, + P_QUSB4PHY_0_GCC_USB4_RX0_CLK, + P_QUSB4PHY_0_GCC_USB4_RX1_CLK, + P_QUSB4PHY_1_GCC_USB4_RX0_CLK, + P_QUSB4PHY_1_GCC_USB4_RX1_CLK, + P_QUSB4PHY_2_GCC_USB4_RX0_CLK, + P_QUSB4PHY_2_GCC_USB4_RX1_CLK, P_SLEEP_CLK, P_USB3_PHY_0_WRAPPER_GCC_USB30_PIPE_CLK, P_USB3_PHY_1_WRAPPER_GCC_USB30_PIPE_CLK, P_USB3_PHY_2_WRAPPER_GCC_USB30_PIPE_CLK, + P_USB4_0_PHY_GCC_USB4_PCIE_PIPE_CLK, + P_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + P_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, + P_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + P_USB4_2_PHY_GCC_USB4_PCIE_PIPE_CLK, + P_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK, }; static struct clk_alpha_pll gcc_gpll0 = { @@ -320,6 +377,342 @@ static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { { } }; +static const struct clk_parent_data gcc_parent_data_13[] = { + { .index = DT_GCC_USB4_0_PHY_DP0_GMUX_CLK_SRC }, + { .index = DT_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .index = DT_GCC_USB4_0_PHY_DP1_GMUX_CLK_SRC }, + { .index = DT_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_15[] = { + { .index = DT_USB4_0_PHY_GCC_USB4_PCIE_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_16[] = { + { .index = DT_GCC_USB4_0_PHY_PCIE_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_0_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_17[] = { + { .index = DT_QUSB4PHY_0_GCC_USB4_RX0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_18[] = { + { .index = DT_QUSB4PHY_0_GCC_USB4_RX1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_19[] = { + { .index = DT_GCC_USB4_0_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_0_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_20[] = { + { .index = DT_GCC_USB4_1_PHY_DP0_GMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_21[] = { + { .index = DT_GCC_USB4_1_PHY_DP1_GMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_22[] = { + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_23[] = { + { .index = DT_GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_24[] = { + { .index = DT_QUSB4PHY_1_GCC_USB4_RX0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_25[] = { + { .index = DT_QUSB4PHY_1_GCC_USB4_RX1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_26[] = { + { .index = DT_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_27[] = { + { .index = DT_GCC_USB4_2_PHY_DP0_GMUX_CLK_SRC }, + { .index = DT_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_28[] = { + { .index = DT_GCC_USB4_2_PHY_DP1_GMUX_CLK_SRC }, + { .index = DT_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_29[] = { + { .index = DT_USB4_2_PHY_GCC_USB4_PCIE_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_30[] = { + { .index = DT_GCC_USB4_2_PHY_PCIE_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_2_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct clk_parent_data gcc_parent_data_31[] = { + { .index = DT_QUSB4PHY_2_GCC_USB4_RX0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_32[] = { + { .index = DT_QUSB4PHY_2_GCC_USB4_RX1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct clk_parent_data gcc_parent_data_33[] = { + { .index = DT_GCC_USB4_2_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_2_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_dp0_clk_src = { + .reg = 0x9f06c, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_dp0_clk_src", + .parent_data = gcc_parent_data_13, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_dp1_clk_src = { + .reg = 0x9f114, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_dp1_clk_src", + .parent_data = gcc_parent_data_14, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_p2rr2p_pipe_clk_src = { + .reg = 0x9f0d4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_p2rr2p_pipe_clk_src", + .parent_data = gcc_parent_data_15, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_pcie_pipe_mux_clk_src = { + .reg = 0x9f104, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_pcie_pipe_mux_clk_src", + .parent_data = gcc_parent_data_16, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_rx0_clk_src = { + .reg = 0x9f0ac, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_rx0_clk_src", + .parent_data = gcc_parent_data_17, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_rx1_clk_src = { + .reg = 0x9f0bc, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_rx1_clk_src", + .parent_data = gcc_parent_data_18, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_0_phy_sys_clk_src = { + .reg = 0x9f0e4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_0_phy_sys_clk_src", + .parent_data = gcc_parent_data_19, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_dp0_clk_src = { + .reg = 0x2b06c, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_dp0_clk_src", + .parent_data = gcc_parent_data_20, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_dp1_clk_src = { + .reg = 0x2b114, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_dp1_clk_src", + .parent_data = gcc_parent_data_21, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_p2rr2p_pipe_clk_src = { + .reg = 0x2b0d4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_p2rr2p_pipe_clk_src", + .parent_data = gcc_parent_data_22, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_pcie_pipe_mux_clk_src = { + .reg = 0x2b104, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_pcie_pipe_mux_clk_src", + .parent_data = gcc_parent_data_23, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_rx0_clk_src = { + .reg = 0x2b0ac, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx0_clk_src", + .parent_data = gcc_parent_data_24, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_rx1_clk_src = { + .reg = 0x2b0bc, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx1_clk_src", + .parent_data = gcc_parent_data_25, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_1_phy_sys_clk_src = { + .reg = 0x2b0e4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_sys_clk_src", + .parent_data = gcc_parent_data_26, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_dp0_clk_src = { + .reg = 0x1106c, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_dp0_clk_src", + .parent_data = gcc_parent_data_27, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_dp1_clk_src = { + .reg = 0x11114, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_dp1_clk_src", + .parent_data = gcc_parent_data_28, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_p2rr2p_pipe_clk_src = { + .reg = 0x110d4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_p2rr2p_pipe_clk_src", + .parent_data = gcc_parent_data_29, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_pcie_pipe_mux_clk_src = { + .reg = 0x11104, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_pcie_pipe_mux_clk_src", + .parent_data = gcc_parent_data_30, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_rx0_clk_src = { + .reg = 0x110ac, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_rx0_clk_src", + .parent_data = gcc_parent_data_31, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_rx1_clk_src = { + .reg = 0x110bc, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_rx1_clk_src", + .parent_data = gcc_parent_data_32, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb4_2_phy_sys_clk_src = { + .reg = 0x110e4, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_2_phy_sys_clk_src", + .parent_data = gcc_parent_data_33, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + static struct clk_rcg2 gcc_gp1_clk_src = { .cmd_rcgr = 0x64004, .mnd_width = 16, @@ -2790,6 +3183,11 @@ static struct clk_branch gcc_pcie_0_pipe_clk = { .enable_mask = BIT(25), .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie_0_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2879,6 +3277,11 @@ static struct clk_branch gcc_pcie_1_pipe_clk = { .enable_mask = BIT(30), .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie_1_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2968,6 +3371,11 @@ static struct clk_branch gcc_pcie_2_pipe_clk = { .enable_mask = BIT(23), .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie_2_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5156,6 +5564,33 @@ static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = { }, }; +static const struct parent_map gcc_parent_map_34[] = { + { P_GCC_USB3_PRIM_PHY_PIPE_CLK_SRC, 0 }, + { P_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 1 }, + { P_GCC_USB4_0_PHY_PIPEGMUX_CLK_SRC, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_34[] = { + { .hw = &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw }, + { .index = DT_USB4_0_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, + { .index = DT_GCC_USB4_0_PHY_PIPEGMUX_CLK_SRC }, +}; + +static struct clk_regmap_mux gcc_usb34_prim_phy_pipe_clk_src = { + .reg = 0x39070, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_34, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb34_prim_phy_pipe_clk_src", + .parent_data = gcc_parent_data_34, + .num_parents = ARRAY_SIZE(gcc_parent_data_34), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { .halt_reg = 0x39068, .halt_check = BRANCH_HALT_SKIP, @@ -5167,7 +5602,7 @@ static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { .hw.init = &(const struct clk_init_data) { .name = "gcc_usb3_prim_phy_pipe_clk", .parent_hws = (const struct clk_hw*[]) { - &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw, + &gcc_usb34_prim_phy_pipe_clk_src.clkr.hw, }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -5227,6 +5662,33 @@ static struct clk_regmap_mux gcc_usb3_sec_phy_pipe_clk_src = { }, }; +static const struct parent_map gcc_parent_map_35[] = { + { P_GCC_USB3_SEC_PHY_PIPE_CLK_SRC, 0 }, + { P_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 1 }, + { P_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_35[] = { + { .hw = &gcc_usb3_sec_phy_pipe_clk_src.clkr.hw }, + { .index = DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, + { .index = DT_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC }, +}; + +static struct clk_regmap_mux gcc_usb34_sec_phy_pipe_clk_src = { + .reg = 0xa1070, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_35, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb34_sec_phy_pipe_clk_src", + .parent_data = gcc_parent_data_35, + .num_parents = ARRAY_SIZE(gcc_parent_data_35), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { .halt_reg = 0xa1068, .halt_check = BRANCH_HALT_SKIP, @@ -5238,7 +5700,7 @@ static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { .hw.init = &(const struct clk_init_data) { .name = "gcc_usb3_sec_phy_pipe_clk", .parent_hws = (const struct clk_hw*[]) { - &gcc_usb3_sec_phy_pipe_clk_src.clkr.hw, + &gcc_usb34_sec_phy_pipe_clk_src.clkr.hw, }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -5298,6 +5760,33 @@ static struct clk_regmap_mux gcc_usb3_tert_phy_pipe_clk_src = { }, }; +static const struct parent_map gcc_parent_map_36[] = { + { P_GCC_USB3_TERT_PHY_PIPE_CLK_SRC, 0 }, + { P_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 1 }, + { P_GCC_USB4_2_PHY_PIPEGMUX_CLK_SRC, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_36[] = { + { .hw = &gcc_usb3_tert_phy_pipe_clk_src.clkr.hw }, + { .index = DT_USB4_2_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, + { .index = DT_GCC_USB4_2_PHY_PIPEGMUX_CLK_SRC }, +}; + +static struct clk_regmap_mux gcc_usb34_tert_phy_pipe_clk_src = { + .reg = 0xa2070, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_36, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb34_tert_phy_pipe_clk_src", + .parent_data = gcc_parent_data_36, + .num_parents = ARRAY_SIZE(gcc_parent_data_36), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + static struct clk_branch gcc_usb3_tert_phy_pipe_clk = { .halt_reg = 0xa2068, .halt_check = BRANCH_HALT_SKIP, @@ -5309,7 +5798,7 @@ static struct clk_branch gcc_usb3_tert_phy_pipe_clk = { .hw.init = &(const struct clk_init_data) { .name = "gcc_usb3_tert_phy_pipe_clk", .parent_hws = (const struct clk_hw*[]) { - &gcc_usb3_tert_phy_pipe_clk_src.clkr.hw, + &gcc_usb34_tert_phy_pipe_clk_src.clkr.hw, }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -5335,12 +5824,17 @@ static struct clk_branch gcc_usb4_0_cfg_ahb_clk = { static struct clk_branch gcc_usb4_0_dp0_clk = { .halt_reg = 0x9f060, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x9f060, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_dp0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_dp0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5348,12 +5842,17 @@ static struct clk_branch gcc_usb4_0_dp0_clk = { static struct clk_branch gcc_usb4_0_dp1_clk = { .halt_reg = 0x9f108, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x9f108, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_dp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_dp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5385,6 +5884,11 @@ static struct clk_branch gcc_usb4_0_phy_p2rr2p_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_phy_p2rr2p_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_p2rr2p_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5398,6 +5902,11 @@ static struct clk_branch gcc_usb4_0_phy_pcie_pipe_clk = { .enable_mask = BIT(19), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_phy_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5405,12 +5914,17 @@ static struct clk_branch gcc_usb4_0_phy_pcie_pipe_clk = { static struct clk_branch gcc_usb4_0_phy_rx0_clk = { .halt_reg = 0x9f0b0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x9f0b0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_phy_rx0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_rx0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5418,12 +5932,17 @@ static struct clk_branch gcc_usb4_0_phy_rx0_clk = { static struct clk_branch gcc_usb4_0_phy_rx1_clk = { .halt_reg = 0x9f0c0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x9f0c0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_phy_rx1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_rx1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5439,6 +5958,11 @@ static struct clk_branch gcc_usb4_0_phy_usb_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_phy_usb_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb34_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5470,6 +5994,11 @@ static struct clk_branch gcc_usb4_0_sys_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_0_sys_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_0_phy_sys_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5512,12 +6041,17 @@ static struct clk_branch gcc_usb4_1_cfg_ahb_clk = { static struct clk_branch gcc_usb4_1_dp0_clk = { .halt_reg = 0x2b060, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2b060, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_dp0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_dp0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5525,12 +6059,17 @@ static struct clk_branch gcc_usb4_1_dp0_clk = { static struct clk_branch gcc_usb4_1_dp1_clk = { .halt_reg = 0x2b108, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2b108, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_dp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_dp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5562,6 +6101,11 @@ static struct clk_branch gcc_usb4_1_phy_p2rr2p_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_phy_p2rr2p_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_p2rr2p_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5575,6 +6119,11 @@ static struct clk_branch gcc_usb4_1_phy_pcie_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_phy_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5582,12 +6131,17 @@ static struct clk_branch gcc_usb4_1_phy_pcie_pipe_clk = { static struct clk_branch gcc_usb4_1_phy_rx0_clk = { .halt_reg = 0x2b0b0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2b0b0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_phy_rx0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_rx0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5595,12 +6149,17 @@ static struct clk_branch gcc_usb4_1_phy_rx0_clk = { static struct clk_branch gcc_usb4_1_phy_rx1_clk = { .halt_reg = 0x2b0c0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2b0c0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_phy_rx1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_rx1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5616,6 +6175,11 @@ static struct clk_branch gcc_usb4_1_phy_usb_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_phy_usb_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb34_sec_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5647,6 +6211,11 @@ static struct clk_branch gcc_usb4_1_sys_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_1_sys_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_1_phy_sys_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5689,12 +6258,17 @@ static struct clk_branch gcc_usb4_2_cfg_ahb_clk = { static struct clk_branch gcc_usb4_2_dp0_clk = { .halt_reg = 0x11060, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x11060, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_dp0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_dp0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5702,12 +6276,17 @@ static struct clk_branch gcc_usb4_2_dp0_clk = { static struct clk_branch gcc_usb4_2_dp1_clk = { .halt_reg = 0x11108, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x11108, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_dp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_dp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5739,6 +6318,11 @@ static struct clk_branch gcc_usb4_2_phy_p2rr2p_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_phy_p2rr2p_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_p2rr2p_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5752,6 +6336,11 @@ static struct clk_branch gcc_usb4_2_phy_pcie_pipe_clk = { .enable_mask = BIT(1), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_phy_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5759,12 +6348,17 @@ static struct clk_branch gcc_usb4_2_phy_pcie_pipe_clk = { static struct clk_branch gcc_usb4_2_phy_rx0_clk = { .halt_reg = 0x110b0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x110b0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_phy_rx0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_rx0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5772,12 +6366,17 @@ static struct clk_branch gcc_usb4_2_phy_rx0_clk = { static struct clk_branch gcc_usb4_2_phy_rx1_clk = { .halt_reg = 0x110c0, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x110c0, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_phy_rx1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb4_2_phy_rx1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -5793,6 +6392,11 @@ static struct clk_branch gcc_usb4_2_phy_usb_pipe_clk = { .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "gcc_usb4_2_phy_usb_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb34_tert_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -6483,6 +7087,9 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { [GCC_USB30_TERT_MOCK_UTMI_CLK_SRC] = &gcc_usb30_tert_mock_utmi_clk_src.clkr, [GCC_USB30_TERT_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_tert_mock_utmi_postdiv_clk_src.clkr, [GCC_USB30_TERT_SLEEP_CLK] = &gcc_usb30_tert_sleep_clk.clkr, + [GCC_USB34_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb34_prim_phy_pipe_clk_src.clkr, + [GCC_USB34_SEC_PHY_PIPE_CLK_SRC] = &gcc_usb34_sec_phy_pipe_clk_src.clkr, + [GCC_USB34_TERT_PHY_PIPE_CLK_SRC] = &gcc_usb34_tert_phy_pipe_clk_src.clkr, [GCC_USB3_MP_PHY_AUX_CLK] = &gcc_usb3_mp_phy_aux_clk.clkr, [GCC_USB3_MP_PHY_AUX_CLK_SRC] = &gcc_usb3_mp_phy_aux_clk_src.clkr, [GCC_USB3_MP_PHY_COM_AUX_CLK] = &gcc_usb3_mp_phy_com_aux_clk.clkr, @@ -6508,11 +7115,18 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { [GCC_USB4_0_DP1_CLK] = &gcc_usb4_0_dp1_clk.clkr, [GCC_USB4_0_MASTER_CLK] = &gcc_usb4_0_master_clk.clkr, [GCC_USB4_0_MASTER_CLK_SRC] = &gcc_usb4_0_master_clk_src.clkr, + [GCC_USB4_0_PHY_DP0_CLK_SRC] = &gcc_usb4_0_phy_dp0_clk_src.clkr, + [GCC_USB4_0_PHY_DP1_CLK_SRC] = &gcc_usb4_0_phy_dp1_clk_src.clkr, [GCC_USB4_0_PHY_P2RR2P_PIPE_CLK] = &gcc_usb4_0_phy_p2rr2p_pipe_clk.clkr, + [GCC_USB4_0_PHY_P2RR2P_PIPE_CLK_SRC] = &gcc_usb4_0_phy_p2rr2p_pipe_clk_src.clkr, [GCC_USB4_0_PHY_PCIE_PIPE_CLK] = &gcc_usb4_0_phy_pcie_pipe_clk.clkr, [GCC_USB4_0_PHY_PCIE_PIPE_CLK_SRC] = &gcc_usb4_0_phy_pcie_pipe_clk_src.clkr, + [GCC_USB4_0_PHY_PCIE_PIPE_MUX_CLK_SRC] = &gcc_usb4_0_phy_pcie_pipe_mux_clk_src.clkr, [GCC_USB4_0_PHY_RX0_CLK] = &gcc_usb4_0_phy_rx0_clk.clkr, + [GCC_USB4_0_PHY_RX0_CLK_SRC] = &gcc_usb4_0_phy_rx0_clk_src.clkr, [GCC_USB4_0_PHY_RX1_CLK] = &gcc_usb4_0_phy_rx1_clk.clkr, + [GCC_USB4_0_PHY_RX1_CLK_SRC] = &gcc_usb4_0_phy_rx1_clk_src.clkr, + [GCC_USB4_0_PHY_SYS_CLK_SRC] = &gcc_usb4_0_phy_sys_clk_src.clkr, [GCC_USB4_0_PHY_USB_PIPE_CLK] = &gcc_usb4_0_phy_usb_pipe_clk.clkr, [GCC_USB4_0_SB_IF_CLK] = &gcc_usb4_0_sb_if_clk.clkr, [GCC_USB4_0_SB_IF_CLK_SRC] = &gcc_usb4_0_sb_if_clk_src.clkr, @@ -6524,11 +7138,18 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { [GCC_USB4_1_DP1_CLK] = &gcc_usb4_1_dp1_clk.clkr, [GCC_USB4_1_MASTER_CLK] = &gcc_usb4_1_master_clk.clkr, [GCC_USB4_1_MASTER_CLK_SRC] = &gcc_usb4_1_master_clk_src.clkr, + [GCC_USB4_1_PHY_DP0_CLK_SRC] = &gcc_usb4_1_phy_dp0_clk_src.clkr, + [GCC_USB4_1_PHY_DP1_CLK_SRC] = &gcc_usb4_1_phy_dp1_clk_src.clkr, [GCC_USB4_1_PHY_P2RR2P_PIPE_CLK] = &gcc_usb4_1_phy_p2rr2p_pipe_clk.clkr, + [GCC_USB4_1_PHY_P2RR2P_PIPE_CLK_SRC] = &gcc_usb4_1_phy_p2rr2p_pipe_clk_src.clkr, [GCC_USB4_1_PHY_PCIE_PIPE_CLK] = &gcc_usb4_1_phy_pcie_pipe_clk.clkr, [GCC_USB4_1_PHY_PCIE_PIPE_CLK_SRC] = &gcc_usb4_1_phy_pcie_pipe_clk_src.clkr, + [GCC_USB4_1_PHY_PCIE_PIPE_MUX_CLK_SRC] = &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr, [GCC_USB4_1_PHY_RX0_CLK] = &gcc_usb4_1_phy_rx0_clk.clkr, + [GCC_USB4_1_PHY_RX0_CLK_SRC] = &gcc_usb4_1_phy_rx0_clk_src.clkr, [GCC_USB4_1_PHY_RX1_CLK] = &gcc_usb4_1_phy_rx1_clk.clkr, + [GCC_USB4_1_PHY_RX1_CLK_SRC] = &gcc_usb4_1_phy_rx1_clk_src.clkr, + [GCC_USB4_1_PHY_SYS_CLK_SRC] = &gcc_usb4_1_phy_sys_clk_src.clkr, [GCC_USB4_1_PHY_USB_PIPE_CLK] = &gcc_usb4_1_phy_usb_pipe_clk.clkr, [GCC_USB4_1_SB_IF_CLK] = &gcc_usb4_1_sb_if_clk.clkr, [GCC_USB4_1_SB_IF_CLK_SRC] = &gcc_usb4_1_sb_if_clk_src.clkr, @@ -6540,11 +7161,18 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { [GCC_USB4_2_DP1_CLK] = &gcc_usb4_2_dp1_clk.clkr, [GCC_USB4_2_MASTER_CLK] = &gcc_usb4_2_master_clk.clkr, [GCC_USB4_2_MASTER_CLK_SRC] = &gcc_usb4_2_master_clk_src.clkr, + [GCC_USB4_2_PHY_DP0_CLK_SRC] = &gcc_usb4_2_phy_dp0_clk_src.clkr, + [GCC_USB4_2_PHY_DP1_CLK_SRC] = &gcc_usb4_2_phy_dp1_clk_src.clkr, [GCC_USB4_2_PHY_P2RR2P_PIPE_CLK] = &gcc_usb4_2_phy_p2rr2p_pipe_clk.clkr, + [GCC_USB4_2_PHY_P2RR2P_PIPE_CLK_SRC] = &gcc_usb4_2_phy_p2rr2p_pipe_clk_src.clkr, [GCC_USB4_2_PHY_PCIE_PIPE_CLK] = &gcc_usb4_2_phy_pcie_pipe_clk.clkr, [GCC_USB4_2_PHY_PCIE_PIPE_CLK_SRC] = &gcc_usb4_2_phy_pcie_pipe_clk_src.clkr, + [GCC_USB4_2_PHY_PCIE_PIPE_MUX_CLK_SRC] = &gcc_usb4_2_phy_pcie_pipe_mux_clk_src.clkr, [GCC_USB4_2_PHY_RX0_CLK] = &gcc_usb4_2_phy_rx0_clk.clkr, + [GCC_USB4_2_PHY_RX0_CLK_SRC] = &gcc_usb4_2_phy_rx0_clk_src.clkr, [GCC_USB4_2_PHY_RX1_CLK] = &gcc_usb4_2_phy_rx1_clk.clkr, + [GCC_USB4_2_PHY_RX1_CLK_SRC] = &gcc_usb4_2_phy_rx1_clk_src.clkr, + [GCC_USB4_2_PHY_SYS_CLK_SRC] = &gcc_usb4_2_phy_sys_clk_src.clkr, [GCC_USB4_2_PHY_USB_PIPE_CLK] = &gcc_usb4_2_phy_usb_pipe_clk.clkr, [GCC_USB4_2_SB_IF_CLK] = &gcc_usb4_2_sb_if_clk.clkr, [GCC_USB4_2_SB_IF_CLK_SRC] = &gcc_usb4_2_sb_if_clk_src.clkr, @@ -6660,16 +7288,52 @@ static const struct qcom_reset_map gcc_x1e80100_resets[] = { [GCC_USB3_UNIPHY_MP0_BCR] = { 0x19000 }, [GCC_USB3_UNIPHY_MP1_BCR] = { 0x54000 }, [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB4PHY_PHY_PRIM_BCR] = { 0x5000c }, [GCC_USB3PHY_PHY_SEC_BCR] = { 0x2a004 }, + [GCC_USB4PHY_PHY_SEC_BCR] = { 0x2a00c }, [GCC_USB3PHY_PHY_TERT_BCR] = { 0xa3004 }, + [GCC_USB4PHY_PHY_TERT_BCR] = { 0xa300c }, [GCC_USB3UNIPHY_PHY_MP0_BCR] = { 0x19004 }, [GCC_USB3UNIPHY_PHY_MP1_BCR] = { 0x54004 }, [GCC_USB4_0_BCR] = { 0x9f000 }, [GCC_USB4_0_DP0_PHY_PRIM_BCR] = { 0x50010 }, - [GCC_USB4_1_DP0_PHY_SEC_BCR] = { 0x2a010 }, - [GCC_USB4_2_DP0_PHY_TERT_BCR] = { 0xa3010 }, + [GCC_USB4_0_MISC_USB4_SYS_BCR] = { .reg = 0xad0f8, .bit = 0 }, + [GCC_USB4_0_MISC_RX_CLK_0_BCR] = { .reg = 0xad0f8, .bit = 1 }, + [GCC_USB4_0_MISC_RX_CLK_1_BCR] = { .reg = 0xad0f8, .bit = 2 }, + [GCC_USB4_0_MISC_USB_PIPE_BCR] = { .reg = 0xad0f8, .bit = 3 }, + [GCC_USB4_0_MISC_PCIE_PIPE_BCR] = { .reg = 0xad0f8, .bit = 4 }, + [GCC_USB4_0_MISC_TMU_BCR] = { .reg = 0xad0f8, .bit = 5 }, + [GCC_USB4_0_MISC_SB_IF_BCR] = { .reg = 0xad0f8, .bit = 6 }, + [GCC_USB4_0_MISC_HIA_MSTR_BCR] = { .reg = 0xad0f8, .bit = 7 }, + [GCC_USB4_0_MISC_AHB_BCR] = { .reg = 0xad0f8, .bit = 8 }, + [GCC_USB4_0_MISC_DP0_MAX_PCLK_BCR] = { .reg = 0xad0f8, .bit = 9 }, + [GCC_USB4_0_MISC_DP1_MAX_PCLK_BCR] = { .reg = 0xad0f8, .bit = 10 }, [GCC_USB4_1_BCR] = { 0x2b000 }, + [GCC_USB4_1_DP0_PHY_SEC_BCR] = { 0x2a010 }, + [GCC_USB4_1_MISC_USB4_SYS_BCR] = { .reg = 0xae0f8, .bit = 0 }, + [GCC_USB4_1_MISC_RX_CLK_0_BCR] = { .reg = 0xae0f8, .bit = 1 }, + [GCC_USB4_1_MISC_RX_CLK_1_BCR] = { .reg = 0xae0f8, .bit = 2 }, + [GCC_USB4_1_MISC_USB_PIPE_BCR] = { .reg = 0xae0f8, .bit = 3 }, + [GCC_USB4_1_MISC_PCIE_PIPE_BCR] = { .reg = 0xae0f8, .bit = 4 }, + [GCC_USB4_1_MISC_TMU_BCR] = { .reg = 0xae0f8, .bit = 5 }, + [GCC_USB4_1_MISC_SB_IF_BCR] = { .reg = 0xae0f8, .bit = 6 }, + [GCC_USB4_1_MISC_HIA_MSTR_BCR] = { .reg = 0xae0f8, .bit = 7 }, + [GCC_USB4_1_MISC_AHB_BCR] = { .reg = 0xae0f8, .bit = 8 }, + [GCC_USB4_1_MISC_DP0_MAX_PCLK_BCR] = { .reg = 0xae0f8, .bit = 9 }, + [GCC_USB4_1_MISC_DP1_MAX_PCLK_BCR] = { .reg = 0xae0f8, .bit = 10 }, [GCC_USB4_2_BCR] = { 0x11000 }, + [GCC_USB4_2_DP0_PHY_TERT_BCR] = { 0xa3010 }, + [GCC_USB4_2_MISC_USB4_SYS_BCR] = { .reg = 0xaf0f8, .bit = 0 }, + [GCC_USB4_2_MISC_RX_CLK_0_BCR] = { .reg = 0xaf0f8, .bit = 1 }, + [GCC_USB4_2_MISC_RX_CLK_1_BCR] = { .reg = 0xaf0f8, .bit = 2 }, + [GCC_USB4_2_MISC_USB_PIPE_BCR] = { .reg = 0xaf0f8, .bit = 3 }, + [GCC_USB4_2_MISC_PCIE_PIPE_BCR] = { .reg = 0xaf0f8, .bit = 4 }, + [GCC_USB4_2_MISC_TMU_BCR] = { .reg = 0xaf0f8, .bit = 5 }, + [GCC_USB4_2_MISC_SB_IF_BCR] = { .reg = 0xaf0f8, .bit = 6 }, + [GCC_USB4_2_MISC_HIA_MSTR_BCR] = { .reg = 0xaf0f8, .bit = 7 }, + [GCC_USB4_2_MISC_AHB_BCR] = { .reg = 0xaf0f8, .bit = 8 }, + [GCC_USB4_2_MISC_DP0_MAX_PCLK_BCR] = { .reg = 0xaf0f8, .bit = 9 }, + [GCC_USB4_2_MISC_DP1_MAX_PCLK_BCR] = { .reg = 0xaf0f8, .bit = 10 }, [GCC_USB_0_PHY_BCR] = { 0x50020 }, [GCC_USB_1_PHY_BCR] = { 0x2a020 }, [GCC_USB_2_PHY_BCR] = { 0xa3020 }, From d669ec6be0b1965c67248407d87c848b1b7c12ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Mon, 13 Oct 2025 06:27:16 +0100 Subject: [PATCH 082/684] clk: samsung: clk-pll: simplify samsung_pll_lock_wait() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit readl_relaxed_poll_timeout_atomic() has been updated in 2023 in commit 7349a69cf312 ("iopoll: Do not use timekeeping in read_poll_timeout_atomic()") to avoid usage of timekeeping APIs. It also never used udelay() when no delay was given. With the implementation avoiding timekeeping APIs, and with a caller not passing a delay, the timeout argument simply becomes a loop counter. Therefore the code here can be simplified to unconditionally use readl_relaxed_poll_timeout_atomic(). The difference being the last argument, the timeout (loop counter). Simply adjust it to pass the more generous counter in all cases. This change also allows us to drop all code around the pll_early_timeout variable as it is unused now. Reviewed-by: Sam Protsenko Signed-off-by: André Draszik Link: https://patch.msgid.link/20251013-samsung-clk-pll-simplification-v2-1-b9aab610878c@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-pll.c | 41 +++++++++-------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 7bea7be1d7e45c..0a8fc9649ae297 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,14 +11,12 @@ #include #include #include -#include #include #include #include "clk.h" #include "clk-pll.h" -#define PLL_TIMEOUT_US 20000U -#define PLL_TIMEOUT_LOOPS 1000000U +#define PLL_TIMEOUT_LOOPS 20000U struct samsung_clk_pll { struct clk_hw hw; @@ -71,20 +69,11 @@ static int samsung_pll_determine_rate(struct clk_hw *hw, return 0; } -static bool pll_early_timeout = true; - -static int __init samsung_pll_disable_early_timeout(void) -{ - pll_early_timeout = false; - return 0; -} -arch_initcall(samsung_pll_disable_early_timeout); - /* Wait until the PLL is locked */ static int samsung_pll_lock_wait(struct samsung_clk_pll *pll, unsigned int reg_mask) { - int i, ret; + int ret; u32 val; /* @@ -93,25 +82,15 @@ static int samsung_pll_lock_wait(struct samsung_clk_pll *pll, * initialized, another when the timekeeping is suspended. udelay() also * cannot be used when the clocksource is not running on arm64, since * the current timer is used as cycle counter. So a simple busy loop - * is used here in that special cases. The limit of iterations has been - * derived from experimental measurements of various PLLs on multiple - * Exynos SoC variants. Single register read time was usually in range - * 0.4...1.5 us, never less than 0.4 us. + * is used here. + * The limit of iterations has been derived from experimental + * measurements of various PLLs on multiple Exynos SoC variants. Single + * register read time was usually in range 0.4...1.5 us, never less than + * 0.4 us. */ - if (pll_early_timeout || timekeeping_suspended) { - i = PLL_TIMEOUT_LOOPS; - while (i-- > 0) { - if (readl_relaxed(pll->con_reg) & reg_mask) - return 0; - - cpu_relax(); - } - ret = -ETIMEDOUT; - } else { - ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val, - val & reg_mask, 0, PLL_TIMEOUT_US); - } - + ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val, + val & reg_mask, 0, + PLL_TIMEOUT_LOOPS); if (ret < 0) pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw)); From ad1a008bf0d01747a84e0090ac3aa6aa44ff8f54 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 17 Oct 2025 21:59:02 -0700 Subject: [PATCH 083/684] perf trace: Don't synthesize mmaps unless callchains are enabled Synthesizing mmaps in perf trace is unnecessary unless call chains are being generated. Signed-off-by: Ian Rogers Acked-by: Howard Chu Signed-off-by: Namhyung Kim --- tools/perf/builtin-trace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c607f39b8c8bb0..a743bda294bd34 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2005,7 +2005,9 @@ static int trace__symbols_init(struct trace *trace, int argc, const char **argv, err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, evlist->core.threads, trace__tool_process, - true, false, 1); + /*needs_mmap=*/callchain_param.enabled, + /*mmap_data=*/false, + /*nr_threads_synthesize=*/1); out: if (err) { perf_env__exit(&trace->host_env); From a3ef39eb975d4ba1bd1a29b7dcc4e76d6745b305 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 16 Oct 2025 15:22:26 -0700 Subject: [PATCH 084/684] perf ilist: Don't display deprecated events Unsupported legacy events are flagged as deprecated. Don't display these events in ilist as they won't open and there are over 1,000 legacy cache events. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/python/ilist.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py index 9d6465c60df316..69005a88872e99 100755 --- a/tools/perf/python/ilist.py +++ b/tools/perf/python/ilist.py @@ -439,6 +439,8 @@ def metric_event_tree() -> Tree: pmu_node = pmus.add(pmu_name) try: for event in sorted(pmu.events(), key=lambda x: x["name"]): + if "deprecated" in event: + continue if "name" in event: e = event["name"].lower() if "alias" in event: From 5960aab556c6b727e56b8446c813ff18fcc845d4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 16 Oct 2025 15:22:27 -0700 Subject: [PATCH 085/684] perf python: Add PMU argument to parse_metrics Add an optional PMU argument to parse_metrics to allow restriction of the particular metrics to be opened. If no argument is provided then all metrics with the given name/group are opened Signed-off-by: Ian Rogers Acked-by: Gautam Menghani Signed-off-by: Namhyung Kim --- tools/perf/util/python.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 779fe1280a5673..fa5e4270d18251 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -2051,7 +2051,7 @@ static PyObject *pyrf__parse_events(PyObject *self, PyObject *args) static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args) { - const char *input; + const char *input, *pmu = NULL; struct evlist evlist = {}; PyObject *result; PyObject *pcpus = NULL, *pthreads = NULL; @@ -2059,14 +2059,14 @@ static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args) struct perf_thread_map *threads; int ret; - if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) + if (!PyArg_ParseTuple(args, "s|sOO", &input, &pmu, &pcpus, &pthreads)) return NULL; threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL; cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; evlist__init(&evlist, cpus, threads); - ret = metricgroup__parse_groups(&evlist, /*pmu=*/"all", input, + ret = metricgroup__parse_groups(&evlist, pmu ?: "all", input, /*metric_no_group=*/ false, /*metric_no_merge=*/ false, /*metric_no_threshold=*/ true, From 98f3e85c475e6a118432671c210167c6176d6fcc Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 16 Oct 2025 15:22:28 -0700 Subject: [PATCH 086/684] perf ilist: Add PMU information to metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Duplicate metrics may exist on hybrid platforms, with the metric's PMU being used to select the metric to use. Incorporate the metric PMU into the ilist display and support opening it just for a given PMU. Before: ``` ⭘ Interactive Perf List ├── ▼ TopdownL1 tma_backend_bound │ ├── tma_backend_bound Counts the total number of issue slots that were │ ├── ▶ tma_backend_bound_group not consumed by the backend due to backend stalls │ ├── tma_backend_bound Counts the total number of issue slots that were │ ├── ▶ tma_backend_bound_group not consumed by the backend due to backend stalls. │ ├── tma_bad_speculation Note that uops must be available for consumption │ ├── ▶ tma_bad_speculation_group in order for this event to count. If a uop is not │ ├── tma_bad_speculation available (IQ is empty), this event will not count │ ├── ▶ tma_bad_speculation_group cpu_atom@TOPDOWN_BE_BOUND.ALL@ / (5 * │ ├── tma_frontend_bound cpu_atom@CPU_CLK_UNHALTED.CORE@) │ ├── ▶ tma_frontend_bound_group tma_backend_bound > 0.1 │ ├── tma_frontend_bound ▆▆ │ ├── ▶ tma_frontend_bound_group │ ├── tma_retiring │ ├── ▶ tma_retiring_group │ ├── tma_retiring │ └── ▶ tma_retiring_group ├── ▶ TopdownL2 total▄▄▅▅▆▅▅▂▁▁▁▁▂▃▂▂▃▄▄▇▇█▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▄▅▅▅▄▆▆▆▅▅▅▅▅▅▇▇▇▇▆▅▆▆▆▆▅▅▅▄▃▃▃▃▃▃▃▃▃▃▄▄▄▅▅▅▅▅▆▆▆▆▆▆ cpu0▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu1▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu2▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ cpu3▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄▄▄█████▆▆▆▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ cpu4████▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ cpu5▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▇▇▇▇▇▇▇▇▇▇▆▆ cpu6▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ cpu7▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu8▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu9▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂█████▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ cpu10▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu11▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇█████▁▁▁▁▁▁▁▁▁ cpu12▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu13▁▁▁▁▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu14▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇█████▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ cpu15▁▁▁▁▁▁▁▁▁▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu16▃▃▃▃▃▃▃▃▃▄▄▃▃▃▃▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▄▄▃▃▃▃▃▃▃▃▄▄▄▄▄▄▁▁▃▃▃▃▃▃▃▃▃▃▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ cpu17▁▁▁▁▁▄▄▅▅▅▅▅▅▅▅▄▄▄▄▄▄▄▄▃▃▃▃▂▂▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▄▄▄▄▃▃▃▃▂▂▂▂▄▄▄▄▄▄▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ s Search n Next p Previous c Collapse ^q Quit ▏^p palette ``` After: ``` ⭘ Interactive Perf List ├── ▼ TopdownL1 tma_backend_bound │ ├── tma_backend_bound (cpu_atom) Counts the total number of issue slots that were │ ├── ▼ tma_backend_bound_group (cpu_atom) not consumed by the backend due to backend stalls │ │ ├── tma_core_bound (cpu_atom) Counts the total number of issue slots that were │ │ ├── ▶ tma_core_bound_group (cpu_atom not consumed by the backend due to backend stalls. │ │ ├── tma_resource_bound (cpu_atom) Note that uops must be available for consumption │ │ └── ▶ tma_resource_bound_group (cpu_ in order for this event to count. If a uop is not │ ├── tma_backend_bound (cpu_core) available (IQ is empty), this event will not count │ ├── ▶ tma_backend_bound_group (cpu_core) cpu_atom@TOPDOWN_BE_BOUND.ALL@ / (5 * │ ├── tma_bad_speculation (cpu_atom) cpu_atom@CPU_CLK_UNHALTED.CORE@) │ ├── ▶ tma_bad_speculation_group (cpu_ato▆▆tma_backend_bound > 0.1 │ ├── tma_bad_speculation (cpu_core) │ ├── ▶ tma_bad_speculation_group (cpu_cor▃▃ │ ├── tma_frontend_bound (cpu_atom) │ ├── ▶ tma_frontend_bound_group (cpu_atom │ ├── tma_frontend_bound (cpu_core) │ ├── ▶ tma_frontend_bound_group (cpu_core ▌ total▁▁▁▁▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▂▂▂▂▃▃▃▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▄▄▄▄▄▄▅▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▆▇▇ cpu16▇▇▇▇▇▇▇▇▇▇▇▆▆▁▁▁▁▁▁▁▁▁▁▁▁▂▂▄▄▅▅▅▅▅▅▆▆▆▆▆▆▆▆▇▇▇▇▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▄▄▄▄▃▃▄▄▄▄▇▇▇▇▇▇▇▇▇▇ cpu17█▇▇▇▇▇▇▇▇▆▆▆▆▆▆▅▅▅▅▃▃▃▃▂▂▁▁▅▅▅▅▅▅▅▅▄▄▄▄▄▄▄▄▄▄▄▄▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▅▅▄▄▂▂▇▇▇▇▆▆▅▅▆▆ cpu18▇▇▇▇▇██▇▇▃▃▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▃▃▃▃▃▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▅▅▅▅▅▅▅▅ cpu19▇▃▃▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▁▁▂▂▃▃▃▃▅▅▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇██▇▇▇▇▇▇▆▆▅▅▅▅▆▆▄▄▄▄▅▅ cpu20▃▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▄▄▄▄▅▅▅▅▅▅▆▆▇▇ cpu21▇▇▇▇▇▇▇██▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▅▅▄▄▂▂▂▂▂▂▁▁▁▁ cpu22█▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▂▂▁▁▁▁▂▂▂▂▂▂▂▂ cpu23▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▃▄▄▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▇▇▇▇▆▆██▇▇▇▇▇▇ cpu24▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▅▅▇▇▆▆▆▆▆▆▇▇▇▇ cpu25▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▆▆▆▆▇▇▇▇▇▇██ cpu26▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▃▄▄▇▇▇▇▇▇▇▇▇▇██▇▇▇▇▇▇▇▇▇▇▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▆▆▆▆▆▆▆▆▆▆▂▂▁▁▁▁▂▂▂▂▂▂▂▂ cpu27▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▄▄▄▄▅▅▅▅▅▅▇▇ total 7.4923074548462605 cpu16 0.2961618003253457 cpu17 0.3065719718925585 cpu18 0.27800656881051855 cpu19 0.28564742078353406 cpu20 0.2764790653117084 s Search n Next p Previous c Collapse ^q Quit ▏^p palette ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/python/ilist.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py index 69005a88872e99..eb687ce9d5a6af 100755 --- a/tools/perf/python/ilist.py +++ b/tools/perf/python/ilist.py @@ -51,6 +51,7 @@ def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) - class Metric(TreeValue): """A metric in the tree.""" metric_name: str + metric_pmu: str def name(self) -> str: return self.metric_name @@ -60,6 +61,8 @@ def description(self) -> str: for metric in perf.metrics(): if metric["MetricName"] != self.metric_name: continue + if self.metric_pmu and metric["PMU"] != self.metric_pmu: + continue desc = get_info(metric, "BriefDescription") desc += get_info(metric, "PublicDescription") desc += get_info(metric, "MetricExpr") @@ -71,7 +74,7 @@ def matches(self, query: str) -> bool: return query in self.metric_name def parse(self) -> perf.evlist: - return perf.parse_metrics(self.metric_name) + return perf.parse_metrics(self.metric_name, self.metric_pmu) def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) -> float: val = evlist.compute_metric(self.metric_name, cpu, thread) @@ -456,14 +459,25 @@ def metric_event_tree() -> Tree: for metric in perf.metrics(): groups.update(metric["MetricGroup"]) - def add_metrics_to_tree(node: TreeNode[TreeValue], parent: str): + def add_metrics_to_tree(node: TreeNode[TreeValue], parent: str, pmu: str = None): for metric in sorted(perf.metrics(), key=lambda x: x["MetricName"]): + metric_pmu = metric.get('PMU') + if pmu and metric_pmu and metric_pmu != pmu: + continue if parent in metric["MetricGroup"]: name = metric["MetricName"] - node.add_leaf(name, data=Metric(name)) + display_name = name + if metric_pmu: + display_name += f" ({metric_pmu})" + node.add_leaf(display_name, data=Metric(name, metric_pmu)) child_group_name = f'{name}_group' if child_group_name in groups: - add_metrics_to_tree(node.add(child_group_name), child_group_name) + display_child_group_name = child_group_name + if metric_pmu: + display_child_group_name += f" ({metric_pmu})" + add_metrics_to_tree(node.add(display_child_group_name), + child_group_name, + metric_pmu) for group in sorted(groups): if group.endswith('_group'): From b8308511f6e090db769e35b958e2fb9714e5456f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 16 Oct 2025 08:07:18 -0700 Subject: [PATCH 087/684] perf stat bperf cgroup: Increase MAX_EVENTS from 32 to 1024 The MAX_EVENTS value ensured a counted loop presumably to satisfy the BPF verifier. It is possible to go past 32 events when gathering uncore events. Increase the amount to 1024 as that should provide some amount of headroom. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/bpf_skel/bperf_cgroup.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c b/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c index 57cab7647a9ad7..18ab4d9b49ffbd 100644 --- a/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c +++ b/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c @@ -7,7 +7,7 @@ #include #define MAX_LEVELS 10 // max cgroup hierarchy level: arbitrary -#define MAX_EVENTS 32 // max events per cgroup: arbitrary +#define MAX_EVENTS 1024 // max events per cgroup: arbitrary // NOTE: many of map and global data will be modified before loading // from the userspace (perf tool) using the skeleton helpers. From cd3466cd2639783da563253f1f9e3fb2ba936317 Mon Sep 17 00:00:00 2001 From: Tianyou Li Date: Mon, 13 Oct 2025 22:48:10 +0800 Subject: [PATCH 088/684] perf c2c: Add annotation support to perf c2c report Perf c2c report currently specified the code address and source:line information in the cacheline browser, while it is lack of annotation support like perf report to directly show the disassembly code for the particular symbol shared that same cacheline. This patches add a key 'a' binding to the cacheline browser which reuse the annotation browser to show the disassembly view for easier analysis of cacheline contentions. Signed-off-by: Tianyou Li Reviewed-by: Dapeng Mi Reviewed-by: Thomas Falcon Reviewed-by: Jiebin Sun Reviewed-by: Pan Deng Reviewed-by: Zhiguo Zhou Reviewed-by: Wangyang Guo Tested-by: Ravi Bangoria Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-c2c.txt | 7 ++ tools/perf/builtin-c2c.c | 155 +++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 5 deletions(-) diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt index f4af2dd6ab3185..40b0f71a2c44eb 100644 --- a/tools/perf/Documentation/perf-c2c.txt +++ b/tools/perf/Documentation/perf-c2c.txt @@ -143,6 +143,13 @@ REPORT OPTIONS feature, which causes cacheline sharing to behave like the cacheline size is doubled. +-M:: +--disassembler-style=:: + Set disassembler style for objdump. + +--objdump=:: + Path to objdump binary. + C2C RECORD ---------- The perf c2c record command setup options related to HITM cacheline analysis diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 9e9ff471ddd16e..a37e886ff3d753 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -45,6 +45,8 @@ #include "pmus.h" #include "string2.h" #include "util/util.h" +#include "util/symbol.h" +#include "util/annotate.h" struct c2c_hists { struct hists hists; @@ -62,6 +64,7 @@ struct compute_stats { struct c2c_hist_entry { struct c2c_hists *hists; + struct evsel *evsel; struct c2c_stats stats; unsigned long *cpuset; unsigned long *nodeset; @@ -225,6 +228,12 @@ he__get_c2c_hists(struct hist_entry *he, return hists; } +static void c2c_he__set_evsel(struct c2c_hist_entry *c2c_he, + struct evsel *evsel) +{ + c2c_he->evsel = evsel; +} + static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he, struct perf_sample *sample) { @@ -275,6 +284,33 @@ static void compute_stats(struct c2c_hist_entry *c2c_he, update_stats(&cstats->load, weight); } +/* + * Return true if annotation is possible. When list is NULL, + * it means that we are called at the c2c_browser level, + * in that case we allow annotation to be initialized. When list + * is non-NULL, it means that we are called at the cacheline_browser + * level, in that case we allow annotation only if use_browser + * is set and symbol information is available. + */ +static bool perf_c2c__has_annotation(struct perf_hpp_list *list) +{ + if (use_browser != 1) + return false; + return !list || list->sym; +} + +static void perf_c2c__evsel_hists_inc_stats(struct evsel *evsel, + struct hist_entry *he, + struct perf_sample *sample) +{ + struct hists *evsel_hists = evsel__hists(evsel); + + hists__inc_nr_samples(evsel_hists, he->filtered); + evsel_hists->stats.total_period += sample->period; + if (!he->filtered) + evsel_hists->stats.total_non_filtered_period += sample->period; +} + static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, @@ -334,8 +370,15 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, c2c_he__set_cpu(c2c_he, sample); c2c_he__set_node(c2c_he, sample); + c2c_he__set_evsel(c2c_he, evsel); hists__inc_nr_samples(&c2c_hists->hists, he->filtered); + + if (perf_c2c__has_annotation(NULL)) { + perf_c2c__evsel_hists_inc_stats(evsel, he, sample); + addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample, evsel); + } + ret = hist_entry__append_callchain(he, sample); if (!ret) { @@ -371,6 +414,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, c2c_he__set_cpu(c2c_he, sample); c2c_he__set_node(c2c_he, sample); + c2c_he__set_evsel(c2c_he, evsel); hists__inc_nr_samples(&c2c_hists->hists, he->filtered); ret = hist_entry__append_callchain(he, sample); @@ -1997,6 +2041,9 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name, stru if (dim == &dim_dso) hpp_list->dso = 1; + if (dim == &dim_symbol || dim == &dim_iaddr) + hpp_list->sym = 1; + perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt); return 0; } @@ -2550,6 +2597,40 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session) } #ifdef HAVE_SLANG_SUPPORT + +static int perf_c2c__toggle_annotation(struct hist_browser *browser) +{ + struct hist_entry *he = browser->he_selection; + struct symbol *sym = NULL; + struct annotated_source *src = NULL; + struct c2c_hist_entry *c2c_he = NULL; + + if (!perf_c2c__has_annotation(he->hists->hpp_list)) { + ui_browser__help_window(&browser->b, "No annotation support"); + return 0; + } + + if (he == NULL) { + ui_browser__help_window(&browser->b, "No entry selected for annotation"); + return 0; + } + + sym = he->ms.sym; + if (sym == NULL) { + ui_browser__help_window(&browser->b, "Can not annotate, no symbol found"); + return 0; + } + + src = symbol__hists(sym, 0); + if (src == NULL) { + ui_browser__help_window(&browser->b, "Failed to initialize annotation source"); + return 0; + } + + c2c_he = container_of(he, struct c2c_hist_entry, he); + return hist_entry__tui_annotate(he, c2c_he->evsel, NULL); +} + static void c2c_browser__update_nr_entries(struct hist_browser *hb) { u64 nr_entries = 0; @@ -2617,6 +2698,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he) " ENTER Toggle callchains (if present) \n" " n Toggle Node details info \n" " s Toggle full length of symbol and source line columns \n" + " a Toggle annotation view \n" " q Return back to cacheline list \n"; if (!he) @@ -2651,6 +2733,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he) c2c.node_info = (c2c.node_info + 1) % 3; setup_nodes_header(); break; + case 'a': + perf_c2c__toggle_annotation(browser); + break; case 'q': goto out; case '?': @@ -3006,6 +3091,7 @@ static int perf_c2c__report(int argc, const char **argv) const char *display = NULL; const char *coalesce = NULL; bool no_source = false; + const char *disassembler_style = NULL, *objdump_path = NULL; const struct option options[] = { OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), @@ -3033,6 +3119,10 @@ static int perf_c2c__report(int argc, const char **argv) OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr, "Enable LBR callgraph stitching approach"), OPT_BOOLEAN(0, "double-cl", &chk_double_cl, "Detect adjacent cacheline false sharing"), + OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", + "Specify disassembler style (e.g. -M intel for intel syntax)"), + OPT_STRING(0, "objdump", &objdump_path, "path", + "objdump binary to use for disassembly and annotations"), OPT_PARENT(c2c_options), OPT_END() }; @@ -3040,6 +3130,12 @@ static int perf_c2c__report(int argc, const char **argv) const char *output_str, *sort_str = NULL; struct perf_env *env; + annotation_options__init(); + + err = hists__init(); + if (err < 0) + goto out; + argc = parse_options(argc, argv, options, report_c2c_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (argc) @@ -3052,6 +3148,27 @@ static int perf_c2c__report(int argc, const char **argv) if (c2c.stats_only) c2c.use_stdio = true; + /** + * Annotation related options disassembler_style, objdump_path are set + * in the c2c_options, so we can use them here. + */ + if (disassembler_style) { + annotate_opts.disassembler_style = strdup(disassembler_style); + if (!annotate_opts.disassembler_style) { + err = -ENOMEM; + pr_err("Failed to allocate memory for annotation options\n"); + goto out; + } + } + if (objdump_path) { + annotate_opts.objdump_path = strdup(objdump_path); + if (!annotate_opts.objdump_path) { + err = -ENOMEM; + pr_err("Failed to allocate memory for annotation options\n"); + goto out; + } + } + err = symbol__validate_sym_arguments(); if (err) goto out; @@ -3126,6 +3243,38 @@ static int perf_c2c__report(int argc, const char **argv) if (err) goto out_mem2node; + if (c2c.use_stdio) + use_browser = 0; + else + use_browser = 1; + + /* + * Only in the TUI browser we are doing integrated annotation, + * so don't allocate extra space that won't be used in the stdio + * implementation. + */ + if (perf_c2c__has_annotation(NULL)) { + int ret = symbol__annotation_init(); + + if (ret < 0) + goto out_mem2node; + /* + * For searching by name on the "Browse map details". + * providing it only in verbose mode not to bloat too + * much struct symbol. + */ + if (verbose > 0) { + /* + * XXX: Need to provide a less kludgy way to ask for + * more space per symbol, the u32 is for the index on + * the ui browser. + * See symbol__browser_index. + */ + symbol_conf.priv_size += sizeof(u32); + } + annotation_config__init(); + } + if (symbol__init(env) < 0) goto out_mem2node; @@ -3135,11 +3284,6 @@ static int perf_c2c__report(int argc, const char **argv) goto out_mem2node; } - if (c2c.use_stdio) - use_browser = 0; - else - use_browser = 1; - setup_browser(false); err = perf_session__process_events(session); @@ -3210,6 +3354,7 @@ static int perf_c2c__report(int argc, const char **argv) out_session: perf_session__delete(session); out: + annotation_options__exit(); return err; } From ad83f3b7155db28e82de24dbaa1af2b8f5d972a3 Mon Sep 17 00:00:00 2001 From: Tianyou Li Date: Mon, 13 Oct 2025 22:48:11 +0800 Subject: [PATCH 089/684] perf c2c annotate: Start from the contention line Add support to highlight the contention line in the annotate browser, use 'TAB'/'UNTAB' to refocus to the contention line. Signed-off-by: Tianyou Li Reviewed-by: Dapeng Mi Reviewed-by: Thomas Falcon Reviewed-by: Jiebin Sun Reviewed-by: Pan Deng Reviewed-by: Zhiguo Zhou Reviewed-by: Wangyang Guo Tested-by: Ravi Bangoria Signed-off-by: Namhyung Kim --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-c2c.c | 6 +++- tools/perf/ui/browsers/annotate.c | 48 ++++++++++++++++++++++++++++--- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/hist.h | 6 ++-- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 646f43b0f7c4c9..112b15952016d8 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -519,7 +519,7 @@ static void hists__find_annotations(struct hists *hists, /* skip missing symbols */ nd = rb_next(nd); } else if (use_browser == 1) { - key = hist_entry__tui_annotate(he, evsel, NULL); + key = hist_entry__tui_annotate(he, evsel, NULL, NO_ADDR); switch (key) { case -1: diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index a37e886ff3d753..14c3823f8fed5b 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2604,6 +2604,7 @@ static int perf_c2c__toggle_annotation(struct hist_browser *browser) struct symbol *sym = NULL; struct annotated_source *src = NULL; struct c2c_hist_entry *c2c_he = NULL; + u64 al_addr = NO_ADDR; if (!perf_c2c__has_annotation(he->hists->hpp_list)) { ui_browser__help_window(&browser->b, "No annotation support"); @@ -2627,8 +2628,11 @@ static int perf_c2c__toggle_annotation(struct hist_browser *browser) return 0; } + if (he->mem_info) + al_addr = mem_info__iaddr(he->mem_info)->al_addr; + c2c_he = container_of(he, struct c2c_hist_entry, he); - return hist_entry__tui_annotate(he, c2c_he->evsel, NULL); + return hist_entry__tui_annotate(he, c2c_he->evsel, NULL, al_addr); } static void c2c_browser__update_nr_entries(struct hist_browser *hb) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 8fe699f985423e..112fe6ad112e8d 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -605,7 +605,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, target_ms.map = ms->map; target_ms.sym = dl->ops.target.sym; annotation__unlock(notes); - __hist_entry__tui_annotate(browser->he, &target_ms, evsel, hbt); + __hist_entry__tui_annotate(browser->he, &target_ms, evsel, hbt, NO_ADDR); /* * The annotate_browser above changed the title with the target function @@ -852,6 +852,16 @@ static void annotate_browser__debuginfo_warning(struct annotate_browser *browser } } +static s64 annotate_browser__curr_hot_offset(struct annotate_browser *browser) +{ + struct annotation_line *al = NULL; + + if (browser->curr_hot) + al = rb_entry(browser->curr_hot, struct annotation_line, rb_node); + + return al ? al->offset : 0; +} + static int annotate_browser__run(struct annotate_browser *browser, struct evsel *evsel, struct hist_browser_timer *hbt) @@ -873,6 +883,11 @@ static int annotate_browser__run(struct annotate_browser *browser, annotate_browser__calc_percent(browser, evsel); + if (browser->selection != NULL) { + browser->curr_hot = &browser->selection->rb_node; + browser->b.use_navkeypressed = false; + } + if (browser->curr_hot) { annotate_browser__set_rb_top(browser, browser->curr_hot); browser->b.navkeypressed = false; @@ -969,8 +984,19 @@ static int annotate_browser__run(struct annotate_browser *browser, nd = browser->curr_hot; break; case 's': + struct annotation_line *al = NULL; + s64 offset = annotate_browser__curr_hot_offset(browser); + if (annotate_browser__toggle_source(browser, evsel)) ui_helpline__puts(help); + + /* Update the annotation browser's rb_tree, and reset the nd */ + annotate_browser__calc_percent(browser, evsel); + /* Try to find the same asm line as before */ + al = annotated_source__get_line(notes->src, offset); + browser->curr_hot = al ? &al->rb_node : NULL; + nd = browser->curr_hot; + annotate__scnprintf_title(hists, title, sizeof(title)); annotate_browser__show(browser, title, help); continue; @@ -1106,19 +1132,19 @@ static int annotate_browser__run(struct annotate_browser *browser, } int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, - struct hist_browser_timer *hbt) + struct hist_browser_timer *hbt, u64 al_addr) { /* reset abort key so that it can get Ctrl-C as a key */ SLang_reset_tty(); SLang_init_tty(0, 0, 0); SLtty_set_suspend_state(true); - return __hist_entry__tui_annotate(he, &he->ms, evsel, hbt); + return __hist_entry__tui_annotate(he, &he->ms, evsel, hbt, al_addr); } int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, struct evsel *evsel, - struct hist_browser_timer *hbt) + struct hist_browser_timer *hbt, u64 al_addr) { struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); @@ -1188,6 +1214,20 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, if (annotate_opts.hide_src_code) ui_browser__init_asm_mode(&browser.b); + /* + * If al_addr is set, it means that there should be a line + * intentionally selected, not based on the percentages + * which caculated by the event sampling. In this case, we + * convey this information into the browser selection, where + * the selection in other cases should be empty. + */ + if (al_addr != NO_ADDR) { + struct annotation_line *al = annotated_source__get_line(notes->src, + al_addr - sym->start); + + browser.selection = al; + } + ret = annotate_browser__run(&browser, evsel, hbt); debuginfo__delete(browser.dbg); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 487c0b08c00387..08fecbe28a5244 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2485,7 +2485,7 @@ do_annotate(struct hist_browser *browser, struct popup_action *act) evsel = hists_to_evsel(browser->hists); he = hist_browser__selected_entry(browser); - err = __hist_entry__tui_annotate(he, &act->ms, evsel, browser->hbt); + err = __hist_entry__tui_annotate(he, &act->ms, evsel, browser->hbt, NO_ADDR); /* * offer option to annotate the other branch source or target * (if they exists) when returning from annotate diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index c64005278687cb..6795816eee856e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -713,12 +713,14 @@ struct block_hist { #include "../ui/keysyms.h" void attr_to_script(char *buf, struct perf_event_attr *attr); +#define NO_ADDR 0 + int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, struct evsel *evsel, - struct hist_browser_timer *hbt); + struct hist_browser_timer *hbt, u64 al_addr); int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, - struct hist_browser_timer *hbt); + struct hist_browser_timer *hbt, u64 al_addr); int evlist__tui_browse_hists(struct evlist *evlist, const char *help, struct hist_browser_timer *hbt, float min_pcnt, struct perf_env *env, bool warn_lost_event); From 800201997a509c298e74696da3586d82b1a2b6f4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 17 Oct 2025 16:03:57 -0700 Subject: [PATCH 090/684] perf parse-events: Make X modifier more respectful of groups Events with an X modifier were reordered within a group, for example slots was made the leader in: ``` $ perf record -e '{cpu/mem-stores/ppu,cpu/slots/uX}' -- sleep 1 ``` Fix by making `dont_regroup` evsels always use their index for sorting. Make the cur_leader, when fixing the groups, be that of `dont_regroup` evsel so that the `dont_regroup` evsel doesn't become a leader. On a tigerlake this patch corrects this and meets expectations in: ``` $ perf stat -e '{cpu/mem-stores/,cpu/slots/uX}' -a -- sleep 0.1 Performance counter stats for 'system wide': 83,458,652 cpu/mem-stores/ 2,720,854,880 cpu/slots/uX 0.103780587 seconds time elapsed $ perf stat -e 'slots,slots:X' -a -- sleep 0.1 Performance counter stats for 'system wide': 732,042,247 slots (48.96%) 643,288,155 slots:X (51.04%) 0.102731018 seconds time elapsed ``` Closes: https://lore.kernel.org/lkml/18f20d38-070c-4e17-bc90-cf7102e1e53d@linux.intel.com/ Fixes: 035c17893082 ("perf parse-events: Add 'X' modifier to exclude an event from being regrouped") Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3aec86aebdc6bc..0c0dc20b1c1375 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1973,14 +1973,18 @@ static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct li * event's index is used. An index may be forced for events that * must be in the same group, namely Intel topdown events. */ - if (*force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)) { + if (lhs->dont_regroup) { + lhs_sort_idx = lhs_core->idx; + } else if (*force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)) { lhs_sort_idx = *force_grouped_idx; } else { bool lhs_has_group = lhs_core->leader != lhs_core || lhs_core->nr_members > 1; lhs_sort_idx = lhs_has_group ? lhs_core->leader->idx : lhs_core->idx; } - if (*force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)) { + if (rhs->dont_regroup) { + rhs_sort_idx = rhs_core->idx; + } else if (*force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)) { rhs_sort_idx = *force_grouped_idx; } else { bool rhs_has_group = rhs_core->leader != rhs_core || rhs_core->nr_members > 1; @@ -2078,10 +2082,10 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) */ idx = 0; list_for_each_entry(pos, list, core.node) { - const struct evsel *pos_leader = evsel__leader(pos); + struct evsel *pos_leader = evsel__leader(pos); const char *pos_pmu_name = pos->group_pmu_name; const char *cur_leader_pmu_name; - bool pos_force_grouped = force_grouped_idx != -1 && + bool pos_force_grouped = force_grouped_idx != -1 && !pos->dont_regroup && arch_evsel__must_be_in_group(pos); /* Reset index and nr_members. */ @@ -2095,8 +2099,8 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) * groups can't span PMUs. */ if (!cur_leader || pos->dont_regroup) { - cur_leader = pos; - cur_leaders_grp = &pos->core; + cur_leader = pos->dont_regroup ? pos_leader : pos; + cur_leaders_grp = &cur_leader->core; if (pos_force_grouped) force_grouped_leader = pos; } From 84a222d1b369ba83f8947948670f775367e653f1 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 10 Oct 2025 12:46:32 +0000 Subject: [PATCH 091/684] firmware: exynos-acpm: add DVFS protocol Add ACPM DVFS protocol handler. It constructs DVFS messages that the APM firmware can understand. Signed-off-by: Tudor Ambarus Reviewed-by: Peter Griffin Tested-by: Peter Griffin # on gs101-oriole Link: https://patch.msgid.link/20251010-acpm-clk-v6-2-321ee8826fd4@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/firmware/samsung/Makefile | 4 +- drivers/firmware/samsung/exynos-acpm-dvfs.c | 80 +++++++++++++++++++ drivers/firmware/samsung/exynos-acpm-dvfs.h | 21 +++++ drivers/firmware/samsung/exynos-acpm.c | 5 ++ .../firmware/samsung/exynos-acpm-protocol.h | 10 +++ 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/samsung/exynos-acpm-dvfs.c create mode 100644 drivers/firmware/samsung/exynos-acpm-dvfs.h diff --git a/drivers/firmware/samsung/Makefile b/drivers/firmware/samsung/Makefile index 7b4c9f6f34f54f..80d4f89b33a955 100644 --- a/drivers/firmware/samsung/Makefile +++ b/drivers/firmware/samsung/Makefile @@ -1,4 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -acpm-protocol-objs := exynos-acpm.o exynos-acpm-pmic.o +acpm-protocol-objs := exynos-acpm.o +acpm-protocol-objs += exynos-acpm-pmic.o +acpm-protocol-objs += exynos-acpm-dvfs.o obj-$(CONFIG_EXYNOS_ACPM_PROTOCOL) += acpm-protocol.o diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.c b/drivers/firmware/samsung/exynos-acpm-dvfs.c new file mode 100644 index 00000000000000..1c5b2b143bcc3f --- /dev/null +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2020 Samsung Electronics Co., Ltd. + * Copyright 2020 Google LLC. + * Copyright 2025 Linaro Ltd. + */ + +#include +#include +#include +#include +#include + +#include "exynos-acpm.h" +#include "exynos-acpm-dvfs.h" + +#define ACPM_DVFS_ID GENMASK(11, 0) +#define ACPM_DVFS_REQ_TYPE GENMASK(15, 0) + +#define ACPM_DVFS_FREQ_REQ 0 +#define ACPM_DVFS_FREQ_GET 1 + +static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, + unsigned int acpm_chan_id, bool response) +{ + xfer->acpm_chan_id = acpm_chan_id; + xfer->txd = cmd; + xfer->txlen = cmdlen; + + if (response) { + xfer->rxd = cmd; + xfer->rxlen = cmdlen; + } +} + +static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id, + unsigned long rate) +{ + cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id); + cmd[1] = rate / HZ_PER_KHZ; + cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_REQ); + cmd[3] = ktime_to_ms(ktime_get()); +} + +int acpm_dvfs_set_rate(const struct acpm_handle *handle, + unsigned int acpm_chan_id, unsigned int clk_id, + unsigned long rate) +{ + struct acpm_xfer xfer = {0}; + u32 cmd[4]; + + acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate); + acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false); + + return acpm_do_xfer(handle, &xfer); +} + +static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id) +{ + cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id); + cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_GET); + cmd[3] = ktime_to_ms(ktime_get()); +} + +unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, + unsigned int acpm_chan_id, unsigned int clk_id) +{ + struct acpm_xfer xfer; + unsigned int cmd[4] = {0}; + int ret; + + acpm_dvfs_init_get_rate_cmd(cmd, clk_id); + acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true); + + ret = acpm_do_xfer(handle, &xfer); + if (ret) + return 0; + + return xfer.rxd[1] * HZ_PER_KHZ; +} diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.h b/drivers/firmware/samsung/exynos-acpm-dvfs.h new file mode 100644 index 00000000000000..9f2778e649c9d8 --- /dev/null +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2020 Samsung Electronics Co., Ltd. + * Copyright 2020 Google LLC. + * Copyright 2025 Linaro Ltd. + */ +#ifndef __EXYNOS_ACPM_DVFS_H__ +#define __EXYNOS_ACPM_DVFS_H__ + +#include + +struct acpm_handle; + +int acpm_dvfs_set_rate(const struct acpm_handle *handle, + unsigned int acpm_chan_id, unsigned int id, + unsigned long rate); +unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, + unsigned int acpm_chan_id, + unsigned int clk_id); + +#endif /* __EXYNOS_ACPM_DVFS_H__ */ diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index 3a69fe3234c75e..9fa0335ccf5db3 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -29,6 +29,7 @@ #include #include "exynos-acpm.h" +#include "exynos-acpm-dvfs.h" #include "exynos-acpm-pmic.h" #define ACPM_PROTOCOL_SEQNUM GENMASK(21, 16) @@ -590,8 +591,12 @@ static int acpm_channels_init(struct acpm_info *acpm) */ static void acpm_setup_ops(struct acpm_info *acpm) { + struct acpm_dvfs_ops *dvfs_ops = &acpm->handle.ops.dvfs_ops; struct acpm_pmic_ops *pmic_ops = &acpm->handle.ops.pmic_ops; + dvfs_ops->set_rate = acpm_dvfs_set_rate; + dvfs_ops->get_rate = acpm_dvfs_get_rate; + pmic_ops->read_reg = acpm_pmic_read_reg; pmic_ops->bulk_read = acpm_pmic_bulk_read; pmic_ops->write_reg = acpm_pmic_write_reg; diff --git a/include/linux/firmware/samsung/exynos-acpm-protocol.h b/include/linux/firmware/samsung/exynos-acpm-protocol.h index f628bf1862c25f..b1e95435240fdb 100644 --- a/include/linux/firmware/samsung/exynos-acpm-protocol.h +++ b/include/linux/firmware/samsung/exynos-acpm-protocol.h @@ -13,6 +13,15 @@ struct acpm_handle; struct device_node; +struct acpm_dvfs_ops { + int (*set_rate)(const struct acpm_handle *handle, + unsigned int acpm_chan_id, unsigned int clk_id, + unsigned long rate); + unsigned long (*get_rate)(const struct acpm_handle *handle, + unsigned int acpm_chan_id, + unsigned int clk_id); +}; + struct acpm_pmic_ops { int (*read_reg)(const struct acpm_handle *handle, unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, @@ -32,6 +41,7 @@ struct acpm_pmic_ops { }; struct acpm_ops { + struct acpm_dvfs_ops dvfs_ops; struct acpm_pmic_ops pmic_ops; }; From bad0d1260b6dc229657b942400c5fc4f257f50cd Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 10 Oct 2025 12:46:33 +0000 Subject: [PATCH 092/684] firmware: exynos-acpm: register ACPM clocks pdev Register by hand a platform device for the ACPM clocks. The ACPM clocks are not modeled as a DT child of ACPM because: 1/ they don't have their own resources. 2/ they are not a block that can be reused. The clock identifying data is reduced (clock ID, clock name and mailbox channel ID) and may differ from a SoC to another. Signed-off-by: Tudor Ambarus Reviewed-by: Peter Griffin Tested-by: Peter Griffin # on gs101-oriole Link: https://patch.msgid.link/20251010-acpm-clk-v6-3-321ee8826fd4@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/firmware/samsung/exynos-acpm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index 9fa0335ccf5db3..0cb269c7046015 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -177,9 +177,11 @@ struct acpm_info { /** * struct acpm_match_data - of_device_id data. * @initdata_base: offset in SRAM where the channels configuration resides. + * @acpm_clk_dev_name: base name for the ACPM clocks device that we're registering. */ struct acpm_match_data { loff_t initdata_base; + const char *acpm_clk_dev_name; }; #define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl) @@ -604,9 +606,15 @@ static void acpm_setup_ops(struct acpm_info *acpm) pmic_ops->update_reg = acpm_pmic_update_reg; } +static void acpm_clk_pdev_unregister(void *data) +{ + platform_device_unregister(data); +} + static int acpm_probe(struct platform_device *pdev) { const struct acpm_match_data *match_data; + struct platform_device *acpm_clk_pdev; struct device *dev = &pdev->dev; struct device_node *shmem; struct acpm_info *acpm; @@ -647,6 +655,18 @@ static int acpm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, acpm); + acpm_clk_pdev = platform_device_register_data(dev, + match_data->acpm_clk_dev_name, + PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(acpm_clk_pdev)) + return dev_err_probe(dev, PTR_ERR(acpm_clk_pdev), + "Failed to register ACPM clocks device.\n"); + + ret = devm_add_action_or_reset(dev, acpm_clk_pdev_unregister, + acpm_clk_pdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to add devm action.\n"); + return devm_of_platform_populate(dev); } @@ -746,6 +766,7 @@ EXPORT_SYMBOL_GPL(devm_acpm_get_by_node); static const struct acpm_match_data acpm_gs101 = { .initdata_base = ACPM_GS101_INITDATA_BASE, + .acpm_clk_dev_name = "gs101-acpm-clk", }; static const struct of_device_id acpm_match[] = { From 40498a74205371400a5b0088acb886ac47a523aa Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 10 Oct 2025 12:46:34 +0000 Subject: [PATCH 093/684] clk: samsung: add Exynos ACPM clock driver Add the Exynos ACPM clock driver. It provides support for clocks that are controlled by firmware that implements the ACPM interface. Signed-off-by: Tudor Ambarus Reviewed-by: Peter Griffin Tested-by: Peter Griffin # on gs101-oriole Link: https://patch.msgid.link/20251010-acpm-clk-v6-4-321ee8826fd4@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/Kconfig | 10 ++ drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-acpm.c | 185 +++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 drivers/clk/samsung/clk-acpm.c diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 76a494e95027af..70a8b82a0136b4 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -95,6 +95,16 @@ config EXYNOS_CLKOUT status of the certains clocks from SoC, but it could also be tied to other devices as an input clock. +config EXYNOS_ACPM_CLK + tristate "Clock driver controlled via ACPM interface" + depends on EXYNOS_ACPM_PROTOCOL || (COMPILE_TEST && !EXYNOS_ACPM_PROTOCOL) + help + This driver provides support for clocks that are controlled by + firmware that implements the ACPM interface. + + This driver uses the ACPM interface to interact with the firmware + providing all the clock controlls. + config TESLA_FSD_COMMON_CLK bool "Tesla FSD clock controller support" if COMPILE_TEST depends on COMMON_CLK_SAMSUNG diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index ef464f434740f9..f3657f2e1b98c6 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos990.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov9.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov920.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-gs101.o +obj-$(CONFIG_EXYNOS_ACPM_CLK) += clk-acpm.o obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o obj-$(CONFIG_TESLA_FSD_COMMON_CLK) += clk-fsd.o diff --git a/drivers/clk/samsung/clk-acpm.c b/drivers/clk/samsung/clk-acpm.c new file mode 100644 index 00000000000000..b90809ce3f882c --- /dev/null +++ b/drivers/clk/samsung/clk-acpm.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Samsung Exynos ACPM protocol based clock driver. + * + * Copyright 2025 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct acpm_clk { + u32 id; + struct clk_hw hw; + unsigned int mbox_chan_id; + const struct acpm_handle *handle; +}; + +struct acpm_clk_variant { + const char *name; +}; + +struct acpm_clk_driver_data { + const struct acpm_clk_variant *clks; + unsigned int nr_clks; + unsigned int mbox_chan_id; +}; + +#define to_acpm_clk(clk) container_of(clk, struct acpm_clk, hw) + +#define ACPM_CLK(cname) \ + { \ + .name = cname, \ + } + +static const struct acpm_clk_variant gs101_acpm_clks[] = { + ACPM_CLK("mif"), + ACPM_CLK("int"), + ACPM_CLK("cpucl0"), + ACPM_CLK("cpucl1"), + ACPM_CLK("cpucl2"), + ACPM_CLK("g3d"), + ACPM_CLK("g3dl2"), + ACPM_CLK("tpu"), + ACPM_CLK("intcam"), + ACPM_CLK("tnr"), + ACPM_CLK("cam"), + ACPM_CLK("mfc"), + ACPM_CLK("disp"), + ACPM_CLK("bo"), +}; + +static const struct acpm_clk_driver_data acpm_clk_gs101 = { + .clks = gs101_acpm_clks, + .nr_clks = ARRAY_SIZE(gs101_acpm_clks), + .mbox_chan_id = 0, +}; + +static unsigned long acpm_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct acpm_clk *clk = to_acpm_clk(hw); + + return clk->handle->ops.dvfs_ops.get_rate(clk->handle, + clk->mbox_chan_id, clk->id); +} + +static int acpm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + /* + * We can't figure out what rate it will be, so just return the + * rate back to the caller. acpm_clk_recalc_rate() will be called + * after the rate is set and we'll know what rate the clock is + * running at then. + */ + return 0; +} + +static int acpm_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct acpm_clk *clk = to_acpm_clk(hw); + + return clk->handle->ops.dvfs_ops.set_rate(clk->handle, + clk->mbox_chan_id, clk->id, rate); +} + +static const struct clk_ops acpm_clk_ops = { + .recalc_rate = acpm_clk_recalc_rate, + .determine_rate = acpm_clk_determine_rate, + .set_rate = acpm_clk_set_rate, +}; + +static int acpm_clk_register(struct device *dev, struct acpm_clk *aclk, + const char *name) +{ + struct clk_init_data init = {}; + + init.name = name; + init.ops = &acpm_clk_ops; + aclk->hw.init = &init; + + return devm_clk_hw_register(dev, &aclk->hw); +} + +static int acpm_clk_probe(struct platform_device *pdev) +{ + const struct acpm_handle *acpm_handle; + struct clk_hw_onecell_data *clk_data; + struct clk_hw **hws; + struct device *dev = &pdev->dev; + struct acpm_clk *aclks; + unsigned int mbox_chan_id; + int i, err, count; + + acpm_handle = devm_acpm_get_by_node(dev, dev->parent->of_node); + if (IS_ERR(acpm_handle)) + return dev_err_probe(dev, PTR_ERR(acpm_handle), + "Failed to get acpm handle\n"); + + count = acpm_clk_gs101.nr_clks; + mbox_chan_id = acpm_clk_gs101.mbox_chan_id; + + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = count; + hws = clk_data->hws; + + aclks = devm_kcalloc(dev, count, sizeof(*aclks), GFP_KERNEL); + if (!aclks) + return -ENOMEM; + + for (i = 0; i < count; i++) { + struct acpm_clk *aclk = &aclks[i]; + + /* + * The code assumes the clock IDs start from zero, + * are sequential and do not have gaps. + */ + aclk->id = i; + aclk->handle = acpm_handle; + aclk->mbox_chan_id = mbox_chan_id; + + hws[i] = &aclk->hw; + + err = acpm_clk_register(dev, aclk, + acpm_clk_gs101.clks[i].name); + if (err) + return dev_err_probe(dev, err, + "Failed to register clock\n"); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + clk_data); +} + +static const struct platform_device_id acpm_clk_id[] = { + { "gs101-acpm-clk" }, + {} +}; +MODULE_DEVICE_TABLE(platform, acpm_clk_id); + +static struct platform_driver acpm_clk_driver = { + .driver = { + .name = "acpm-clocks", + }, + .probe = acpm_clk_probe, + .id_table = acpm_clk_id, +}; +module_platform_driver(acpm_clk_driver); + +MODULE_AUTHOR("Tudor Ambarus "); +MODULE_DESCRIPTION("Samsung Exynos ACPM clock driver"); +MODULE_LICENSE("GPL"); From ad97aba3e64f8e474ecbce0c4e08486023ce8ab2 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 10 Oct 2025 12:46:36 +0000 Subject: [PATCH 094/684] MAINTAINERS: add ACPM clock bindings and driver Extend the Google Tensor SoC support list of files to include the GS101 ACPM clock bindings. Add the ACPM clock driver under the Samsung Exynos ACPM Protocol entry. Signed-off-by: Tudor Ambarus Link: https://patch.msgid.link/20251010-acpm-clk-v6-6-321ee8826fd4@linaro.org Signed-off-by: Krzysztof Kozlowski --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968e4..5d24c16d3ead25 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10601,7 +10601,7 @@ F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml F: arch/arm64/boot/dts/exynos/google/ F: drivers/clk/samsung/clk-gs101.c F: drivers/phy/samsung/phy-gs101-ufs.c -F: include/dt-bindings/clock/google,gs101.h +F: include/dt-bindings/clock/google,gs101* K: [gG]oogle.?[tT]ensor GPD FAN DRIVER @@ -22761,6 +22761,7 @@ L: linux-kernel@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml +F: drivers/clk/samsung/clk-acpm.c F: drivers/firmware/samsung/exynos-acpm* F: include/linux/firmware/samsung/exynos-acpm-protocol.h From 3b37979dcbef0dc3fc1aaba75b21ff9a21799055 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 29 Sep 2025 12:23:24 +0100 Subject: [PATCH 095/684] clk: renesas: cpg-mssr: Add module reset support for RZ/T2H Add support for module reset handling on the RZ/T2H SoC. Unlike earlier CPG/MSSR variants, RZ/T2H uses a unified set of Module Reset Control Registers (MRCR) where both reset and deassert actions are done via read-modify-write (RMW) to the same register. Introduce a new MRCR offset table (mrcr_for_rzt2h) for RZ/T2H and assign it to reset_regs. For this SoC, the number of resets is based on the number of MRCR registers rather than the number of module clocks. Also add cpg_mrcr_reset_ops to implement reset, assert, and deassert using RMW while holding the spinlock. This follows the RZ/T2H requirements, where processing after releasing a module reset must be secured by performing seven dummy reads of the same register, and where a module that is reset and released again must ensure the target bit in the Module Reset Control Register is set to 1. Update the reset controller registration to select cpg_mrcr_reset_ops for RZ/T2H, while keeping the existing cpg_mssr_reset_ops for other SoCs. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Philipp Zabel Link: https://patch.msgid.link/20250929112324.3622148-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 111 ++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index a3d171ddaab992..0ffe6ee8f165c3 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -40,6 +40,8 @@ #define WARN_DEBUG(x) do { } while (0) #endif +#define RZT2H_RESET_REG_READ_COUNT 7 + /* * Module Standby and Software Reset register offets. * @@ -137,6 +139,22 @@ static const u16 srcr_for_gen4[] = { 0x2C60, 0x2C64, 0x2C68, 0x2C6C, 0x2C70, 0x2C74, }; +static const u16 mrcr_for_rzt2h[] = { + 0x240, /* MRCTLA */ + 0x244, /* Reserved */ + 0x248, /* Reserved */ + 0x24C, /* Reserved */ + 0x250, /* MRCTLE */ + 0x254, /* Reserved */ + 0x258, /* Reserved */ + 0x25C, /* Reserved */ + 0x260, /* MRCTLI */ + 0x264, /* Reserved */ + 0x268, /* Reserved */ + 0x26C, /* Reserved */ + 0x270, /* MRCTLM */ +}; + /* * Software Reset Clearing Register offsets */ @@ -739,6 +757,72 @@ static int cpg_mssr_status(struct reset_controller_dev *rcdev, return !!(readl(priv->pub.base0 + priv->reset_regs[reg]) & bitmask); } +static int cpg_mrcr_set_reset_state(struct reset_controller_dev *rcdev, + unsigned long id, bool set) +{ + struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); + unsigned int reg = id / 32; + unsigned int bit = id % 32; + u32 bitmask = BIT(bit); + void __iomem *reg_addr; + unsigned long flags; + unsigned int i; + u32 val; + + dev_dbg(priv->dev, "%s %u%02u\n", set ? "assert" : "deassert", reg, bit); + + spin_lock_irqsave(&priv->pub.rmw_lock, flags); + + reg_addr = priv->pub.base0 + priv->reset_regs[reg]; + /* Read current value and modify */ + val = readl(reg_addr); + if (set) + val |= bitmask; + else + val &= ~bitmask; + writel(val, reg_addr); + + /* + * For secure processing after release from a module reset, one must + * perform multiple dummy reads of the same register. + */ + for (i = 0; !set && i < RZT2H_RESET_REG_READ_COUNT; i++) + readl(reg_addr); + + /* Verify the operation */ + val = readl(reg_addr); + if (set == !(bitmask & val)) { + dev_err(priv->dev, "Reset register %u%02u operation failed\n", reg, bit); + spin_unlock_irqrestore(&priv->pub.rmw_lock, flags); + return -EIO; + } + + spin_unlock_irqrestore(&priv->pub.rmw_lock, flags); + + return 0; +} + +static int cpg_mrcr_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + int ret; + + ret = cpg_mrcr_set_reset_state(rcdev, id, true); + if (ret) + return ret; + + return cpg_mrcr_set_reset_state(rcdev, id, false); +} + +static int cpg_mrcr_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return cpg_mrcr_set_reset_state(rcdev, id, true); +} + +static int cpg_mrcr_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return cpg_mrcr_set_reset_state(rcdev, id, false); +} + static const struct reset_control_ops cpg_mssr_reset_ops = { .reset = cpg_mssr_reset, .assert = cpg_mssr_assert, @@ -746,6 +830,13 @@ static const struct reset_control_ops cpg_mssr_reset_ops = { .status = cpg_mssr_status, }; +static const struct reset_control_ops cpg_mrcr_reset_ops = { + .reset = cpg_mrcr_reset, + .assert = cpg_mrcr_assert, + .deassert = cpg_mrcr_deassert, + .status = cpg_mssr_status, +}; + static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec) { @@ -763,11 +854,23 @@ static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev, static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv) { - priv->rcdev.ops = &cpg_mssr_reset_ops; + /* + * RZ/T2H (and family) has the Module Reset Control Registers + * which allows control resets of certain modules. + * The number of resets is not equal to the number of module clocks. + */ + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) { + priv->rcdev.ops = &cpg_mrcr_reset_ops; + priv->rcdev.nr_resets = ARRAY_SIZE(mrcr_for_rzt2h) * 32; + } else { + priv->rcdev.ops = &cpg_mssr_reset_ops; + priv->rcdev.nr_resets = priv->num_mod_clks; + } + priv->rcdev.of_node = priv->dev->of_node; priv->rcdev.of_reset_n_cells = 1; priv->rcdev.of_xlate = cpg_mssr_reset_xlate; - priv->rcdev.nr_resets = priv->num_mod_clks; + return devm_reset_controller_register(priv->dev, &priv->rcdev); } @@ -1172,6 +1275,7 @@ static int __init cpg_mssr_common_init(struct device *dev, priv->control_regs = stbcr; } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) { priv->control_regs = mstpcr_for_rzt2h; + priv->reset_regs = mrcr_for_rzt2h; } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) { priv->status_regs = mstpsr_for_gen4; priv->control_regs = mstpcr_for_gen4; @@ -1268,8 +1372,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) goto reserve_exit; /* Reset Controller not supported for Standby Control SoCs */ - if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A || - priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) goto reserve_exit; error = cpg_mssr_reset_controller_register(priv); From 40efc872c6ac4029d2eda01af0b4528868ff1be3 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 20 Oct 2025 17:08:26 +0100 Subject: [PATCH 096/684] perf jevents: Fix build when there are other json files in the tree The unquoted glob *.json will expand to a real file if, for example, there is any file in the Perf source ending in .json. This can happen when using tools like Bear and clangd which generate a compile_commands.json file. With the glob already expanded by the shell, the find command will fail to wildcard any real json events files. Fix it by wrapping the star in quotes so it's passed to find rather than the shell. This fixes the following build error (most of the diff output omitted): $ make V=1 -C tools/perf O=/tmp/perf_build_with_json TEST /tmp/perf_build_with_json/pmu-events/empty-pmu-events.log ... /* offset=121053 */ "node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" /* offset=121135 */ "node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" /* offset=121221 */ "node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" ... - { .event_table = { 0, 0 }, .metric_table = { 0, 0 }, }, make[3]: *** [pmu-events/Build:54: /tmp/perf_build_with_json/pmu-events/empty-pmu-events.log] Error 1 Fixes: 4bb55de4ff03 ("perf jevents: Support copying the source json files to OUTPUT") Signed-off-by: James Clark Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index 4ebf37c1497893..ee8ba74f82de0c 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -1,6 +1,6 @@ pmu-events-y += pmu-events.o JDIR = pmu-events/arch/$(SRCARCH) -JSON = $(shell find pmu-events/arch -name *.json -o -name *.csv) +JSON = $(shell find pmu-events/arch -name '*.json' -o -name '*.csv') JDIR_TEST = pmu-events/arch/test JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \ find $(JDIR_TEST) -name '*.json') From 2ef335ead2338b0b317f17f7fe3503717cdc16b2 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 20 Oct 2025 17:08:27 +0100 Subject: [PATCH 097/684] perf jevents: Remove unused makefile variable JDIR is unused since commit 4bb55de4ff03 ("perf jevents: Support copying the source json files to OUTPUT"), remove it. Signed-off-by: James Clark Tested-by: Leo Yan Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/Build | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index ee8ba74f82de0c..c5e2d5f1376687 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -1,5 +1,4 @@ pmu-events-y += pmu-events.o -JDIR = pmu-events/arch/$(SRCARCH) JSON = $(shell find pmu-events/arch -name '*.json' -o -name '*.csv') JDIR_TEST = pmu-events/arch/test JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \ From 29166bd0a41fe6bdcf0b2376ef57e358c8a1e988 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 20 Oct 2025 17:08:28 +0100 Subject: [PATCH 098/684] perf jevents: Suppress circular dependency warnings When doing an in source build, $(OUTPUT) is empty so the rule has the same input and output file. Suppress the warning by only adding the rule when doing an out of source build. The same condition already exists for the clean rule for json files. This fixes the following warnings: make[3]: Circular pmu-events/arch/nds32/mapfile.csv <- pmu-events/arch/nds32/mapfile.csv dependency dropped. make[3]: Circular pmu-events/arch/powerpc/mapfile.csv <- pmu-events/arch/powerpc/mapfile.csv dependency dropped. ... Signed-off-by: James Clark Tested-by: Namhyung Kim Tested-by: Leo Yan Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/Build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index c5e2d5f1376687..a46ab7b612dfc2 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -29,10 +29,12 @@ $(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C) $(call rule_mkdir) $(Q)$(call echo-cmd,gen)cp $< $@ else -# Copy checked-in json for generation. +# Copy checked-in json to OUTPUT for generation if it's an out of source build +ifneq ($(OUTPUT),) $(OUTPUT)pmu-events/arch/%: pmu-events/arch/% $(call rule_mkdir) $(Q)$(call echo-cmd,gen)cp $< $@ +endif $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) $(call rule_mkdir) From 0e6c07a3c30cdc4509fc5e7dc490d4cc6e5c241a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 21 Oct 2025 12:07:50 +0900 Subject: [PATCH 099/684] perf annotate: Fix build with NO_SLANG=1 The recent change for perf c2c annotate broke build without slang support like below. builtin-annotate.c: In function 'hists__find_annotations': builtin-annotate.c:522:73: error: 'NO_ADDR' undeclared (first use in this function); did you mean 'NR_ADDR'? 522 | key = hist_entry__tui_annotate(he, evsel, NULL, NO_ADDR); | ^~~~~~~ | NR_ADDR builtin-annotate.c:522:73: note: each undeclared identifier is reported only once for each function it appears in builtin-annotate.c:522:31: error: too many arguments to function 'hist_entry__tui_annotate' 522 | key = hist_entry__tui_annotate(he, evsel, NULL, NO_ADDR); | ^~~~~~~~~~~~~~~~~~~~~~~~ In file included from util/sort.h:6, from builtin-annotate.c:28: util/hist.h:756:19: note: declared here 756 | static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, | ^~~~~~~~~~~~~~~~~~~~~~~~ And I noticed that it missed to update the other side of #ifdef HAVE_SLANG_SUPPORT. Let's fix it. Cc: Tianyou Li Fixes: cd3466cd2639783d ("perf c2c: Add annotation support to perf c2c report") Signed-off-by: Namhyung Kim --- tools/perf/util/hist.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 6795816eee856e..1d5ea632ca4e1b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -709,12 +709,12 @@ struct block_hist { struct hist_entry he; }; +#define NO_ADDR 0 + #ifdef HAVE_SLANG_SUPPORT #include "../ui/keysyms.h" void attr_to_script(char *buf, struct perf_event_attr *attr); -#define NO_ADDR 0 - int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, u64 al_addr); @@ -748,14 +748,16 @@ int evlist__tui_browse_hists(struct evlist *evlist __maybe_unused, static inline int __hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, struct map_symbol *ms __maybe_unused, struct evsel *evsel __maybe_unused, - struct hist_browser_timer *hbt __maybe_unused) + struct hist_browser_timer *hbt __maybe_unused, + u64 al_addr __maybe_unused) { return 0; } static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, struct evsel *evsel __maybe_unused, - struct hist_browser_timer *hbt __maybe_unused) + struct hist_browser_timer *hbt __maybe_unused, + u64 al_addr __maybe_unused) { return 0; } From 262c61435c0348f3c4652bb200268b2d1bcefbb0 Mon Sep 17 00:00:00 2001 From: Tianyou Li Date: Mon, 20 Oct 2025 15:30:04 +0800 Subject: [PATCH 100/684] perf annotate: fix a crash when annotate the same symbol with 's' and 'T' When perf report with annotation for a symbol, press 's' and 'T', then exit the annotate browser. Once annotate the same symbol, the annotate browser will crash. The browser.arch was required to be correctly updated when data type feature was enabled by 'T'. Usually it was initialized by symbol__annotate2 function. If a symbol has already been correctly annotated at the first time, it should not call the symbol__annotate2 function again, thus the browser.arch will not get initialized. Then at the second time to show the annotate browser, the data type needs to be displayed but the browser.arch is empty. Stack trace as below: Perf: Segmentation fault -------- backtrace -------- #0 0x55d365 in ui__signal_backtrace setup.c:0 #1 0x7f5ff1a3e930 in __restore_rt libc.so.6[3e930] #2 0x570f08 in arch__is perf[570f08] #3 0x562186 in annotate_get_insn_location perf[562186] #4 0x562626 in __hist_entry__get_data_type annotate.c:0 #5 0x56476d in annotation_line__write perf[56476d] #6 0x54e2db in annotate_browser__write annotate.c:0 #7 0x54d061 in ui_browser__list_head_refresh perf[54d061] #8 0x54dc9e in annotate_browser__refresh annotate.c:0 #9 0x54c03d in __ui_browser__refresh browser.c:0 #10 0x54ccf8 in ui_browser__run perf[54ccf8] #11 0x54eb92 in __hist_entry__tui_annotate perf[54eb92] #12 0x552293 in do_annotate hists.c:0 #13 0x55941c in evsel__hists_browse hists.c:0 #14 0x55b00f in evlist__tui_browse_hists perf[55b00f] #15 0x42ff02 in cmd_report perf[42ff02] #16 0x494008 in run_builtin perf.c:0 #17 0x494305 in handle_internal_command perf.c:0 #18 0x410547 in main perf[410547] #19 0x7f5ff1a295d0 in __libc_start_call_main libc.so.6[295d0] #20 0x7f5ff1a29680 in __libc_start_main@@GLIBC_2.34 libc.so.6[29680] #21 0x410b75 in _start perf[410b75] Fixes: 1d4374afd000 ("perf annotate: Add 'T' hot key to toggle data type display") Reviewed-by: James Clark Tested-by: Namhyung Kim Signed-off-by: Tianyou Li Signed-off-by: Namhyung Kim --- tools/perf/ui/browsers/annotate.c | 23 +++++++++++++++++++---- tools/perf/util/annotate.c | 2 +- tools/perf/util/annotate.h | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 112fe6ad112e8d..3a81912279ad13 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -862,6 +862,18 @@ static s64 annotate_browser__curr_hot_offset(struct annotate_browser *browser) return al ? al->offset : 0; } +static void annotate_browser__symbol_annotate_error(struct annotate_browser *browser, int err) +{ + struct map_symbol *ms = browser->b.priv; + struct symbol *sym = ms->sym; + struct dso *dso = map__dso(ms->map); + char msg[BUFSIZ]; + + dso__set_annotate_warned(dso); + symbol__strerror_disassemble(ms, err, msg, sizeof(msg)); + ui__error("Couldn't annotate %s:\n%s", sym->name, msg); +} + static int annotate_browser__run(struct annotate_browser *browser, struct evsel *evsel, struct hist_browser_timer *hbt) @@ -1175,10 +1187,7 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, if (not_annotated || !sym->annotate2) { err = symbol__annotate2(ms, evsel, &browser.arch); if (err) { - char msg[BUFSIZ]; - dso__set_annotate_warned(dso); - symbol__strerror_disassemble(ms, err, msg, sizeof(msg)); - ui__error("Couldn't annotate %s:\n%s", sym->name, msg); + annotate_browser__symbol_annotate_error(&browser, err); return -1; } @@ -1187,6 +1196,12 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, if (!annotation__has_source(notes)) ui__warning("Annotation has no source code."); } + } else { + err = evsel__get_arch(evsel, &browser.arch); + if (err) { + annotate_browser__symbol_annotate_error(&browser, err); + return -1; + } } /* Copy necessary information when it's called from perf top */ diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index a2e34f149a074a..39d6594850f136 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -980,7 +980,7 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel) annotation__calc_percent(notes, evsel, symbol__size(sym)); } -static int evsel__get_arch(struct evsel *evsel, struct arch **parch) +int evsel__get_arch(struct evsel *evsel, struct arch **parch) { struct perf_env *env = evsel__env(evsel); const char *arch_name = perf_env__arch(env); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index eaf6c8aa7f4739..d4990bff29a77c 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -585,4 +585,6 @@ void debuginfo_cache__delete(void); int annotation_br_cntr_entry(char **str, int br_cntr_nr, u64 *br_cntr, int num_aggr, struct evsel *evsel); int annotation_br_cntr_abbr_list(char **str, struct evsel *evsel, bool header); + +int evsel__get_arch(struct evsel *evsel, struct arch **parch); #endif /* __PERF_ANNOTATE_H */ From f1204e5846d22fb2fffbd1164eeb19535f306797 Mon Sep 17 00:00:00 2001 From: Tianyou Li Date: Mon, 20 Oct 2025 15:30:05 +0800 Subject: [PATCH 101/684] perf annotate: Check return value of evsel__get_arch() properly Check the error code of evsel__get_arch() in the symbol__annotate(). Previously it checked non-zero value but after the refactoring it does only for negative values. Fixes: 0669729eb0afb0cf ("perf annotate: Factor out evsel__get_arch()") Suggested-by: James Clark Acked-by: Namhyung Kim Signed-off-by: Tianyou Li Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 39d6594850f136..859e802a1e5ea0 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1021,7 +1021,7 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, int err, nr; err = evsel__get_arch(evsel, &arch); - if (err < 0) + if (err) return err; if (parch) From 068b6a4524262910bc283c7b3c2d7cf0d2c1f833 Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Mon, 13 Oct 2025 18:15:58 +0000 Subject: [PATCH 102/684] perf annotate: Skip annotating data types to lea instructions Introduce a helper function is_address_gen_insn() to check arch-dependent address generation instructions like lea in x86. Remove type annotation on these instructions since they are not accessing memory. It should be counted as `no_mem_ops`. Signed-off-by: Zecheng Li Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 859e802a1e5ea0..cc7764455faf66 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2698,6 +2698,20 @@ static bool is_stack_canary(struct arch *arch, struct annotated_op_loc *loc) return false; } +/** + * Returns true if the instruction has a memory operand without + * performing a load/store + */ +static bool is_address_gen_insn(struct arch *arch, struct disasm_line *dl) +{ + if (arch__is(arch, "x86")) { + if (!strncmp(dl->ins.name, "lea", 3)) + return true; + } + + return false; +} + static struct disasm_line * annotation__prev_asm_line(struct annotation *notes, struct disasm_line *curr) { @@ -2806,6 +2820,12 @@ __hist_entry__get_data_type(struct hist_entry *he, struct arch *arch, return &stackop_type; } + if (is_address_gen_insn(arch, dl)) { + istat->bad++; + ann_data_stat.no_mem_ops++; + return NO_TYPE; + } + for_each_insn_op_loc(&loc, i, op_loc) { struct data_loc_info dloc = { .arch = arch, From 24a30ce9b14ce84b00105b970c4d16eabe09a62a Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Mon, 13 Oct 2025 18:15:59 +0000 Subject: [PATCH 103/684] perf annotate: Track address registers via TSR_KIND_POINTER Introduce TSR_KIND_POINTER to improve the data type profiler's ability to track pointer-based memory accesses and address register variables. TSR_KIND_POINTER represents that the location holds a pointer type to the type in the type state. The semantics match the `breg` registers that describe a memory location. This change implements handling for this new kind in mov instructions and in the check_matching_type() function. When a TSR_KIND_POINTER is moved to the stack, the stack state size is set to the architecture's pointer size. Signed-off-by: Zecheng Li Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/annotate/instructions.c | 15 ++++- tools/perf/util/annotate-data.c | 63 ++++++++++++++++++--- tools/perf/util/annotate-data.h | 1 + 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c index da98a4e3c52c21..746443e0408968 100644 --- a/tools/perf/arch/x86/annotate/instructions.c +++ b/tools/perf/arch/x86/annotate/instructions.c @@ -391,7 +391,7 @@ static void update_insn_state_x86(struct type_state *state, tsr->ok = true; /* To copy back the variable type later (hopefully) */ - if (tsr->kind == TSR_KIND_TYPE) + if (tsr->kind == TSR_KIND_TYPE || tsr->kind == TSR_KIND_POINTER) tsr->copied_from = src->reg1; pr_debug_dtp("mov [%x] reg%d -> reg%d", @@ -455,6 +455,19 @@ static void update_insn_state_x86(struct type_state *state, insn_offset, src->offset, sreg, dst->reg1); pr_debug_type_name(&tsr->type, tsr->kind); } + /* Handle dereference of TSR_KIND_POINTER registers */ + else if (has_reg_type(state, sreg) && state->regs[sreg].ok && + state->regs[sreg].kind == TSR_KIND_POINTER && + die_get_member_type(&state->regs[sreg].type, + src->offset, &type_die)) { + tsr->type = state->regs[sreg].type; + tsr->kind = TSR_KIND_TYPE; + tsr->ok = true; + + pr_debug_dtp("mov [%x] addr %#x(reg%d) -> reg%d", + insn_offset, src->offset, sreg, dst->reg1); + pr_debug_type_name(&tsr->type, tsr->kind); + } /* Or check if it's a global variable */ else if (sreg == DWARF_REG_PC) { struct map_symbol *ms = dloc->ms; diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 903027a6fb7d3a..48f3bf20070f03 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -59,6 +59,10 @@ void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind) pr_info(" constant\n"); return; case TSR_KIND_PERCPU_POINTER: + pr_info(" percpu pointer"); + /* it also prints the type info */ + break; + case TSR_KIND_POINTER: pr_info(" pointer"); /* it also prints the type info */ break; @@ -578,16 +582,25 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, int tag; Dwarf_Word size; - if (dwarf_aggregate_size(type_die, &size) < 0) + if (kind == TSR_KIND_POINTER) { + /* TODO: arch-dependent pointer size */ + size = sizeof(void *); + } + else if (dwarf_aggregate_size(type_die, &size) < 0) size = 0; - tag = dwarf_tag(type_die); - stack->type = *type_die; stack->size = size; stack->offset = offset; stack->kind = kind; + if (kind == TSR_KIND_POINTER) { + stack->compound = false; + return; + } + + tag = dwarf_tag(type_die); + switch (tag) { case DW_TAG_structure_type: case DW_TAG_union_type: @@ -898,13 +911,25 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo reg = &state->regs[var->reg]; - /* For gp registers, skip the address registers for now */ - if (var->is_reg_var_addr) + if (reg->ok && reg->kind == TSR_KIND_TYPE && + (!is_better_type(®->type, &mem_die) || var->is_reg_var_addr)) continue; - if (reg->ok && reg->kind == TSR_KIND_TYPE && - !is_better_type(®->type, &mem_die)) + /* Handle address registers with TSR_KIND_POINTER */ + if (var->is_reg_var_addr) { + if (reg->ok && reg->kind == TSR_KIND_POINTER && + !is_better_type(®->type, &mem_die)) + continue; + + reg->type = mem_die; + reg->kind = TSR_KIND_POINTER; + reg->ok = true; + + pr_debug_dtp("var [%"PRIx64"] reg%d addr offset %x", + insn_offset, var->reg, var->offset); + pr_debug_type_name(&mem_die, TSR_KIND_POINTER); continue; + } orig_type = reg->type; @@ -1116,6 +1141,30 @@ static enum type_match_result check_matching_type(struct type_state *state, return PERF_TMR_OK; } + if (state->regs[reg].kind == TSR_KIND_POINTER) { + struct strbuf sb; + + strbuf_init(&sb, 32); + die_get_typename_from_type(&state->regs[reg].type, &sb); + pr_debug_dtp("(ptr->%s)", sb.buf); + strbuf_release(&sb); + + /* + * Register holds a pointer (address) to the target variable. + * The type is the type of the variable it points to. + */ + *type_die = state->regs[reg].type; + + dloc->type_offset = dloc->op->offset; + + /* Get the size of the actual type */ + if (dwarf_aggregate_size(type_die, &size) < 0 || + (unsigned)dloc->type_offset >= size) + return PERF_TMR_BAD_OFFSET; + + return PERF_TMR_OK; + } + if (state->regs[reg].kind == TSR_KIND_PERCPU_POINTER) { pr_debug_dtp("percpu ptr"); diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index df52a0a1f49653..0267834420569f 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -35,6 +35,7 @@ enum type_state_kind { TSR_KIND_PERCPU_BASE, TSR_KIND_CONST, TSR_KIND_PERCPU_POINTER, + TSR_KIND_POINTER, TSR_KIND_CANARY, }; From 1f4cc4ae3f8ae661bae3722e973a0f5be650fcbf Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Mon, 13 Oct 2025 18:16:00 +0000 Subject: [PATCH 104/684] perf annotate: Track arithmetic instructions on pointers Track the arithmetic operations on registers with pointer types. We handle only add, sub and lea instructions. The original pointer information needs to be preserved for getting outermost struct types. For example, reg0 points to a struct cfs_rq, when we add 0x10 to reg0, it should preserve the information of struct cfs_rq + 0x10 in the register instead of a pointer type to the child field at 0x10. Details: 1. struct type_state_reg now includes an offset, indicating if the register points to the start or an internal part of its associated type. This offset is used in mem to reg and reg to stack mem transfers, and also applied to the final type offset. 2. lea offset(%sp/%fp), reg is now treated as taking the address of a stack variable. It worked fine in most cases, but an issue with this approach is the pointer type may not exist. 3. lea offset(%base), reg is handled by moving the type from %base and adding an offset, similar to an add operation followed by a mov reg to reg. 4. Non-stack variables from DWARF with non-zero offsets in their location expressions are now accepted with register offset tracking. Multi-register addressing modes in LEA are not supported. Signed-off-by: Zecheng Li Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/annotate/instructions.c | 137 +++++++++++++++++++- tools/perf/util/annotate-data.c | 17 ++- tools/perf/util/annotate-data.h | 6 + 3 files changed, 152 insertions(+), 8 deletions(-) diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c index 746443e0408968..def7729a394c95 100644 --- a/tools/perf/arch/x86/annotate/instructions.c +++ b/tools/perf/arch/x86/annotate/instructions.c @@ -248,6 +248,7 @@ static void update_insn_state_x86(struct type_state *state, tsr = &state->regs[state->ret_reg]; tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("call [%x] return -> reg%d", @@ -284,6 +285,7 @@ static void update_insn_state_x86(struct type_state *state, !strcmp(var_name, "this_cpu_off") && tsr->kind == TSR_KIND_CONST) { tsr->kind = TSR_KIND_PERCPU_BASE; + tsr->offset = 0; tsr->ok = true; imm_value = tsr->imm_value; } @@ -291,6 +293,19 @@ static void update_insn_state_x86(struct type_state *state, else return; + /* Ignore add to non-pointer or non-const types */ + if (tsr->kind == TSR_KIND_POINTER || + (dwarf_tag(&tsr->type) == DW_TAG_pointer_type && + src->reg1 != DWARF_REG_PC && tsr->kind == TSR_KIND_TYPE && !dst->mem_ref)) { + tsr->offset += imm_value; + pr_debug_dtp("add [%x] offset %#"PRIx64" to reg%d", + insn_offset, imm_value, dst->reg1); + pr_debug_type_name(&tsr->type, tsr->kind); + } + + if (tsr->kind == TSR_KIND_CONST) + tsr->imm_value += imm_value; + if (tsr->kind != TSR_KIND_PERCPU_BASE) return; @@ -302,6 +317,7 @@ static void update_insn_state_x86(struct type_state *state, */ tsr->type = type_die; tsr->kind = TSR_KIND_PERCPU_POINTER; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("add [%x] percpu %#"PRIx64" -> reg%d", @@ -311,6 +327,106 @@ static void update_insn_state_x86(struct type_state *state, return; } + if (!strncmp(dl->ins.name, "sub", 3)) { + u64 imm_value = -1ULL; + + if (!has_reg_type(state, dst->reg1)) + return; + + tsr = &state->regs[dst->reg1]; + tsr->copied_from = -1; + + if (src->imm) + imm_value = src->offset; + else if (has_reg_type(state, src->reg1) && + state->regs[src->reg1].kind == TSR_KIND_CONST) + imm_value = state->regs[src->reg1].imm_value; + + if (tsr->kind == TSR_KIND_POINTER || + (dwarf_tag(&tsr->type) == DW_TAG_pointer_type && + src->reg1 != DWARF_REG_PC && tsr->kind == TSR_KIND_TYPE && !dst->mem_ref)) { + tsr->offset -= imm_value; + pr_debug_dtp("sub [%x] offset %#"PRIx64" to reg%d", + insn_offset, imm_value, dst->reg1); + pr_debug_type_name(&tsr->type, tsr->kind); + } + + if (tsr->kind == TSR_KIND_CONST) + tsr->imm_value -= imm_value; + + return; + } + + if (!strncmp(dl->ins.name, "lea", 3)) { + int sreg = src->reg1; + struct type_state_reg src_tsr; + + if (!has_reg_type(state, sreg) || + !has_reg_type(state, dst->reg1) || + !src->mem_ref) + return; + + src_tsr = state->regs[sreg]; + tsr = &state->regs[dst->reg1]; + + tsr->copied_from = -1; + tsr->ok = false; + + /* Case 1: Based on stack pointer or frame pointer */ + if (sreg == fbreg || sreg == state->stack_reg) { + struct type_state_stack *stack; + int offset = src->offset - fboff; + + stack = find_stack_state(state, offset); + if (!stack) + return; + + tsr->type = stack->type; + tsr->kind = TSR_KIND_POINTER; + tsr->offset = offset - stack->offset; + tsr->ok = true; + + if (sreg == fbreg) { + pr_debug_dtp("lea [%x] address of -%#x(stack) -> reg%d", + insn_offset, -src->offset, dst->reg1); + } else { + pr_debug_dtp("lea [%x] address of %#x(reg%d) -> reg%d", + insn_offset, src->offset, sreg, dst->reg1); + } + + pr_debug_type_name(&tsr->type, tsr->kind); + } + /* Case 2: Based on a register holding a typed pointer */ + else if (src_tsr.ok && (src_tsr.kind == TSR_KIND_POINTER || + (dwarf_tag(&src_tsr.type) == DW_TAG_pointer_type && + src_tsr.kind == TSR_KIND_TYPE))) { + + if (src_tsr.kind == TSR_KIND_TYPE && + __die_get_real_type(&state->regs[sreg].type, &type_die) == NULL) + return; + + if (src_tsr.kind == TSR_KIND_POINTER) + type_die = state->regs[sreg].type; + + /* Check if the target type has a member at the new offset */ + if (die_get_member_type(&type_die, + src->offset + src_tsr.offset, &type_die) == NULL) + return; + + tsr->type = src_tsr.type; + tsr->kind = src_tsr.kind; + tsr->offset = src->offset + src_tsr.offset; + tsr->ok = true; + + pr_debug_dtp("lea [%x] address of %s%#x(reg%d) -> reg%d", + insn_offset, src->offset < 0 ? "-" : "", + abs(src->offset), sreg, dst->reg1); + + pr_debug_type_name(&tsr->type, tsr->kind); + } + return; + } + if (strncmp(dl->ins.name, "mov", 3)) return; @@ -345,6 +461,7 @@ static void update_insn_state_x86(struct type_state *state, if (var_addr == 40) { tsr->kind = TSR_KIND_CANARY; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] stack canary -> reg%d\n", @@ -361,6 +478,7 @@ static void update_insn_state_x86(struct type_state *state, tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] this-cpu addr=%#"PRIx64" -> reg%d", @@ -372,6 +490,7 @@ static void update_insn_state_x86(struct type_state *state, if (src->imm) { tsr->kind = TSR_KIND_CONST; tsr->imm_value = src->offset; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] imm=%#x -> reg%d\n", @@ -388,6 +507,7 @@ static void update_insn_state_x86(struct type_state *state, tsr->type = state->regs[src->reg1].type; tsr->kind = state->regs[src->reg1].kind; tsr->imm_value = state->regs[src->reg1].imm_value; + tsr->offset = state->regs[src->reg1].offset; tsr->ok = true; /* To copy back the variable type later (hopefully) */ @@ -421,12 +541,14 @@ static void update_insn_state_x86(struct type_state *state, } else if (!stack->compound) { tsr->type = stack->type; tsr->kind = stack->kind; + tsr->offset = 0; tsr->ok = true; } else if (die_get_member_type(&stack->type, offset - stack->offset, &type_die)) { tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; } else { tsr->ok = false; @@ -446,9 +568,10 @@ static void update_insn_state_x86(struct type_state *state, else if (has_reg_type(state, sreg) && state->regs[sreg].ok && state->regs[sreg].kind == TSR_KIND_TYPE && die_deref_ptr_type(&state->regs[sreg].type, - src->offset, &type_die)) { + src->offset + state->regs[sreg].offset, &type_die)) { tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] %#x(reg%d) -> reg%d", @@ -459,9 +582,10 @@ static void update_insn_state_x86(struct type_state *state, else if (has_reg_type(state, sreg) && state->regs[sreg].ok && state->regs[sreg].kind == TSR_KIND_POINTER && die_get_member_type(&state->regs[sreg].type, - src->offset, &type_die)) { + src->offset + state->regs[sreg].offset, &type_die)) { tsr->type = state->regs[sreg].type; tsr->kind = TSR_KIND_TYPE; + tsr->offset = src->offset + state->regs[sreg].offset; tsr->ok = true; pr_debug_dtp("mov [%x] addr %#x(reg%d) -> reg%d", @@ -486,6 +610,7 @@ static void update_insn_state_x86(struct type_state *state, tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] global addr=%"PRIx64" -> reg%d", @@ -517,6 +642,7 @@ static void update_insn_state_x86(struct type_state *state, die_get_member_type(&type_die, offset, &type_die)) { tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; if (src->multi_regs) { @@ -539,6 +665,7 @@ static void update_insn_state_x86(struct type_state *state, src->offset, &type_die)) { tsr->type = type_die; tsr->kind = TSR_KIND_TYPE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] pointer %#x(reg%d) -> reg%d", @@ -561,6 +688,7 @@ static void update_insn_state_x86(struct type_state *state, &var_name, &offset) && !strcmp(var_name, "__per_cpu_offset")) { tsr->kind = TSR_KIND_PERCPU_BASE; + tsr->offset = 0; tsr->ok = true; pr_debug_dtp("mov [%x] percpu base reg%d\n", @@ -609,6 +737,11 @@ static void update_insn_state_x86(struct type_state *state, pr_debug_dtp("mov [%x] reg%d -> %#x(reg%d)", insn_offset, src->reg1, offset, dst->reg1); } + if (tsr->offset != 0) { + pr_debug_dtp(" reg%d offset %#x ->", + src->reg1, tsr->offset); + } + pr_debug_type_name(&tsr->type, tsr->kind); } /* diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 48f3bf20070f03..4204a7956ee5a8 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -905,7 +905,7 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo insn_offset, -offset); } pr_debug_type_name(&mem_die, TSR_KIND_TYPE); - } else if (has_reg_type(state, var->reg) && var->offset == 0) { + } else if (has_reg_type(state, var->reg)) { struct type_state_reg *reg; Dwarf_Die orig_type; @@ -921,6 +921,7 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo !is_better_type(®->type, &mem_die)) continue; + reg->offset = -var->offset; reg->type = mem_die; reg->kind = TSR_KIND_POINTER; reg->ok = true; @@ -932,13 +933,17 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo } orig_type = reg->type; - + /* + * var->offset + reg value is the beginning of the struct + * reg->offset is the offset the reg points + */ + reg->offset = -var->offset; reg->type = mem_die; reg->kind = TSR_KIND_TYPE; reg->ok = true; - pr_debug_dtp("var [%"PRIx64"] reg%d", - insn_offset, var->reg); + pr_debug_dtp("var [%"PRIx64"] reg%d offset %x", + insn_offset, var->reg, var->offset); pr_debug_type_name(&mem_die, TSR_KIND_TYPE); /* @@ -1126,7 +1131,7 @@ static enum type_match_result check_matching_type(struct type_state *state, if (__die_get_real_type(&state->regs[reg].type, type_die) == NULL) return PERF_TMR_NO_POINTER; - dloc->type_offset = dloc->op->offset; + dloc->type_offset = dloc->op->offset + state->regs[reg].offset; if (dwarf_tag(type_die) == DW_TAG_typedef) die_get_real_type(type_die, &sized_type); @@ -1155,7 +1160,7 @@ static enum type_match_result check_matching_type(struct type_state *state, */ *type_die = state->regs[reg].type; - dloc->type_offset = dloc->op->offset; + dloc->type_offset = dloc->op->offset + state->regs[reg].offset; /* Get the size of the actual type */ if (dwarf_aggregate_size(type_die, &size) < 0 || diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 0267834420569f..14655b76db65ae 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -174,6 +174,12 @@ extern struct annotated_data_stat ann_data_stat; struct type_state_reg { Dwarf_Die type; u32 imm_value; + /* + * The offset within the struct that the register points to. + * A value of 0 means the register points to the beginning. + * type_offset = op->offset + reg->offset + */ + s32 offset; bool ok; bool caller_saved; u8 kind; From 109218718de2f7173fabdd507cc6786e79ad1690 Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Mon, 13 Oct 2025 18:16:01 +0000 Subject: [PATCH 105/684] perf annotate: Save pointer offset in stack state The tracked pointer offset was not being preserved in the stack state, which could lead to incorrect type analysis. This change adds a ptr_offset field to the type_state_stack struct and passes it to set_stack_state and findnew_stack_state to ensure the offset is preserved after the pointer is loaded from a stack location. It improves the type annotation coverage and quality. Signed-off-by: Zecheng Li Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/annotate/instructions.c | 6 +++--- tools/perf/util/annotate-data.c | 12 +++++++----- tools/perf/util/annotate-data.h | 7 +++++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c index def7729a394c95..0c87e42ca3dc24 100644 --- a/tools/perf/arch/x86/annotate/instructions.c +++ b/tools/perf/arch/x86/annotate/instructions.c @@ -541,7 +541,7 @@ static void update_insn_state_x86(struct type_state *state, } else if (!stack->compound) { tsr->type = stack->type; tsr->kind = stack->kind; - tsr->offset = 0; + tsr->offset = stack->ptr_offset; tsr->ok = true; } else if (die_get_member_type(&stack->type, offset - stack->offset, @@ -724,10 +724,10 @@ static void update_insn_state_x86(struct type_state *state, */ if (!stack->compound) set_stack_state(stack, offset, tsr->kind, - &tsr->type); + &tsr->type, tsr->offset); } else { findnew_stack_state(state, offset, tsr->kind, - &tsr->type); + &tsr->type, tsr->offset); } if (dst->reg1 == fbreg) { diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 4204a7956ee5a8..e183c6104d5940 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -577,7 +577,7 @@ struct type_state_stack *find_stack_state(struct type_state *state, } void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, - Dwarf_Die *type_die) + Dwarf_Die *type_die, int ptr_offset) { int tag; Dwarf_Word size; @@ -592,6 +592,7 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, stack->type = *type_die; stack->size = size; stack->offset = offset; + stack->ptr_offset = ptr_offset; stack->kind = kind; if (kind == TSR_KIND_POINTER) { @@ -614,18 +615,19 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, struct type_state_stack *findnew_stack_state(struct type_state *state, int offset, u8 kind, - Dwarf_Die *type_die) + Dwarf_Die *type_die, + int ptr_offset) { struct type_state_stack *stack = find_stack_state(state, offset); if (stack) { - set_stack_state(stack, offset, kind, type_die); + set_stack_state(stack, offset, kind, type_die, ptr_offset); return stack; } stack = malloc(sizeof(*stack)); if (stack) { - set_stack_state(stack, offset, kind, type_die); + set_stack_state(stack, offset, kind, type_die, ptr_offset); list_add(&stack->list, &state->stack_vars); } return stack; @@ -895,7 +897,7 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo continue; findnew_stack_state(state, offset, TSR_KIND_TYPE, - &mem_die); + &mem_die, /*ptr_offset=*/0); if (var->reg == state->stack_reg) { pr_debug_dtp("var [%"PRIx64"] %#x(reg%d)", diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 14655b76db65ae..869307c7f1300b 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -191,6 +191,8 @@ struct type_state_stack { struct list_head list; Dwarf_Die type; int offset; + /* pointer offset, saves tsr->offset on the stack state */ + int ptr_offset; int size; bool compound; u8 kind; @@ -247,9 +249,10 @@ int annotated_data_type__get_member_name(struct annotated_data_type *adt, bool has_reg_type(struct type_state *state, int reg); struct type_state_stack *findnew_stack_state(struct type_state *state, int offset, u8 kind, - Dwarf_Die *type_die); + Dwarf_Die *type_die, + int ptr_offset); void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, - Dwarf_Die *type_die); + Dwarf_Die *type_die, int ptr_offset); struct type_state_stack *find_stack_state(struct type_state *state, int offset); bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc, From a1d8548c23076c66d96647f5f6f25aa43567f247 Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Mon, 13 Oct 2025 18:16:02 +0000 Subject: [PATCH 106/684] perf annotate: Invalidate register states for untracked instructions When tracking variable types, instructions that modify a pointer value in an untracked way can lead to incorrect type propagation. To prevent this, invalidate the register state when encountering such instructions. This change invalidates pointer types for various arithmetic and bitwise operations that current pointer offset tracking doesn't support, like imul, shl, and, inc, etc. A special case is added for 'xor reg, reg', which is a common idiom for zeroing a register. For this, the register state is updated to be a constant with a value of 0. This could introduce slight regressions if a variable is zeroed and then reused. This can be addressed in the future by using all DWARF locations for instruction tracking instead of only the first one. Signed-off-by: Zecheng Li Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/annotate/instructions.c | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c index 0c87e42ca3dc24..803f9351a3fb61 100644 --- a/tools/perf/arch/x86/annotate/instructions.c +++ b/tools/perf/arch/x86/annotate/instructions.c @@ -427,6 +427,35 @@ static void update_insn_state_x86(struct type_state *state, return; } + /* Invalidate register states for other ops which may change pointers */ + if (has_reg_type(state, dst->reg1) && !dst->mem_ref && + dwarf_tag(&state->regs[dst->reg1].type) == DW_TAG_pointer_type) { + if (!strncmp(dl->ins.name, "imul", 4) || !strncmp(dl->ins.name, "mul", 3) || + !strncmp(dl->ins.name, "idiv", 4) || !strncmp(dl->ins.name, "div", 3) || + !strncmp(dl->ins.name, "shl", 3) || !strncmp(dl->ins.name, "shr", 3) || + !strncmp(dl->ins.name, "sar", 3) || !strncmp(dl->ins.name, "and", 3) || + !strncmp(dl->ins.name, "or", 2) || !strncmp(dl->ins.name, "neg", 3) || + !strncmp(dl->ins.name, "inc", 3) || !strncmp(dl->ins.name, "dec", 3)) { + pr_debug_dtp("%s [%x] invalidate reg%d\n", + dl->ins.name, insn_offset, dst->reg1); + state->regs[dst->reg1].ok = false; + state->regs[dst->reg1].copied_from = -1; + return; + } + + if (!strncmp(dl->ins.name, "xor", 3) && dst->reg1 == src->reg1) { + /* xor reg, reg clears the register */ + pr_debug_dtp("xor [%x] clear reg%d\n", + insn_offset, dst->reg1); + + state->regs[dst->reg1].kind = TSR_KIND_CONST; + state->regs[dst->reg1].imm_value = 0; + state->regs[dst->reg1].ok = true; + state->regs[dst->reg1].copied_from = -1; + return; + } + } + if (strncmp(dl->ins.name, "mov", 3)) return; From 6837c006d4e72d6add451411bcf407e0dea4ad25 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 21 Oct 2025 15:24:47 +0000 Subject: [PATCH 107/684] firmware: exynos-acpm: add empty method to allow compile test Provide empty method for devm_acpm_get_by_node() if we aren't building in the CONFIG_EXYNOS_ACPM_PROTOCOL. This allows to test-build the CONFIG_EXYNOS_ACPM_CLK code. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202510211905.RgfWkgss-lkp@intel.com/ Fixes: 40498a742053 ("clk: samsung: add Exynos ACPM clock driver") Signed-off-by: Tudor Ambarus Link: https://patch.msgid.link/20251021-fix-acpm-clk-build-test-v1-1-236a3d6db7f5@linaro.org Signed-off-by: Krzysztof Kozlowski --- include/linux/firmware/samsung/exynos-acpm-protocol.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/firmware/samsung/exynos-acpm-protocol.h b/include/linux/firmware/samsung/exynos-acpm-protocol.h index b1e95435240fdb..2091da965a5ad2 100644 --- a/include/linux/firmware/samsung/exynos-acpm-protocol.h +++ b/include/linux/firmware/samsung/exynos-acpm-protocol.h @@ -55,7 +55,16 @@ struct acpm_handle { struct device; +#if IS_ENABLED(CONFIG_EXYNOS_ACPM_PROTOCOL) const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, struct device_node *np); +#else + +static inline const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, + struct device_node *np) +{ + return NULL; +} +#endif #endif /* __EXYNOS_ACPM_PROTOCOL_H */ From 8c10adaf337fb24a9f43dd08c37476da26d0be5d Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 13 Oct 2025 14:12:05 -0500 Subject: [PATCH 108/684] dt-bindings: pinctrl: Convert actions,s700-pinctrl to DT schema Convert the actions,s700-pinctrl binding to DT schema format. It's a straight-forward conversion. Signed-off-by: Rob Herring (Arm) Acked-by: Manivannan Sadhasivam Signed-off-by: Linus Walleij --- .../bindings/pinctrl/actions,s700-pinctrl.txt | 170 --------------- .../pinctrl/actions,s700-pinctrl.yaml | 204 ++++++++++++++++++ 2 files changed, 204 insertions(+), 170 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.txt deleted file mode 100644 index d13ff82f8518f9..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.txt +++ /dev/null @@ -1,170 +0,0 @@ -Actions Semi S700 Pin Controller - -This binding describes the pin controller found in the S700 SoC. - -Required Properties: - -- compatible: Should be "actions,s700-pinctrl" -- reg: Should contain the register base address and size of - the pin controller. -- clocks: phandle of the clock feeding the pin controller -- gpio-controller: Marks the device node as a GPIO controller. -- gpio-ranges: Specifies the mapping between gpio controller and - pin-controller pins. -- #gpio-cells: Should be two. The first cell is the gpio pin number - and the second cell is used for optional parameters. -- interrupt-controller: Marks the device node as an interrupt controller. -- #interrupt-cells: Specifies the number of cells needed to encode an - interrupt. Shall be set to 2. The first cell - defines the interrupt number, the second encodes - the trigger flags described in - bindings/interrupt-controller/interrupts.txt -- interrupts: The interrupt outputs from the controller. There is one GPIO - interrupt per GPIO bank. The number of interrupts listed depends - on the number of GPIO banks on the SoC. The interrupts must be - ordered by bank, starting with bank 0. - -Please refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the meaning of the -phrase "pin configuration node". - -The pin configuration nodes act as a container for an arbitrary number of -subnodes. Each of these subnodes represents some desired configuration for a -pin, a group, or a list of pins or groups. This configuration can include the -mux function to select on those group(s), and various pin configuration -parameters, such as pull-up, drive strength, etc. - -PIN CONFIGURATION NODES: - -The name of each subnode is not important; all subnodes should be enumerated -and processed purely based on their content. - -Each subnode only affects those parameters that are explicitly listed. In -other words, a subnode that lists a mux function but no pin configuration -parameters implies no information about any pin configuration parameters. -Similarly, a pin subnode that describes a pullup parameter implies no -information about e.g. the mux function. - -Pinmux functions are available only for the pin groups while pinconf -parameters are available for both pin groups and individual pins. - -The following generic properties as defined in pinctrl-bindings.txt are valid -to specify in a pin configuration subnode: - -Required Properties: - -- pins: An array of strings, each string containing the name of a pin. - These pins are used for selecting the pull control and schmitt - trigger parameters. The following are the list of pins - available: - - eth_txd0, eth_txd1, eth_txd2, eth_txd3, eth_txen, eth_rxer, - eth_crs_dv, eth_rxd1, eth_rxd0, eth_rxd2, eth_rxd3, eth_ref_clk, - eth_mdc, eth_mdio, sirq0, sirq1, sirq2, i2s_d0, i2s_bclk0, - i2s_lrclk0, i2s_mclk0, i2s_d1, i2s_bclk1, i2s_lrclk1, i2s_mclk1, - pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, ks_in0, ks_in1, ks_in2, - ks_in3, ks_out0, ks_out1, ks_out2, lvds_oep, lvds_oen, lvds_odp, - lvds_odn, lvds_ocp, lvds_ocn, lvds_obp, lvds_obn, lvds_oap, - lvds_oan, lvds_eep, lvds_een, lvds_edp, lvds_edn, lvds_ecp, - lvds_ecn, lvds_ebp, lvds_ebn, lvds_eap, lvds_ean, lcd0_d18, - lcd0_d2, dsi_dp3, dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, dsi_cn, - dsi_dp0, dsi_dn0, dsi_dp2, dsi_dn2, sd0_d0, sd0_d1, sd0_d2, - sd0_d3, sd1_d0, sd1_d1, sd1_d2, sd1_d3, sd0_cmd, sd0_clk, - sd1_cmd, sd1_clk, spi0_ss, spi0_miso, uart0_rx, uart0_tx, - uart2_rx, uart2_tx, uart2_rtsb, uart2_ctsb, uart3_rx, uart3_tx, - uart3_rtsb, uart3_ctsb, i2c0_sclk, i2c0_sdata, i2c1_sclk, - i2c1_sdata, i2c2_sdata, csi_dn0, csi_dp0, csi_dn1, csi_dp1, - csi_cn, csi_cp, csi_dn2, csi_dp2, csi_dn3, csi_dp3, - sensor0_pclk, sensor0_ckout, dnand_d0, dnand_d1, dnand_d2, - dnand_d3, dnand_d4, dnand_d5, dnand_d6, dnand_d7, dnand_wrb, - dnand_rdb, dnand_rdbn, dnand_dqs, dnand_dqsn, dnand_rb0, - dnand_ale, dnand_cle, dnand_ceb0, dnand_ceb1, dnand_ceb2, - dnand_ceb3, porb, clko_25m, bsel, pkg0, pkg1, pkg2, pkg3 - -- groups: An array of strings, each string containing the name of a pin - group. These pin groups are used for selecting the pinmux - functions. - rgmii_txd23_mfp, rgmii_rxd2_mfp, rgmii_rxd3_mfp, lcd0_d18_mfp, - rgmii_txd01_mfp, rgmii_txd0_mfp, rgmii_txd1_mfp, rgmii_txen_mfp, - rgmii_rxen_mfp, rgmii_rxd1_mfp, rgmii_rxd0_mfp, rgmii_ref_clk_mfp, - i2s_d0_mfp, i2s_pcm1_mfp, i2s0_pcm0_mfp, i2s1_pcm0_mfp, - i2s_d1_mfp, ks_in2_mfp, ks_in1_mfp, ks_in0_mfp, ks_in3_mfp, - ks_out0_mfp, ks_out1_mfp, ks_out2_mfp, lvds_o_pn_mfp, dsi_dn0_mfp, - dsi_dp2_mfp, lcd0_d2_mfp, dsi_dp3_mfp, dsi_dn3_mfp, dsi_dp0_mfp, - lvds_ee_pn_mfp, uart2_rx_tx_mfp, spi0_i2c_pcm_mfp, dsi_dnp1_cp_d2_mfp, - dsi_dnp1_cp_d17_mfp, lvds_e_pn_mfp, dsi_dn2_mfp, uart2_rtsb_mfp, - uart2_ctsb_mfp, uart3_rtsb_mfp, uart3_ctsb_mfp, sd0_d0_mfp, sd0_d1_mfp, - sd0_d2_d3_mfp, sd1_d0_d3_mfp, sd0_cmd_mfp, sd0_clk_mfp, sd1_cmd_mfp, - uart0_rx_mfp, clko_25m_mfp, csi_cn_cp_mfp, sens0_ckout_mfp, uart0_tx_mfp, - i2c0_mfp, csi_dn_dp_mfp, sen0_pclk_mfp, pcm1_in_mfp, pcm1_clk_mfp, - pcm1_sync_mfp, pcm1_out_mfp, dnand_data_wr_mfp, dnand_acle_ce0_mfp, - nand_ceb2_mfp, nand_ceb3_mfp - - These pin groups are used for selecting the drive strength - parameters. - - sirq_drv, rgmii_txd23_drv, rgmii_rxd23_drv, rgmii_txd01_txen_drv, - rgmii_rxer_drv, rgmii_crs_drv, rgmii_rxd10_drv, rgmii_ref_clk_drv, - smi_mdc_mdio_drv, i2s_d0_drv, i2s_bclk0_drv, i2s3_drv, i2s13_drv, - pcm1_drv, ks_in_drv, ks_out_drv, lvds_all_drv, lcd_d18_d2_drv, - dsi_all_drv, sd0_d0_d3_drv, sd0_cmd_drv, sd0_clk_drv, spi0_all_drv, - uart0_rx_drv, uart0_tx_drv, uart2_all_drv, i2c0_all_drv, i2c12_all_drv, - sens0_pclk_drv, sens0_ckout_drv, uart3_all_drv - -- function: An array of strings, each string containing the name of the - pinmux functions. These functions can only be selected by - the corresponding pin groups. The following are the list of - pinmux functions available: - - nor, eth_rgmii, eth_sgmii, spi0, spi1, spi2, spi3, seNs0, sens1, - uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0, i2s1, - pcm1, pcm0, ks, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, p0, - sd0, sd1, sd2, i2c0, i2c1, i2c2, i2c3, dsi, lvds, usb30, - clko_25m, mipi_csi, nand, spdif, sirq0, sirq1, sirq2, bt, lcd0 - -Optional Properties: - -- bias-pull-down: No arguments. The specified pins should be configured as - pull down. -- bias-pull-up: No arguments. The specified pins should be configured as - pull up. -- input-schmitt-enable: No arguments: Enable schmitt trigger for the specified - pins -- input-schmitt-disable: No arguments: Disable schmitt trigger for the specified - pins -- drive-strength: Integer. Selects the drive strength for the specified - pins in mA. - Valid values are: - <2> - <4> - <8> - <12> - -Example: - - pinctrl: pinctrl@e01b0000 { - compatible = "actions,s700-pinctrl"; - reg = <0x0 0xe01b0000 0x0 0x1000>; - clocks = <&cmu CLK_GPIO>; - gpio-controller; - gpio-ranges = <&pinctrl 0 0 136>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = , - , - , - , - ; - - uart3-default: uart3-default { - pinmux { - groups = "uart3_rtsb_mfp", "uart3_ctsb_mfp"; - function = "uart3"; - }; - pinconf { - groups = "uart3_all_drv"; - drive-strength = <2>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.yaml new file mode 100644 index 00000000000000..9597b983c332e3 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/actions,s700-pinctrl.yaml @@ -0,0 +1,204 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/actions,s700-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Actions Semi S700 Pin Controller + +maintainers: + - Manivannan Sadhasivam + +properties: + compatible: + const: actions,s700-pinctrl + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + gpio-controller: true + + gpio-line-names: + maxItems: 136 + + gpio-ranges: true + + '#gpio-cells': + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + interrupts: + maxItems: 5 + description: + The interrupt outputs from the controller. There is one GPIO interrupt per + GPIO bank. The interrupts must be ordered by bank, starting with + bank 0. + +additionalProperties: + type: object + description: Pin configuration subnode + additionalProperties: false + + properties: + pinmux: + description: Configure pin multiplexing. + type: object + $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + groups: + items: + enum: [ + rgmii_txd23_mfp, rgmii_rxd2_mfp, rgmii_rxd3_mfp, lcd0_d18_mfp, + rgmii_txd01_mfp, rgmii_txd0_mfp, rgmii_txd1_mfp, rgmii_txen_mfp, + rgmii_rxen_mfp, rgmii_rxd1_mfp, rgmii_rxd0_mfp, rgmii_ref_clk_mfp, + i2c1_dummy, i2c2_dummy, i2s_d0_mfp, i2s_pcm1_mfp, i2s0_pcm0_mfp, i2s1_pcm0_mfp, + i2s_d1_mfp, ks_in2_mfp, ks_in1_mfp, ks_in0_mfp, ks_in3_mfp, + ks_out0_mfp, ks_out1_mfp, ks_out2_mfp, lvds_o_pn_mfp, dsi_dn0_mfp, + dsi_dp2_mfp, lcd0_d2_mfp, dsi_dp3_mfp, dsi_dn3_mfp, dsi_dp0_mfp, + lvds_ee_pn_mfp, uart2_rx_tx_mfp, spi0_i2c_pcm_mfp, + dsi_dnp1_cp_d2_mfp, dsi_dnp1_cp_d17_mfp, lvds_e_pn_mfp, + dsi_dn2_mfp, uart2_rtsb_mfp, uart2_ctsb_mfp, uart3_rtsb_mfp, + uart3_ctsb_mfp, sd0_d0_mfp, sd0_d1_mfp, sd0_d2_d3_mfp, + sd1_d0_d3_mfp, sd0_cmd_mfp, sd0_clk_mfp, sd1_cmd_mfp, + uart0_rx_mfp, clko_25m_mfp, csi_cn_cp_mfp, sens0_ckout_mfp, + uart0_tx_mfp, i2c0_mfp, csi_dn_dp_mfp, sen0_pclk_mfp, pcm1_in_mfp, + pcm1_clk_mfp, pcm1_sync_mfp, pcm1_out_mfp, dnand_data_wr_mfp, + dnand_acle_ce0_mfp, nand_ceb2_mfp, nand_ceb3_mfp + ] + + function: + items: + enum: [ + nor, eth_rgmii, eth_sgmii, spi0, spi1, spi2, spi3, seNs0, sens1, + uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0, i2s1, pcm1, + pcm0, ks, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, p0, sd0, sd1, + sd2, i2c0, i2c1, i2c2, i2c3, dsi, lvds, usb30, clko_25m, mipi_csi, + nand, spdif, sirq0, sirq1, sirq2, bt, lcd0 + ] + + required: + - groups + - function + + pinconf: + description: Configure pin-specific parameters. + type: object + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + groups: + items: + enum: [ + sirq_drv, rgmii_txd23_drv, rgmii_rxd23_drv, rgmii_txd01_txen_drv, + rgmii_rxer_drv, rgmii_crs_drv, rgmii_rxd10_drv, rgmii_ref_clk_drv, + smi_mdc_mdio_drv, i2s_d0_drv, i2s_bclk0_drv, i2s3_drv, i2s13_drv, + pcm1_drv, ks_in_drv, ks_out_drv, lvds_all_drv, lcd_d18_d2_drv, + dsi_all_drv, sd0_d0_d3_drv, sd0_cmd_drv, sd0_clk_drv, + spi0_all_drv, uart0_rx_drv, uart0_tx_drv, uart2_all_drv, + i2c0_all_drv, i2c12_all_drv, sens0_pclk_drv, sens0_ckout_drv, + uart3_all_drv + ] + + pins: + items: + enum: [ + eth_txd0, eth_txd1, eth_txd2, eth_txd3, eth_txen, eth_rxer, + eth_crs_dv, eth_rxd1, eth_rxd0, eth_rxd2, eth_rxd3, eth_ref_clk, + eth_mdc, eth_mdio, sirq0, sirq1, sirq2, i2s_d0, i2s_bclk0, + i2s_lrclk0, i2s_mclk0, i2s_d1, i2s_bclk1, i2s_lrclk1, i2s_mclk1, + pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, ks_in0, ks_in1, ks_in2, + ks_in3, ks_out0, ks_out1, ks_out2, lvds_oep, lvds_oen, lvds_odp, + lvds_odn, lvds_ocp, lvds_ocn, lvds_obp, lvds_obn, lvds_oap, + lvds_oan, lvds_eep, lvds_een, lvds_edp, lvds_edn, lvds_ecp, + lvds_ecn, lvds_ebp, lvds_ebn, lvds_eap, lvds_ean, lcd0_d18, + lcd0_d2, dsi_dp3, dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, dsi_cn, + dsi_dp0, dsi_dn0, dsi_dp2, dsi_dn2, sd0_d0, sd0_d1, sd0_d2, + sd0_d3, sd1_d0, sd1_d1, sd1_d2, sd1_d3, sd0_cmd, sd0_clk, sd1_cmd, + sd1_clk, spi0_ss, spi0_miso, uart0_rx, uart0_tx, uart2_rx, + uart2_tx, uart2_rtsb, uart2_ctsb, uart3_rx, uart3_tx, uart3_rtsb, + uart3_ctsb, i2c0_sclk, i2c0_sdata, i2c1_sclk, i2c1_sdata, + i2c2_sclk, i2c2_sdata, csi_dn0, csi_dp0, csi_dn1, csi_dp1, csi_cn, csi_cp, + csi_dn2, csi_dp2, csi_dn3, csi_dp3, sensor0_pclk, sensor0_ckout, + dnand_d0, dnand_d1, dnand_d2, dnand_d3, dnand_d4, dnand_d5, + dnand_d6, dnand_d7, dnand_wrb, dnand_rdb, dnand_rdbn, dnand_dqs, + dnand_dqsn, dnand_rb0, dnand_ale, dnand_cle, dnand_ceb0, + dnand_ceb1, dnand_ceb2, dnand_ceb3, porb, clko_25m, bsel, pkg0, + pkg1, pkg2, pkg3 + ] + + bias-pull-down: + type: boolean + + bias-pull-up: + type: boolean + + drive-strength: + description: Selects the drive strength for the specified pins in mA. + enum: [2, 4, 8, 12] + + input-schmitt-enable: true + input-schmitt-disable: true + + oneOf: + - required: + - groups + - required: + - pins + + anyOf: + - required: [ pinmux ] + - required: [ pinconf ] + +required: + - compatible + - reg + - clocks + - gpio-controller + - gpio-ranges + - '#gpio-cells' + - interrupt-controller + - '#interrupt-cells' + - interrupts + +examples: + - | + #include + + pinctrl: pinctrl@e01b0000 { + compatible = "actions,s700-pinctrl"; + reg = <0xe01b0000 0x1000>; + clocks = <&cmu 1>; + gpio-controller; + gpio-ranges = <&pinctrl 0 0 136>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = , + , + , + , + ; + + uart3-default { + pinmux { + groups = "uart3_rtsb_mfp", "uart3_ctsb_mfp"; + function = "uart3"; + }; + pinconf { + groups = "uart3_all_drv"; + drive-strength = <2>; + }; + }; + }; From af1825d7668d98c6bb8dfd1abeb503ac6e0b449b Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 13 Oct 2025 14:12:16 -0500 Subject: [PATCH 109/684] dt-bindings: pinctrl: Convert actions,s900-pinctrl to DT schema Convert the actions,s900-pinctrl binding to DT schema format. It's a straight-forward conversion. Signed-off-by: Rob Herring (Arm) Acked-by: Manivannan Sadhasivam Signed-off-by: Linus Walleij --- .../bindings/pinctrl/actions,s900-pinctrl.txt | 204 ---------------- .../pinctrl/actions,s900-pinctrl.yaml | 219 ++++++++++++++++++ 2 files changed, 219 insertions(+), 204 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt deleted file mode 100644 index 81b58dddd3edcb..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt +++ /dev/null @@ -1,204 +0,0 @@ -Actions Semi S900 Pin Controller - -This binding describes the pin controller found in the S900 SoC. - -Required Properties: - -- compatible: Should be "actions,s900-pinctrl" -- reg: Should contain the register base address and size of - the pin controller. -- clocks: phandle of the clock feeding the pin controller -- gpio-controller: Marks the device node as a GPIO controller. -- gpio-ranges: Specifies the mapping between gpio controller and - pin-controller pins. -- #gpio-cells: Should be two. The first cell is the gpio pin number - and the second cell is used for optional parameters. -- interrupt-controller: Marks the device node as an interrupt controller. -- #interrupt-cells: Specifies the number of cells needed to encode an - interrupt. Shall be set to 2. The first cell - defines the interrupt number, the second encodes - the trigger flags described in - bindings/interrupt-controller/interrupts.txt -- interrupts: The interrupt outputs from the controller. There is one GPIO - interrupt per GPIO bank. The number of interrupts listed depends - on the number of GPIO banks on the SoC. The interrupts must be - ordered by bank, starting with bank 0. - -Please refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the meaning of the -phrase "pin configuration node". - -The pin configuration nodes act as a container for an arbitrary number of -subnodes. Each of these subnodes represents some desired configuration for a -pin, a group, or a list of pins or groups. This configuration can include the -mux function to select on those group(s), and various pin configuration -parameters, such as pull-up, drive strength, etc. - -PIN CONFIGURATION NODES: - -The name of each subnode is not important; all subnodes should be enumerated -and processed purely based on their content. - -Each subnode only affects those parameters that are explicitly listed. In -other words, a subnode that lists a mux function but no pin configuration -parameters implies no information about any pin configuration parameters. -Similarly, a pin subnode that describes a pullup parameter implies no -information about e.g. the mux function. - -Pinmux functions are available only for the pin groups while pinconf -parameters are available for both pin groups and individual pins. - -The following generic properties as defined in pinctrl-bindings.txt are valid -to specify in a pin configuration subnode: - -Required Properties: - -- pins: An array of strings, each string containing the name of a pin. - These pins are used for selecting the pull control and schmitt - trigger parameters. The following are the list of pins - available: - - eth_txd0, eth_txd1, eth_txen, eth_rxer, eth_crs_dv, - eth_rxd1, eth_rxd0, eth_ref_clk, eth_mdc, eth_mdio, - sirq0, sirq1, sirq2, i2s_d0, i2s_bclk0, i2s_lrclk0, - i2s_mclk0, i2s_d1, i2s_bclk1, i2s_lrclk1, i2s_mclk1, - pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, eram_a5, - eram_a6, eram_a7, eram_a8, eram_a9, eram_a10, eram_a11, - lvds_oep, lvds_oen, lvds_odp, lvds_odn, lvds_ocp, - lvds_ocn, lvds_obp, lvds_obn, lvds_oap, lvds_oan, - lvds_eep, lvds_een, lvds_edp, lvds_edn, lvds_ecp, - lvds_ecn, lvds_ebp, lvds_ebn, lvds_eap, lvds_ean, - sd0_d0, sd0_d1, sd0_d2, sd0_d3, sd1_d0, sd1_d1, - sd1_d2, sd1_d3, sd0_cmd, sd0_clk, sd1_cmd, sd1_clk, - spi0_sclk, spi0_ss, spi0_miso, spi0_mosi, uart0_rx, - uart0_tx, uart2_rx, uart2_tx, uart2_rtsb, uart2_ctsb, - uart3_rx, uart3_tx, uart3_rtsb, uart3_ctsb, uart4_rx, - uart4_tx, i2c0_sclk, i2c0_sdata, i2c1_sclk, i2c1_sdata, - i2c2_sclk, i2c2_sdata, csi0_dn0, csi0_dp0, csi0_dn1, - csi0_dp1, csi0_cn, csi0_cp, csi0_dn2, csi0_dp2, csi0_dn3, - csi0_dp3, dsi_dp3, dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, - dsi_cn, dsi_dp0, dsi_dn0, dsi_dp2, dsi_dn2, sensor0_pclk, - csi1_dn0,csi1_dp0,csi1_dn1, csi1_dp1, csi1_cn, csi1_cp, - sensor0_ckout, nand0_d0, nand0_d1, nand0_d2, nand0_d3, - nand0_d4, nand0_d5, nand0_d6, nand0_d7, nand0_dqs, - nand0_dqsn, nand0_ale, nand0_cle, nand0_ceb0, nand0_ceb1, - nand0_ceb2, nand0_ceb3, nand1_d0, nand1_d1, nand1_d2, - nand1_d3, nand1_d4, nand1_d5, nand1_d6, nand1_d7, nand1_dqs, - nand1_dqsn, nand1_ale, nand1_cle, nand1_ceb0, nand1_ceb1, - nand1_ceb2, nand1_ceb3, sgpio0, sgpio1, sgpio2, sgpio3 - -- groups: An array of strings, each string containing the name of a pin - group. These pin groups are used for selecting the pinmux - functions. - - lvds_oxx_uart4_mfp, rmii_mdc_mfp, rmii_mdio_mfp, sirq0_mfp, - sirq1_mfp, rmii_txd0_mfp, rmii_txd1_mfp, rmii_txen_mfp, - rmii_rxer_mfp, rmii_crs_dv_mfp, rmii_rxd1_mfp, rmii_rxd0_mfp, - rmii_ref_clk_mfp, i2s_d0_mfp, i2s_d1_mfp, i2s_lr_m_clk0_mfp, - i2s_bclk0_mfp, i2s_bclk1_mclk1_mfp, pcm1_in_out_mfp, - pcm1_clk_mfp, pcm1_sync_mfp, eram_a5_mfp, eram_a6_mfp, - eram_a7_mfp, eram_a8_mfp, eram_a9_mfp, eram_a10_mfp, - eram_a11_mfp, lvds_oep_odn_mfp, lvds_ocp_obn_mfp, - lvds_oap_oan_mfp, lvds_e_mfp, spi0_sclk_mosi_mfp, spi0_ss_mfp, - spi0_miso_mfp, uart2_rtsb_mfp, uart2_ctsb_mfp, uart3_rtsb_mfp, - uart3_ctsb_mfp, sd0_d0_mfp, sd0_d1_mfp, sd0_d2_d3_mfp, - sd1_d0_d3_mfp, sd0_cmd_mfp, sd0_clk_mfp, sd1_cmd_clk_mfp, - uart0_rx_mfp, nand0_d0_ceb3_mfp, uart0_tx_mfp, i2c0_mfp, - csi0_cn_cp_mfp, csi0_dn0_dp3_mfp, csi1_dn0_cp_mfp, - dsi_dp3_dn1_mfp, dsi_cp_dn0_mfp, dsi_dp2_dn2_mfp, - nand1_d0_ceb1_mfp, nand1_ceb3_mfp, nand1_ceb0_mfp, - csi1_dn0_dp0_mfp, uart4_rx_tx_mfp - - - These pin groups are used for selecting the drive strength - parameters. - - sgpio3_drv, sgpio2_drv, sgpio1_drv, sgpio0_drv, - rmii_tx_d0_d1_drv, rmii_txen_rxer_drv, rmii_crs_dv_drv, - rmii_rx_d1_d0_drv, rmii_ref_clk_drv, rmii_mdc_mdio_drv, - sirq_0_1_drv, sirq2_drv, i2s_d0_d1_drv, i2s_lr_m_clk0_drv, - i2s_blk1_mclk1_drv, pcm1_in_out_drv, lvds_oap_oan_drv, - lvds_oep_odn_drv, lvds_ocp_obn_drv, lvds_e_drv, sd0_d3_d0_drv, - sd1_d3_d0_drv, sd0_sd1_cmd_clk_drv, spi0_sclk_mosi_drv, - spi0_ss_miso_drv, uart0_rx_tx_drv, uart4_rx_tx_drv, uart2_drv, - uart3_drv, i2c0_drv, i2c1_drv, i2c2_drv, sensor0_drv - - These pin groups are used for selecting the slew rate - parameters. - - sgpio3_sr, sgpio2_sr, sgpio1_sr, sgpio0_sr, rmii_tx_d0_d1_sr, - rmii_txen_rxer_sr, rmii_crs_dv_sr, rmii_rx_d1_d0_sr, - rmii_ref_clk_sr, rmii_mdc_mdio_sr, sirq_0_1_sr, sirq2_sr, - i2s_do_d1_sr, i2s_lr_m_clk0_sr, i2s_bclk0_mclk1_sr, - pcm1_in_out_sr, sd1_d3_d0_sr, sd0_sd1_clk_cmd_sr, - spi0_sclk_mosi_sr, spi0_ss_miso_sr, uart0_rx_tx_sr, - uart4_rx_tx_sr, uart2_sr, uart3_sr, i2c0_sr, i2c1_sr, i2c2_sr, - sensor0_sr - -- function: An array of strings, each string containing the name of the - pinmux functions. These functions can only be selected by - the corresponding pin groups. The following are the list of - pinmux functions available: - - eram, eth_rmii, eth_smii, spi0, spi1, spi2, spi3, sens0, - uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0, i2s1, - pcm0, pcm1, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, sd0, - sd1, sd2, sd3, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, lvds, - usb30, usb20, gpu, mipi_csi0, mipi_csi1, mipi_dsi, nand0, - nand1, spdif, sirq0, sirq1, sirq2 - -Optional Properties: - -- bias-bus-hold: No arguments. The specified pins should retain the previous - state value. -- bias-high-impedance: No arguments. The specified pins should be configured - as high impedance. -- bias-pull-down: No arguments. The specified pins should be configured as - pull down. -- bias-pull-up: No arguments. The specified pins should be configured as - pull up. -- input-schmitt-enable: No arguments: Enable schmitt trigger for the specified - pins -- input-schmitt-disable: No arguments: Disable schmitt trigger for the specified - pins -- slew-rate: Integer. Sets slew rate for the specified pins. - Valid values are: - <0> - Slow - <1> - Fast -- drive-strength: Integer. Selects the drive strength for the specified - pins in mA. - Valid values are: - <2> - <4> - <8> - <12> - -Example: - - pinctrl: pinctrl@e01b0000 { - compatible = "actions,s900-pinctrl"; - reg = <0x0 0xe01b0000 0x0 0x1000>; - clocks = <&cmu CLK_GPIO>; - gpio-controller; - gpio-ranges = <&pinctrl 0 0 146>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = , - , - , - , - , - ; - - uart2-default: uart2-default { - pinmux { - groups = "lvds_oep_odn_mfp"; - function = "uart2"; - }; - pinconf { - groups = "lvds_oep_odn_drv"; - drive-strength = <12>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.yaml new file mode 100644 index 00000000000000..5c7b9f13226d00 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.yaml @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/actions,s900-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Actions Semi S900 Pin Controller + +maintainers: + - Manivannan Sadhasivam + +properties: + compatible: + const: actions,s900-pinctrl + + reg: + maxItems: 1 + + interrupts: + maxItems: 6 + description: The interrupt outputs from the controller. There is one GPIO + interrupt per GPIO bank. The number of interrupts listed depends on the + number of GPIO banks on the SoC. The interrupts must be ordered by bank, + starting with bank 0. + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + clocks: + maxItems: 1 + + gpio-controller: true + + gpio-line-names: + maxItems: 146 + + gpio-ranges: true + + "#gpio-cells": + const: 2 + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - "#interrupt-cells" + - clocks + - gpio-controller + - gpio-ranges + - "#gpio-cells" + +additionalProperties: + type: object + description: Pin configuration subnode + additionalProperties: false + + properties: + pinmux: + type: object + description: Pin mux configuration + $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + groups: + items: + enum: [ + lvds_oxx_uart4_mfp, rmii_mdc_mfp, rmii_mdio_mfp, sirq0_mfp, + sirq1_mfp, rmii_txd0_mfp, rmii_txd1_mfp, rmii_txen_mfp, + rmii_rxer_mfp, rmii_crs_dv_mfp, rmii_rxd1_mfp, rmii_rxd0_mfp, + rmii_ref_clk_mfp, i2s_d0_mfp, i2s_d1_mfp, i2s_lr_m_clk0_mfp, + i2s_bclk0_mfp, i2s_bclk1_mclk1_mfp, pcm1_in_out_mfp, pcm1_clk_mfp, + pcm1_sync_mfp, eram_a5_mfp, eram_a6_mfp, eram_a7_mfp, eram_a8_mfp, + eram_a9_mfp, eram_a10_mfp, eram_a11_mfp, lvds_oep_odn_mfp, + lvds_ocp_obn_mfp, lvds_oap_oan_mfp, lvds_e_mfp, + spi0_sclk_mosi_mfp, spi0_ss_mfp, spi0_miso_mfp, uart2_rtsb_mfp, + uart2_ctsb_mfp, uart3_rtsb_mfp, uart3_ctsb_mfp, sd0_d0_mfp, + sd0_d1_mfp, sd0_d2_d3_mfp, sd1_d0_d3_mfp, sd0_cmd_mfp, + sd0_clk_mfp, sd1_cmd_clk_mfp, uart0_rx_mfp, nand0_d0_ceb3_mfp, + uart0_tx_mfp, i2c0_mfp, csi0_cn_cp_mfp, csi0_dn0_dp3_mfp, + csi1_dn0_cp_mfp, dsi_dp3_dn1_mfp, dsi_cp_dn0_mfp, dsi_dp2_dn2_mfp, + nand1_d0_ceb1_mfp, nand1_ceb3_mfp, nand1_ceb0_mfp, + csi1_dn0_dp0_mfp, uart4_rx_tx_mfp + ] + + function: + items: + enum: [ + eram, eth_rmii, eth_smii, spi0, spi1, spi2, spi3, sens0, + uart0, uart1, uart2, uart3, uart4, uart5, uart6, i2s0, i2s1, + pcm0, pcm1, jtag, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, sd0, + sd1, sd2, sd3, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, lvds, + usb30, usb20, gpu, mipi_csi0, mipi_csi1, mipi_dsi, nand0, + nand1, spdif, sirq0, sirq1, sirq2 + ] + + required: + - groups + - function + + pinconf: + type: object + description: Pin configuration parameters + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + + additionalProperties: false + + properties: + groups: + items: + enum: [ + # pin groups for drive strength + sgpio3_drv, sgpio2_drv, sgpio1_drv, sgpio0_drv, rmii_tx_d0_d1_drv, + rmii_txen_rxer_drv, rmii_crs_dv_drv, rmii_rx_d1_d0_drv, + rmii_ref_clk_drv, rmii_mdc_mdio_drv, sirq_0_1_drv, sirq2_drv, + i2s_d0_d1_drv, i2s_lr_m_clk0_drv, i2s_blk1_mclk1_drv, + pcm1_in_out_drv, lvds_oap_oan_drv, lvds_oep_odn_drv, + lvds_ocp_obn_drv, lvds_e_drv, sd0_d3_d0_drv, sd1_d3_d0_drv, + sd0_sd1_cmd_clk_drv, spi0_sclk_mosi_drv, spi0_ss_miso_drv, + uart0_rx_tx_drv, uart4_rx_tx_drv, uart2_drv, uart3_drv, i2c0_drv, + i2c1_drv, i2c2_drv, sensor0_drv, + # pin groups for slew rate + sgpio3_sr, sgpio2_sr, sgpio1_sr, sgpio0_sr, rmii_tx_d0_d1_sr, + rmii_txen_rxer_sr, rmii_crs_dv_sr, rmii_rx_d1_d0_sr, + rmii_ref_clk_sr, rmii_mdc_mdio_sr, sirq_0_1_sr, sirq2_sr, + i2s_do_d1_sr, i2s_lr_m_clk0_sr, i2s_bclk0_mclk1_sr, + pcm1_in_out_sr, sd1_d3_d0_sr, sd0_sd1_clk_cmd_sr, + spi0_sclk_mosi_sr, spi0_ss_miso_sr, uart0_rx_tx_sr, + uart4_rx_tx_sr, uart2_sr, uart3_sr, i2c0_sr, i2c1_sr, i2c2_sr, + sensor0_sr + ] + + pins: + items: + enum: [ + eth_txd0, eth_txd1, eth_txen, eth_rxer, eth_crs_dv, eth_rxd1, + eth_rxd0, eth_ref_clk, eth_mdc, eth_mdio, sirq0, sirq1, sirq2, + i2s_d0, i2s_bclk0, i2s_lrclk0, i2s_mclk0, i2s_d1, i2s_bclk1, + i2s_lrclk1, i2s_mclk1, pcm1_in, pcm1_clk, pcm1_sync, pcm1_out, + eram_a5, eram_a6, eram_a7, eram_a8, eram_a9, eram_a10, eram_a11, + lvds_oep, lvds_oen, lvds_odp, lvds_odn, lvds_ocp, lvds_ocn, + lvds_obp, lvds_obn, lvds_oap, lvds_oan, lvds_eep, lvds_een, + lvds_edp, lvds_edn, lvds_ecp, lvds_ecn, lvds_ebp, lvds_ebn, + lvds_eap, lvds_ean, sd0_d0, sd0_d1, sd0_d2, sd0_d3, sd1_d0, + sd1_d1, sd1_d2, sd1_d3, sd0_cmd, sd0_clk, sd1_cmd, sd1_clk, + spi0_sclk, spi0_ss, spi0_miso, spi0_mosi, uart0_rx, uart0_tx, + uart2_rx, uart2_tx, uart2_rtsb, uart2_ctsb, uart3_rx, uart3_tx, + uart3_rtsb, uart3_ctsb, uart4_rx, uart4_tx, i2c0_sclk, i2c0_sdata, + i2c1_sclk, i2c1_sdata, i2c2_sclk, i2c2_sdata, csi0_dn0, csi0_dp0, + csi0_dn1, csi0_dp1, csi0_cn, csi0_cp, csi0_dn2, csi0_dp2, + csi0_dn3, csi0_dp3, dsi_dp3, dsi_dn3, dsi_dp1, dsi_dn1, dsi_cp, + dsi_cn, dsi_dp0, dsi_dn0, dsi_dp2, dsi_dn2, sensor0_pclk, + csi1_dn0, csi1_dp0, csi1_dn1, csi1_dp1, csi1_cn, csi1_cp, + sensor0_ckout, nand0_d0, nand0_d1, nand0_d2, nand0_d3, nand0_d4, + nand0_d5, nand0_d6, nand0_d7, nand0_dqs, nand0_dqsn, nand0_ale, + nand0_cle, nand0_ceb0, nand0_ceb1, nand0_ceb2, nand0_ceb3, + nand1_d0, nand1_d1, nand1_d2, nand1_d3, nand1_d4, nand1_d5, + nand1_d6, nand1_d7, nand1_dqs, nand1_dqsn, nand1_ale, nand1_cle, + nand1_ceb0, nand1_ceb1, nand1_ceb2, nand1_ceb3, sgpio0, sgpio1, + sgpio2, sgpio3 + ] + + bias-bus-hold: true + bias-high-impedance: true + + bias-pull-down: + type: boolean + + bias-pull-up: + type: boolean + + input-schmitt-enable: true + input-schmitt-disable: true + slew-rate: true + drive-strength: true + + oneOf: + - required: + - groups + - required: + - pins + +examples: + - | + #include + + pinctrl: pinctrl@e01b0000 { + compatible = "actions,s900-pinctrl"; + reg = <0xe01b0000 0x1000>; + clocks = <&cmu 1>; + gpio-controller; + gpio-ranges = <&pinctrl 0 0 146>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = , + , + , + , + , + ; + + uart2-default { + pinmux { + groups = "lvds_oep_odn_mfp"; + function = "uart2"; + }; + + pinconf { + groups = "lvds_oep_odn_drv"; + drive-strength = <12>; + }; + }; + }; From f84f54841dd091a909027e6eaf5ea3dc29937592 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 13 Oct 2025 14:12:25 -0500 Subject: [PATCH 110/684] dt-bindings: pinctrl: Convert brcm,ns2-pinmux to DT schema Convert the brcm,ns2-pinmux binding to DT schema format. It's a straight-forward conversion. Signed-off-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../bindings/pinctrl/brcm,ns2-pinmux.txt | 102 ---------------- .../bindings/pinctrl/brcm,ns2-pinmux.yaml | 111 ++++++++++++++++++ 2 files changed, 111 insertions(+), 102 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt deleted file mode 100644 index 40e0a9a19525b4..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt +++ /dev/null @@ -1,102 +0,0 @@ -Broadcom Northstar2 IOMUX Controller - -The Northstar2 IOMUX controller supports group based mux configuration. There -are some individual pins that support modifying the pinconf parameters. - -Required properties: - -- compatible: - Must be "brcm,ns2-pinmux" - -- reg: - Define the base and range of the I/O address space that contains the - Northstar2 IOMUX and pin configuration registers. - -Properties in sub nodes: - -- function: - The mux function to select - -- groups: - The list of groups to select with a given function - -- pins: - List of pin names to change configuration - -The generic properties bias-disable, bias-pull-down, bias-pull-up, -drive-strength, slew-rate, input-enable, input-disable are supported -for some individual pins listed at the end. - -For more details, refer to -Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - -For example: - - pinctrl: pinctrl@6501d130 { - compatible = "brcm,ns2-pinmux"; - reg = <0x6501d130 0x08>, - <0x660a0028 0x04>, - <0x660009b0 0x40>; - - pinctrl-names = "default"; - pinctrl-0 = <&nand_sel>, <&uart3_rx>, <&sdio0_d4>; - - /* Select nand function */ - nand_sel: nand_sel { - function = "nand"; - groups = "nand_grp"; - }; - - /* Pull up the uart3 rx pin */ - uart3_rx: uart3_rx { - pins = "uart3_sin"; - bias-pull-up; - }; - - /* Set the drive strength of sdio d4 pin */ - sdio0_d4: sdio0_d4 { - pins = "sdio0_data4"; - drive-strength = <8>; - }; - }; - -List of supported functions and groups in Northstar2: - -"nand": "nand_grp" - -"nor": "nor_data_grp", "nor_adv_grp", "nor_addr_0_3_grp", "nor_addr_4_5_grp", - "nor_addr_6_7_grp", "nor_addr_8_9_grp", "nor_addr_10_11_grp", - "nor_addr_12_15_grp" - -"gpio": "gpio_0_1_grp", "gpio_2_5_grp", "gpio_6_7_grp", "gpio_8_9_grp", - "gpio_10_11_grp", "gpio_12_13_grp", "gpio_14_17_grp", "gpio_18_19_grp", - "gpio_20_21_grp", "gpio_22_23_grp", "gpio_24_25_grp", "gpio_26_27_grp", - "gpio_28_29_grp", "gpio_30_31_grp" - -"pcie": "pcie_ab1_clk_wak_grp", "pcie_a3_clk_wak_grp", "pcie_b3_clk_wak_grp", - "pcie_b2_clk_wak_grp", "pcie_a2_clk_wak_grp" - -"uart0": "uart0_modem_grp", "uart0_rts_cts_grp", "uart0_in_out_grp" - -"uart1": "uart1_ext_clk_grp", "uart1_dcd_dsr_grp", "uart1_ri_dtr_grp", - "uart1_rts_cts_grp", "uart1_in_out_grp" - -"uart2": "uart2_rts_cts_grp" - -"pwm": "pwm_0_grp", "pwm_1_grp", "pwm_2_grp", "pwm_3_grp" - - -List of pins that support pinconf parameters: - -"qspi_wp", "qspi_hold", "qspi_cs", "qspi_sck", "uart3_sin", "uart3_sout", -"qspi_mosi", "qspi_miso", "spi0_fss", "spi0_rxd", "spi0_txd", "spi0_sck", -"spi1_fss", "spi1_rxd", "spi1_txd", "spi1_sck", "sdio0_data7", -"sdio0_emmc_rst", "sdio0_led_on", "sdio0_wp", "sdio0_data3", "sdio0_data4", -"sdio0_data5", "sdio0_data6", "sdio0_cmd", "sdio0_data0", "sdio0_data1", -"sdio0_data2", "sdio1_led_on", "sdio1_wp", "sdio0_cd_l", "sdio0_clk", -"sdio1_data5", "sdio1_data6", "sdio1_data7", "sdio1_emmc_rst", "sdio1_data1", -"sdio1_data2", "sdio1_data3", "sdio1_data4", "sdio1_cd_l", "sdio1_clk", -"sdio1_cmd", "sdio1_data0", "ext_mdio_0", "ext_mdc_0", "usb3_p1_vbus_ppc", -"usb3_p1_overcurrent", "usb3_p0_vbus_ppc", "usb3_p0_overcurrent", -"usb2_presence_indication", "usb2_vbus_present", "usb2_vbus_ppc", -"usb2_overcurrent", "sata_led1", "sata_led0" diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.yaml new file mode 100644 index 00000000000000..1de23c06fa49b1 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/brcm,ns2-pinmux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Northstar2 IOMUX Controller + +maintainers: + - Ray Jui + - Scott Branden + +properties: + compatible: + const: brcm,ns2-pinmux + + reg: + maxItems: 3 + +additionalProperties: + description: Pin group node properties + type: object + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + function: + description: The mux function to select + $ref: /schemas/types.yaml#/definitions/string + + groups: + items: + enum: [ + nand_grp, nor_data_grp, nor_adv_grp, nor_addr_0_3_grp, + nor_addr_4_5_grp, nor_addr_6_7_grp, nor_addr_8_9_grp, + nor_addr_10_11_grp, nor_addr_12_15_grp, gpio_0_1_grp, gpio_2_5_grp, + gpio_6_7_grp, gpio_8_9_grp, gpio_10_11_grp, gpio_12_13_grp, + gpio_14_17_grp, gpio_18_19_grp, gpio_20_21_grp, gpio_22_23_grp, + gpio_24_25_grp, gpio_26_27_grp, gpio_28_29_grp, gpio_30_31_grp, + pcie_ab1_clk_wak_grp, pcie_a3_clk_wak_grp, pcie_b3_clk_wak_grp, + pcie_b2_clk_wak_grp, pcie_a2_clk_wak_grp, uart0_modem_grp, + uart0_rts_cts_grp, uart0_in_out_grp, uart1_ext_clk_grp, + uart1_dcd_dsr_grp, uart1_ri_dtr_grp, uart1_rts_cts_grp, + uart1_in_out_grp, uart2_rts_cts_grp, pwm_0_grp, pwm_1_grp, pwm_2_grp, + pwm_3_grp + ] + + pins: + items: + enum: [ + qspi_wp, qspi_hold, qspi_cs, qspi_sck, uart3_sin, uart3_sout, + qspi_mosi, qspi_miso, spi0_fss, spi0_rxd, spi0_txd, spi0_sck, + spi1_fss, spi1_rxd, spi1_txd, spi1_sck, sdio0_data7, sdio0_emmc_rst, + sdio0_led_on, sdio0_wp, sdio0_data3, sdio0_data4, sdio0_data5, + sdio0_data6, sdio0_cmd, sdio0_data0, sdio0_data1, sdio0_data2, + sdio1_led_on, sdio1_wp, sdio0_cd_l, sdio0_clk, sdio1_data5, + sdio1_data6, sdio1_data7, sdio1_emmc_rst, sdio1_data1, sdio1_data2, + sdio1_data3, sdio1_data4, sdio1_cd_l, sdio1_clk, sdio1_cmd, + sdio1_data0, ext_mdio_0, ext_mdc_0, usb3_p1_vbus_ppc, + usb3_p1_overcurrent, usb3_p0_vbus_ppc, usb3_p0_overcurrent, + usb2_presence_indication, usb2_vbus_present, usb2_vbus_ppc, + usb2_overcurrent, sata_led1, sata_led0 + ] + + bias-disable: true + bias-pull-down: true + bias-pull-up: true + drive-strength: true + slew-rate: true + input-enable: true + input-disable: true + + oneOf: + - required: + - groups + - function + - required: + - pins + +required: + - compatible + - reg + +examples: + - | + pinctrl@6501d130 { + compatible = "brcm,ns2-pinmux"; + reg = <0x6501d130 0x08>, + <0x660a0028 0x04>, + <0x660009b0 0x40>; + + /* Select nand function */ + nand-sel { + function = "nand"; + groups = "nand_grp"; + }; + + /* Pull up the uart3 rx pin */ + uart3-rx { + pins = "uart3_sin"; + bias-pull-up; + }; + + /* Set the drive strength of sdio d4 pin */ + sdio0-d4 { + pins = "sdio0_data4"; + drive-strength = <8>; + }; + }; From a419bc0f13f3d13c3947d99accf6df9c690d4f25 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 13 Oct 2025 14:12:33 -0500 Subject: [PATCH 111/684] dt-bindings: pinctrl: Convert bitmain,bm1880-pinctrl to DT schema Convert the bitmain,bm1880-pinctrl binding to DT schema format. It's a straight-forward conversion. Signed-off-by: Rob Herring (Arm) Acked-by: Manivannan Sadhasivam Signed-off-by: Linus Walleij --- .../pinctrl/bitmain,bm1880-pinctrl.txt | 126 ----------------- .../pinctrl/bitmain,bm1880-pinctrl.yaml | 132 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 133 insertions(+), 127 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt deleted file mode 100644 index 4980776122ccc0..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt +++ /dev/null @@ -1,126 +0,0 @@ -Bitmain BM1880 Pin Controller - -This binding describes the pin controller found in the BM1880 SoC. - -Required Properties: - -- compatible: Should be "bitmain,bm1880-pinctrl" -- reg: Offset and length of pinctrl space in SCTRL. - -Please refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the meaning of the -phrase "pin configuration node". - -The pin configuration nodes act as a container for an arbitrary number of -subnodes. Each of these subnodes represents some desired configuration for a -pin, a group, or a list of pins or groups. This configuration for BM1880 SoC -includes pinmux and various pin configuration parameters, such as pull-up, -slew rate etc... - -Each configuration node can consist of multiple nodes describing the pinmux -options. The name of each subnode is not important; all subnodes should be -enumerated and processed purely based on their content. - -The following generic properties as defined in pinctrl-bindings.txt are valid -to specify in a pinmux subnode: - -Required Properties: - -- pins: An array of strings, each string containing the name of a pin. - Valid values for pins are: - - MIO0 - MIO111 - -- groups: An array of strings, each string containing the name of a pin - group. Valid values for groups are: - - nand_grp, spi_grp, emmc_grp, sdio_grp, eth0_grp, pwm0_grp, - pwm1_grp, pwm2_grp, pwm3_grp, pwm4_grp, pwm5_grp, pwm6_grp, - pwm7_grp, pwm8_grp, pwm9_grp, pwm10_grp, pwm11_grp, pwm12_grp, - pwm13_grp, pwm14_grp, pwm15_grp, pwm16_grp, pwm17_grp, - pwm18_grp, pwm19_grp, pwm20_grp, pwm21_grp, pwm22_grp, - pwm23_grp, pwm24_grp, pwm25_grp, pwm26_grp, pwm27_grp, - pwm28_grp, pwm29_grp, pwm30_grp, pwm31_grp, pwm32_grp, - pwm33_grp, pwm34_grp, pwm35_grp, pwm36_grp, i2c0_grp, - i2c1_grp, i2c2_grp, i2c3_grp, i2c4_grp, uart0_grp, uart1_grp, - uart2_grp, uart3_grp, uart4_grp, uart5_grp, uart6_grp, - uart7_grp, uart8_grp, uart9_grp, uart10_grp, uart11_grp, - uart12_grp, uart13_grp, uart14_grp, uart15_grp, gpio0_grp, - gpio1_grp, gpio2_grp, gpio3_grp, gpio4_grp, gpio5_grp, - gpio6_grp, gpio7_grp, gpio8_grp, gpio9_grp, gpio10_grp, - gpio11_grp, gpio12_grp, gpio13_grp, gpio14_grp, gpio15_grp, - gpio16_grp, gpio17_grp, gpio18_grp, gpio19_grp, gpio20_grp, - gpio21_grp, gpio22_grp, gpio23_grp, gpio24_grp, gpio25_grp, - gpio26_grp, gpio27_grp, gpio28_grp, gpio29_grp, gpio30_grp, - gpio31_grp, gpio32_grp, gpio33_grp, gpio34_grp, gpio35_grp, - gpio36_grp, gpio37_grp, gpio38_grp, gpio39_grp, gpio40_grp, - gpio41_grp, gpio42_grp, gpio43_grp, gpio44_grp, gpio45_grp, - gpio46_grp, gpio47_grp, gpio48_grp, gpio49_grp, gpio50_grp, - gpio51_grp, gpio52_grp, gpio53_grp, gpio54_grp, gpio55_grp, - gpio56_grp, gpio57_grp, gpio58_grp, gpio59_grp, gpio60_grp, - gpio61_grp, gpio62_grp, gpio63_grp, gpio64_grp, gpio65_grp, - gpio66_grp, gpio67_grp, eth1_grp, i2s0_grp, i2s0_mclkin_grp, - i2s1_grp, i2s1_mclkin_grp, spi0_grp - -- function: An array of strings, each string containing the name of the - pinmux functions. The following are the list of pinmux - functions available: - - nand, spi, emmc, sdio, eth0, pwm0, pwm1, pwm2, pwm3, pwm4, - pwm5, pwm6, pwm7, pwm8, pwm9, pwm10, pwm11, pwm12, pwm13, - pwm14, pwm15, pwm16, pwm17, pwm18, pwm19, pwm20, pwm21, pwm22, - pwm23, pwm24, pwm25, pwm26, pwm27, pwm28, pwm29, pwm30, pwm31, - pwm32, pwm33, pwm34, pwm35, pwm36, i2c0, i2c1, i2c2, i2c3, - i2c4, uart0, uart1, uart2, uart3, uart4, uart5, uart6, uart7, - uart8, uart9, uart10, uart11, uart12, uart13, uart14, uart15, - gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7, gpio8, - gpio9, gpio10, gpio11, gpio12, gpio13, gpio14, gpio15, gpio16, - gpio17, gpio18, gpio19, gpio20, gpio21, gpio22, gpio23, - gpio24, gpio25, gpio26, gpio27, gpio28, gpio29, gpio30, - gpio31, gpio32, gpio33, gpio34, gpio35, gpio36, gpio37, - gpio38, gpio39, gpio40, gpio41, gpio42, gpio43, gpio44, - gpio45, gpio46, gpio47, gpio48, gpio49, gpio50, gpio51, - gpio52, gpio53, gpio54, gpio55, gpio56, gpio57, gpio58, - gpio59, gpio60, gpio61, gpio62, gpio63, gpio64, gpio65, - gpio66, gpio67, eth1, i2s0, i2s0_mclkin, i2s1, i2s1_mclkin, - spi0 - -Optional Properties: - -- bias-disable: No arguments. Disable pin bias. -- bias-pull-down: No arguments. The specified pins should be configured as - pull down. -- bias-pull-up: No arguments. The specified pins should be configured as - pull up. -- input-schmitt-enable: No arguments: Enable schmitt trigger for the specified - pins -- input-schmitt-disable: No arguments: Disable schmitt trigger for the specified - pins -- slew-rate: Integer. Sets slew rate for the specified pins. - Valid values are: - <0> - Slow - <1> - Fast -- drive-strength: Integer. Selects the drive strength for the specified - pins in mA. - Valid values are: - <4> - <8> - <12> - <16> - <20> - <24> - <28> - <32> - -Example: - pinctrl: pinctrl@400 { - compatible = "bitmain,bm1880-pinctrl"; - reg = <0x400 0x120>; - - pinctrl_uart0_default: uart0-default { - pinmux { - groups = "uart0_grp"; - function = "uart0"; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.yaml new file mode 100644 index 00000000000000..542be98708382a --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.yaml @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/bitmain,bm1880-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bitmain BM1880 Pin Controller + +maintainers: + - Manivannan Sadhasivam + +properties: + compatible: + const: bitmain,bm1880-pinctrl + + reg: + maxItems: 1 + +additionalProperties: + description: A pin configuration node. + type: object + additionalProperties: false + + properties: + pinmux: + type: object + description: Pin multiplexing parameters. + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + pins: + items: + pattern: '^MIO[0-9]+$' + + groups: + items: + enum: [ + nand_grp, spi_grp, emmc_grp, sdio_grp, eth0_grp, pwm0_grp, + pwm1_grp, pwm2_grp, pwm3_grp, pwm4_grp, pwm5_grp, pwm6_grp, + pwm7_grp, pwm8_grp, pwm9_grp, pwm10_grp, pwm11_grp, pwm12_grp, + pwm13_grp, pwm14_grp, pwm15_grp, pwm16_grp, pwm17_grp, + pwm18_grp, pwm19_grp, pwm20_grp, pwm21_grp, pwm22_grp, + pwm23_grp, pwm24_grp, pwm25_grp, pwm26_grp, pwm27_grp, + pwm28_grp, pwm29_grp, pwm30_grp, pwm31_grp, pwm32_grp, + pwm33_grp, pwm34_grp, pwm35_grp, pwm36_grp, i2c0_grp, + i2c1_grp, i2c2_grp, i2c3_grp, i2c4_grp, uart0_grp, uart1_grp, + uart2_grp, uart3_grp, uart4_grp, uart5_grp, uart6_grp, + uart7_grp, uart8_grp, uart9_grp, uart10_grp, uart11_grp, + uart12_grp, uart13_grp, uart14_grp, uart15_grp, gpio0_grp, + gpio1_grp, gpio2_grp, gpio3_grp, gpio4_grp, gpio5_grp, + gpio6_grp, gpio7_grp, gpio8_grp, gpio9_grp, gpio10_grp, + gpio11_grp, gpio12_grp, gpio13_grp, gpio14_grp, gpio15_grp, + gpio16_grp, gpio17_grp, gpio18_grp, gpio19_grp, gpio20_grp, + gpio21_grp, gpio22_grp, gpio23_grp, gpio24_grp, gpio25_grp, + gpio26_grp, gpio27_grp, gpio28_grp, gpio29_grp, gpio30_grp, + gpio31_grp, gpio32_grp, gpio33_grp, gpio34_grp, gpio35_grp, + gpio36_grp, gpio37_grp, gpio38_grp, gpio39_grp, gpio40_grp, + gpio41_grp, gpio42_grp, gpio43_grp, gpio44_grp, gpio45_grp, + gpio46_grp, gpio47_grp, gpio48_grp, gpio49_grp, gpio50_grp, + gpio51_grp, gpio52_grp, gpio53_grp, gpio54_grp, gpio55_grp, + gpio56_grp, gpio57_grp, gpio58_grp, gpio59_grp, gpio60_grp, + gpio61_grp, gpio62_grp, gpio63_grp, gpio64_grp, gpio65_grp, + gpio66_grp, gpio67_grp, eth1_grp, i2s0_grp, i2s0_mclkin_grp, + i2s1_grp, i2s1_mclkin_grp, spi0_grp + ] + + function: + items: + enum: [ + nand, spi, emmc, sdio, eth0, pwm0, pwm1, pwm2, pwm3, pwm4, + pwm5, pwm6, pwm7, pwm8, pwm9, pwm10, pwm11, pwm12, pwm13, + pwm14, pwm15, pwm16, pwm17, pwm18, pwm19, pwm20, pwm21, pwm22, + pwm23, pwm24, pwm25, pwm26, pwm27, pwm28, pwm29, pwm30, pwm31, + pwm32, pwm33, pwm34, pwm35, pwm36, i2c0, i2c1, i2c2, i2c3, + i2c4, uart0, uart1, uart2, uart3, uart4, uart5, uart6, uart7, + uart8, uart9, uart10, uart11, uart12, uart13, uart14, uart15, + gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7, gpio8, + gpio9, gpio10, gpio11, gpio12, gpio13, gpio14, gpio15, gpio16, + gpio17, gpio18, gpio19, gpio20, gpio21, gpio22, gpio23, + gpio24, gpio25, gpio26, gpio27, gpio28, gpio29, gpio30, + gpio31, gpio32, gpio33, gpio34, gpio35, gpio36, gpio37, + gpio38, gpio39, gpio40, gpio41, gpio42, gpio43, gpio44, + gpio45, gpio46, gpio47, gpio48, gpio49, gpio50, gpio51, + gpio52, gpio53, gpio54, gpio55, gpio56, gpio57, gpio58, + gpio59, gpio60, gpio61, gpio62, gpio63, gpio64, gpio65, + gpio66, gpio67, eth1, i2s0, i2s0_mclkin, i2s1, i2s1_mclkin, + spi0 + ] + + bias-disable: true + bias-pull-down: true + bias-pull-up: true + input-schmitt-enable: true + input-schmitt-disable: true + + slew-rate: + description: > + Sets slew rate. Valid values: 0 = Slow, 1 = Fast. + enum: [0, 1] + + drive-strength: + enum: [4, 8, 12, 16, 20, 24, 28, 32] + + oneOf: + - required: + - pins + - required: + - groups + + required: + - function + +required: + - compatible + - reg + +examples: + - | + pinctrl@400 { + compatible = "bitmain,bm1880-pinctrl"; + reg = <0x400 0x120>; + + uart0-default { + pinmux { + groups = "uart0_grp"; + function = "uart0"; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968e4..bdbcd05095b175 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2529,7 +2529,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/bitmain.yaml F: Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml -F: Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.txt +F: Documentation/devicetree/bindings/pinctrl/bitmain,bm1880-pinctrl.yaml F: arch/arm64/boot/dts/bitmain/ F: drivers/clk/clk-bm1880.c F: drivers/pinctrl/pinctrl-bm1880.c From d8f1121ebf4036884fc9ab1968f606523dd1c1fe Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:45 +0300 Subject: [PATCH 112/684] clk: qcom: camcc-sm8550: Specify Titan GDSC power domain as a parent to other When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be described in the CAMCC driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of all other GDSC power domains provided by the SM8550 camera clock controller to enforce a correct sequence of enabling and disabling power domains by the consumers, this fixes the CAMCC as a supplier of power domains to CAMSS IP and its driver. Fixes: ccc4e6a061a2 ("clk: qcom: camcc-sm8550: Add camera clock controller driver for SM8550") Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-2-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm8550.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm8550.c b/drivers/clk/qcom/camcc-sm8550.c index 63aed9e4c362d5..b8ece8a57a8a9d 100644 --- a/drivers/clk/qcom/camcc-sm8550.c +++ b/drivers/clk/qcom/camcc-sm8550.c @@ -3204,6 +3204,8 @@ static struct clk_branch cam_cc_sfe_1_fast_ahb_clk = { }, }; +static struct gdsc cam_cc_titan_top_gdsc; + static struct gdsc cam_cc_bps_gdsc = { .gdscr = 0x10004, .en_rest_wait_val = 0x2, @@ -3213,6 +3215,7 @@ static struct gdsc cam_cc_bps_gdsc = { .name = "cam_cc_bps_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3225,6 +3228,7 @@ static struct gdsc cam_cc_ife_0_gdsc = { .name = "cam_cc_ife_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3237,6 +3241,7 @@ static struct gdsc cam_cc_ife_1_gdsc = { .name = "cam_cc_ife_1_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3249,6 +3254,7 @@ static struct gdsc cam_cc_ife_2_gdsc = { .name = "cam_cc_ife_2_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3261,6 +3267,7 @@ static struct gdsc cam_cc_ipe_0_gdsc = { .name = "cam_cc_ipe_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3273,6 +3280,7 @@ static struct gdsc cam_cc_sbi_gdsc = { .name = "cam_cc_sbi_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3285,6 +3293,7 @@ static struct gdsc cam_cc_sfe_0_gdsc = { .name = "cam_cc_sfe_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -3297,6 +3306,7 @@ static struct gdsc cam_cc_sfe_1_gdsc = { .name = "cam_cc_sfe_1_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; From a76ce61d7225934b0a52c8172a8cd944002a8c6f Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:46 +0300 Subject: [PATCH 113/684] clk: qcom: camcc-sm6350: Specify Titan GDSC power domain as a parent to other When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be described in the CAMCC driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of all other GDSC power domains provided by the SM6350 camera clock controller to enforce a correct sequence of enabling and disabling power domains by the consumers, this fixes the CAMCC as a supplier of power domains to CAMSS IP and its driver. Fixes: 80f5451d9a7c ("clk: qcom: Add camera clock controller driver for SM6350") Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-3-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm6350.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm6350.c b/drivers/clk/qcom/camcc-sm6350.c index 8aac97d29ce3ff..6c272f7b07219d 100644 --- a/drivers/clk/qcom/camcc-sm6350.c +++ b/drivers/clk/qcom/camcc-sm6350.c @@ -1693,6 +1693,8 @@ static struct clk_branch camcc_sys_tmr_clk = { }, }; +static struct gdsc titan_top_gdsc; + static struct gdsc bps_gdsc = { .gdscr = 0x6004, .en_rest_wait_val = 0x2, @@ -1702,6 +1704,7 @@ static struct gdsc bps_gdsc = { .name = "bps_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, .flags = VOTABLE, }; @@ -1714,6 +1717,7 @@ static struct gdsc ipe_0_gdsc = { .name = "ipe_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, .flags = VOTABLE, }; @@ -1726,6 +1730,7 @@ static struct gdsc ife_0_gdsc = { .name = "ife_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ife_1_gdsc = { @@ -1737,6 +1742,7 @@ static struct gdsc ife_1_gdsc = { .name = "ife_1_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ife_2_gdsc = { @@ -1748,6 +1754,7 @@ static struct gdsc ife_2_gdsc = { .name = "ife_2_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc titan_top_gdsc = { From ee2867ca99e2b5b6788ff421f7e784d9a0da426f Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:47 +0300 Subject: [PATCH 114/684] clk: qcom: camcc-sdm845: Specify Titan GDSC power domain as a parent to other When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be properly described in the power domain provider driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of other GDSC power domains provided by the SDM845 camera clock controller, including IPE0/1 and BPS ones. Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-4-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sdm845.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/camcc-sdm845.c b/drivers/clk/qcom/camcc-sdm845.c index cf60e8dd292a93..fb313da7165b8b 100644 --- a/drivers/clk/qcom/camcc-sdm845.c +++ b/drivers/clk/qcom/camcc-sdm845.c @@ -1543,6 +1543,7 @@ static struct gdsc bps_gdsc = { .name = "bps_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -1552,6 +1553,7 @@ static struct gdsc ipe_0_gdsc = { .name = "ipe_0_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -1561,6 +1563,7 @@ static struct gdsc ipe_1_gdsc = { .name = "ipe_1_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; From 37cf953a120a69114b810eee74530a8836d9a781 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:48 +0300 Subject: [PATCH 115/684] clk: qcom: camcc-sm7150: Specify Titan GDSC power domain as a parent to IPEx and BPS When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be described in the CAMCC driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of other GDSC power domains provided by the SM7150 camera clock controller, including IPE0/1 and BPS ones. Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-5-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm7150.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm7150.c b/drivers/clk/qcom/camcc-sm7150.c index 4a3baf5d8e858c..0e072ae39ec04d 100644 --- a/drivers/clk/qcom/camcc-sm7150.c +++ b/drivers/clk/qcom/camcc-sm7150.c @@ -1846,6 +1846,7 @@ static struct gdsc camcc_bps_gdsc = { .name = "camcc_bps_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &camcc_titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -1875,6 +1876,7 @@ static struct gdsc camcc_ipe_0_gdsc = { .name = "camcc_ipe_0_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &camcc_titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -1884,6 +1886,7 @@ static struct gdsc camcc_ipe_1_gdsc = { .name = "camcc_ipe_1_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &camcc_titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; From fc3985b21f86db33e4ec8a820d211e4e505c9048 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:49 +0300 Subject: [PATCH 116/684] clk: qcom: camcc-sm8250: Specify Titan GDSC power domain as a parent to IPE/BPS/SBI When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be described in the CAMCC driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of other GDSC power domains provided by the SM8250 camera clock controller, including IPE, BPS and SBI ones. Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-6-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm8250.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c index 6da89c49ba3d88..c95a00628630ed 100644 --- a/drivers/clk/qcom/camcc-sm8250.c +++ b/drivers/clk/qcom/camcc-sm8250.c @@ -2213,6 +2213,7 @@ static struct gdsc bps_gdsc = { .name = "bps_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -2222,6 +2223,7 @@ static struct gdsc ipe_0_gdsc = { .name = "ipe_0_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -2231,6 +2233,7 @@ static struct gdsc sbi_gdsc = { .name = "sbi_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; From 70dc5425fe1af90901d8109941e09005de38b7ea Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Oct 2025 02:44:50 +0300 Subject: [PATCH 117/684] clk: qcom: camcc-sm8450: Specify Titan GDSC power domain as a parent to IPE/BPS/SBI When a consumer turns on/off a power domain dependent on another power domain in hardware, the parent power domain shall be turned on/off by the power domain provider as well, and to get it the power domain hardware hierarchy shall be described in the CAMCC driver. Establish the power domain hierarchy with a Titan GDSC set as a parent of other GDSC power domains provided by the SM8450 camera clock controller, including IPE, BPS and SBI ones. Reviewed-by: Konrad Dybcio Reviewed-by: Imran Shaik Reviewed-by: Bryan O'Donoghue Signed-off-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/20251021234450.2271279-7-vladimir.zapolskiy@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm8450.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm8450.c b/drivers/clk/qcom/camcc-sm8450.c index 4dd8be8cc9881c..ef8cf54d0eed6d 100644 --- a/drivers/clk/qcom/camcc-sm8450.c +++ b/drivers/clk/qcom/camcc-sm8450.c @@ -2935,6 +2935,7 @@ static struct gdsc bps_gdsc = { .name = "bps_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -2944,6 +2945,7 @@ static struct gdsc ipe_0_gdsc = { .name = "ipe_0_gdsc", }, .flags = HW_CTRL | POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; @@ -2953,6 +2955,7 @@ static struct gdsc sbi_gdsc = { .name = "sbi_gdsc", }, .flags = POLL_CFG_GDSCR, + .parent = &titan_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, }; From 17e4db05930e455770b15b77708a07681ed24efc Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 27 Jun 2025 21:37:58 +0200 Subject: [PATCH 118/684] clk: qcom: rpmh: Define RPMH_IPA_CLK on QCS615 This was previously (mis)represented in the interconnect driver, move the resource under the clk-rpmh driver control, just like we did for all platforms in the past, see e.g. Commit aa055bf158cd ("clk: qcom: rpmh: define IPA clocks where required") Fixes: 42a1905a10d6 ("clk: qcom: rpmhcc: Add support for QCS615 Clocks") Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250627-topic-qcs615_icc_ipa-v1-4-dc47596cde69@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rpmh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 63c38cb47bc459..1a98b3a0c528c2 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -855,6 +855,7 @@ static struct clk_hw *qcs615_rpmh_clocks[] = { [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw, [RPMH_RF_CLK2] = &clk_rpmh_rf_clk2_a.hw, [RPMH_RF_CLK2_A] = &clk_rpmh_rf_clk2_a_ao.hw, + [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw, }; static const struct clk_rpmh_desc clk_rpmh_qcs615 = { From 502099e9c832c95b485835ff58a5f735d9d956a1 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 19 Sep 2025 11:57:24 +0200 Subject: [PATCH 119/684] clk: qcom: dispcc-sm6350: Add MDSS_CORE & MDSS_RSCC resets Add the offsets for two resets inside the dispcc on SM6350 SoC. Signed-off-by: Luca Weiss Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250919-sm6350-mdss-reset-v1-2-48dcac917c73@fairphone.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm6350.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c index b0bd163a449ccd..5b1d8f86515f25 100644 --- a/drivers/clk/qcom/dispcc-sm6350.c +++ b/drivers/clk/qcom/dispcc-sm6350.c @@ -679,6 +679,11 @@ static struct clk_branch disp_cc_xo_clk = { }, }; +static const struct qcom_reset_map disp_cc_sm6350_resets[] = { + [DISP_CC_MDSS_CORE_BCR] = { 0x1000 }, + [DISP_CC_MDSS_RSCC_BCR] = { 0x2000 }, +}; + static struct gdsc mdss_gdsc = { .gdscr = 0x1004, .en_rest_wait_val = 0x2, @@ -746,6 +751,8 @@ static const struct qcom_cc_desc disp_cc_sm6350_desc = { .num_clks = ARRAY_SIZE(disp_cc_sm6350_clocks), .gdscs = disp_cc_sm6350_gdscs, .num_gdscs = ARRAY_SIZE(disp_cc_sm6350_gdscs), + .resets = disp_cc_sm6350_resets, + .num_resets = ARRAY_SIZE(disp_cc_sm6350_resets), }; static const struct of_device_id disp_cc_sm6350_match_table[] = { From 2238840342af8e8d37a9355f0a2ad4285c32f854 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Fri, 19 Sep 2025 14:34:30 +0200 Subject: [PATCH 120/684] dt-bindings: clock: sm7150-dispcc: Add MDSS_CORE reset Add the index for a reset inside the dispcc on SM7150 SoC. Signed-off-by: Jens Reidel Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250919-sm7150-dispcc-fixes-v1-1-308ad47c5fce@mainlining.org Signed-off-by: Bjorn Andersson --- include/dt-bindings/clock/qcom,sm7150-dispcc.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/clock/qcom,sm7150-dispcc.h b/include/dt-bindings/clock/qcom,sm7150-dispcc.h index fc1fefe8fd7248..1e4e6432d5065b 100644 --- a/include/dt-bindings/clock/qcom,sm7150-dispcc.h +++ b/include/dt-bindings/clock/qcom,sm7150-dispcc.h @@ -53,6 +53,9 @@ #define DISPCC_SLEEP_CLK 41 #define DISPCC_SLEEP_CLK_SRC 42 +/* DISPCC resets */ +#define DISPCC_MDSS_CORE_BCR 0 + /* DISPCC GDSCR */ #define MDSS_GDSC 0 From 176465fd8c4e2cbb4410b5a66f6ba74ed491d2a5 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Fri, 19 Sep 2025 14:34:31 +0200 Subject: [PATCH 121/684] clk: qcom: dispcc-sm7150: Add MDSS_CORE reset Add the offsets for a reset inside the dispcc on SM7150 SoC. Signed-off-by: Jens Reidel Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250919-sm7150-dispcc-fixes-v1-2-308ad47c5fce@mainlining.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm7150.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/qcom/dispcc-sm7150.c b/drivers/clk/qcom/dispcc-sm7150.c index bdfff246ed3fe0..0a7f6ec7a2a737 100644 --- a/drivers/clk/qcom/dispcc-sm7150.c +++ b/drivers/clk/qcom/dispcc-sm7150.c @@ -20,6 +20,7 @@ #include "clk-regmap-divider.h" #include "common.h" #include "gdsc.h" +#include "reset.h" enum { DT_BI_TCXO, @@ -951,6 +952,10 @@ static struct gdsc *dispcc_sm7150_gdscs[] = { [MDSS_GDSC] = &mdss_gdsc, }; +static const struct qcom_reset_map dispcc_sm7150_resets[] = { + [DISPCC_MDSS_CORE_BCR] = { 0x2000 }, +}; + static const struct regmap_config dispcc_sm7150_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -965,6 +970,8 @@ static const struct qcom_cc_desc dispcc_sm7150_desc = { .num_clks = ARRAY_SIZE(dispcc_sm7150_clocks), .gdscs = dispcc_sm7150_gdscs, .num_gdscs = ARRAY_SIZE(dispcc_sm7150_gdscs), + .resets = dispcc_sm7150_resets, + .num_resets = ARRAY_SIZE(dispcc_sm7150_resets), }; static const struct of_device_id dispcc_sm7150_match_table[] = { From e3c13e0caa8ceb7dec1a7c4fcfd9dbef56a69fbe Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Fri, 19 Sep 2025 14:34:32 +0200 Subject: [PATCH 122/684] clk: qcom: dispcc-sm7150: Fix dispcc_mdss_pclk0_clk_src Set CLK_OPS_PARENT_ENABLE to ensure the parent gets prepared and enabled when switching to it, fixing an "rcg didn't update its configuration" warning. Signed-off-by: Jens Reidel Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250919-sm7150-dispcc-fixes-v1-3-308ad47c5fce@mainlining.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm7150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/dispcc-sm7150.c b/drivers/clk/qcom/dispcc-sm7150.c index 0a7f6ec7a2a737..811d380a8e9f9b 100644 --- a/drivers/clk/qcom/dispcc-sm7150.c +++ b/drivers/clk/qcom/dispcc-sm7150.c @@ -357,7 +357,7 @@ static struct clk_rcg2 dispcc_mdss_pclk0_clk_src = { .name = "dispcc_mdss_pclk0_clk_src", .parent_data = dispcc_parent_data_4, .num_parents = ARRAY_SIZE(dispcc_parent_data_4), - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, .ops = &clk_pixel_ops, }, }; From 393f7834cd2b1eaf4a9eff2701e706e73e660dd7 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 24 Sep 2025 00:08:30 +0530 Subject: [PATCH 123/684] clk: qcom: gcc-sm8750: Add a new frequency for sdcc2 clock The SD card support requires a 37.5MHz clock; add it to the frequency list for the storage SW driver to be able to request for the frequency. Fixes: 3267c774f3ff ("clk: qcom: Add support for GCC on SM8750") Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Link: https://lore.kernel.org/r/20250924-sm8750_gcc_sdcc2_frequency-v1-1-541fd321125f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-sm8750.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gcc-sm8750.c b/drivers/clk/qcom/gcc-sm8750.c index 8092dd6b37b56f..def86b71a3da53 100644 --- a/drivers/clk/qcom/gcc-sm8750.c +++ b/drivers/clk/qcom/gcc-sm8750.c @@ -1012,6 +1012,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s7_clk_src = { static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { F(400000, P_BI_TCXO, 12, 1, 4), F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(37500000, P_GCC_GPLL0_OUT_EVEN, 8, 0, 0), F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0), F(202000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0), From 18da820eb632fbd99167f3fc6650a30db714ddfd Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 25 Sep 2025 15:49:00 +0530 Subject: [PATCH 124/684] clk: qcom: gcc-glymur: Update the halt check flags for pipe clocks The pipe clocks for PCIE and USB are externally sourced and they should not be polled by the clock driver. Update the halt_check flags to 'SKIP' to disable polling for these clocks. This helps avoid the clock status stuck at 'off' warnings, which are benign, since all consumers of the PHYs must initialize a given instance before performing any operations. Fixes: efe504300a17 ("clk: qcom: gcc: Add support for Global Clock Controller") Reviewed-by: Konrad Dybcio Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250925-glymur_gcc_usb_fixes-v2-1-ee4619571efe@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-glymur.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/clk/qcom/gcc-glymur.c b/drivers/clk/qcom/gcc-glymur.c index 62059120f9720b..d938e7dc5b66ec 100644 --- a/drivers/clk/qcom/gcc-glymur.c +++ b/drivers/clk/qcom/gcc-glymur.c @@ -6760,7 +6760,7 @@ static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { .halt_reg = 0x3f088, - .halt_check = BRANCH_HALT_DELAY, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0x3f088, .hwcg_bit = 1, .clkr = { @@ -6816,7 +6816,7 @@ static struct clk_branch gcc_usb3_sec_phy_com_aux_clk = { static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { .halt_reg = 0xe2078, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0xe2078, .hwcg_bit = 1, .clkr = { @@ -6872,7 +6872,7 @@ static struct clk_branch gcc_usb3_tert_phy_com_aux_clk = { static struct clk_branch gcc_usb3_tert_phy_pipe_clk = { .halt_reg = 0xe1078, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0xe1078, .hwcg_bit = 1, .clkr = { @@ -6961,7 +6961,7 @@ static struct clk_branch gcc_usb4_0_master_clk = { static struct clk_branch gcc_usb4_0_phy_p2rr2p_pipe_clk = { .halt_reg = 0x2b0f4, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2b0f4, .enable_mask = BIT(0), @@ -6979,7 +6979,7 @@ static struct clk_branch gcc_usb4_0_phy_p2rr2p_pipe_clk = { static struct clk_branch gcc_usb4_0_phy_pcie_pipe_clk = { .halt_reg = 0x2b04c, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x62010, .enable_mask = BIT(11), @@ -7033,7 +7033,7 @@ static struct clk_branch gcc_usb4_0_phy_rx1_clk = { static struct clk_branch gcc_usb4_0_phy_usb_pipe_clk = { .halt_reg = 0x2b0bc, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0x2b0bc, .hwcg_bit = 1, .clkr = { @@ -7196,7 +7196,7 @@ static struct clk_branch gcc_usb4_1_master_clk = { static struct clk_branch gcc_usb4_1_phy_p2rr2p_pipe_clk = { .halt_reg = 0x2d118, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x2d118, .enable_mask = BIT(0), @@ -7214,7 +7214,7 @@ static struct clk_branch gcc_usb4_1_phy_p2rr2p_pipe_clk = { static struct clk_branch gcc_usb4_1_phy_pcie_pipe_clk = { .halt_reg = 0x2d04c, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x62010, .enable_mask = BIT(12), @@ -7268,7 +7268,7 @@ static struct clk_branch gcc_usb4_1_phy_rx1_clk = { static struct clk_branch gcc_usb4_1_phy_usb_pipe_clk = { .halt_reg = 0x2d0e0, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0x2d0e0, .hwcg_bit = 1, .clkr = { @@ -7431,7 +7431,7 @@ static struct clk_branch gcc_usb4_2_master_clk = { static struct clk_branch gcc_usb4_2_phy_p2rr2p_pipe_clk = { .halt_reg = 0xe00f8, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0xe00f8, .enable_mask = BIT(0), @@ -7449,7 +7449,7 @@ static struct clk_branch gcc_usb4_2_phy_p2rr2p_pipe_clk = { static struct clk_branch gcc_usb4_2_phy_pcie_pipe_clk = { .halt_reg = 0xe004c, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x62010, .enable_mask = BIT(13), @@ -7503,7 +7503,7 @@ static struct clk_branch gcc_usb4_2_phy_rx1_clk = { static struct clk_branch gcc_usb4_2_phy_usb_pipe_clk = { .halt_reg = 0xe00c0, - .halt_check = BRANCH_HALT_VOTED, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0xe00c0, .hwcg_bit = 1, .clkr = { From f0691a3f7558d33b5b4a900e8312613fbe4afb9d Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 30 Sep 2025 11:56:08 -0700 Subject: [PATCH 125/684] clk: qcom: Fix SM_VIDEOCC_6350 dependencies It is possible to select CONFIG_SM_GCC_6350 when targeting ARCH=arm, causing a Kconfig warning when selecting CONFIG_SM_GCC_6350 without its dependencies, CONFIG_ARM64 or CONFIG_COMPILE_TEST. WARNING: unmet direct dependencies detected for SM_GCC_6350 Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] && (ARM64 || COMPILE_TEST [=n]) Selected by [m]: - SM_VIDEOCC_6350 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] Add the same dependency to clear up the warning. Cc: stable@vger.kernel.org Fixes: 720b1e8f2004 ("clk: qcom: Add video clock controller driver for SM6350") Signed-off-by: Nathan Chancellor Reviewed-by: Imran Shaik Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250930-clk-qcom-kconfig-fixes-arm-v1-1-15ae1ae9ec9f@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 78a3038426136e..ec7d1a9b578e6e 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1448,6 +1448,7 @@ config SA_VIDEOCC_8775P config SM_VIDEOCC_6350 tristate "SM6350 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_6350 select QCOM_GDSC help From 7ec1ba01ae37897f0ecf6ab0c980378cb8a2f388 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 30 Sep 2025 11:56:09 -0700 Subject: [PATCH 126/684] clk: qcom: Fix dependencies of QCS_{DISP,GPU,VIDEO}CC_615 It is possible to select CONFIG_QCS_{DISP,GPU,VIDEO}CC_615 when targeting ARCH=arm, causing a Kconfig warning when selecting CONFIG_QCS_GCC_615 without its dependencies, CONFIG_ARM64 or CONFIG_COMPILE_TEST. WARNING: unmet direct dependencies detected for QCS_GCC_615 Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] && (ARM64 || COMPILE_TEST [=n]) Selected by [m]: - QCS_DISPCC_615 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] - QCS_GPUCC_615 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] - QCS_VIDEOCC_615 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] Add the same dependency to these configurations to clear up the warnings. Cc: stable@vger.kernel.org Fixes: 9b47105f5434 ("clk: qcom: dispcc-qcs615: Add QCS615 display clock controller driver") Fixes: f4b5b40805ab ("clk: qcom: gpucc-qcs615: Add QCS615 graphics clock controller driver") Fixes: f6a8abe0cc16 ("clk: qcom: videocc-qcs615: Add QCS615 video clock controller driver") Signed-off-by: Nathan Chancellor Reviewed-by: Imran Shaik Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250930-clk-qcom-kconfig-fixes-arm-v1-2-15ae1ae9ec9f@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index ec7d1a9b578e6e..6fef0bfc17736b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -531,6 +531,7 @@ config QCM_DISPCC_2290 config QCS_DISPCC_615 tristate "QCS615 Display Clock Controller" + depends on ARM64 || COMPILE_TEST select QCS_GCC_615 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -586,6 +587,7 @@ config QCS_GCC_615 config QCS_GPUCC_615 tristate "QCS615 Graphics clock controller" + depends on ARM64 || COMPILE_TEST select QCS_GCC_615 help Support for the graphics clock controller on QCS615 devices. @@ -594,6 +596,7 @@ config QCS_GPUCC_615 config QCS_VIDEOCC_615 tristate "QCS615 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select QCS_GCC_615 help Support for the video clock controller on QCS615 devices. From 205a5d29b47ecd6ffbc53b02a3952684d6720fd7 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 10 Oct 2025 12:24:50 +0200 Subject: [PATCH 127/684] clk: qcom: gcc-sc8280xp: Remove 85.71 MHz USB4 master clock frequency The USB4 HPG says this frequency remains unused, remove it from the frequency table to avoid any misunderstandings. The reason it's unused seems to be that the lower RPMh level required to support it (LOW_SVS) is not enough for other pieces of the pipeline which require SVS, which in turn is enough to support a faster, 175 MHz rate. Signed-off-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20251010-topic-gcc_usb4_unused_freq-v1-1-4be5e77d2307@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-sc8280xp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c index b683795475e341..2ab111585d7fcb 100644 --- a/drivers/clk/qcom/gcc-sc8280xp.c +++ b/drivers/clk/qcom/gcc-sc8280xp.c @@ -2224,7 +2224,6 @@ static struct clk_rcg2 gcc_usb3_sec_phy_aux_clk_src = { }; static const struct freq_tbl ftbl_gcc_usb4_1_master_clk_src[] = { - F(85714286, P_GCC_GPLL0_OUT_EVEN, 3.5, 0, 0), F(175000000, P_GCC_GPLL8_OUT_MAIN, 4, 0, 0), F(350000000, P_GCC_GPLL8_OUT_MAIN, 2, 0, 0), { } From 54e5da4d1fbccf03042de1ecfa33987e2ff80268 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 10 Oct 2025 12:24:51 +0200 Subject: [PATCH 128/684] clk: qcom: gcc-x1e80100: Remove 85.71 MHz USB4 master clock frequency The USB4 HPG says this frequency remains unused, remove it from the frequency table to avoid any misunderstandings. The reason it's unused seems to be that the lower RPMh level required to support it (LOW_SVS) is not enough for other pieces of the pipeline which require SVS, which in turn is enough to support a faster, 175 MHz rate. Signed-off-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20251010-topic-gcc_usb4_unused_freq-v1-2-4be5e77d2307@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-x1e80100.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-x1e80100.c b/drivers/clk/qcom/gcc-x1e80100.c index 8804ad5d70be0b..b63c8abdd2fc24 100644 --- a/drivers/clk/qcom/gcc-x1e80100.c +++ b/drivers/clk/qcom/gcc-x1e80100.c @@ -1849,7 +1849,6 @@ static struct clk_rcg2 gcc_usb3_tert_phy_aux_clk_src = { }; static const struct freq_tbl ftbl_gcc_usb4_0_master_clk_src[] = { - F(85714286, P_GCC_GPLL0_OUT_EVEN, 3.5, 0, 0), F(175000000, P_GCC_GPLL8_OUT_MAIN, 4, 0, 0), F(350000000, P_GCC_GPLL8_OUT_MAIN, 2, 0, 0), { } From 5e26bb2a17789754e44aec2519fa719bd1fc04e0 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 10 Oct 2025 12:24:52 +0200 Subject: [PATCH 129/684] clk: qcom: gcc-glymur: Remove 85.71 MHz USB4 master clock frequency The USB4 HPG says this frequency remains unused, remove it from the frequency table to avoid any misunderstandings. The reason it's unused seems to be that the lower RPMh level required to support it (LOW_SVS) is not enough for other pieces of the pipeline which require SVS, which in turn is enough to support a faster, 175-ish MHz rate. Signed-off-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20251010-topic-gcc_usb4_unused_freq-v1-3-4be5e77d2307@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-glymur.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-glymur.c b/drivers/clk/qcom/gcc-glymur.c index d938e7dc5b66ec..deab819576d0e1 100644 --- a/drivers/clk/qcom/gcc-glymur.c +++ b/drivers/clk/qcom/gcc-glymur.c @@ -2643,7 +2643,6 @@ static struct clk_rcg2 gcc_usb3_tert_phy_aux_clk_src = { }; static const struct freq_tbl ftbl_gcc_usb4_0_master_clk_src[] = { - F(85714286, P_GCC_GPLL0_OUT_EVEN, 3.5, 0, 0), F(177666750, P_GCC_GPLL8_OUT_MAIN, 4, 0, 0), F(355333500, P_GCC_GPLL8_OUT_MAIN, 2, 0, 0), { } From 464ce94531f5a62ce29081a9d3c70eb4d525f443 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Tue, 14 Oct 2025 22:35:26 +0800 Subject: [PATCH 130/684] clk: qcom: gcc-ipq5424: Correct the icc_first_node_id Update to use the expected icc_first_node_id for registering the icc clocks, ensuring correct association of clocks with interconnect nodes. Fixes: 170f3d2c065e ("clk: qcom: ipq5424: Use icc-clk for enabling NoC related clocks") Reviewed-by: Konrad Dybcio Signed-off-by: Luo Jie Link: https://lore.kernel.org/r/20251014-qcom_ipq5424_nsscc-v7-1-081f4956be02@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5424.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c index 3d42f3d85c7a92..71afa1b86b7233 100644 --- a/drivers/clk/qcom/gcc-ipq5424.c +++ b/drivers/clk/qcom/gcc-ipq5424.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -3284,6 +3284,7 @@ static const struct qcom_cc_desc gcc_ipq5424_desc = { .num_clk_hws = ARRAY_SIZE(gcc_ipq5424_hws), .icc_hws = icc_ipq5424_hws, .num_icc_hws = ARRAY_SIZE(icc_ipq5424_hws), + .icc_first_node_id = IPQ_APPS_ID, }; static int gcc_ipq5424_probe(struct platform_device *pdev) From e2cf3b73573e24283e1c640eb9a186cfe3c01d84 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Tue, 14 Oct 2025 22:35:29 +0800 Subject: [PATCH 131/684] clk: qcom: gcc-ipq5424: Enable NSS NoC clocks to use icc-clk Add NSS NoC clocks using the icc-clk framework to create interconnect paths. The network subsystem (NSS) can be connected to these NoCs. Additionally, add the LPASS CNOC and SNOC nodes to establish the complete interconnect path. Reviewed-by: Konrad Dybcio Signed-off-by: Luo Jie Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251014-qcom_ipq5424_nsscc-v7-4-081f4956be02@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5424.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c index 71afa1b86b7233..6cfe4f2b28887a 100644 --- a/drivers/clk/qcom/gcc-ipq5424.c +++ b/drivers/clk/qcom/gcc-ipq5424.c @@ -3250,6 +3250,16 @@ static const struct qcom_icc_hws_data icc_ipq5424_hws[] = { { MASTER_ANOC_PCIE3, SLAVE_ANOC_PCIE3, GCC_ANOC_PCIE3_2LANE_M_CLK }, { MASTER_CNOC_PCIE3, SLAVE_CNOC_PCIE3, GCC_CNOC_PCIE3_2LANE_S_CLK }, { MASTER_CNOC_USB, SLAVE_CNOC_USB, GCC_CNOC_USB_CLK }, + { MASTER_NSSNOC_NSSCC, SLAVE_NSSNOC_NSSCC, GCC_NSSNOC_NSSCC_CLK }, + { MASTER_NSSNOC_SNOC_0, SLAVE_NSSNOC_SNOC_0, GCC_NSSNOC_SNOC_CLK }, + { MASTER_NSSNOC_SNOC_1, SLAVE_NSSNOC_SNOC_1, GCC_NSSNOC_SNOC_1_CLK }, + { MASTER_NSSNOC_PCNOC_1, SLAVE_NSSNOC_PCNOC_1, GCC_NSSNOC_PCNOC_1_CLK }, + { MASTER_NSSNOC_QOSGEN_REF, SLAVE_NSSNOC_QOSGEN_REF, GCC_NSSNOC_QOSGEN_REF_CLK }, + { MASTER_NSSNOC_TIMEOUT_REF, SLAVE_NSSNOC_TIMEOUT_REF, GCC_NSSNOC_TIMEOUT_REF_CLK }, + { MASTER_NSSNOC_XO_DCD, SLAVE_NSSNOC_XO_DCD, GCC_NSSNOC_XO_DCD_CLK }, + { MASTER_NSSNOC_ATB, SLAVE_NSSNOC_ATB, GCC_NSSNOC_ATB_CLK }, + { MASTER_CNOC_LPASS_CFG, SLAVE_CNOC_LPASS_CFG, GCC_CNOC_LPASS_CFG_CLK }, + { MASTER_SNOC_LPASS, SLAVE_SNOC_LPASS, GCC_SNOC_LPASS_CLK }, }; static const struct of_device_id gcc_ipq5424_match_table[] = { From d08882c66d7a929c321cfaca9dee64e40eba3bd2 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Tue, 14 Oct 2025 22:35:31 +0800 Subject: [PATCH 132/684] clk: qcom: gcc-ipq5424: Add gpll0_out_aux clock The clock gpll0_out_aux acts as the parent clock for some of the NSS (Network Subsystem) clocks. Reviewed-by: Konrad Dybcio Signed-off-by: Luo Jie Link: https://lore.kernel.org/r/20251014-qcom_ipq5424_nsscc-v7-6-081f4956be02@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5424.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c index 6cfe4f2b28887a..35af6ffeeb8554 100644 --- a/drivers/clk/qcom/gcc-ipq5424.c +++ b/drivers/clk/qcom/gcc-ipq5424.c @@ -79,6 +79,20 @@ static struct clk_fixed_factor gpll0_div2 = { }, }; +static struct clk_alpha_pll_postdiv gpll0_out_aux = { + .offset = 0x20000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll0_out_aux", + .parent_hws = (const struct clk_hw *[]) { + &gpll0.clkr.hw + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + static struct clk_alpha_pll gpll2 = { .offset = 0x21000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA], @@ -2934,6 +2948,7 @@ static struct clk_regmap *gcc_ipq5424_clocks[] = { [GPLL2] = &gpll2.clkr, [GPLL2_OUT_MAIN] = &gpll2_out_main.clkr, [GPLL4] = &gpll4.clkr, + [GPLL0_OUT_AUX] = &gpll0_out_aux.clkr, }; static const struct qcom_reset_map gcc_ipq5424_resets[] = { From fd0b632efbbdf427678a7a880abeb828bc4633fe Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Tue, 14 Oct 2025 22:35:33 +0800 Subject: [PATCH 133/684] clk: qcom: Add NSS clock controller driver for IPQ5424 NSS (Network Subsystem) clock controller provides the clocks and resets to the networking hardware blocks of the IPQ5424 SoC. The icc-clk framework is used to enable NoC related clocks to create paths so that the networking blocks can connect to these NoCs. Acked-by: Konrad Dybcio Signed-off-by: Luo Jie Link: https://lore.kernel.org/r/20251014-qcom_ipq5424_nsscc-v7-8-081f4956be02@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 11 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/nsscc-ipq5424.c | 1340 ++++++++++++++++++++++++++++++ 3 files changed, 1352 insertions(+) create mode 100644 drivers/clk/qcom/nsscc-ipq5424.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 6fef0bfc17736b..4a78099e706c2c 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -317,6 +317,17 @@ config IPQ_GCC_9574 i2c, USB, SD/eMMC, etc. Select this for the root clock of ipq9574. +config IPQ_NSSCC_5424 + tristate "IPQ5424 NSS Clock Controller" + depends on ARM64 || COMPILE_TEST + depends on IPQ_GCC_5424 + help + Support for NSS clock controller on ipq5424 devices. + NSSCC receives the clock sources from GCC, CMN PLL and UNIPHY (PCS). + It in turn supplies the clocks and resets to the networking hardware. + Say Y or M if you want to enable networking function on the + IPQ5424 devices. + config IPQ_NSSCC_9574 tristate "IPQ9574 NSS Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 8051d481c439bd..5a0fd1d843c87a 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o obj-$(CONFIG_IPQ_GCC_9574) += gcc-ipq9574.o +obj-$(CONFIG_IPQ_NSSCC_5424) += nsscc-ipq5424.o obj-$(CONFIG_IPQ_NSSCC_9574) += nsscc-ipq9574.o obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o obj-$(CONFIG_IPQ_NSSCC_QCA8K) += nsscc-qca8k.o diff --git a/drivers/clk/qcom/nsscc-ipq5424.c b/drivers/clk/qcom/nsscc-ipq5424.c new file mode 100644 index 00000000000000..5893c714618007 --- /dev/null +++ b/drivers/clk/qcom/nsscc-ipq5424.c @@ -0,0 +1,1340 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "reset.h" + +/* Need to match the order of clocks in DT binding */ +enum { + DT_CMN_PLL_XO_CLK, + DT_CMN_PLL_NSS_300M_CLK, + DT_CMN_PLL_NSS_375M_CLK, + DT_GCC_GPLL0_OUT_AUX, + DT_UNIPHY0_NSS_RX_CLK, + DT_UNIPHY0_NSS_TX_CLK, + DT_UNIPHY1_NSS_RX_CLK, + DT_UNIPHY1_NSS_TX_CLK, + DT_UNIPHY2_NSS_RX_CLK, + DT_UNIPHY2_NSS_TX_CLK, +}; + +enum { + P_CMN_PLL_XO_CLK, + P_CMN_PLL_NSS_300M_CLK, + P_CMN_PLL_NSS_375M_CLK, + P_GCC_GPLL0_OUT_AUX, + P_UNIPHY0_NSS_RX_CLK, + P_UNIPHY0_NSS_TX_CLK, + P_UNIPHY1_NSS_RX_CLK, + P_UNIPHY1_NSS_TX_CLK, + P_UNIPHY2_NSS_RX_CLK, + P_UNIPHY2_NSS_TX_CLK, +}; + +static const struct parent_map nss_cc_parent_map_0[] = { + { P_CMN_PLL_XO_CLK, 0 }, + { P_GCC_GPLL0_OUT_AUX, 2 }, + { P_CMN_PLL_NSS_300M_CLK, 5 }, + { P_CMN_PLL_NSS_375M_CLK, 6 }, +}; + +static const struct clk_parent_data nss_cc_parent_data_0[] = { + { .index = DT_CMN_PLL_XO_CLK }, + { .index = DT_GCC_GPLL0_OUT_AUX }, + { .index = DT_CMN_PLL_NSS_300M_CLK }, + { .index = DT_CMN_PLL_NSS_375M_CLK }, +}; + +static const struct parent_map nss_cc_parent_map_1[] = { + { P_CMN_PLL_XO_CLK, 0 }, + { P_GCC_GPLL0_OUT_AUX, 2 }, + { P_UNIPHY0_NSS_RX_CLK, 3 }, + { P_UNIPHY0_NSS_TX_CLK, 4 }, + { P_CMN_PLL_NSS_300M_CLK, 5 }, + { P_CMN_PLL_NSS_375M_CLK, 6 }, +}; + +static const struct clk_parent_data nss_cc_parent_data_1[] = { + { .index = DT_CMN_PLL_XO_CLK }, + { .index = DT_GCC_GPLL0_OUT_AUX }, + { .index = DT_UNIPHY0_NSS_RX_CLK }, + { .index = DT_UNIPHY0_NSS_TX_CLK }, + { .index = DT_CMN_PLL_NSS_300M_CLK }, + { .index = DT_CMN_PLL_NSS_375M_CLK }, +}; + +static const struct parent_map nss_cc_parent_map_2[] = { + { P_CMN_PLL_XO_CLK, 0 }, + { P_GCC_GPLL0_OUT_AUX, 2 }, + { P_UNIPHY1_NSS_RX_CLK, 3 }, + { P_UNIPHY1_NSS_TX_CLK, 4 }, + { P_CMN_PLL_NSS_300M_CLK, 5 }, + { P_CMN_PLL_NSS_375M_CLK, 6 }, +}; + +static const struct clk_parent_data nss_cc_parent_data_2[] = { + { .index = DT_CMN_PLL_XO_CLK }, + { .index = DT_GCC_GPLL0_OUT_AUX }, + { .index = DT_UNIPHY1_NSS_RX_CLK }, + { .index = DT_UNIPHY1_NSS_TX_CLK }, + { .index = DT_CMN_PLL_NSS_300M_CLK }, + { .index = DT_CMN_PLL_NSS_375M_CLK }, +}; + +static const struct parent_map nss_cc_parent_map_3[] = { + { P_CMN_PLL_XO_CLK, 0 }, + { P_GCC_GPLL0_OUT_AUX, 2 }, + { P_UNIPHY2_NSS_RX_CLK, 3 }, + { P_UNIPHY2_NSS_TX_CLK, 4 }, + { P_CMN_PLL_NSS_300M_CLK, 5 }, + { P_CMN_PLL_NSS_375M_CLK, 6 }, +}; + +static const struct clk_parent_data nss_cc_parent_data_3[] = { + { .index = DT_CMN_PLL_XO_CLK }, + { .index = DT_GCC_GPLL0_OUT_AUX }, + { .index = DT_UNIPHY2_NSS_RX_CLK }, + { .index = DT_UNIPHY2_NSS_TX_CLK }, + { .index = DT_CMN_PLL_NSS_300M_CLK }, + { .index = DT_CMN_PLL_NSS_375M_CLK }, +}; + +static const struct freq_tbl ftbl_nss_cc_ce_clk_src[] = { + F(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + F(375000000, P_CMN_PLL_NSS_375M_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_ce_clk_src = { + .cmd_rcgr = 0x5e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_0, + .freq_tbl = ftbl_nss_cc_ce_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ce_clk_src", + .parent_data = nss_cc_parent_data_0, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_nss_cc_cfg_clk_src[] = { + F(100000000, P_GCC_GPLL0_OUT_AUX, 8, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_cfg_clk_src = { + .cmd_rcgr = 0x6a8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_0, + .freq_tbl = ftbl_nss_cc_cfg_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_cfg_clk_src", + .parent_data = nss_cc_parent_data_0, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_nss_cc_eip_bfdcd_clk_src[] = { + F(300000000, P_CMN_PLL_NSS_300M_CLK, 1, 0, 0), + F(375000000, P_CMN_PLL_NSS_375M_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_eip_bfdcd_clk_src = { + .cmd_rcgr = 0x644, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_0, + .freq_tbl = ftbl_nss_cc_eip_bfdcd_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_eip_bfdcd_clk_src", + .parent_data = nss_cc_parent_data_0, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_25[] = { + C(P_UNIPHY0_NSS_RX_CLK, 12.5, 0, 0), + C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_125[] = { + C(P_UNIPHY0_NSS_RX_CLK, 2.5, 0, 0), + C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port1_rx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port1_rx_clk_src_25), + FMS(78125000, P_UNIPHY0_NSS_RX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port1_rx_clk_src_125), + FMS(156250000, P_UNIPHY0_NSS_RX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port1_rx_clk_src = { + .cmd_rcgr = 0x4b4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_1, + .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port1_rx_clk_src", + .parent_data = nss_cc_parent_data_1, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_25[] = { + C(P_UNIPHY0_NSS_TX_CLK, 12.5, 0, 0), + C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_125[] = { + C(P_UNIPHY0_NSS_TX_CLK, 2.5, 0, 0), + C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port1_tx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port1_tx_clk_src_25), + FMS(78125000, P_UNIPHY0_NSS_TX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port1_tx_clk_src_125), + FMS(156250000, P_UNIPHY0_NSS_TX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port1_tx_clk_src = { + .cmd_rcgr = 0x4c0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_1, + .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port1_tx_clk_src", + .parent_data = nss_cc_parent_data_1, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port2_rx_clk_src_25[] = { + C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0), + C(P_UNIPHY1_NSS_RX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port2_rx_clk_src_125[] = { + C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0), + C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port2_rx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port2_rx_clk_src_25), + FMS(78125000, P_UNIPHY1_NSS_RX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port2_rx_clk_src_125), + FMS(156250000, P_UNIPHY1_NSS_RX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port2_rx_clk_src = { + .cmd_rcgr = 0x4cc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_2, + .freq_multi_tbl = ftbl_nss_cc_port2_rx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port2_rx_clk_src", + .parent_data = nss_cc_parent_data_2, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port2_tx_clk_src_25[] = { + C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0), + C(P_UNIPHY1_NSS_TX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port2_tx_clk_src_125[] = { + C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0), + C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port2_tx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port2_tx_clk_src_25), + FMS(78125000, P_UNIPHY1_NSS_TX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port2_tx_clk_src_125), + FMS(156250000, P_UNIPHY1_NSS_TX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port2_tx_clk_src = { + .cmd_rcgr = 0x4d8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_2, + .freq_multi_tbl = ftbl_nss_cc_port2_tx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port2_tx_clk_src", + .parent_data = nss_cc_parent_data_2, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port3_rx_clk_src_25[] = { + C(P_UNIPHY2_NSS_RX_CLK, 12.5, 0, 0), + C(P_UNIPHY2_NSS_RX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port3_rx_clk_src_125[] = { + C(P_UNIPHY2_NSS_RX_CLK, 2.5, 0, 0), + C(P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port3_rx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port3_rx_clk_src_25), + FMS(78125000, P_UNIPHY2_NSS_RX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port3_rx_clk_src_125), + FMS(156250000, P_UNIPHY2_NSS_RX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port3_rx_clk_src = { + .cmd_rcgr = 0x4e4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_3, + .freq_multi_tbl = ftbl_nss_cc_port3_rx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port3_rx_clk_src", + .parent_data = nss_cc_parent_data_3, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static const struct freq_conf ftbl_nss_cc_port3_tx_clk_src_25[] = { + C(P_UNIPHY2_NSS_TX_CLK, 12.5, 0, 0), + C(P_UNIPHY2_NSS_TX_CLK, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_cc_port3_tx_clk_src_125[] = { + C(P_UNIPHY2_NSS_TX_CLK, 2.5, 0, 0), + C(P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_cc_port3_tx_clk_src[] = { + FMS(24000000, P_CMN_PLL_XO_CLK, 1, 0, 0), + FM(25000000, ftbl_nss_cc_port3_tx_clk_src_25), + FMS(78125000, P_UNIPHY2_NSS_TX_CLK, 4, 0, 0), + FM(125000000, ftbl_nss_cc_port3_tx_clk_src_125), + FMS(156250000, P_UNIPHY2_NSS_TX_CLK, 2, 0, 0), + FMS(312500000, P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 nss_cc_port3_tx_clk_src = { + .cmd_rcgr = 0x4f0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_3, + .freq_multi_tbl = ftbl_nss_cc_port3_tx_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port3_tx_clk_src", + .parent_data = nss_cc_parent_data_3, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), + .ops = &clk_rcg2_fm_ops, + }, +}; + +static struct clk_rcg2 nss_cc_ppe_clk_src = { + .cmd_rcgr = 0x3ec, + .mnd_width = 0, + .hid_width = 5, + .parent_map = nss_cc_parent_map_0, + .freq_tbl = ftbl_nss_cc_ce_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_clk_src", + .parent_data = nss_cc_parent_data_0, + .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port1_rx_div_clk_src = { + .reg = 0x4bc, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port1_rx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port1_tx_div_clk_src = { + .reg = 0x4c8, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port1_tx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port2_rx_div_clk_src = { + .reg = 0x4d4, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port2_rx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port2_tx_div_clk_src = { + .reg = 0x4e0, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port2_tx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port3_rx_div_clk_src = { + .reg = 0x4ec, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port3_rx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_port3_tx_div_clk_src = { + .reg = 0x4f8, + .shift = 0, + .width = 9, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_port3_tx_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div nss_cc_xgmac0_ptp_ref_div_clk_src = { + .reg = 0x3f4, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_xgmac0_ptp_ref_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div nss_cc_xgmac1_ptp_ref_div_clk_src = { + .reg = 0x3f8, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_xgmac1_ptp_ref_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div nss_cc_xgmac2_ptp_ref_div_clk_src = { + .reg = 0x3fc, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "nss_cc_xgmac2_ptp_ref_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch nss_cc_ce_apb_clk = { + .halt_reg = 0x5e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5e8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ce_apb_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ce_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ce_axi_clk = { + .halt_reg = 0x5ec, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5ec, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ce_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ce_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_debug_clk = { + .halt_reg = 0x70c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x70c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_debug_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_eip_clk = { + .halt_reg = 0x658, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x658, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_eip_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_eip_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nss_csr_clk = { + .halt_reg = 0x6b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nss_csr_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_cfg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_ce_apb_clk = { + .halt_reg = 0x5f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_ce_apb_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ce_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_ce_axi_clk = { + .halt_reg = 0x5f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_ce_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ce_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_eip_clk = { + .halt_reg = 0x660, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x660, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_eip_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_eip_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_nss_csr_clk = { + .halt_reg = 0x6b4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6b4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_nss_csr_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_cfg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_ppe_cfg_clk = { + .halt_reg = 0x444, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x444, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_ppe_cfg_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_nssnoc_ppe_clk = { + .halt_reg = 0x440, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x440, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_nssnoc_ppe_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port1_mac_clk = { + .halt_reg = 0x428, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x428, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port1_mac_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port1_rx_clk = { + .halt_reg = 0x4fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port1_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port1_tx_clk = { + .halt_reg = 0x504, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x504, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port1_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port2_mac_clk = { + .halt_reg = 0x430, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x430, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port2_mac_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port2_rx_clk = { + .halt_reg = 0x50c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port2_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port2_tx_clk = { + .halt_reg = 0x514, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x514, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port2_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port3_mac_clk = { + .halt_reg = 0x438, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x438, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port3_mac_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port3_rx_clk = { + .halt_reg = 0x51c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port3_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_port3_tx_clk = { + .halt_reg = 0x524, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x524, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_port3_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_edma_cfg_clk = { + .halt_reg = 0x424, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x424, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_edma_cfg_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_edma_clk = { + .halt_reg = 0x41c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x41c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_edma_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_switch_btq_clk = { + .halt_reg = 0x408, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x408, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_switch_btq_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_switch_cfg_clk = { + .halt_reg = 0x418, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x418, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_switch_cfg_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_switch_clk = { + .halt_reg = 0x410, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x410, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_switch_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_ppe_switch_ipe_clk = { + .halt_reg = 0x400, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x400, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_ppe_switch_ipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_ppe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port1_rx_clk = { + .halt_reg = 0x57c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x57c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port1_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port1_tx_clk = { + .halt_reg = 0x580, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x580, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port1_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port1_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port2_rx_clk = { + .halt_reg = 0x584, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x584, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port2_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port2_tx_clk = { + .halt_reg = 0x588, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x588, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port2_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port2_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port3_rx_clk = { + .halt_reg = 0x58c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port3_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_rx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_uniphy_port3_tx_clk = { + .halt_reg = 0x590, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x590, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_uniphy_port3_tx_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_port3_tx_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_xgmac0_ptp_ref_clk = { + .halt_reg = 0x448, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x448, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_xgmac0_ptp_ref_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_xgmac1_ptp_ref_clk = { + .halt_reg = 0x44c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x44c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_xgmac1_ptp_ref_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch nss_cc_xgmac2_ptp_ref_clk = { + .halt_reg = 0x450, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x450, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "nss_cc_xgmac2_ptp_ref_clk", + .parent_hws = (const struct clk_hw*[]){ + &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *nss_cc_ipq5424_clocks[] = { + [NSS_CC_CE_APB_CLK] = &nss_cc_ce_apb_clk.clkr, + [NSS_CC_CE_AXI_CLK] = &nss_cc_ce_axi_clk.clkr, + [NSS_CC_CE_CLK_SRC] = &nss_cc_ce_clk_src.clkr, + [NSS_CC_CFG_CLK_SRC] = &nss_cc_cfg_clk_src.clkr, + [NSS_CC_DEBUG_CLK] = &nss_cc_debug_clk.clkr, + [NSS_CC_EIP_BFDCD_CLK_SRC] = &nss_cc_eip_bfdcd_clk_src.clkr, + [NSS_CC_EIP_CLK] = &nss_cc_eip_clk.clkr, + [NSS_CC_NSS_CSR_CLK] = &nss_cc_nss_csr_clk.clkr, + [NSS_CC_NSSNOC_CE_APB_CLK] = &nss_cc_nssnoc_ce_apb_clk.clkr, + [NSS_CC_NSSNOC_CE_AXI_CLK] = &nss_cc_nssnoc_ce_axi_clk.clkr, + [NSS_CC_NSSNOC_EIP_CLK] = &nss_cc_nssnoc_eip_clk.clkr, + [NSS_CC_NSSNOC_NSS_CSR_CLK] = &nss_cc_nssnoc_nss_csr_clk.clkr, + [NSS_CC_NSSNOC_PPE_CFG_CLK] = &nss_cc_nssnoc_ppe_cfg_clk.clkr, + [NSS_CC_NSSNOC_PPE_CLK] = &nss_cc_nssnoc_ppe_clk.clkr, + [NSS_CC_PORT1_MAC_CLK] = &nss_cc_port1_mac_clk.clkr, + [NSS_CC_PORT1_RX_CLK] = &nss_cc_port1_rx_clk.clkr, + [NSS_CC_PORT1_RX_CLK_SRC] = &nss_cc_port1_rx_clk_src.clkr, + [NSS_CC_PORT1_RX_DIV_CLK_SRC] = &nss_cc_port1_rx_div_clk_src.clkr, + [NSS_CC_PORT1_TX_CLK] = &nss_cc_port1_tx_clk.clkr, + [NSS_CC_PORT1_TX_CLK_SRC] = &nss_cc_port1_tx_clk_src.clkr, + [NSS_CC_PORT1_TX_DIV_CLK_SRC] = &nss_cc_port1_tx_div_clk_src.clkr, + [NSS_CC_PORT2_MAC_CLK] = &nss_cc_port2_mac_clk.clkr, + [NSS_CC_PORT2_RX_CLK] = &nss_cc_port2_rx_clk.clkr, + [NSS_CC_PORT2_RX_CLK_SRC] = &nss_cc_port2_rx_clk_src.clkr, + [NSS_CC_PORT2_RX_DIV_CLK_SRC] = &nss_cc_port2_rx_div_clk_src.clkr, + [NSS_CC_PORT2_TX_CLK] = &nss_cc_port2_tx_clk.clkr, + [NSS_CC_PORT2_TX_CLK_SRC] = &nss_cc_port2_tx_clk_src.clkr, + [NSS_CC_PORT2_TX_DIV_CLK_SRC] = &nss_cc_port2_tx_div_clk_src.clkr, + [NSS_CC_PORT3_MAC_CLK] = &nss_cc_port3_mac_clk.clkr, + [NSS_CC_PORT3_RX_CLK] = &nss_cc_port3_rx_clk.clkr, + [NSS_CC_PORT3_RX_CLK_SRC] = &nss_cc_port3_rx_clk_src.clkr, + [NSS_CC_PORT3_RX_DIV_CLK_SRC] = &nss_cc_port3_rx_div_clk_src.clkr, + [NSS_CC_PORT3_TX_CLK] = &nss_cc_port3_tx_clk.clkr, + [NSS_CC_PORT3_TX_CLK_SRC] = &nss_cc_port3_tx_clk_src.clkr, + [NSS_CC_PORT3_TX_DIV_CLK_SRC] = &nss_cc_port3_tx_div_clk_src.clkr, + [NSS_CC_PPE_CLK_SRC] = &nss_cc_ppe_clk_src.clkr, + [NSS_CC_PPE_EDMA_CFG_CLK] = &nss_cc_ppe_edma_cfg_clk.clkr, + [NSS_CC_PPE_EDMA_CLK] = &nss_cc_ppe_edma_clk.clkr, + [NSS_CC_PPE_SWITCH_BTQ_CLK] = &nss_cc_ppe_switch_btq_clk.clkr, + [NSS_CC_PPE_SWITCH_CFG_CLK] = &nss_cc_ppe_switch_cfg_clk.clkr, + [NSS_CC_PPE_SWITCH_CLK] = &nss_cc_ppe_switch_clk.clkr, + [NSS_CC_PPE_SWITCH_IPE_CLK] = &nss_cc_ppe_switch_ipe_clk.clkr, + [NSS_CC_UNIPHY_PORT1_RX_CLK] = &nss_cc_uniphy_port1_rx_clk.clkr, + [NSS_CC_UNIPHY_PORT1_TX_CLK] = &nss_cc_uniphy_port1_tx_clk.clkr, + [NSS_CC_UNIPHY_PORT2_RX_CLK] = &nss_cc_uniphy_port2_rx_clk.clkr, + [NSS_CC_UNIPHY_PORT2_TX_CLK] = &nss_cc_uniphy_port2_tx_clk.clkr, + [NSS_CC_UNIPHY_PORT3_RX_CLK] = &nss_cc_uniphy_port3_rx_clk.clkr, + [NSS_CC_UNIPHY_PORT3_TX_CLK] = &nss_cc_uniphy_port3_tx_clk.clkr, + [NSS_CC_XGMAC0_PTP_REF_CLK] = &nss_cc_xgmac0_ptp_ref_clk.clkr, + [NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC] = &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr, + [NSS_CC_XGMAC1_PTP_REF_CLK] = &nss_cc_xgmac1_ptp_ref_clk.clkr, + [NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC] = &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr, + [NSS_CC_XGMAC2_PTP_REF_CLK] = &nss_cc_xgmac2_ptp_ref_clk.clkr, + [NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC] = &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr, +}; + +static const struct qcom_reset_map nss_cc_ipq5424_resets[] = { + [NSS_CC_CE_APB_CLK_ARES] = { 0x5e8, 2 }, + [NSS_CC_CE_AXI_CLK_ARES] = { 0x5ec, 2 }, + [NSS_CC_DEBUG_CLK_ARES] = { 0x70c, 2 }, + [NSS_CC_EIP_CLK_ARES] = { 0x658, 2 }, + [NSS_CC_NSS_CSR_CLK_ARES] = { 0x6b0, 2 }, + [NSS_CC_NSSNOC_CE_APB_CLK_ARES] = { 0x5f4, 2 }, + [NSS_CC_NSSNOC_CE_AXI_CLK_ARES] = { 0x5f8, 2 }, + [NSS_CC_NSSNOC_EIP_CLK_ARES] = { 0x660, 2 }, + [NSS_CC_NSSNOC_NSS_CSR_CLK_ARES] = { 0x6b4, 2 }, + [NSS_CC_NSSNOC_PPE_CLK_ARES] = { 0x440, 2 }, + [NSS_CC_NSSNOC_PPE_CFG_CLK_ARES] = { 0x444, 2 }, + [NSS_CC_PORT1_MAC_CLK_ARES] = { 0x428, 2 }, + [NSS_CC_PORT1_RX_CLK_ARES] = { 0x4fc, 2 }, + [NSS_CC_PORT1_TX_CLK_ARES] = { 0x504, 2 }, + [NSS_CC_PORT2_MAC_CLK_ARES] = { 0x430, 2 }, + [NSS_CC_PORT2_RX_CLK_ARES] = { 0x50c, 2 }, + [NSS_CC_PORT2_TX_CLK_ARES] = { 0x514, 2 }, + [NSS_CC_PORT3_MAC_CLK_ARES] = { 0x438, 2 }, + [NSS_CC_PORT3_RX_CLK_ARES] = { 0x51c, 2 }, + [NSS_CC_PORT3_TX_CLK_ARES] = { 0x524, 2 }, + [NSS_CC_PPE_BCR] = { 0x3e8 }, + [NSS_CC_PPE_EDMA_CLK_ARES] = { 0x41c, 2 }, + [NSS_CC_PPE_EDMA_CFG_CLK_ARES] = { 0x424, 2 }, + [NSS_CC_PPE_SWITCH_BTQ_CLK_ARES] = { 0x408, 2 }, + [NSS_CC_PPE_SWITCH_CLK_ARES] = { 0x410, 2 }, + [NSS_CC_PPE_SWITCH_CFG_CLK_ARES] = { 0x418, 2 }, + [NSS_CC_PPE_SWITCH_IPE_CLK_ARES] = { 0x400, 2 }, + [NSS_CC_UNIPHY_PORT1_RX_CLK_ARES] = { 0x57c, 2 }, + [NSS_CC_UNIPHY_PORT1_TX_CLK_ARES] = { 0x580, 2 }, + [NSS_CC_UNIPHY_PORT2_RX_CLK_ARES] = { 0x584, 2 }, + [NSS_CC_UNIPHY_PORT2_TX_CLK_ARES] = { 0x588, 2 }, + [NSS_CC_UNIPHY_PORT3_RX_CLK_ARES] = { 0x58c, 2 }, + [NSS_CC_UNIPHY_PORT3_TX_CLK_ARES] = { 0x590, 2 }, + [NSS_CC_XGMAC0_PTP_REF_CLK_ARES] = { 0x448, 2 }, + [NSS_CC_XGMAC1_PTP_REF_CLK_ARES] = { 0x44c, 2 }, + [NSS_CC_XGMAC2_PTP_REF_CLK_ARES] = { 0x450, 2 }, +}; + +static const struct regmap_config nss_cc_ipq5424_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x800, + .fast_io = true, +}; + +static const struct qcom_icc_hws_data icc_ipq5424_nss_hws[] = { + { MASTER_NSSNOC_PPE, SLAVE_NSSNOC_PPE, NSS_CC_NSSNOC_PPE_CLK }, + { MASTER_NSSNOC_PPE_CFG, SLAVE_NSSNOC_PPE_CFG, NSS_CC_NSSNOC_PPE_CFG_CLK }, + { MASTER_NSSNOC_NSS_CSR, SLAVE_NSSNOC_NSS_CSR, NSS_CC_NSSNOC_NSS_CSR_CLK }, + { MASTER_NSSNOC_CE_AXI, SLAVE_NSSNOC_CE_AXI, NSS_CC_NSSNOC_CE_AXI_CLK}, + { MASTER_NSSNOC_CE_APB, SLAVE_NSSNOC_CE_APB, NSS_CC_NSSNOC_CE_APB_CLK}, + { MASTER_NSSNOC_EIP, SLAVE_NSSNOC_EIP, NSS_CC_NSSNOC_EIP_CLK}, +}; + +#define IPQ_NSSCC_ID (5424 * 2) /* some unique value */ + +static const struct qcom_cc_desc nss_cc_ipq5424_desc = { + .config = &nss_cc_ipq5424_regmap_config, + .clks = nss_cc_ipq5424_clocks, + .num_clks = ARRAY_SIZE(nss_cc_ipq5424_clocks), + .resets = nss_cc_ipq5424_resets, + .num_resets = ARRAY_SIZE(nss_cc_ipq5424_resets), + .icc_hws = icc_ipq5424_nss_hws, + .num_icc_hws = ARRAY_SIZE(icc_ipq5424_nss_hws), + .icc_first_node_id = IPQ_NSSCC_ID, +}; + +static const struct dev_pm_ops nss_cc_ipq5424_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static const struct of_device_id nss_cc_ipq5424_match_table[] = { + { .compatible = "qcom,ipq5424-nsscc" }, + { } +}; +MODULE_DEVICE_TABLE(of, nss_cc_ipq5424_match_table); + +static int nss_cc_ipq5424_probe(struct platform_device *pdev) +{ + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Fail to enable runtime PM\n"); + + ret = devm_pm_clk_create(&pdev->dev); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Fail to create PM clock\n"); + + ret = pm_clk_add(&pdev->dev, "bus"); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n"); + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Fail to resume\n"); + + ret = qcom_cc_probe(pdev, &nss_cc_ipq5424_desc); + pm_runtime_put(&pdev->dev); + + return ret; +} + +static struct platform_driver nss_cc_ipq5424_driver = { + .probe = nss_cc_ipq5424_probe, + .driver = { + .name = "qcom,ipq5424-nsscc", + .of_match_table = nss_cc_ipq5424_match_table, + .pm = &nss_cc_ipq5424_pm_ops, + .sync_state = icc_sync_state, + }, +}; +module_platform_driver(nss_cc_ipq5424_driver); + +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. NSSCC IPQ5424 Driver"); +MODULE_LICENSE("GPL"); From ab0e13141d679fdffdd3463a272c5c1b10be1794 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Tue, 21 Oct 2025 20:08:54 +0200 Subject: [PATCH 134/684] clk: qcom: camcc-sm6350: Fix PLL config of PLL2 The 'Agera' PLLs (with clk_agera_pll_configure) do not take some of the parameters that are provided in the vendor driver. Instead the upstream configuration should provide the final user_ctl value that is written to the USER_CTL register. Fix the config so that the PLL is configured correctly, and fixes CAMCC_MCLK* being stuck off. Fixes: 80f5451d9a7c ("clk: qcom: Add camera clock controller driver for SM6350") Suggested-by: Taniya Das Signed-off-by: Luca Weiss Reviewed-by: Abel Vesa Reviewed-by: Taniya Das Link: https://lore.kernel.org/r/20251021-agera-pll-fixups-v1-1-8c1d8aff4afc@fairphone.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm6350.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clk/qcom/camcc-sm6350.c b/drivers/clk/qcom/camcc-sm6350.c index 6c272f7b07219d..7df12c1311c682 100644 --- a/drivers/clk/qcom/camcc-sm6350.c +++ b/drivers/clk/qcom/camcc-sm6350.c @@ -145,15 +145,11 @@ static struct clk_alpha_pll_postdiv camcc_pll1_out_even = { static const struct alpha_pll_config camcc_pll2_config = { .l = 0x64, .alpha = 0x0, - .post_div_val = 0x3 << 8, - .post_div_mask = 0x3 << 8, - .aux_output_mask = BIT(1), - .main_output_mask = BIT(0), - .early_output_mask = BIT(3), .config_ctl_val = 0x20000800, .config_ctl_hi_val = 0x400003d2, .test_ctl_val = 0x04000400, .test_ctl_hi_val = 0x00004000, + .user_ctl_val = 0x0000030b, }; static struct clk_alpha_pll camcc_pll2 = { From 415aad75c7e5cdb72e0672dc1159be1a99535ecd Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Tue, 21 Oct 2025 20:08:55 +0200 Subject: [PATCH 135/684] clk: qcom: camcc-sm7150: Fix PLL config of PLL2 The 'Agera' PLLs (with clk_agera_pll_configure) do not take some of the parameters that are provided in the vendor driver. Instead the upstream configuration should provide the final user_ctl value that is written to the USER_CTL register. Fix the config so that the PLL is configured correctly. Fixes: 9f0532da4226 ("clk: qcom: Add Camera Clock Controller driver for SM7150") Suggested-by: Taniya Das Signed-off-by: Luca Weiss Reviewed-by: Abel Vesa Reviewed-by: Taniya Das Link: https://lore.kernel.org/r/20251021-agera-pll-fixups-v1-2-8c1d8aff4afc@fairphone.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm7150.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clk/qcom/camcc-sm7150.c b/drivers/clk/qcom/camcc-sm7150.c index 0e072ae39ec04d..8b06af8d15096c 100644 --- a/drivers/clk/qcom/camcc-sm7150.c +++ b/drivers/clk/qcom/camcc-sm7150.c @@ -139,13 +139,9 @@ static struct clk_fixed_factor camcc_pll1_out_even = { /* 1920MHz configuration */ static const struct alpha_pll_config camcc_pll2_config = { .l = 0x64, - .post_div_val = 0x3 << 8, - .post_div_mask = 0x3 << 8, - .early_output_mask = BIT(3), - .aux_output_mask = BIT(1), - .main_output_mask = BIT(0), .config_ctl_hi_val = 0x400003d6, .config_ctl_val = 0x20000954, + .user_ctl_val = 0x0000030b, }; static struct clk_alpha_pll camcc_pll2 = { From 2050b57ecda040010ec797fb07713889372c5041 Mon Sep 17 00:00:00 2001 From: Khairul Anuar Romli Date: Mon, 6 Oct 2025 11:10:15 +0800 Subject: [PATCH 136/684] clk: socfpga: agilex5: add clock driver for Agilex5 Add the new Clock manager driver to support new Agilex5 platform. The new driver got rid of the clk_parent_data structures as there are no 'clock-names' property in the DT bindings and use parent_names internally. This is based on the previous feedback from the maintainer. Signed-off-by: Ang Tien Sung Signed-off-by: Khairul Anuar Romli Signed-off-by: Dinh Nguyen --- drivers/clk/socfpga/Kconfig | 2 +- drivers/clk/socfpga/Makefile | 2 +- drivers/clk/socfpga/clk-agilex5.c | 561 +++++++++++++++++++++++++++ drivers/clk/socfpga/clk-gate-s10.c | 53 +++ drivers/clk/socfpga/clk-periph-s10.c | 41 ++ drivers/clk/socfpga/clk-pll-s10.c | 36 ++ drivers/clk/socfpga/stratix10-clk.h | 43 ++ 7 files changed, 736 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/socfpga/clk-agilex5.c diff --git a/drivers/clk/socfpga/Kconfig b/drivers/clk/socfpga/Kconfig index 0cf16b894efb3a..d88277e2a89815 100644 --- a/drivers/clk/socfpga/Kconfig +++ b/drivers/clk/socfpga/Kconfig @@ -13,7 +13,7 @@ config CLK_INTEL_SOCFPGA32 default ARM && ARCH_INTEL_SOCFPGA config CLK_INTEL_SOCFPGA64 - bool "Intel Stratix / Agilex / N5X clock controller support" if COMPILE_TEST && (!ARM64 || !ARCH_INTEL_SOCFPGA) + bool "Intel Stratix / Agilex / N5X / Agilex5 clock controller support" if COMPILE_TEST && (!ARM64 || !ARCH_INTEL_SOCFPGA) default ARM64 && ARCH_INTEL_SOCFPGA endif # CLK_INTEL_SOCFPGA diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index e8dfce339c915e..a1ea2b988eaf48 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_CLK_INTEL_SOCFPGA32) += clk.o clk-gate.o clk-pll.o clk-periph.o \ clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o obj-$(CONFIG_CLK_INTEL_SOCFPGA64) += clk-s10.o \ clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o \ - clk-agilex.o + clk-agilex.o clk-agilex5.o diff --git a/drivers/clk/socfpga/clk-agilex5.c b/drivers/clk/socfpga/clk-agilex5.c new file mode 100644 index 00000000000000..f7f0ad884f6450 --- /dev/null +++ b/drivers/clk/socfpga/clk-agilex5.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022-2024, Intel Corporation + * Copyright (C) 2025, Altera Corporation + */ +#include +#include +#include +#include +#include +#include "stratix10-clk.h" +#include "clk.h" + +/* External parent clocks come from DT via fw_name */ +static const char * const boot_pll_parents[] = { + "osc1", + "cb-intosc-hs-div2-clk", +}; + +static const char * const main_pll_parents[] = { + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const periph_pll_parents[] = { + "osc1", + "cb-intosc-hs-div2-clk", +}; + +/* Core free muxes */ +static const char * const core0_free_mux[] = { + "main_pll_c1", + "peri_pll_c0", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const core1_free_mux[] = { + "main_pll_c1", + "peri_pll_c0", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const core2_free_mux[] = { + "main_pll_c0", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const core3_free_mux[] = { + "main_pll_c0", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const dsu_free_mux[] = { + "main_pll_c2", + "peri_pll_c0", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const noc_free_mux[] = { + "main_pll_c3", + "peri_pll_c1", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const emac_ptp_free_mux[] = { + "main_pll_c3", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const emaca_free_mux[] = { + "main_pll_c2", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const emacb_free_mux[] = { + "main_pll_c3", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const gpio_db_free_mux[] = { + "main_pll_c3", + "peri_pll_c1", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const psi_ref_free_mux[] = { + "main_pll_c1", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const usb31_free_mux[] = { + "main_pll_c3", + "peri_pll_c2", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const s2f_user0_free_mux[] = { + "main_pll_c1", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +static const char * const s2f_user1_free_mux[] = { + "main_pll_c1", + "peri_pll_c3", + "osc1", + "cb-intosc-hs-div2-clk", + "f2s-free-clk", +}; + +/* Secondary muxes between free_clk and boot_clk */ +static const char * const core0_mux[] = { + "core0_free_clk", + "boot_clk", +}; + +static const char * const core1_mux[] = { + "core1_free_clk", + "boot_clk", +}; + +static const char * const core2_mux[] = { + "core2_free_clk", + "boot_clk", +}; + +static const char * const core3_mux[] = { + "core3_free_clk", + "boot_clk", +}; + +static const char * const dsu_mux[] = { + "dsu_free_clk", + "boot_clk", +}; + +static const char * const noc_mux[] = { + "noc_free_clk", + "boot_clk", +}; + +static const char * const emac_mux[] = { + "emaca_free_clk", + "emacb_free_clk", + "boot_clk", +}; + +static const char * const s2f_user0_mux[] = { + "s2f_user0_free_clk", + "boot_clk", +}; + +static const char * const s2f_user1_mux[] = { + "s2f_user1_free_clk", + "boot_clk", +}; + +static const char * const psi_mux[] = { + "psi_ref_free_clk", + "boot_clk", +}; + +static const char * const gpio_db_mux[] = { + "gpio_db_free_clk", + "boot_clk", +}; + +static const char * const emac_ptp_mux[] = { + "emac_ptp_free_clk", + "boot_clk", +}; + +static const char * const usb31_mux[] = { + "usb31_free_clk", + "boot_clk", +}; + +static const struct agilex5_pll_clock agilex5_pll_clks[] = { + { + .id = AGILEX5_BOOT_CLK, + .name = "boot_clk", + .parent_names = boot_pll_parents, + .num_parents = ARRAY_SIZE(boot_pll_parents), + .flags = 0, + .offset = 0x0, + }, + { + .id = AGILEX5_MAIN_PLL_CLK, + .name = "main_pll", + .parent_names = main_pll_parents, + .num_parents = ARRAY_SIZE(main_pll_parents), + .flags = 0, + .offset = 0x48, + }, + { + .id = AGILEX5_PERIPH_PLL_CLK, + .name = "periph_pll", + .parent_names = periph_pll_parents, + .num_parents = ARRAY_SIZE(periph_pll_parents), + .flags = 0, + .offset = 0x9C, + }, +}; + +/* Main PLL C0, C1, C2, C3 and Peri PLL C0, C1, C2, C3. With ping-pong counter. */ +static const struct stratix10_perip_c_clock agilex5_main_perip_c_clks[] = { + { AGILEX5_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, + 0x5C }, + { AGILEX5_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, + 0x60 }, + { AGILEX5_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, + 0x64 }, + { AGILEX5_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, + 0x68 }, + { AGILEX5_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, + 0xB0 }, + { AGILEX5_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, + 0xB4 }, + { AGILEX5_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, + 0xB8 }, + { AGILEX5_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, + 0xBC }, +}; + +/* Non-SW clock-gated enabled clocks */ +static const struct agilex5_perip_cnt_clock agilex5_main_perip_cnt_clks[] = { + { AGILEX5_CORE0_FREE_CLK, "core0_free_clk", core0_free_mux, + ARRAY_SIZE(core0_free_mux), 0, 0x0100, 0, 0, 0}, + { AGILEX5_CORE1_FREE_CLK, "core1_free_clk", core1_free_mux, + ARRAY_SIZE(core1_free_mux), 0, 0x0104, 0, 0, 0}, + { AGILEX5_CORE2_FREE_CLK, "core2_free_clk", core2_free_mux, + ARRAY_SIZE(core2_free_mux), 0, 0x010C, 0, 0, 0}, + { AGILEX5_CORE3_FREE_CLK, "core3_free_clk", core3_free_mux, + ARRAY_SIZE(core3_free_mux), 0, 0x0110, 0, 0, 0}, + { AGILEX5_DSU_FREE_CLK, "dsu_free_clk", dsu_free_mux, + ARRAY_SIZE(dsu_free_mux), 0, 0xfc, 0, 0, 0}, + { AGILEX5_NOC_FREE_CLK, "noc_free_clk", noc_free_mux, + ARRAY_SIZE(noc_free_mux), 0, 0x40, 0, 0, 0 }, + { AGILEX5_EMAC_A_FREE_CLK, "emaca_free_clk", emaca_free_mux, + ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0 }, + { AGILEX5_EMAC_B_FREE_CLK, "emacb_free_clk", emacb_free_mux, + ARRAY_SIZE(emacb_free_mux), 0, 0xD8, 0, 0x88, 1 }, + { AGILEX5_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", emac_ptp_free_mux, + ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2 }, + { AGILEX5_GPIO_DB_FREE_CLK, "gpio_db_free_clk", gpio_db_free_mux, + ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3 }, + { AGILEX5_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", s2f_user0_free_mux, + ARRAY_SIZE(s2f_user0_free_mux), 0, 0xE8, 0, 0x30, 2 }, + { AGILEX5_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", s2f_user1_free_mux, + ARRAY_SIZE(s2f_user1_free_mux), 0, 0xEC, 0, 0x88, 5 }, + { AGILEX5_PSI_REF_FREE_CLK, "psi_ref_free_clk", psi_ref_free_mux, + ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6 }, + { AGILEX5_USB31_FREE_CLK, "usb31_free_clk", usb31_free_mux, + ARRAY_SIZE(usb31_free_mux), 0, 0xF8, 0, 0x88, 7}, +}; + +static const char * const cs_pdbg_parents[] = { "cs_at_clk" }; +static const char * const usb31_bus_clk_early_parents[] = { "l4_main_clk" }; +static const char * const l4_mp_clk_parent[] = { "l4_mp_clk" }; +static const char * const l4_sp_clk_parent[] = { "l4_sp_clk" }; +static const char * const dfi_clk_parent[] = { "dfi_clk" }; + +/* SW Clock gate enabled clocks */ +static const struct agilex5_gate_clock agilex5_gate_clks[] = { + { AGILEX5_CORE0_CLK, "core0_clk", core0_mux, + ARRAY_SIZE(core0_mux), 0, 0x24, 8, 0, 0, 0, 0x30, 5, 0 }, + { AGILEX5_CORE1_CLK, "core1_clk", core1_mux, + ARRAY_SIZE(core1_mux), 0, 0x24, 9, 0, 0, 0, 0x30, 5, 0 }, + { AGILEX5_CORE2_CLK, "core2_clk", core2_mux, + ARRAY_SIZE(core2_mux), 0, 0x24, 10, 0, 0, 0, 0x30, 6, 0 }, + { AGILEX5_CORE3_CLK, "core3_clk", core3_mux, + ARRAY_SIZE(core3_mux), 0, 0x24, 11, 0, 0, 0, 0x30, 7, 0 }, + { AGILEX5_MPU_CLK, "dsu_clk", dsu_mux, ARRAY_SIZE(dsu_mux), 0, 0, 0, + 0, 0, 0, 0x34, 4, 0 }, + { AGILEX5_MPU_PERIPH_CLK, "mpu_periph_clk", dsu_mux, + ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 20, 2, 0x34, 4, 0 }, + { AGILEX5_MPU_CCU_CLK, "mpu_ccu_clk", dsu_mux, + ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 18, 2, 0x34, 4, 0 }, + { AGILEX5_L4_MAIN_CLK, "l4_main_clk", noc_mux, ARRAY_SIZE(noc_mux), + CLK_IS_CRITICAL, 0x24, 1, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_L4_MP_CLK, "l4_mp_clk", noc_mux, ARRAY_SIZE(noc_mux), 0, + 0x24, 2, 0x44, 4, 2, 0x30, 1, 0 }, + { AGILEX5_L4_SYS_FREE_CLK, "l4_sys_free_clk", noc_mux, + ARRAY_SIZE(noc_mux), 0, 0, 0, 0x44, 2, 2, 0x30, 1, 0 }, + { AGILEX5_L4_SP_CLK, "l4_sp_clk", noc_mux, ARRAY_SIZE(noc_mux), + CLK_IS_CRITICAL, 0x24, 3, 0x44, 6, 2, 0x30, 1, 0 }, + + /* Core sight clocks*/ + { AGILEX5_CS_AT_CLK, "cs_at_clk", noc_mux, ARRAY_SIZE(noc_mux), 0, + 0x24, 4, 0x44, 24, 2, 0x30, 1, 0 }, + { AGILEX5_CS_TRACE_CLK, "cs_trace_clk", noc_mux, + ARRAY_SIZE(noc_mux), 0, 0x24, 4, 0x44, 26, 2, 0x30, 1, 0 }, + { AGILEX5_CS_PDBG_CLK, "cs_pdbg_clk", cs_pdbg_parents, 1, 0, 0x24, 4, + 0x44, 28, 1, 0, 0, 0 }, + + /* Main Peripheral PLL1 Begin */ + { AGILEX5_EMAC0_CLK, "emac0_clk", emac_mux, ARRAY_SIZE(emac_mux), + 0, 0x7C, 0, 0, 0, 0, 0x94, 26, 0 }, + { AGILEX5_EMAC1_CLK, "emac1_clk", emac_mux, ARRAY_SIZE(emac_mux), + 0, 0x7C, 1, 0, 0, 0, 0x94, 27, 0 }, + { AGILEX5_EMAC2_CLK, "emac2_clk", emac_mux, ARRAY_SIZE(emac_mux), + 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0 }, + { AGILEX5_EMAC_PTP_CLK, "emac_ptp_clk", emac_ptp_mux, + ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, 3, 0, 0, 0, 0x88, 2, 0 }, + { AGILEX5_GPIO_DB_CLK, "gpio_db_clk", gpio_db_mux, + ARRAY_SIZE(gpio_db_mux), 0, 0x7C, 4, 0x98, 0, 16, 0x88, 3, 1 }, + /* Main Peripheral PLL1 End */ + + /* Peripheral clocks */ + { AGILEX5_S2F_USER0_CLK, "s2f_user0_clk", s2f_user0_mux, + ARRAY_SIZE(s2f_user0_mux), 0, 0x24, 6, 0, 0, 0, 0x30, 2, 0 }, + { AGILEX5_S2F_USER1_CLK, "s2f_user1_clk", s2f_user1_mux, + ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, 6, 0, 0, 0, 0x88, 5, 0 }, + { AGILEX5_PSI_REF_CLK, "psi_ref_clk", psi_mux, + ARRAY_SIZE(psi_mux), 0, 0x7C, 7, 0, 0, 0, 0x88, 6, 0 }, + { AGILEX5_USB31_SUSPEND_CLK, "usb31_suspend_clk", usb31_mux, + ARRAY_SIZE(usb31_mux), 0, 0x7C, 25, 0, 0, 0, 0x88, 7, 0 }, + { AGILEX5_USB31_BUS_CLK_EARLY, "usb31_bus_clk_early", usb31_bus_clk_early_parents, + 1, 0, 0x7C, 25, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_USB2OTG_HCLK, "usb2otg_hclk", l4_mp_clk_parent, 1, 0, 0x7C, + 8, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPIM_0_CLK, "spim_0_clk", l4_mp_clk_parent, 1, 0, 0x7C, 9, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPIM_1_CLK, "spim_1_clk", l4_mp_clk_parent, 1, 0, 0x7C, 11, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPIS_0_CLK, "spis_0_clk", l4_sp_clk_parent, 1, 0, 0x7C, 12, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPIS_1_CLK, "spis_1_clk", l4_sp_clk_parent, 1, 0, 0x7C, 13, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_DMA_CORE_CLK, "dma_core_clk", l4_mp_clk_parent, 1, 0, 0x7C, + 14, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_DMA_HS_CLK, "dma_hs_clk", l4_mp_clk_parent, 1, 0, 0x7C, 14, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I3C_0_CORE_CLK, "i3c_0_core_clk", l4_mp_clk_parent, 1, 0, + 0x7C, 18, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I3C_1_CORE_CLK, "i3c_1_core_clk", l4_mp_clk_parent, 1, 0, + 0x7C, 19, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I2C_0_PCLK, "i2c_0_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 15, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I2C_1_PCLK, "i2c_1_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 16, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I2C_EMAC0_PCLK, "i2c_emac0_pclk", l4_sp_clk_parent, 1, 0, + 0x7C, 17, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I2C_EMAC1_PCLK, "i2c_emac1_pclk", l4_sp_clk_parent, 1, 0, + 0x7C, 22, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_I2C_EMAC2_PCLK, "i2c_emac2_pclk", l4_sp_clk_parent, 1, 0, + 0x7C, 27, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_UART_0_PCLK, "uart_0_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 20, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_UART_1_PCLK, "uart_1_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 21, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPTIMER_0_PCLK, "sptimer_0_pclk", l4_sp_clk_parent, 1, 0, + 0x7C, 23, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SPTIMER_1_PCLK, "sptimer_1_pclk", l4_sp_clk_parent, 1, 0, + 0x7C, 24, 0, 0, 0, 0, 0, 0 }, + + /*NAND, SD/MMC and SoftPHY overall clocking*/ + { AGILEX5_DFI_CLK, "dfi_clk", l4_mp_clk_parent, 1, 0, 0, 0, 0x44, 16, + 2, 0, 0, 0 }, + { AGILEX5_NAND_NF_CLK, "nand_nf_clk", dfi_clk_parent, 1, 0, 0x7C, 10, + 0, 0, 0, 0, 0, 0 }, + { AGILEX5_NAND_BCH_CLK, "nand_bch_clk", l4_mp_clk_parent, 1, 0, 0x7C, + 10, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SDMMC_SDPHY_REG_CLK, "sdmmc_sdphy_reg_clk", l4_mp_clk_parent, + 1, 0, 0x7C, 5, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SDMCLK, "sdmclk", dfi_clk_parent, 1, 0, 0x7C, 5, 0, 0, 0, + 0, 0, 0 }, + { AGILEX5_SOFTPHY_REG_PCLK, "softphy_reg_pclk", l4_mp_clk_parent, 1, 0, + 0x7C, 26, 0, 0, 0, 0, 0, 0 }, + { AGILEX5_SOFTPHY_PHY_CLK, "softphy_phy_clk", l4_mp_clk_parent, 1, 0, + 0x7C, 26, 0x44, 16, 2, 0, 0, 0 }, + { AGILEX5_SOFTPHY_CTRL_CLK, "softphy_ctrl_clk", dfi_clk_parent, 1, 0, + 0x7C, 26, 0, 0, 0, 0, 0, 0 }, +}; + +static int +agilex5_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk_hw *hw_clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + hw_clk = s10_register_periph(&clks[i], base); + if (IS_ERR(hw_clk)) { + pr_err("%s: failed to register clock %s\n", __func__, + clks[i].name); + continue; + } + data->clk_data.hws[clks[i].id] = hw_clk; + } + return 0; +} + +static int +agilex5_clk_register_cnt_perip(const struct agilex5_perip_cnt_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk_hw *hw_clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + hw_clk = agilex5_register_cnt_periph(&clks[i], base); + if (IS_ERR(hw_clk)) { + pr_err("%s: failed to register clock %s\n", __func__, + clks[i].name); + continue; + } + data->clk_data.hws[clks[i].id] = hw_clk; + } + + return 0; +} + +static int agilex5_clk_register_gate(const struct agilex5_gate_clock *clks, + int nums, + struct stratix10_clock_data *data) +{ + struct clk_hw *hw_clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + hw_clk = agilex5_register_gate(&clks[i], base); + if (IS_ERR(hw_clk)) { + pr_err("%s: failed to register clock %s\n", __func__, + clks[i].name); + continue; + } + data->clk_data.hws[clks[i].id] = hw_clk; + } + + return 0; +} + +static int agilex5_clk_register_pll(const struct agilex5_pll_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk_hw *hw_clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + hw_clk = agilex5_register_pll(&clks[i], base); + if (IS_ERR(hw_clk)) { + pr_err("%s: failed to register clock %s\n", __func__, + clks[i].name); + continue; + } + data->clk_data.hws[clks[i].id] = hw_clk; + } + + return 0; +} + +static int agilex5_clkmgr_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct stratix10_clock_data *clk_data; + void __iomem *base; + int i, num_clks; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + num_clks = AGILEX5_NUM_CLKS; + + clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, + num_clks), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->base = base; + clk_data->clk_data.num = num_clks; + + for (i = 0; i < num_clks; i++) + clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); + + agilex5_clk_register_pll(agilex5_pll_clks, ARRAY_SIZE(agilex5_pll_clks), + clk_data); + + /* mainPLL C0, C1, C2, C3 and periph PLL C0, C1, C2, C3*/ + agilex5_clk_register_c_perip(agilex5_main_perip_c_clks, + ARRAY_SIZE(agilex5_main_perip_c_clks), + clk_data); + + agilex5_clk_register_cnt_perip(agilex5_main_perip_cnt_clks, + ARRAY_SIZE(agilex5_main_perip_cnt_clks), + clk_data); + + agilex5_clk_register_gate(agilex5_gate_clks, + ARRAY_SIZE(agilex5_gate_clks), clk_data); + + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data); + return 0; +} + +static int agilex5_clkmgr_probe(struct platform_device *pdev) +{ + int (*probe_func)(struct platform_device *init_func); + + probe_func = of_device_get_match_data(&pdev->dev); + if (!probe_func) + return -ENODEV; + return probe_func(pdev); +} + +static const struct of_device_id agilex5_clkmgr_match_table[] = { + { .compatible = "intel,agilex5-clkmgr", .data = agilex5_clkmgr_init }, + {} +}; + +static struct platform_driver agilex5_clkmgr_driver = { + .probe = agilex5_clkmgr_probe, + .driver = { + .name = "agilex5-clkmgr", + .suppress_bind_attrs = true, + .of_match_table = agilex5_clkmgr_match_table, + }, +}; + +static int __init agilex5_clk_init(void) +{ + return platform_driver_register(&agilex5_clkmgr_driver); +} +core_initcall(agilex5_clk_init); diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index 3930d922efb4d3..dce3ef137bf376 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -239,3 +239,56 @@ struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, voi } return hw_clk; } + +struct clk_hw *agilex5_register_gate(const struct agilex5_gate_clock *clks, void __iomem *regbase) +{ + struct clk_hw *hw_clk; + struct socfpga_gate_clk *socfpga_clk; + struct clk_init_data init; + int ret; + + socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); + if (!socfpga_clk) + return NULL; + + socfpga_clk->hw.reg = regbase + clks->gate_reg; + socfpga_clk->hw.bit_idx = clks->gate_idx; + + gateclk_ops.enable = clk_gate_ops.enable; + gateclk_ops.disable = clk_gate_ops.disable; + + socfpga_clk->fixed_div = clks->fixed_div; + + if (clks->div_reg) + socfpga_clk->div_reg = regbase + clks->div_reg; + else + socfpga_clk->div_reg = NULL; + + socfpga_clk->width = clks->div_width; + socfpga_clk->shift = clks->div_offset; + + if (clks->bypass_reg) + socfpga_clk->bypass_reg = regbase + clks->bypass_reg; + else + socfpga_clk->bypass_reg = NULL; + socfpga_clk->bypass_shift = clks->bypass_shift; + + if (streq(clks->name, "cs_pdbg_clk")) + init.ops = &dbgclk_ops; + else + init.ops = &agilex_gateclk_ops; + + init.name = clks->name; + init.flags = clks->flags; + init.num_parents = clks->num_parents; + init.parent_names = clks->parent_names; + socfpga_clk->hw.hw.init = &init; + hw_clk = &socfpga_clk->hw.hw; + + ret = clk_hw_register(NULL, &socfpga_clk->hw.hw); + if (ret) { + kfree(socfpga_clk); + return ERR_PTR(ret); + } + return hw_clk; +} diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index f5c1ca42b66866..f12ca43ffe7c8e 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -214,3 +214,44 @@ struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *c } return hw_clk; } + +struct clk_hw *agilex5_register_cnt_periph(const struct agilex5_perip_cnt_clock *clks, + void __iomem *regbase) +{ + struct clk_hw *hw_clk; + struct socfpga_periph_clk *periph_clk; + struct clk_init_data init; + const char *name = clks->name; + int ret; + + periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); + if (WARN_ON(!periph_clk)) + return NULL; + + if (clks->offset) + periph_clk->hw.reg = regbase + clks->offset; + else + periph_clk->hw.reg = NULL; + + if (clks->bypass_reg) + periph_clk->bypass_reg = regbase + clks->bypass_reg; + else + periph_clk->bypass_reg = NULL; + periph_clk->bypass_shift = clks->bypass_shift; + periph_clk->fixed_div = clks->fixed_divider; + + init.name = name; + init.ops = &peri_cnt_clk_ops; + init.flags = clks->flags; + init.num_parents = clks->num_parents; + init.parent_names = clks->parent_names; + periph_clk->hw.hw.init = &init; + hw_clk = &periph_clk->hw.hw; + + ret = clk_hw_register(NULL, hw_clk); + if (ret) { + kfree(periph_clk); + return ERR_PTR(ret); + } + return hw_clk; +} diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index a88c212bda129b..1be92827cd938a 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -304,3 +304,39 @@ struct clk_hw *n5x_register_pll(const struct stratix10_pll_clock *clks, } return hw_clk; } + +struct clk_hw *agilex5_register_pll(const struct agilex5_pll_clock *clks, + void __iomem *reg) +{ + struct clk_hw *hw_clk; + struct socfpga_pll *pll_clk; + struct clk_init_data init; + const char *name = clks->name; + int ret; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (WARN_ON(!pll_clk)) + return NULL; + + pll_clk->hw.reg = reg + clks->offset; + + if (streq(name, SOCFPGA_BOOT_CLK)) + init.ops = &clk_boot_ops; + else + init.ops = &agilex_clk_pll_ops; + + init.name = name; + init.flags = clks->flags; + init.num_parents = clks->num_parents; + init.parent_names = clks->parent_names; + pll_clk->hw.hw.init = &init; + pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; + hw_clk = &pll_clk->hw.hw; + + ret = clk_hw_register(NULL, hw_clk); + if (ret) { + kfree(pll_clk); + return ERR_PTR(ret); + } + return hw_clk; +} diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index 83fe4eb3133cbe..d1fe4578b3e08d 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -73,12 +73,55 @@ struct stratix10_gate_clock { u8 fixed_div; }; +struct agilex5_pll_clock { + unsigned int id; + const char *name; + const char * const *parent_names; + u8 num_parents; + unsigned long flags; + unsigned long offset; +}; + +struct agilex5_perip_cnt_clock { + unsigned int id; + const char *name; + const char * const *parent_names; + u8 num_parents; + unsigned long flags; + unsigned long offset; + u8 fixed_divider; + unsigned long bypass_reg; + unsigned long bypass_shift; +}; + +struct agilex5_gate_clock { + unsigned int id; + const char *name; + const char * const *parent_names; + u8 num_parents; + unsigned long flags; + unsigned long gate_reg; + u8 gate_idx; + unsigned long div_reg; + u8 div_offset; + u8 div_width; + unsigned long bypass_reg; + u8 bypass_shift; + u8 fixed_div; +}; + struct clk_hw *s10_register_pll(const struct stratix10_pll_clock *clks, void __iomem *reg); struct clk_hw *agilex_register_pll(const struct stratix10_pll_clock *clks, void __iomem *reg); struct clk_hw *n5x_register_pll(const struct stratix10_pll_clock *clks, void __iomem *reg); +struct clk_hw *agilex5_register_pll(const struct agilex5_pll_clock *clks, + void __iomem *reg); +struct clk_hw *agilex5_register_cnt_periph(const struct agilex5_perip_cnt_clock *clks, + void __iomem *regbase); +struct clk_hw *agilex5_register_gate(const struct agilex5_gate_clock *clks, + void __iomem *regbase); struct clk_hw *s10_register_periph(const struct stratix10_perip_c_clock *clks, void __iomem *reg); struct clk_hw *n5x_register_periph(const struct n5x_perip_c_clock *clks, From 7958b4bb806c1af800ca23c8333a98231b3ab0b1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 22 Oct 2025 15:23:42 +0200 Subject: [PATCH 137/684] pinctrl: pinmux: Add missing .function_is_gpio kerneldoc This callback was undocumented, add the docs. Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- include/linux/pinctrl/pinmux.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index 6db6c3e1ccc224..094bbe2fd6fd5e 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -35,6 +35,16 @@ struct pinctrl_gpio_range; * name can be used with the generic @pinctrl_ops to retrieve the * actual pins affected. The applicable groups will be returned in * @groups and the number of groups in @num_groups + * @function_is_gpio: determine if the indicated function selector passed + * corresponds to the GPIO function which is used by the accelerated GPIO + * functions @gpio_request_enable, @gpio_disable_free and + * @gpio_set_direction. When the pin control core can properly determine + * if a function is a GPIO function, it is easier to use the @strict mode + * on the pin controller. Since a single function is passed, this is + * only useful on pin controllers that use a specific function for GPIO, + * and that usually presupposes that a one-group-per-pin approach is + * used, so that a single function can be set on a single pin to turn + * it to GPIO mode. * @set_mux: enable a certain muxing function with a certain pin group. The * driver does not need to figure out whether enabling this function * conflicts some other use of the pins in that group, such collisions From 2b195e2bab1d7b4983c3348d8a2e457bb767ce36 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 22 Oct 2025 15:34:27 +0200 Subject: [PATCH 138/684] dt-bindings: pinctrl: toshiba,visconti: Drop redundant functions type Referenced pinmux-node.yaml schema already defines type for "functions" so $ref is redundant. Signed-off-by: Krzysztof Kozlowski Acked-by: Conor Dooley Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml index 19d47fd414bc06..a811a643bb88c0 100644 --- a/Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml @@ -42,7 +42,6 @@ patternProperties: function: description: Function to mux. - $ref: /schemas/types.yaml#/definitions/string enum: [i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c8, spi0, spi1, spi2, spi3, spi4, spi5, spi6, uart0, uart1, uart2, uart3, pwm, pcmif_out, pcmif_in] From 934dcccf3ffc7568fdeb363842bb9fc36e1be608 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 14 Oct 2025 11:53:48 +0100 Subject: [PATCH 139/684] clk: renesas: cpg-mssr: Add read-back and delay handling for RZ/T2H MSTP On the RZ/T2H SoC, a specific sequence is required when releasing a module from the module stop state (i.e. when clearing the corresponding bit in the MSTPCRm register to '0'). After writing to the MSTPCRm register, a read-back of the same register must be performed, followed by at least seven dummy reads of any register within the IP block that is being released. To avoid mapping device registers for this purpose, a short delay is introduced after the read-back to ensure proper hardware stabilization before the module becomes accessible. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251014105348.93705-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 0ffe6ee8f165c3..66c20698927c35 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -308,10 +308,21 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) spin_unlock_irqrestore(&priv->pub.rmw_lock, flags); - if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A || - priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) + if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A) return 0; + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) { + /* + * For the RZ/T2H case, it is necessary to perform a read-back after + * accessing the MSTPCRm register and to dummy-read any register of + * the IP at least seven times. Instead of memory-mapping the IP + * register, we simply add a delay after the read operation. + */ + cpg_rzt2h_mstp_read(hw, priv->control_regs[reg]); + udelay(10); + return 0; + } + error = readl_poll_timeout_atomic(priv->pub.base0 + priv->status_regs[reg], value, !(value & bitmask), 0, 10); if (error) From 919bf298dc9fe2cee5abfacb281fb201cda65a44 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Mon, 20 Oct 2025 14:31:05 +0000 Subject: [PATCH 140/684] clk: renesas: r9a09g057: Add clock and reset entries for TSU Add module clock and reset entries for the TSU0 and TSU1 blocks on the Renesas RZ/V2H (R9A09G057) SoC. Signed-off-by: Ovidiu Panait Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251020143107.13974-2-ovidiu.panait.rb@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g057-cpg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index c9c117c6782cb2..4684af31177eb9 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -387,6 +387,10 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { BUS_MSTOP(3, BIT(4))), DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18, BUS_MSTOP(3, BIT(4))), + DEF_MOD("tsu_0_pclk", CLK_QEXTAL, 16, 9, 8, 9, + BUS_MSTOP(5, BIT(2))), + DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10, + BUS_MSTOP(2, BIT(15))), }; static const struct rzv2h_reset r9a09g057_resets[] __initconst = { @@ -459,6 +463,8 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = { DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */ + DEF_RST(15, 7, 7, 8), /* TSU_0_PRESETN */ + DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */ }; const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = { From a7231aaf4a10ce8793a347e78988539e778cbdf9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Oct 2025 10:03:56 +0200 Subject: [PATCH 141/684] clk: renesas: cpg-mssr: Spelling s/offets/offsets/ Fix a misspelling of "offsets". Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/47bf5186c3a234f6a6e53d8fdc81fafd2e981534.1761033805.git.geert+renesas@glider.be --- drivers/clk/renesas/renesas-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 66c20698927c35..7f9b7aa397906d 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -43,7 +43,7 @@ #define RZT2H_RESET_REG_READ_COUNT 7 /* - * Module Standby and Software Reset register offets. + * Module Standby and Software Reset register offsets. * * If the registers exist, these are valid for SH-Mobile, R-Mobile, * R-Car Gen2, R-Car Gen3, and RZ/G1. From 7a03ef9f8223434f19e19a37acc32dcb581ab475 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Tue, 21 Oct 2025 08:07:00 +0000 Subject: [PATCH 142/684] clk: renesas: r9a09g057: Add clock and reset entries for RTC Add module clock and reset entries for the RTC module on the Renesas RZ/V2H (R9A09G057) SoC. Signed-off-by: Ovidiu Panait Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251021080705.18116-2-ovidiu.panait.rb@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g057-cpg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index 4684af31177eb9..dce5755d85ec1a 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -241,6 +241,8 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { BUS_MSTOP(5, BIT(13))), DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18, BUS_MSTOP(5, BIT(13))), + DEF_MOD("rtc_0_clk_rtc", CLK_PLLCM33_DIV16, 5, 3, 2, 19, + BUS_MSTOP(3, BIT(11) | BIT(12))), DEF_MOD("rspi_0_pclk", CLK_PLLCLN_DIV8, 5, 4, 2, 20, BUS_MSTOP(11, BIT(0))), DEF_MOD("rspi_0_pclk_sfr", CLK_PLLCLN_DIV8, 5, 5, 2, 21, @@ -415,6 +417,8 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = { DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */ DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */ DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */ + DEF_RST(7, 9, 3, 10), /* RTC_0_RST_RTC */ + DEF_RST(7, 10, 3, 11), /* RTC_0_RST_RTC_V */ DEF_RST(7, 11, 3, 12), /* RSPI_0_PRESETN */ DEF_RST(7, 12, 3, 13), /* RSPI_0_TRESETN */ DEF_RST(7, 13, 3, 14), /* RSPI_1_PRESETN */ From aa09d5a147702814ee8cf8faf0aea8f001cee1bc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Oct 2025 10:06:05 +0200 Subject: [PATCH 143/684] pinctrl: renesas: rza1: Make mux_conf const in rza1_pin_mux_single() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rza1_mux_conf object pointed to by the mux_conf parameter of rza1_pin_mux_single() is never modified. Make it const. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://patch.msgid.link/168e06bc57081aa3c42ff9aa2740a0a108df7d34.1761033950.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pinctrl-rza1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rza1.c b/drivers/pinctrl/renesas/pinctrl-rza1.c index 4c7326e3de07ce..3cfa4c8be80eaf 100644 --- a/drivers/pinctrl/renesas/pinctrl-rza1.c +++ b/drivers/pinctrl/renesas/pinctrl-rza1.c @@ -668,7 +668,7 @@ static inline int rza1_pin_get(struct rza1_port *port, unsigned int pin) * @mux_conf: pin multiplexing descriptor */ static int rza1_pin_mux_single(struct rza1_pinctrl *rza1_pctl, - struct rza1_mux_conf *mux_conf) + const struct rza1_mux_conf *mux_conf) { struct rza1_port *port = &rza1_pctl->ports[mux_conf->port]; unsigned int pin = mux_conf->pin; @@ -1118,7 +1118,7 @@ static int rza1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, unsigned int group) { struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev); - struct rza1_mux_conf *mux_confs; + const struct rza1_mux_conf *mux_confs; const struct function_desc *func; struct group_desc *grp; int i; @@ -1131,7 +1131,7 @@ static int rza1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, if (!func) return -EINVAL; - mux_confs = (struct rza1_mux_conf *)func->data; + mux_confs = (const struct rza1_mux_conf *)func->data; for (i = 0; i < grp->grp.npins; ++i) { int ret; From f2195c5b435e59f39f897780751584bb04c7464b Mon Sep 17 00:00:00 2001 From: James Clark Date: Wed, 22 Oct 2025 12:02:40 +0100 Subject: [PATCH 144/684] perf annotate: Fix Clang build by adding block in switch case Clang and GCC disagree with what constitutes a "declaration after statement". GCC allows declarations in switch cases without an extra block, as long as it's immediately after the label. Clang does not. Unfortunately this is the case even in the latest versions of both compilers. The only option that makes them behave in the same way is -Wpedantic, which can't be enabled in Perf because of the number of warnings it generates. Add a block to fix the Clang build, which is the only thing we can do. Fixes the build error: ui/browsers/annotate.c:999:4: error: expected expression struct annotation_line *al = NULL; ui/browsers/annotate.c:1008:4: error: use of undeclared identifier 'al' al = annotated_source__get_line(notes->src, offset); ui/browsers/annotate.c:1009:24: error: use of undeclared identifier 'al' browser->curr_hot = al ? &al->rb_node : NULL; ui/browsers/annotate.c:1009:30: error: use of undeclared identifier 'al' browser->curr_hot = al ? &al->rb_node : NULL; ui/browsers/annotate.c:1000:8: error: mixing declarations and code is incompatible with standards before C99 [-Werror,-Wdeclaration-after-statement] s64 offset = annotate_browser__curr_hot_offset(browser); Fixes: ad83f3b7155d ("perf c2c annotate: Start from the contention line") Signed-off-by: James Clark Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/ui/browsers/annotate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 3a81912279ad13..36aca8d6d0039b 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -995,7 +995,7 @@ static int annotate_browser__run(struct annotate_browser *browser, case 'H': nd = browser->curr_hot; break; - case 's': + case 's': { struct annotation_line *al = NULL; s64 offset = annotate_browser__curr_hot_offset(browser); @@ -1012,6 +1012,7 @@ static int annotate_browser__run(struct annotate_browser *browser, annotate__scnprintf_title(hists, title, sizeof(title)); annotate_browser__show(browser, title, help); continue; + } case 'o': annotate_opts.use_offset = !annotate_opts.use_offset; annotation__update_column_widths(notes); From 9960889b32a45af39c53a46db6fd36ff1fa71a4f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 21 Oct 2025 23:21:48 +0000 Subject: [PATCH 145/684] tools: arm64: Add Cortex-A720AE definitions Add cputype definitions for Cortex-A720AE. These will be used for errata detection in subsequent patches. These values can be found in the Cortex-A720AE TRM: https://developer.arm.com/documentation/102828/0001/ ... in Table A-187 Signed-off-by: Kuninori Morimoto Reviewed-by: Leo Yan Acked-by: Will Deacon Signed-off-by: Namhyung Kim --- tools/arch/arm64/include/asm/cputype.h | 2 ++ tools/perf/util/arm-spe.c | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h index 139d5e87dc9593..0192dc7ec9ca99 100644 --- a/tools/arch/arm64/include/asm/cputype.h +++ b/tools/arch/arm64/include/asm/cputype.h @@ -96,6 +96,7 @@ #define ARM_CPU_PART_NEOVERSE_V3 0xD84 #define ARM_CPU_PART_CORTEX_X925 0xD85 #define ARM_CPU_PART_CORTEX_A725 0xD87 +#define ARM_CPU_PART_CORTEX_A720AE 0xD89 #define ARM_CPU_PART_NEOVERSE_N3 0xD8E #define APM_CPU_PART_XGENE 0x000 @@ -185,6 +186,7 @@ #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) #define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) #define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) +#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE) #define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 71be979f507718..9561951a005547 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -571,6 +571,7 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, static const struct midr_range common_ds_encoding_cpus[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A720AE), MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), From 3e98f0203e10bc9d379852faf424f769ef5049a6 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 22 Oct 2025 15:28:49 +0100 Subject: [PATCH 146/684] perf cs-etm: Mute enumeration value warning When the OpenCSD library introduces a new enumeration value (for example, in the v1.7.1 release), the perf build fails with an error: util/cs-etm-decoder/cs-etm-decoder.c:600:10: error: enumeration value 'OCSD_GEN_TRC_ELEM_ITMTRACE' not explicitly handled in switch [-Werror, -Wswitch-enum] 600 | switch (elem->elem_type) { | ^~~~~~~~~~~~~~~ 1 error generated. Convert to if-else sentences to mute the enumeration value warning, which can avoid build failures whenever the lib is updated. No functional change. Suggested-by: Suzuki K Poulose Signed-off-by: Leo Yan Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 44 +++++-------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index b85a8837bddcda..3050fe2126665b 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -588,6 +588,7 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( const ocsd_generic_trace_elem *elem) { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + ocsd_gen_trc_elem_t type; struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context; struct cs_etm_queue *etmq = decoder->data; struct cs_etm_packet_queue *packet_queue; @@ -597,52 +598,29 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( if (!packet_queue) return OCSD_RESP_FATAL_SYS_ERR; - switch (elem->elem_type) { - case OCSD_GEN_TRC_ELEM_UNKNOWN: - break; - case OCSD_GEN_TRC_ELEM_EO_TRACE: - case OCSD_GEN_TRC_ELEM_NO_SYNC: - case OCSD_GEN_TRC_ELEM_TRACE_ON: + type = elem->elem_type; + + if (type == OCSD_GEN_TRC_ELEM_EO_TRACE || + type == OCSD_GEN_TRC_ELEM_NO_SYNC || + type == OCSD_GEN_TRC_ELEM_TRACE_ON) resp = cs_etm_decoder__buffer_discontinuity(etmq, packet_queue, trace_chan_id); - break; - case OCSD_GEN_TRC_ELEM_INSTR_RANGE: + else if (type == OCSD_GEN_TRC_ELEM_INSTR_RANGE) resp = cs_etm_decoder__buffer_range(etmq, packet_queue, elem, trace_chan_id); - break; - case OCSD_GEN_TRC_ELEM_EXCEPTION: + else if (type == OCSD_GEN_TRC_ELEM_EXCEPTION) resp = cs_etm_decoder__buffer_exception(etmq, packet_queue, elem, trace_chan_id); - break; - case OCSD_GEN_TRC_ELEM_EXCEPTION_RET: + else if (type == OCSD_GEN_TRC_ELEM_EXCEPTION_RET) resp = cs_etm_decoder__buffer_exception_ret(etmq, packet_queue, trace_chan_id); - break; - case OCSD_GEN_TRC_ELEM_TIMESTAMP: + else if (type == OCSD_GEN_TRC_ELEM_TIMESTAMP) resp = cs_etm_decoder__do_hard_timestamp(etmq, elem, trace_chan_id, indx); - break; - case OCSD_GEN_TRC_ELEM_PE_CONTEXT: + else if (type == OCSD_GEN_TRC_ELEM_PE_CONTEXT) resp = cs_etm_decoder__set_tid(etmq, packet_queue, elem, trace_chan_id); - break; - /* Unused packet types */ - case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH: - case OCSD_GEN_TRC_ELEM_ADDR_NACC: - case OCSD_GEN_TRC_ELEM_CYCLE_COUNT: - case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN: - case OCSD_GEN_TRC_ELEM_EVENT: - case OCSD_GEN_TRC_ELEM_SWTRACE: - case OCSD_GEN_TRC_ELEM_CUSTOM: - case OCSD_GEN_TRC_ELEM_SYNC_MARKER: - case OCSD_GEN_TRC_ELEM_MEMTRANS: -#if (OCSD_VER_NUM >= 0x010400) - case OCSD_GEN_TRC_ELEM_INSTRUMENTATION: -#endif - default: - break; - } return resp; } From 645f1095d317854816bcfa13201f4bcf121465fe Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 23 Oct 2025 18:14:57 +0100 Subject: [PATCH 147/684] dt-bindings: pinctrl: document pic64gx "gpio2" pinmux The pic64gx has a second pinmux "downstream" of the iomux0 pinmux. The documentation for the SoC provides no name for this device, but it is used to swap pins between either GPIO controller #2 or select other functions, hence the "gpio2" name. Currently there is no documentation about what each bit actually does that is publicly available, nor (I believe) what pins are affected. That info is as follows: pin role (1/0) --- ---------- E14 MAC_0_MDC/GPIO_2_0 E15 MAC_0_MDIO/GPIO_2_1 F16 MAC_1_MDC/GPIO_2_2 F17 MAC_1_MDIO/GPIO_2_3 D19 SPI_0_CLK/GPIO_2_4 B18 SPI_0_SS0/GPIO_2_5 B10 CAN_0_RXBUS/GPIO_2_6 C14 PCIE_PERST_2#/GPIO_2_7 E18 PCIE_WAKE#/GPIO_2_8 D18 PCIE_PERST_1#/GPIO_2_9 E19 SPI_0_DO/GPIO_2_10 C7 SPI_0_DI/GPIO_2_11 D6 QSPI_SS0/GPIO_2_12 D7 QSPI_CLK (B)/GPIO_2_13 C9 QSPI_DATA0/GPIO_2_14 C10 QSPI_DATA1/GPIO_2_15 A5 QSPI_DATA2/GPIO_2_16 A6 QSPI_DATA3/GPIO_2_17 D8 MMUART_3_RXD/GPIO_2_18 D9 MMUART_3_TXD/GPIO_2_19 B8 MMUART_4_RXD/GPIO_2_20 A8 MMUART_4_TXD/GPIO_2_21 C12 CAN_1_TXBUS/GPIO_2_22 B12 CAN_1_RXBUS/GPIO_2_23 A11 CAN_0_TX_EBL_N/GPIO_2_24 A10 CAN_1_TX_EBL_N/GPIO_2_25 D11 MMUART_2_RXD/GPIO_2_26 C11 MMUART_2_TXD/GPIO_2_27 B9 CAN_0_TXBUS/GPIO_2_28 Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley Signed-off-by: Linus Walleij --- .../microchip,pic64gx-pinctrl-gpio2.yaml | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml new file mode 100644 index 00000000000000..e3792679de587d --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip PIC64GX GPIO2 Mux + +maintainers: + - Conor Dooley + +description: + The "GPIO2 Mux" determines whether GPIO2 or select other functions are + available on package pins on PIC64GX. Some of these functions must be + mapped to this mux via iomux0 for settings here to have any impact. + +properties: + compatible: + const: microchip,pic64gx-pinctrl-gpio2 + + reg: + maxItems: 1 + + pinctrl-use-default: true + +patternProperties: + '^mux-': + type: object + $ref: pinmux-node.yaml + additionalProperties: false + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [ mdio0, mdio1, spi0, can0, pcie, qspi, uart3, uart4, can1, uart2, gpio ] + + groups: + description: + An array of strings. Each string contains the name of a group. + items: + enum: [ mdio0, mdio1, spi0, can0, pcie, qspi, uart3, uart4, can1, uart2, + gpio_mdio0, gpio_mdio1, gpio_spi0, gpio_can0, gpio_pcie, + gpio_qspi, gpio_uart3, gpio_uart4, gpio_can1, gpio_uart2 ] + + required: + - function + - groups + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pinctrl@41000000 { + compatible = "microchip,pic64gx-pinctrl-gpio2"; + reg = <0x41000000 0x4>; + pinctrl-use-default; + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_gpio2>, <&mdio1_gpio2>, <&spi0_gpio2>, <&qspi_gpio2>, + <&uart3_gpio2>, <&uart4_gpio2>, <&can1_gpio2>, <&can0_gpio2>, + <&uart2_gpio2>; + + mux-gpio2 { + function = "gpio"; + groups = "gpio_mdio1", "gpio_spi0", "gpio_can0", "gpio_pcie", + "gpio_qspi", "gpio_uart3", "gpio_uart4", "gpio_can1"; + }; + }; + +... From 38cf9d6413142290316776c80f19eb92a4e19a9f Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 23 Oct 2025 18:14:58 +0100 Subject: [PATCH 148/684] pinctrl: add pic64gx "gpio2" pinmux driver The pic64gx has a second pinmux "downstream" of the iomux0 pinmux. The documentation for the SoC provides no name for this device, but it is used to swap pins between either GPIO controller #2 or select other functions, hence the "gpio2" name. Add a driver for it. Signed-off-by: Conor Dooley Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 8 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pic64gx-gpio2.c | 356 ++++++++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pic64gx-gpio2.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 4f8507ebbdacdd..e83fda9bf3080c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -486,6 +486,14 @@ config PINCTRL_PIC32MZDA def_bool y if PIC32MZDA select PINCTRL_PIC32 +config PINCTRL_PIC64GX + bool "pic64gx gpio2 pinctrl driver" + depends on ARCH_MICROCHIP || COMPILE_TEST + select GENERIC_PINCONF + default y + help + This selects the pinctrl driver for gpio2 on pic64gx. + config PINCTRL_PISTACHIO bool "IMG Pistachio SoC pinctrl driver" depends on OF && (MIPS || COMPILE_TEST) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e0cfb9b7c99bae..f33976a6c91b33 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o +obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o diff --git a/drivers/pinctrl/pinctrl-pic64gx-gpio2.c b/drivers/pinctrl/pinctrl-pic64gx-gpio2.c new file mode 100644 index 00000000000000..f322bb5e618144 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pic64gx-gpio2.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pinctrl-utils.h" + +#define PIC64GX_PINMUX_REG 0x0 + +static const struct regmap_config pic64gx_gpio2_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .max_register = 0x0, +}; + +struct pic64gx_gpio2_pinctrl { + struct pinctrl_dev *pctrl; + struct device *dev; + struct regmap *regmap; + struct pinctrl_desc desc; +}; + +struct pic64gx_gpio2_pin_group { + const char *name; + const unsigned int *pins; + const unsigned int num_pins; + u32 mask; + u32 setting; +}; + +struct pic64gx_gpio2_function { + const char *name; + const char * const *groups; + const unsigned int num_groups; +}; + +static const struct pinctrl_pin_desc pic64gx_gpio2_pins[] = { + PINCTRL_PIN(0, "E14"), + PINCTRL_PIN(1, "E15"), + PINCTRL_PIN(2, "F16"), + PINCTRL_PIN(3, "F17"), + PINCTRL_PIN(4, "D19"), + PINCTRL_PIN(5, "B18"), + PINCTRL_PIN(6, "B10"), + PINCTRL_PIN(7, "C14"), + PINCTRL_PIN(8, "E18"), + PINCTRL_PIN(9, "D18"), + PINCTRL_PIN(10, "E19"), + PINCTRL_PIN(11, "C7"), + PINCTRL_PIN(12, "D6"), + PINCTRL_PIN(13, "D7"), + PINCTRL_PIN(14, "C9"), + PINCTRL_PIN(15, "C10"), + PINCTRL_PIN(16, "A5"), + PINCTRL_PIN(17, "A6"), + PINCTRL_PIN(18, "D8"), + PINCTRL_PIN(19, "D9"), + PINCTRL_PIN(20, "B8"), + PINCTRL_PIN(21, "A8"), + PINCTRL_PIN(22, "C12"), + PINCTRL_PIN(23, "B12"), + PINCTRL_PIN(24, "A11"), + PINCTRL_PIN(25, "A10"), + PINCTRL_PIN(26, "D11"), + PINCTRL_PIN(27, "C11"), + PINCTRL_PIN(28, "B9"), +}; + +static const unsigned int pic64gx_gpio2_mdio0_pins[] = { + 0, 1 +}; + +static const unsigned int pic64gx_gpio2_mdio1_pins[] = { + 2, 3 +}; + +static const unsigned int pic64gx_gpio2_spi0_pins[] = { + 4, 5, 10, 11 +}; + +static const unsigned int pic64gx_gpio2_can0_pins[] = { + 6, 24, 28 +}; + +static const unsigned int pic64gx_gpio2_pcie_pins[] = { + 7, 8, 9 +}; + +static const unsigned int pic64gx_gpio2_qspi_pins[] = { + 12, 13, 14, 15, 16, 17 +}; + +static const unsigned int pic64gx_gpio2_uart3_pins[] = { + 18, 19 +}; + +static const unsigned int pic64gx_gpio2_uart4_pins[] = { + 20, 21 +}; + +static const unsigned int pic64gx_gpio2_can1_pins[] = { + 22, 23, 25 +}; + +static const unsigned int pic64gx_gpio2_uart2_pins[] = { + 26, 27 +}; + +#define PIC64GX_PINCTRL_GROUP(_name, _mask) { \ + .name = "gpio_" #_name, \ + .pins = pic64gx_gpio2_##_name##_pins, \ + .num_pins = ARRAY_SIZE(pic64gx_gpio2_##_name##_pins), \ + .mask = _mask, \ + .setting = 0x0, \ +}, { \ + .name = #_name, \ + .pins = pic64gx_gpio2_##_name##_pins, \ + .num_pins = ARRAY_SIZE(pic64gx_gpio2_##_name##_pins), \ + .mask = _mask, \ + .setting = _mask, \ +} + +static const struct pic64gx_gpio2_pin_group pic64gx_gpio2_pin_groups[] = { + PIC64GX_PINCTRL_GROUP(mdio0, BIT(0) | BIT(1)), + PIC64GX_PINCTRL_GROUP(mdio1, BIT(2) | BIT(3)), + PIC64GX_PINCTRL_GROUP(spi0, BIT(4) | BIT(5) | BIT(10) | BIT(11)), + PIC64GX_PINCTRL_GROUP(can0, BIT(6) | BIT(24) | BIT(28)), + PIC64GX_PINCTRL_GROUP(pcie, BIT(7) | BIT(8) | BIT(9)), + PIC64GX_PINCTRL_GROUP(qspi, GENMASK(17, 12)), + PIC64GX_PINCTRL_GROUP(uart3, BIT(18) | BIT(19)), + PIC64GX_PINCTRL_GROUP(uart4, BIT(20) | BIT(21)), + PIC64GX_PINCTRL_GROUP(can1, BIT(22) | BIT(23) | BIT(25)), + PIC64GX_PINCTRL_GROUP(uart2, BIT(26) | BIT(27)), +}; + +static const char * const pic64gx_gpio2_gpio_groups[] = { + "gpio_mdio0", "gpio_mdio1", "gpio_spi0", "gpio_can0", "gpio_pcie", + "gpio_qspi", "gpio_uart3", "gpio_uart4", "gpio_can1", "gpio_uart2" +}; + +static const char * const pic64gx_gpio2_mdio0_groups[] = { + "mdio0" +}; + +static const char * const pic64gx_gpio2_mdio1_groups[] = { + "mdio1" +}; + +static const char * const pic64gx_gpio2_spi0_groups[] = { + "spi0" +}; + +static const char * const pic64gx_gpio2_can0_groups[] = { + "can0" +}; + +static const char * const pic64gx_gpio2_pcie_groups[] = { + "pcie" +}; + +static const char * const pic64gx_gpio2_qspi_groups[] = { + "qspi" +}; + +static const char * const pic64gx_gpio2_uart3_groups[] = { + "uart3" +}; + +static const char * const pic64gx_gpio2_uart4_groups[] = { + "uart4" +}; + +static const char * const pic64gx_gpio2_can1_groups[] = { + "can1" +}; + +static const char * const pic64gx_gpio2_uart2_groups[] = { + "uart2" +}; + +#define PIC64GX_PINCTRL_FUNCTION(_name) { \ + .name = #_name, \ + .groups = pic64gx_gpio2_##_name##_groups, \ + .num_groups = ARRAY_SIZE(pic64gx_gpio2_##_name##_groups), \ +} + +static const struct pic64gx_gpio2_function pic64gx_gpio2_functions[] = { + PIC64GX_PINCTRL_FUNCTION(gpio), + PIC64GX_PINCTRL_FUNCTION(mdio0), + PIC64GX_PINCTRL_FUNCTION(mdio1), + PIC64GX_PINCTRL_FUNCTION(spi0), + PIC64GX_PINCTRL_FUNCTION(can0), + PIC64GX_PINCTRL_FUNCTION(pcie), + PIC64GX_PINCTRL_FUNCTION(qspi), + PIC64GX_PINCTRL_FUNCTION(uart3), + PIC64GX_PINCTRL_FUNCTION(uart4), + PIC64GX_PINCTRL_FUNCTION(can1), + PIC64GX_PINCTRL_FUNCTION(uart2), +}; + +static void pic64gx_gpio2_pin_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, + unsigned int pin) +{ + struct pic64gx_gpio2_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 val; + + regmap_read(pctrl->regmap, PIC64GX_PINMUX_REG, &val); + val = (val & BIT(pin)) >> pin; + seq_printf(seq, "pin: %u val: %x\n", pin, val); +} + +static int pic64gx_gpio2_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(pic64gx_gpio2_pin_groups); +} + +static const char *pic64gx_gpio2_group_name(struct pinctrl_dev *pctldev, unsigned int selector) +{ + return pic64gx_gpio2_pin_groups[selector].name; +} + +static int pic64gx_gpio2_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, unsigned int *num_pins) +{ + *pins = pic64gx_gpio2_pin_groups[selector].pins; + *num_pins = pic64gx_gpio2_pin_groups[selector].num_pins; + + return 0; +} + +static const struct pinctrl_ops pic64gx_gpio2_pinctrl_ops = { + .get_groups_count = pic64gx_gpio2_groups_count, + .get_group_name = pic64gx_gpio2_group_name, + .get_group_pins = pic64gx_gpio2_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_free_map, + .pin_dbg_show = pic64gx_gpio2_pin_dbg_show, +}; + +static int pic64gx_gpio2_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(pic64gx_gpio2_functions); +} + +static const char *pic64gx_gpio2_pinmux_get_func_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return pic64gx_gpio2_functions[selector].name; +} + +static int pic64gx_gpio2_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups = pic64gx_gpio2_functions[selector].groups; + *num_groups = pic64gx_gpio2_functions[selector].num_groups; + + return 0; +} + +static int pic64gx_gpio2_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel, + unsigned int gsel) +{ + struct pic64gx_gpio2_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + struct device *dev = pctrl->dev; + const struct pic64gx_gpio2_pin_group *group; + const struct pic64gx_gpio2_function *function; + + group = &pic64gx_gpio2_pin_groups[gsel]; + function = &pic64gx_gpio2_functions[fsel]; + + dev_dbg(dev, "Setting func %s mask %x setting %x\n", + function->name, group->mask, group->setting); + regmap_assign_bits(pctrl->regmap, PIC64GX_PINMUX_REG, group->mask, group->setting); + + return 0; +} + +static const struct pinmux_ops pic64gx_gpio2_pinmux_ops = { + .get_functions_count = pic64gx_gpio2_pinmux_get_funcs_count, + .get_function_name = pic64gx_gpio2_pinmux_get_func_name, + .get_function_groups = pic64gx_gpio2_pinmux_get_groups, + .set_mux = pic64gx_gpio2_pinmux_set_mux, +}; + +static int pic64gx_gpio2_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pic64gx_gpio2_pinctrl *pctrl; + void __iomem *base; + + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + dev_err(dev, "Failed get resource\n"); + return PTR_ERR(base); + } + + pctrl->regmap = devm_regmap_init_mmio(dev, base, &pic64gx_gpio2_regmap_config); + if (IS_ERR(pctrl->regmap)) { + dev_err(dev, "Failed to map regmap\n"); + return PTR_ERR(pctrl->regmap); + } + + pctrl->desc.name = dev_name(dev); + pctrl->desc.pins = pic64gx_gpio2_pins; + pctrl->desc.npins = ARRAY_SIZE(pic64gx_gpio2_pins); + pctrl->desc.pctlops = &pic64gx_gpio2_pinctrl_ops; + pctrl->desc.pmxops = &pic64gx_gpio2_pinmux_ops; + pctrl->desc.owner = THIS_MODULE; + + pctrl->dev = dev; + + platform_set_drvdata(pdev, pctrl); + + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); + if (IS_ERR(pctrl->pctrl)) + return PTR_ERR(pctrl->pctrl); + + return 0; +} + +static const struct of_device_id pic64gx_gpio2_of_match[] = { + { .compatible = "microchip,pic64gx-pinctrl-gpio2" }, + { } +}; +MODULE_DEVICE_TABLE(of, pic64gx_gpio2_of_match); + +static struct platform_driver pic64gx_gpio2_driver = { + .driver = { + .name = "pic64gx-pinctrl-gpio2", + .of_match_table = pic64gx_gpio2_of_match, + }, + .probe = pic64gx_gpio2_probe, +}; +module_platform_driver(pic64gx_gpio2_driver); + +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("pic64gx gpio2 pinctrl driver"); +MODULE_LICENSE("GPL"); From 2f0073afd9bf88263c3d5136680a0e33a413383f Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 23 Oct 2025 18:14:59 +0100 Subject: [PATCH 149/684] dt-bindings: pinctrl: document polarfire soc iomux0 pinmux On Polarfire SoC, iomux0 is responsible for routing functions to either Multiprocessor Subsystem (MSS) IOs or to the FPGA fabric, where they can either interface with custom RTL or be routed to the FPGA fabric's IOs. Document it. Reviewed-by: Rob Herring (Arm) Signed-off-by: Conor Dooley Signed-off-by: Linus Walleij --- .../microchip,mpfs-pinctrl-iomux0.yaml | 89 +++++++++++++++++++ .../microchip,mpfs-mss-top-sysreg.yaml | 13 ++- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml new file mode 100644 index 00000000000000..3c98eb35fb821f --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip PolarFire SoC iomux0 + +maintainers: + - Conor Dooley + +description: + iomux0 is responsible for routing some functions to either the FPGA fabric, + or to MSSIOs. It only performs muxing, and has no IO configuration role, as + fabric IOs are configured separately and just routing a function to MSSIOs is + not sufficient for it to actually get mapped to an MSSIO, just makes it + possible. + +properties: + compatible: + oneOf: + - const: microchip,mpfs-pinctrl-iomux0 + - items: + - const: microchip,pic64gx-pinctrl-iomux0 + - const: microchip,mpfs-pinctrl-iomux0 + + reg: + maxItems: 1 + + pinctrl-use-default: true + +patternProperties: + '^mux-': + type: object + $ref: pinmux-node.yaml + additionalProperties: false + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [ spi0, spi1, i2c0, i2c1, can0, can1, qspi, uart0, uart1, uart2, + uart3, uart4, mdio0, mdio1 ] + + groups: + description: + An array of strings. Each string contains the name of a group. + items: + enum: [ spi0_fabric, spi0_mssio, spi1_fabric, spi1_mssio, i2c0_fabric, + i2c0_mssio, i2c1_fabric, i2c1_mssio, can0_fabric, can0_mssio, + can1_fabric, can1_mssio, qspi_fabric, qspi_mssio, + uart0_fabric, uart0_mssio, uart1_fabric, uart1_mssio, + uart2_fabric, uart2_mssio, uart3_fabric, uart3_mssio, + uart4_fabric, uart4_mssio, mdio0_fabric, mdio0_mssio, + mdio1_fabric, mdio1_mssio ] + + required: + - function + - groups + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + soc { + #size-cells = <1>; + #address-cells = <1>; + + pinctrl@200 { + compatible = "microchip,mpfs-pinctrl-iomux0"; + reg = <0x200 0x4>; + + mux-spi0-fabric { + function = "spi0"; + groups = "spi0_fabric"; + }; + + mux-spi1-mssio { + function = "spi1"; + groups = "spi1_mssio"; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml index 1ab691db879500..39987f72241184 100644 --- a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml @@ -18,10 +18,17 @@ properties: items: - const: microchip,mpfs-mss-top-sysreg - const: syscon + - const: simple-mfd reg: maxItems: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + '#reset-cells': description: The AHB/AXI peripherals on the PolarFire SoC have reset support, so @@ -31,6 +38,10 @@ properties: of PolarFire clock/reset IDs. const: 1 + pinctrl@200: + type: object + $ref: /schemas/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml + required: - compatible - reg @@ -40,7 +51,7 @@ additionalProperties: false examples: - | syscon@20002000 { - compatible = "microchip,mpfs-mss-top-sysreg", "syscon"; + compatible = "microchip,mpfs-mss-top-sysreg", "syscon", "simple-mfd"; reg = <0x20002000 0x1000>; #reset-cells = <1>; }; From 46397274da2284f46e550dc795de5ceeef8f89bf Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 23 Oct 2025 18:15:00 +0100 Subject: [PATCH 150/684] pinctrl: add polarfire soc iomux0 pinmux driver On Polarfire SoC, iomux0 is responsible for routing functions to either Multiprocessor Subsystem (MSS) IOs or to the FPGA fabric, where they can either interface with custom RTL or be routed to the FPGA fabric's IOs. Add a driver for it. Signed-off-by: Conor Dooley Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 8 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-mpfs-iomux0.c | 278 ++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-mpfs-iomux0.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e83fda9bf3080c..4ec2bb7f67cfaf 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -505,6 +505,14 @@ config PINCTRL_PISTACHIO help This support pinctrl and GPIO driver for IMG Pistachio SoC. +config PINCTRL_POLARFIRE_SOC + bool "Polarfire SoC pinctrl driver" + depends on ARCH_MICROCHIP || COMPILE_TEST + select GENERIC_PINCONF + default y + help + This selects the pinctrl driver for Microchip Polarfire SoC. + config PINCTRL_RK805 tristate "Pinctrl and GPIO driver for RK805 PMIC" depends on MFD_RK8XX diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f33976a6c91b33..ea4e890766e13a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o +obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o diff --git a/drivers/pinctrl/pinctrl-mpfs-iomux0.c b/drivers/pinctrl/pinctrl-mpfs-iomux0.c new file mode 100644 index 00000000000000..49d9fcec0a162b --- /dev/null +++ b/drivers/pinctrl/pinctrl-mpfs-iomux0.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "core.h" +#include "pinctrl-utils.h" +#include "pinconf.h" +#include "pinmux.h" + +#define MPFS_IOMUX0_REG 0x200 + +struct mpfs_iomux0_pinctrl { + struct pinctrl_dev *pctrl; + struct device *dev; + struct regmap *regmap; + struct pinctrl_desc desc; +}; + +struct mpfs_iomux0_pin_group { + const char *name; + const unsigned int *pins; + u32 mask; + u32 setting; +}; + +struct mpfs_iomux0_function { + const char *name; + const char * const *groups; +}; + +static const struct pinctrl_pin_desc mpfs_iomux0_pins[] = { + PINCTRL_PIN(0, "spi0"), + PINCTRL_PIN(1, "spi1"), + PINCTRL_PIN(2, "i2c0"), + PINCTRL_PIN(3, "i2c1"), + PINCTRL_PIN(4, "can0"), + PINCTRL_PIN(5, "can1"), + PINCTRL_PIN(6, "qspi"), + PINCTRL_PIN(7, "uart0"), + PINCTRL_PIN(8, "uart1"), + PINCTRL_PIN(9, "uart2"), + PINCTRL_PIN(10, "uart3"), + PINCTRL_PIN(11, "uart4"), + PINCTRL_PIN(12, "mdio0"), + PINCTRL_PIN(13, "mdio1"), +}; + +static const unsigned int mpfs_iomux0_spi0_pins[] = { 0 }; +static const unsigned int mpfs_iomux0_spi1_pins[] = { 1 }; +static const unsigned int mpfs_iomux0_i2c0_pins[] = { 2 }; +static const unsigned int mpfs_iomux0_i2c1_pins[] = { 3 }; +static const unsigned int mpfs_iomux0_can0_pins[] = { 4 }; +static const unsigned int mpfs_iomux0_can1_pins[] = { 5 }; +static const unsigned int mpfs_iomux0_qspi_pins[] = { 6 }; +static const unsigned int mpfs_iomux0_uart0_pins[] = { 7 }; +static const unsigned int mpfs_iomux0_uart1_pins[] = { 8 }; +static const unsigned int mpfs_iomux0_uart2_pins[] = { 9 }; +static const unsigned int mpfs_iomux0_uart3_pins[] = { 10 }; +static const unsigned int mpfs_iomux0_uart4_pins[] = { 11 }; +static const unsigned int mpfs_iomux0_mdio0_pins[] = { 12 }; +static const unsigned int mpfs_iomux0_mdio1_pins[] = { 13 }; + +#define MPFS_IOMUX0_GROUP(_name) { \ + .name = #_name "_mssio", \ + .pins = mpfs_iomux0_##_name##_pins, \ + .mask = BIT(mpfs_iomux0_##_name##_pins[0]), \ + .setting = 0x0, \ +}, { \ + .name = #_name "_fabric", \ + .pins = mpfs_iomux0_##_name##_pins, \ + .mask = BIT(mpfs_iomux0_##_name##_pins[0]), \ + .setting = BIT(mpfs_iomux0_##_name##_pins[0]), \ +} + +static const struct mpfs_iomux0_pin_group mpfs_iomux0_pin_groups[] = { + MPFS_IOMUX0_GROUP(spi0), + MPFS_IOMUX0_GROUP(spi1), + MPFS_IOMUX0_GROUP(i2c0), + MPFS_IOMUX0_GROUP(i2c1), + MPFS_IOMUX0_GROUP(can0), + MPFS_IOMUX0_GROUP(can1), + MPFS_IOMUX0_GROUP(qspi), + MPFS_IOMUX0_GROUP(uart0), + MPFS_IOMUX0_GROUP(uart1), + MPFS_IOMUX0_GROUP(uart2), + MPFS_IOMUX0_GROUP(uart3), + MPFS_IOMUX0_GROUP(uart4), + MPFS_IOMUX0_GROUP(mdio0), + MPFS_IOMUX0_GROUP(mdio1), +}; + +static const char * const mpfs_iomux0_spi0_groups[] = { "spi0_mssio", "spi0_fabric" }; +static const char * const mpfs_iomux0_spi1_groups[] = { "spi1_mssio", "spi1_fabric" }; +static const char * const mpfs_iomux0_i2c0_groups[] = { "i2c0_mssio", "i2c0_fabric" }; +static const char * const mpfs_iomux0_i2c1_groups[] = { "i2c1_mssio", "i2c1_fabric" }; +static const char * const mpfs_iomux0_can0_groups[] = { "can0_mssio", "can0_fabric" }; +static const char * const mpfs_iomux0_can1_groups[] = { "can1_mssio", "can1_fabric" }; +static const char * const mpfs_iomux0_qspi_groups[] = { "qspi_mssio", "qspi_fabric" }; +static const char * const mpfs_iomux0_uart0_groups[] = { "uart0_mssio", "uart0_fabric" }; +static const char * const mpfs_iomux0_uart1_groups[] = { "uart1_mssio", "uart1_fabric" }; +static const char * const mpfs_iomux0_uart2_groups[] = { "uart2_mssio", "uart2_fabric" }; +static const char * const mpfs_iomux0_uart3_groups[] = { "uart3_mssio", "uart3_fabric" }; +static const char * const mpfs_iomux0_uart4_groups[] = { "uart4_mssio", "uart4_fabric" }; +static const char * const mpfs_iomux0_mdio0_groups[] = { "mdio0_mssio", "mdio0_fabric" }; +static const char * const mpfs_iomux0_mdio1_groups[] = { "mdio1_mssio", "mdio1_fabric" }; + +#define MPFS_IOMUX0_FUNCTION(_name) { \ + .name = #_name, \ + .groups = mpfs_iomux0_##_name##_groups, \ +} + +static const struct mpfs_iomux0_function mpfs_iomux0_functions[] = { + MPFS_IOMUX0_FUNCTION(spi0), + MPFS_IOMUX0_FUNCTION(spi1), + MPFS_IOMUX0_FUNCTION(i2c0), + MPFS_IOMUX0_FUNCTION(i2c1), + MPFS_IOMUX0_FUNCTION(can0), + MPFS_IOMUX0_FUNCTION(can1), + MPFS_IOMUX0_FUNCTION(qspi), + MPFS_IOMUX0_FUNCTION(uart0), + MPFS_IOMUX0_FUNCTION(uart1), + MPFS_IOMUX0_FUNCTION(uart2), + MPFS_IOMUX0_FUNCTION(uart3), + MPFS_IOMUX0_FUNCTION(uart4), + MPFS_IOMUX0_FUNCTION(mdio0), + MPFS_IOMUX0_FUNCTION(mdio1), +}; + +static void mpfs_iomux0_pin_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, + unsigned int pin) +{ + struct mpfs_iomux0_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 val; + + seq_printf(seq, "reg: %x, pin: %u ", MPFS_IOMUX0_REG, pin); + + regmap_read(pctrl->regmap, MPFS_IOMUX0_REG, &val); + val = (val & BIT(pin)) >> pin; + + seq_printf(seq, "val: %x\n", val); +} + +static int mpfs_iomux0_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(mpfs_iomux0_pin_groups); +} + +static const char *mpfs_iomux0_group_name(struct pinctrl_dev *pctldev, unsigned int selector) +{ + return mpfs_iomux0_pin_groups[selector].name; +} + +static int mpfs_iomux0_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, unsigned int *num_pins) +{ + *pins = mpfs_iomux0_pin_groups[selector].pins; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops mpfs_iomux0_pinctrl_ops = { + .get_groups_count = mpfs_iomux0_groups_count, + .get_group_name = mpfs_iomux0_group_name, + .get_group_pins = mpfs_iomux0_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_free_map, + .pin_dbg_show = mpfs_iomux0_pin_dbg_show, +}; + +static int mpfs_iomux0_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel, + unsigned int gsel) +{ + struct mpfs_iomux0_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + struct device *dev = pctrl->dev; + const struct mpfs_iomux0_pin_group *group; + const struct mpfs_iomux0_function *function; + + group = &mpfs_iomux0_pin_groups[gsel]; + function = &mpfs_iomux0_functions[fsel]; + + dev_dbg(dev, "Setting func %s mask %x setting %x\n", + function->name, group->mask, group->setting); + regmap_assign_bits(pctrl->regmap, MPFS_IOMUX0_REG, group->mask, group->setting); + + return 0; +} + +static int mpfs_iomux0_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(mpfs_iomux0_functions); +} + +static const char *mpfs_iomux0_pinmux_get_func_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return mpfs_iomux0_functions[selector].name; +} + +static int mpfs_iomux0_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups = mpfs_iomux0_functions[selector].groups; + *num_groups = 2; + + return 0; +} + +static const struct pinmux_ops mpfs_iomux0_pinmux_ops = { + .get_functions_count = mpfs_iomux0_pinmux_get_funcs_count, + .get_function_name = mpfs_iomux0_pinmux_get_func_name, + .get_function_groups = mpfs_iomux0_pinmux_get_groups, + .set_mux = mpfs_iomux0_pinmux_set_mux, +}; + +static int mpfs_iomux0_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mpfs_iomux0_pinctrl *pctrl; + + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + pctrl->regmap = device_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(pctrl->regmap)) + dev_err_probe(dev, PTR_ERR(pctrl->regmap), "Failed to find syscon regmap\n"); + + pctrl->desc.name = dev_name(dev); + pctrl->desc.pins = mpfs_iomux0_pins; + pctrl->desc.npins = ARRAY_SIZE(mpfs_iomux0_pins); + pctrl->desc.pctlops = &mpfs_iomux0_pinctrl_ops; + pctrl->desc.pmxops = &mpfs_iomux0_pinmux_ops; + pctrl->desc.owner = THIS_MODULE; + + pctrl->dev = dev; + + platform_set_drvdata(pdev, pctrl); + + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); + if (IS_ERR(pctrl->pctrl)) + return PTR_ERR(pctrl->pctrl); + + return 0; +} + +static const struct of_device_id mpfs_iomux0_of_match[] = { + { .compatible = "microchip,mpfs-pinctrl-iomux0" }, + { } +}; +MODULE_DEVICE_TABLE(of, mpfs_iomux0_of_match); + +static struct platform_driver mpfs_iomux0_driver = { + .driver = { + .name = "mpfs-pinctrl-iomux0", + .of_match_table = mpfs_iomux0_of_match, + }, + .probe = mpfs_iomux0_probe, +}; +module_platform_driver(mpfs_iomux0_driver); + +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("Polarfire SoC iomux0 pinctrl driver"); +MODULE_LICENSE("GPL"); From e5cea3c87c3f92c1d7193e0b8eb9ef139ce8d4d6 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 23 Oct 2025 18:15:01 +0100 Subject: [PATCH 151/684] MAINTAINERS: add Microchip RISC-V pinctrl drivers/bindings to entry Add the new gpio2 and iomux0 drivers and bindings to the existing entry for Microchip RISC-V devices. Signed-off-by: Conor Dooley Signed-off-by: Linus Walleij --- MAINTAINERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index bdbcd05095b175..181a58ec4a8d5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22089,6 +22089,8 @@ F: Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml F: Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml F: Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml F: Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml +F: Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml +F: Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml F: Documentation/devicetree/bindings/riscv/microchip.yaml F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml @@ -22102,6 +22104,8 @@ F: drivers/gpio/gpio-mpfs.c F: drivers/i2c/busses/i2c-microchip-corei2c.c F: drivers/mailbox/mailbox-mpfs.c F: drivers/pci/controller/plda/pcie-microchip-host.c +F: drivers/pinctrl/pinctrl-mpfs-iomux0.c +F: drivers/pinctrl/pinctrl-pic64gx-gpio2.c F: drivers/pwm/pwm-microchip-core.c F: drivers/reset/reset-mpfs.c F: drivers/rtc/rtc-mpfs.c From e462fc48ceb8224811c3224650afed05cb7f0872 Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Fri, 3 Oct 2025 15:43:08 -0700 Subject: [PATCH 152/684] f2fs: maintain one time GC mode is enabled during whole zoned GC cycle The current version missed setting one time GC for normal zoned GC cycle. So, valid threshold control is not working. Need to fix it to prevent excessive GC for zoned devices. Fixes: e791d00bd06c ("f2fs: add valid block ratio not to do excessive GC for one time GC") Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index a7708cf80c04ed..8abf521530ff3f 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -38,13 +38,14 @@ static int gc_thread_func(void *data) struct f2fs_gc_control gc_control = { .victim_segno = NULL_SEGNO, .should_migrate_blocks = false, - .err_gc_skipped = false }; + .err_gc_skipped = false, + .one_time = false }; wait_ms = gc_th->min_sleep_time; set_freezable(); do { - bool sync_mode, foreground = false; + bool sync_mode, foreground = false, gc_boost = false; wait_event_freezable_timeout(*wq, kthread_should_stop() || @@ -52,8 +53,12 @@ static int gc_thread_func(void *data) gc_th->gc_wake, msecs_to_jiffies(wait_ms)); - if (test_opt(sbi, GC_MERGE) && waitqueue_active(fggc_wq)) + if (test_opt(sbi, GC_MERGE) && waitqueue_active(fggc_wq)) { foreground = true; + gc_control.one_time = false; + } else if (f2fs_sb_has_blkzoned(sbi)) { + gc_control.one_time = true; + } /* give it a try one time */ if (gc_th->gc_wake) @@ -81,8 +86,6 @@ static int gc_thread_func(void *data) continue; } - gc_control.one_time = false; - /* * [GC triggering condition] * 0. GC is not conducted currently. @@ -132,7 +135,7 @@ static int gc_thread_func(void *data) if (need_to_boost_gc(sbi)) { decrease_sleep_time(gc_th, &wait_ms); if (f2fs_sb_has_blkzoned(sbi)) - gc_control.one_time = true; + gc_boost = true; } else { increase_sleep_time(gc_th, &wait_ms); } @@ -141,7 +144,7 @@ static int gc_thread_func(void *data) FOREGROUND : BACKGROUND); sync_mode = (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC) || - (gc_control.one_time && gc_th->boost_gc_greedy); + (gc_boost && gc_th->boost_gc_greedy); /* foreground GC was been triggered via f2fs_balance_fs() */ if (foreground && !f2fs_sb_has_blkzoned(sbi)) From 81464df36094340395cadc9235e24eb4defa8c43 Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Tue, 7 Oct 2025 09:46:14 -0700 Subject: [PATCH 153/684] f2fs: set default valid_thresh_ratio to 80 for zoned devices Zoned storage devices provide marginal over-capacity space, typically around 10%, for filesystem level storage control. By utilizing this extra capacity, we can safely reduce the default 'valid_thresh_ratio' to 80. This action helps to significantly prevent excessive garbage collection (GC) and the resulting power consumption, as the filesystem becomes less aggressive about cleaning segments that still hold a high percentage of valid data. Reviewed-by: Chao Yu Signed-off-by: Daeho Jeong Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index 24e8b1c27acc4a..6c4d4567571eb5 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -25,7 +25,7 @@ #define DEF_GC_THREAD_CANDIDATE_RATIO 20 /* select 20% oldest sections as candidates */ #define DEF_GC_THREAD_MAX_CANDIDATE_COUNT 10 /* select at most 10 sections as candidates */ #define DEF_GC_THREAD_AGE_WEIGHT 60 /* age weight */ -#define DEF_GC_THREAD_VALID_THRESH_RATIO 95 /* do not GC over 95% valid block ratio for one time GC */ +#define DEF_GC_THREAD_VALID_THRESH_RATIO 80 /* do not GC over 80% valid block ratio for one time GC */ #define DEFAULT_ACCURACY_CLASS 10000 /* accuracy class */ #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ From e4384545e22024d39edc13c63433f37e31960671 Mon Sep 17 00:00:00 2001 From: Pedro Demarchi Gomes Date: Sat, 4 Oct 2025 00:12:17 -0300 Subject: [PATCH 154/684] f2fs: use folio_nr_pages() instead of shift operation folio_nr_pages() is a faster helper function to get the number of pages when NR_PAGES_IN_LARGE_FOLIO is enabled. Signed-off-by: Pedro Demarchi Gomes Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5b4e9548a231f3..b6e35fdd5fd3d4 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2096,7 +2096,7 @@ static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi) static inline struct f2fs_super_block *F2FS_SUPER_BLOCK(struct folio *folio, pgoff_t index) { - pgoff_t idx_in_folio = index % (1 << folio_order(folio)); + pgoff_t idx_in_folio = index % folio_nr_pages(folio); return (struct f2fs_super_block *) (page_address(folio_page(folio, idx_in_folio)) + From be806f06adfb2ec587b3b1076d1812b1f1032ac2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 25 Oct 2025 13:28:34 -0700 Subject: [PATCH 155/684] perf stat: Add/fix bperf cgroup max events workarounds Commit b8308511f6e0 bumped the max events to 1024 but this results in BPF verifier issues if the number of command line events is too large. Workaround this by: 1) moving the constants to a header file to share between BPF and perf C code, 2) testing that the maximum number of events doesn't cause BPF verifier issues in debug builds, 3) lower the max events from 1024 to 128, 4) in perf stat, if there are more events than the BPF counters can support then disable BPF counter usage. The rodata setup is factored into its own function to avoid duplicating it in the testing code. Signed-off-by: Ian Rogers Fixes: b8308511f6e0 ("perf stat bperf cgroup: Increase MAX_EVENTS from 32 to 1024") Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 13 +++- tools/perf/util/bpf_counter_cgroup.c | 79 +++++++++++++++------ tools/perf/util/bpf_skel/bperf_cgroup.bpf.c | 18 +++-- tools/perf/util/bpf_skel/bperf_cgroup.h | 15 ++++ 4 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 tools/perf/util/bpf_skel/bperf_cgroup.h diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3c3188a57016f8..886727ae8529b5 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -96,6 +96,10 @@ #include #include +#ifdef HAVE_BPF_SKEL +#include "util/bpf_skel/bperf_cgroup.h" +#endif + #define DEFAULT_SEPARATOR " " #define FREEZE_ON_SMI_PATH "bus/event_source/devices/cpu/freeze_on_smi" @@ -2852,7 +2856,14 @@ int cmd_stat(int argc, const char **argv) goto out; } } - +#ifdef HAVE_BPF_SKEL + if (target.use_bpf && nr_cgroups && + (evsel_list->core.nr_entries / nr_cgroups) > BPERF_CGROUP__MAX_EVENTS) { + pr_warning("Disabling BPF counters due to more events (%d) than the max (%d)\n", + evsel_list->core.nr_entries / nr_cgroups, BPERF_CGROUP__MAX_EVENTS); + target.use_bpf = false; + } +#endif // HAVE_BPF_SKEL evlist__warn_user_requested_cpus(evsel_list, target.cpu_list); evlist__for_each_entry(evsel_list, counter) { diff --git a/tools/perf/util/bpf_counter_cgroup.c b/tools/perf/util/bpf_counter_cgroup.c index 690be3ce3e1143..68bd994c88807b 100644 --- a/tools/perf/util/bpf_counter_cgroup.c +++ b/tools/perf/util/bpf_counter_cgroup.c @@ -27,6 +27,7 @@ #include "cpumap.h" #include "thread_map.h" +#include "bpf_skel/bperf_cgroup.h" #include "bpf_skel/bperf_cgroup.skel.h" static struct perf_event_attr cgrp_switch_attr = { @@ -42,6 +43,55 @@ static struct bperf_cgroup_bpf *skel; #define FD(evt, cpu) (*(int *)xyarray__entry(evt->core.fd, cpu, 0)) +static void setup_rodata(struct bperf_cgroup_bpf *sk, int evlist_size) +{ + int map_size, total_cpus = cpu__max_cpu().cpu; + + sk->rodata->num_cpus = total_cpus; + sk->rodata->num_events = evlist_size / nr_cgroups; + + if (cgroup_is_v2("perf_event") > 0) + sk->rodata->use_cgroup_v2 = 1; + + BUG_ON(evlist_size % nr_cgroups != 0); + + /* we need one copy of events per cpu for reading */ + map_size = total_cpus * evlist_size / nr_cgroups; + bpf_map__set_max_entries(sk->maps.events, map_size); + bpf_map__set_max_entries(sk->maps.cgrp_idx, nr_cgroups); + /* previous result is saved in a per-cpu array */ + map_size = evlist_size / nr_cgroups; + bpf_map__set_max_entries(sk->maps.prev_readings, map_size); + /* cgroup result needs all events (per-cpu) */ + map_size = evlist_size; + bpf_map__set_max_entries(sk->maps.cgrp_readings, map_size); +} + +static void test_max_events_program_load(void) +{ +#ifndef NDEBUG + /* + * Test that the program verifies with the maximum number of events. If + * this test fails unfortunately perf needs recompiling with a lower + * BPERF_CGROUP__MAX_EVENTS to avoid BPF verifier issues. + */ + int err, max_events = BPERF_CGROUP__MAX_EVENTS * nr_cgroups; + struct bperf_cgroup_bpf *test_skel = bperf_cgroup_bpf__open(); + + if (!test_skel) { + pr_err("Failed to open cgroup skeleton\n"); + return; + } + setup_rodata(test_skel, max_events); + err = bperf_cgroup_bpf__load(test_skel); + if (err) { + pr_err("Failed to load cgroup skeleton with max events %d.\n", + BPERF_CGROUP__MAX_EVENTS); + } + bperf_cgroup_bpf__destroy(test_skel); +#endif +} + static int bperf_load_program(struct evlist *evlist) { struct bpf_link *link; @@ -50,35 +100,18 @@ static int bperf_load_program(struct evlist *evlist) int i, j; struct perf_cpu cpu; int total_cpus = cpu__max_cpu().cpu; - int map_size, map_fd; - int prog_fd, err; + int map_fd, prog_fd, err; + + set_max_rlimit(); + + test_max_events_program_load(); skel = bperf_cgroup_bpf__open(); if (!skel) { pr_err("Failed to open cgroup skeleton\n"); return -1; } - - skel->rodata->num_cpus = total_cpus; - skel->rodata->num_events = evlist->core.nr_entries / nr_cgroups; - - if (cgroup_is_v2("perf_event") > 0) - skel->rodata->use_cgroup_v2 = 1; - - BUG_ON(evlist->core.nr_entries % nr_cgroups != 0); - - /* we need one copy of events per cpu for reading */ - map_size = total_cpus * evlist->core.nr_entries / nr_cgroups; - bpf_map__set_max_entries(skel->maps.events, map_size); - bpf_map__set_max_entries(skel->maps.cgrp_idx, nr_cgroups); - /* previous result is saved in a per-cpu array */ - map_size = evlist->core.nr_entries / nr_cgroups; - bpf_map__set_max_entries(skel->maps.prev_readings, map_size); - /* cgroup result needs all events (per-cpu) */ - map_size = evlist->core.nr_entries; - bpf_map__set_max_entries(skel->maps.cgrp_readings, map_size); - - set_max_rlimit(); + setup_rodata(skel, evlist->core.nr_entries); err = bperf_cgroup_bpf__load(skel); if (err) { diff --git a/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c b/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c index 18ab4d9b49ffbd..c2298a2decc909 100644 --- a/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c +++ b/tools/perf/util/bpf_skel/bperf_cgroup.bpf.c @@ -1,14 +1,12 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // Copyright (c) 2021 Facebook // Copyright (c) 2021 Google +#include "bperf_cgroup.h" #include "vmlinux.h" #include #include #include -#define MAX_LEVELS 10 // max cgroup hierarchy level: arbitrary -#define MAX_EVENTS 1024 // max events per cgroup: arbitrary - // NOTE: many of map and global data will be modified before loading // from the userspace (perf tool) using the skeleton helpers. @@ -97,7 +95,7 @@ static inline int get_cgroup_v1_idx(__u32 *cgrps, int size) cgrp = BPF_CORE_READ(p, cgroups, subsys[perf_subsys_id], cgroup); level = BPF_CORE_READ(cgrp, level); - for (cnt = 0; i < MAX_LEVELS; i++) { + for (cnt = 0; i < BPERF_CGROUP__MAX_LEVELS; i++) { __u64 cgrp_id; if (i > level) @@ -123,7 +121,7 @@ static inline int get_cgroup_v2_idx(__u32 *cgrps, int size) __u32 *elem; int cnt; - for (cnt = 0; i < MAX_LEVELS; i++) { + for (cnt = 0; i < BPERF_CGROUP__MAX_LEVELS; i++) { __u64 cgrp_id = bpf_get_current_ancestor_cgroup_id(i); if (cgrp_id == 0) @@ -148,17 +146,17 @@ static int bperf_cgroup_count(void) register int c = 0; struct bpf_perf_event_value val, delta, *prev_val, *cgrp_val; __u32 cpu = bpf_get_smp_processor_id(); - __u32 cgrp_idx[MAX_LEVELS]; + __u32 cgrp_idx[BPERF_CGROUP__MAX_LEVELS]; int cgrp_cnt; __u32 key, cgrp; long err; if (use_cgroup_v2) - cgrp_cnt = get_cgroup_v2_idx(cgrp_idx, MAX_LEVELS); + cgrp_cnt = get_cgroup_v2_idx(cgrp_idx, BPERF_CGROUP__MAX_LEVELS); else - cgrp_cnt = get_cgroup_v1_idx(cgrp_idx, MAX_LEVELS); + cgrp_cnt = get_cgroup_v1_idx(cgrp_idx, BPERF_CGROUP__MAX_LEVELS); - for ( ; idx < MAX_EVENTS; idx++) { + for ( ; idx < BPERF_CGROUP__MAX_EVENTS; idx++) { if (idx == num_events) break; @@ -186,7 +184,7 @@ static int bperf_cgroup_count(void) delta.enabled = val.enabled - prev_val->enabled; delta.running = val.running - prev_val->running; - for (c = 0; c < MAX_LEVELS; c++) { + for (c = 0; c < BPERF_CGROUP__MAX_LEVELS; c++) { if (c == cgrp_cnt) break; diff --git a/tools/perf/util/bpf_skel/bperf_cgroup.h b/tools/perf/util/bpf_skel/bperf_cgroup.h new file mode 100644 index 00000000000000..3fb84b19d39afd --- /dev/null +++ b/tools/perf/util/bpf_skel/bperf_cgroup.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* Data structures shared between BPF and tools. */ +#ifndef __BPERF_CGROUP_H +#define __BPERF_CGROUP_H + +// These constants impact code size of bperf_cgroup.bpf.c that may result in BPF +// verifier issues. They are exposed to control the size and also to disable BPF +// counters when the number of user events is too large. + +// max cgroup hierarchy level: arbitrary +#define BPERF_CGROUP__MAX_LEVELS 10 +// max events per cgroup: arbitrary +#define BPERF_CGROUP__MAX_EVENTS 128 + +#endif /* __BPERF_CGROUP_H */ From ab29ff9f6fe06d23c16b5565fcae96bad21be900 Mon Sep 17 00:00:00 2001 From: tanze Date: Fri, 24 Oct 2025 16:56:25 +0800 Subject: [PATCH 156/684] perf auxtrace: Add auxtrace_synth_id_range_start() helper To avoid hardcoding the offset value for synthetic event IDs in multiple auxtrace modules (arm-spe, cs-etm, intel-pt, etc.), and to improve code reusability, this patch unifies the handling of the ID offset via a dedicated helper function. Signed-off-by: tanze Reviewed-by: Adrian Hunter Tested-by: Leo Yan Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe.c | 5 +---- tools/perf/util/auxtrace.c | 16 ++++++++++++++++ tools/perf/util/auxtrace.h | 1 + tools/perf/util/cs-etm.c | 5 +---- tools/perf/util/intel-bts.c | 4 +--- tools/perf/util/intel-pt.c | 4 +--- tools/perf/util/powerpc-vpadtl.c | 4 +--- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 9561951a005547..614ce032f87e46 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -1733,10 +1733,7 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) attr.sample_period = spe->synth_opts.period; /* create new id val to be a fixed offset from evsel id */ - id = evsel->core.id[0] + 1000000000; - - if (!id) - id = 1; + id = auxtrace_synth_id_range_start(evsel); if (spe->synth_opts.flc) { spe->sample_flc = true; diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 1539c1dc823c20..35f4745f6b2bf0 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -62,6 +62,22 @@ #include #include "util/sample.h" +#define AUXTRACE_SYNTH_EVENT_ID_OFFSET 1000000000ULL + +/* + * Event IDs are allocated sequentially, so a big offset from any + * existing ID will reach a unused range. + */ +u64 auxtrace_synth_id_range_start(struct evsel *evsel) +{ + u64 id = evsel->core.id[0] + AUXTRACE_SYNTH_EVENT_ID_OFFSET; + + if (!id) + id = 1; + + return id; +} + /* * Make a group from 'leader' to 'last', requiring that the events were not * already grouped to a different leader. diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index e0a5b39fed1235..ed3a1aaaf5d9df 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -648,6 +648,7 @@ void auxtrace__free_events(struct perf_session *session); void auxtrace__free(struct perf_session *session); bool auxtrace__evsel_is_auxtrace(struct perf_session *session, struct evsel *evsel); +u64 auxtrace_synth_id_range_start(struct evsel *evsel); #define ITRACE_HELP \ " i[period]: synthesize instructions events\n" \ diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 30f4bb3e7fa303..62812bef1edfee 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1726,10 +1726,7 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, attr.read_format = evsel->core.attr.read_format; /* create new id val to be a fixed offset from evsel id */ - id = evsel->core.id[0] + 1000000000; - - if (!id) - id = 1; + id = auxtrace_synth_id_range_start(evsel); if (etm->synth_opts.branches) { attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 3625c622475024..382255393fb3bf 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -777,9 +777,7 @@ static int intel_bts_synth_events(struct intel_bts *bts, attr.sample_id_all = evsel->core.attr.sample_id_all; attr.read_format = evsel->core.attr.read_format; - id = evsel->core.id[0] + 1000000000; - if (!id) - id = 1; + id = auxtrace_synth_id_range_start(evsel); if (bts->synth_opts.branches) { attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 9b1011fe482671..fc9eec8b54b824 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -3987,9 +3987,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, attr.sample_id_all = evsel->core.attr.sample_id_all; attr.read_format = evsel->core.attr.read_format; - id = evsel->core.id[0] + 1000000000; - if (!id) - id = 1; + id = auxtrace_synth_id_range_start(evsel); if (pt->synth_opts.branches) { attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; diff --git a/tools/perf/util/powerpc-vpadtl.c b/tools/perf/util/powerpc-vpadtl.c index 39a3fb3f133013..bfa4156d7a9782 100644 --- a/tools/perf/util/powerpc-vpadtl.c +++ b/tools/perf/util/powerpc-vpadtl.c @@ -656,9 +656,7 @@ powerpc_vpadtl_synth_events(struct powerpc_vpadtl *vpa, struct perf_session *ses attr.config = PERF_SYNTH_POWERPC_VPA_DTL; /* create new id val to be a fixed offset from evsel id */ - id = evsel->core.id[0] + 1000000000; - if (!id) - id = 1; + id = auxtrace_synth_id_range_start(evsel); err = perf_session__deliver_synth_attr_event(session, &attr, id); if (err) From a5fad3aeff41f89ac94230d66ee5f9c1526cb3ce Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Wed, 22 Oct 2025 10:40:58 +0300 Subject: [PATCH 157/684] pinctrl: renesas: rzg2l: Remove useless wrappers rzg2l_gpio_irq_set_type() and rzg2l_gpio_irqc_eoi() only call the equivalent parent functions, replace their usage with the parent functions and remove them. Signed-off-by: Cosmin Tanislav Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251022074100.1994447-1-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index 947bce7bfc0e9a..f25ecada5c6929 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -2494,16 +2494,6 @@ static void rzg2l_gpio_irq_enable(struct irq_data *d) __rzg2l_gpio_irq_enable(d, true); } -static int rzg2l_gpio_irq_set_type(struct irq_data *d, unsigned int type) -{ - return irq_chip_set_type_parent(d, type); -} - -static void rzg2l_gpio_irqc_eoi(struct irq_data *d) -{ - irq_chip_eoi_parent(d); -} - static void rzg2l_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p) { struct gpio_chip *gc = irq_data_get_irq_chip_data(data); @@ -2539,8 +2529,8 @@ static const struct irq_chip rzg2l_gpio_irqchip = { .irq_enable = rzg2l_gpio_irq_enable, .irq_mask = irq_chip_mask_parent, .irq_unmask = irq_chip_unmask_parent, - .irq_set_type = rzg2l_gpio_irq_set_type, - .irq_eoi = rzg2l_gpio_irqc_eoi, + .irq_set_type = irq_chip_set_type_parent, + .irq_eoi = irq_chip_eoi_parent, .irq_print_chip = rzg2l_gpio_irq_print_chip, .irq_set_affinity = irq_chip_set_affinity_parent, .irq_set_wake = rzg2l_gpio_irq_set_wake, @@ -2640,7 +2630,7 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl) * interrupt. */ raw_spin_lock_irqsave(&pctrl->lock, flags); - ret = rzg2l_gpio_irq_set_type(data, irqd_get_trigger_type(data)); + ret = irq_chip_set_type_parent(data, irqd_get_trigger_type(data)); if (!ret && !irqd_irq_disabled(data)) __rzg2l_gpio_irq_enable(data, false); raw_spin_unlock_irqrestore(&pctrl->lock, flags); From 36a23904b4def05bfbb589af9fab5bc06144d241 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 15 Oct 2025 20:26:05 +0100 Subject: [PATCH 158/684] clk: renesas: rzv2h: Add instance field to struct pll Add a two-bit "instance" member to struct pll and extend the PLL_PACK() macro to accept an instance parameter. Initialize all existing PLL definitions with instance 0 to preserve legacy behavior. This change enables support for SoCs with multiple PLL instances (for example, RZ/G3E we have two PLL DSIs). Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251015192611.241920-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzv2h-cpg.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index 840eed25aeda72..e2053049c29991 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -16,20 +16,23 @@ * * @offset: STBY register offset * @has_clkn: Flag to indicate if CLK1/2 are accessible or not + * @instance: PLL instance number */ struct pll { unsigned int offset:9; unsigned int has_clkn:1; + unsigned int instance:2; }; -#define PLL_PACK(_offset, _has_clkn) \ +#define PLL_PACK(_offset, _has_clkn, _instance) \ ((struct pll){ \ .offset = _offset, \ - .has_clkn = _has_clkn \ + .has_clkn = _has_clkn, \ + .instance = _instance \ }) -#define PLLCA55 PLL_PACK(0x60, 1) -#define PLLGPU PLL_PACK(0x120, 1) +#define PLLCA55 PLL_PACK(0x60, 1, 0) +#define PLLGPU PLL_PACK(0x120, 1, 0) /** * struct ddiv - Structure for dynamic switching divider From a8943f7f0a736e211faa400fa9df1af8dd945347 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 15 Oct 2025 20:26:06 +0100 Subject: [PATCH 159/684] clk: renesas: rzv2h: Use GENMASK for PLL fields Replace the older FIELD_GET-wrapping helper macros with plain GENMASK definitions for the PLL CLK1/CLK2 field masks (CPG_PLL_CLK1_KDIV, CPG_PLL_CLK1_MDIV, CPG_PLL_CLK1_PDIV and CPG_PLL_CLK2_SDIV). Update rzv2h_cpg_pll_clk_recalc_rate() to explicitly extract those fields with FIELD_GET and cast the KDIV extraction to s16 to ensure proper sign extension when computing the PLL output rate. Co-developed-by: Fabrizio Castro Signed-off-by: Fabrizio Castro Signed-off-by: Lad Prabhakar Acked-by: Tomi Valkeinen Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251015192611.241920-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzv2h-cpg.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 2197d1d2453a3f..6abac15d3475ba 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -49,11 +49,11 @@ #define CPG_PLL_STBY_RESETB BIT(0) #define CPG_PLL_STBY_RESETB_WEN BIT(16) #define CPG_PLL_CLK1(x) ((x) + 0x004) -#define CPG_PLL_CLK1_KDIV(x) ((s16)FIELD_GET(GENMASK(31, 16), (x))) -#define CPG_PLL_CLK1_MDIV(x) FIELD_GET(GENMASK(15, 6), (x)) -#define CPG_PLL_CLK1_PDIV(x) FIELD_GET(GENMASK(5, 0), (x)) +#define CPG_PLL_CLK1_KDIV GENMASK(31, 16) +#define CPG_PLL_CLK1_MDIV GENMASK(15, 6) +#define CPG_PLL_CLK1_PDIV GENMASK(5, 0) #define CPG_PLL_CLK2(x) ((x) + 0x008) -#define CPG_PLL_CLK2_SDIV(x) FIELD_GET(GENMASK(2, 0), (x)) +#define CPG_PLL_CLK2_SDIV GENMASK(2, 0) #define CPG_PLL_MON(x) ((x) + 0x010) #define CPG_PLL_MON_RESETB BIT(0) #define CPG_PLL_MON_LOCK BIT(4) @@ -231,10 +231,11 @@ static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw, clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset)); clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset)); - rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) + - CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2)); + rate = mul_u64_u32_shr(parent_rate, (FIELD_GET(CPG_PLL_CLK1_MDIV, clk1) << 16) + + (s16)FIELD_GET(CPG_PLL_CLK1_KDIV, clk1), + 16 + FIELD_GET(CPG_PLL_CLK2_SDIV, clk2)); - return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1)); + return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV, clk1)); } static const struct clk_ops rzv2h_cpg_pll_ops = { From f864e4b721e386be132cc973eadefe5d52cdfd94 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 15 Oct 2025 20:26:07 +0100 Subject: [PATCH 160/684] clk: renesas: rzv2h: Add support for DSI clocks Add support for PLLDSI and its post-dividers in the RZ/V2H CPG driver and export helper APIs for use by the DSI driver. Introduce per-PLL-DSI state in the CPG private structure and provide a set of helper functions that find valid PLL parameter combinations for a requested frequency. The new helpers are rzv2h_get_pll_pars(), rzv2h_get_pll_div_pars(), rzv2h_get_pll_divs_pars() and rzv2h_get_pll_dtable_pars() and they are exported in the "RZV2H_CPG" namespace for use by other consumers (notably the DSI driver). These helpers perform iterative searches over PLL parameters (M, K, P, S) and optional post-dividers and return the best match (or an exact match when possible). Move PLL/CLK related limits and parameter types into the shared include (include/linux/clk/renesas.h) by adding struct rzv2h_pll_limits, struct rzv2h_pll_pars and struct rzv2h_pll_div_pars plus the RZV2H_CPG_PLL_DSI_LIMITS() helper macro to define DSI PLL limits. This change centralises the PLLDSI algorithms so the CPG and DSI drivers compute PLL parameters consistently and allows the DSI driver to accurately request rates and program its PLL. Co-developed-by: Fabrizio Castro Signed-off-by: Fabrizio Castro Signed-off-by: Lad Prabhakar Acked-by: Tomi Valkeinen Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251015192611.241920-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzv2h-cpg.c | 497 ++++++++++++++++++++++++++++++++ drivers/clk/renesas/rzv2h-cpg.h | 19 +- include/linux/clk/renesas.h | 145 ++++++++++ 3 files changed, 659 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 6abac15d3475ba..1824378003291f 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -14,9 +14,14 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -26,6 +31,7 @@ #include #include #include +#include #include @@ -47,7 +53,9 @@ #define CPG_PLL_STBY(x) ((x)) #define CPG_PLL_STBY_RESETB BIT(0) +#define CPG_PLL_STBY_SSC_EN BIT(2) #define CPG_PLL_STBY_RESETB_WEN BIT(16) +#define CPG_PLL_STBY_SSC_EN_WEN BIT(18) #define CPG_PLL_CLK1(x) ((x) + 0x004) #define CPG_PLL_CLK1_KDIV GENMASK(31, 16) #define CPG_PLL_CLK1_MDIV GENMASK(15, 6) @@ -65,6 +73,22 @@ #define CPG_CLKSTATUS0 (0x700) +/* On RZ/G3E SoC we have two DSI PLLs */ +#define MAX_CPG_DSI_PLL 2 + +/** + * struct rzv2h_pll_dsi_info - PLL DSI information, holds the limits and parameters + * + * @pll_dsi_limits: PLL DSI parameters limits + * @pll_dsi_parameters: Calculated PLL DSI parameters + * @req_pll_dsi_rate: Requested PLL DSI rate + */ +struct rzv2h_pll_dsi_info { + const struct rzv2h_pll_limits *pll_dsi_limits; + struct rzv2h_pll_div_pars pll_dsi_parameters; + unsigned long req_pll_dsi_rate; +}; + /** * struct rzv2h_cpg_priv - Clock Pulse Generator Private Data * @@ -80,6 +104,7 @@ * @ff_mod_status_ops: Fixed Factor Module Status Clock operations * @mstop_count: Array of mstop values * @rcdev: Reset controller entity + * @pll_dsi_info: Array of PLL DSI information, holds the limits and parameters */ struct rzv2h_cpg_priv { struct device *dev; @@ -98,6 +123,8 @@ struct rzv2h_cpg_priv { atomic_t *mstop_count; struct reset_controller_dev rcdev; + + struct rzv2h_pll_dsi_info pll_dsi_info[MAX_CPG_DSI_PLL]; }; #define rcdev_to_priv(x) container_of(x, struct rzv2h_cpg_priv, rcdev) @@ -168,6 +195,460 @@ struct rzv2h_ff_mod_status_clk { #define to_rzv2h_ff_mod_status_clk(_hw) \ container_of(_hw, struct rzv2h_ff_mod_status_clk, fix.hw) +/** + * struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock + * + * @dtable: divider table + * @priv: CPG private data + * @hw: divider clk + * @ddiv: divider configuration + */ +struct rzv2h_plldsi_div_clk { + const struct clk_div_table *dtable; + struct rzv2h_cpg_priv *priv; + struct clk_hw hw; + struct ddiv ddiv; +}; + +#define to_plldsi_div_clk(_hw) \ + container_of(_hw, struct rzv2h_plldsi_div_clk, hw) + +#define RZ_V2H_OSC_CLK_IN_MEGA (24 * MEGA) +#define RZV2H_MAX_DIV_TABLES (16) + +/** + * rzv2h_get_pll_pars - Finds the best combination of PLL parameters + * for a given frequency. + * + * @limits: Pointer to the structure containing the limits for the PLL parameters + * @pars: Pointer to the structure where the best calculated PLL parameters values + * will be stored + * @freq_millihz: Target output frequency in millihertz + * + * This function calculates the best set of PLL parameters (M, K, P, S) to achieve + * the desired frequency. + * There is no direct formula to calculate the PLL parameters, as it's an open + * system of equations, therefore this function uses an iterative approach to + * determine the best solution. The best solution is one that minimizes the error + * (desired frequency - actual frequency). + * + * Return: true if a valid set of parameters values is found, false otherwise. + */ +bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, u64 freq_millihz) +{ + u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI); + u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI); + struct rzv2h_pll_pars p, best; + + if (freq_millihz > fout_max_millihz || + freq_millihz < fout_min_millihz) + return false; + + /* Initialize best error to maximum possible value */ + best.error_millihz = S64_MAX; + + for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) { + u32 fref = RZ_V2H_OSC_CLK_IN_MEGA / p.p; + u16 divider; + + for (divider = 1 << limits->s.min, p.s = limits->s.min; + p.s <= limits->s.max; p.s++, divider <<= 1) { + for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) { + u64 output_m, output_k_range; + s64 pll_k, output_k; + u64 fvco, output; + + /* + * The frequency generated by the PLL + divider + * is calculated as follows: + * + * With: + * Freq = Ffout = Ffvco / 2^(pll_s) + * Ffvco = (pll_m + (pll_k / 65536)) * Ffref + * Ffref = 24MHz / pll_p + * + * Freq can also be rewritten as: + * Freq = Ffvco / 2^(pll_s) + * = ((pll_m + (pll_k / 65536)) * Ffref) / 2^(pll_s) + * = (pll_m * Ffref) / 2^(pll_s) + ((pll_k / 65536) * Ffref) / 2^(pll_s) + * = output_m + output_k + * + * Every parameter has been determined at this + * point, but pll_k. + * + * Considering that: + * limits->k.min <= pll_k <= limits->k.max + * Then: + * -0.5 <= (pll_k / 65536) < 0.5 + * Therefore: + * -Ffref / (2 * 2^(pll_s)) <= output_k < Ffref / (2 * 2^(pll_s)) + */ + + /* Compute output M component (in mHz) */ + output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI, + divider); + /* Compute range for output K (in mHz) */ + output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI), + 2 * divider); + /* + * No point in continuing if we can't achieve + * the desired frequency + */ + if (freq_millihz < (output_m - output_k_range) || + freq_millihz >= (output_m + output_k_range)) { + continue; + } + + /* + * Compute the K component + * + * Since: + * Freq = output_m + output_k + * Then: + * output_k = Freq - output_m + * = ((pll_k / 65536) * Ffref) / 2^(pll_s) + * Therefore: + * pll_k = (output_k * 65536 * 2^(pll_s)) / Ffref + */ + output_k = freq_millihz - output_m; + pll_k = div_s64(output_k * 65536ULL * divider, + fref); + pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI); + + /* Validate K value within allowed limits */ + if (pll_k < limits->k.min || + pll_k > limits->k.max) + continue; + + p.k = pll_k; + + /* Compute (Ffvco * 65536) */ + fvco = mul_u32_u32(p.m * 65536 + p.k, fref); + if (fvco < mul_u32_u32(limits->fvco.min, 65536) || + fvco > mul_u32_u32(limits->fvco.max, 65536)) + continue; + + /* PLL_M component of (output * 65536 * PLL_P) */ + output = mul_u32_u32(p.m * 65536, RZ_V2H_OSC_CLK_IN_MEGA); + /* PLL_K component of (output * 65536 * PLL_P) */ + output += p.k * RZ_V2H_OSC_CLK_IN_MEGA; + /* Make it in mHz */ + output *= MILLI; + output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider); + + /* Check output frequency against limits */ + if (output < fout_min_millihz || + output > fout_max_millihz) + continue; + + p.error_millihz = freq_millihz - output; + p.freq_millihz = output; + + /* If an exact match is found, return immediately */ + if (p.error_millihz == 0) { + *pars = p; + return true; + } + + /* Update best match if error is smaller */ + if (abs(best.error_millihz) > abs(p.error_millihz)) + best = p; + } + } + } + + /* If no valid parameters were found, return false */ + if (best.error_millihz == S64_MAX) + return false; + + *pars = best; + return true; +} +EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_pars, "RZV2H_CPG"); + +/* + * rzv2h_get_pll_divs_pars - Finds the best combination of PLL parameters + * and divider value for a given frequency. + * + * @limits: Pointer to the structure containing the limits for the PLL parameters + * @pars: Pointer to the structure where the best calculated PLL parameters and + * divider values will be stored + * @table: Pointer to the array of valid divider values + * @table_size: Size of the divider values array + * @freq_millihz: Target output frequency in millihertz + * + * This function calculates the best set of PLL parameters (M, K, P, S) and divider + * value to achieve the desired frequency. See rzv2h_get_pll_pars() for more details + * on how the PLL parameters are calculated. + * + * freq_millihz is the desired frequency generated by the PLL followed by a + * a gear. + */ +bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, u64 freq_millihz) +{ + struct rzv2h_pll_div_pars p, best; + + best.div.error_millihz = S64_MAX; + p.div.error_millihz = S64_MAX; + for (unsigned int i = 0; i < table_size; i++) { + if (!rzv2h_get_pll_pars(limits, &p.pll, freq_millihz * table[i])) + continue; + + p.div.divider_value = table[i]; + p.div.freq_millihz = DIV_U64_ROUND_CLOSEST(p.pll.freq_millihz, table[i]); + p.div.error_millihz = freq_millihz - p.div.freq_millihz; + + if (p.div.error_millihz == 0) { + *pars = p; + return true; + } + + if (abs(best.div.error_millihz) > abs(p.div.error_millihz)) + best = p; + } + + if (best.div.error_millihz == S64_MAX) + return false; + + *pars = best; + return true; +} +EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_divs_pars, "RZV2H_CPG"); + +static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw); + struct rzv2h_cpg_priv *priv = dsi_div->priv; + struct ddiv ddiv = dsi_div->ddiv; + u32 div; + + div = readl(priv->base + ddiv.offset); + div >>= ddiv.shift; + div &= clk_div_mask(ddiv.width); + div = dsi_div->dtable[div].div; + + return DIV_ROUND_CLOSEST_ULL(parent_rate, div); +} + +static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw); + struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw)); + struct rzv2h_cpg_priv *priv = dsi_div->priv; + u8 table[RZV2H_MAX_DIV_TABLES] = { 0 }; + struct rzv2h_pll_div_pars *dsi_params; + struct rzv2h_pll_dsi_info *dsi_info; + const struct clk_div_table *div; + unsigned int i = 0; + u64 rate_millihz; + + dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance]; + dsi_params = &dsi_info->pll_dsi_parameters; + + rate_millihz = mul_u32_u32(req->rate, MILLI); + if (rate_millihz == dsi_params->div.error_millihz + dsi_params->div.freq_millihz) + goto exit_determine_rate; + + for (div = dsi_div->dtable; div->div; div++) { + if (i >= RZV2H_MAX_DIV_TABLES) + return -EINVAL; + table[i++] = div->div; + } + + if (!rzv2h_get_pll_divs_pars(dsi_info->pll_dsi_limits, dsi_params, table, i, + rate_millihz)) { + dev_err(priv->dev, "failed to determine rate for req->rate: %lu\n", + req->rate); + return -EINVAL; + } + +exit_determine_rate: + req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params->div.freq_millihz, MILLI); + req->best_parent_rate = req->rate * dsi_params->div.divider_value; + dsi_info->req_pll_dsi_rate = req->best_parent_rate; + + return 0; +} + +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw); + struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw)); + struct rzv2h_cpg_priv *priv = dsi_div->priv; + struct rzv2h_pll_div_pars *dsi_params; + struct rzv2h_pll_dsi_info *dsi_info; + struct ddiv ddiv = dsi_div->ddiv; + const struct clk_div_table *clkt; + bool divider_found = false; + u32 val, shift; + + dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance]; + dsi_params = &dsi_info->pll_dsi_parameters; + + for (clkt = dsi_div->dtable; clkt->div; clkt++) { + if (clkt->div == dsi_params->div.divider_value) { + divider_found = true; + break; + } + } + + if (!divider_found) + return -EINVAL; + + shift = ddiv.shift; + val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift); + val &= ~(clk_div_mask(ddiv.width) << shift); + val |= clkt->val << shift; + writel(val, priv->base + ddiv.offset); + + return 0; +} + +static const struct clk_ops rzv2h_cpg_plldsi_div_ops = { + .recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate, + .determine_rate = rzv2h_cpg_plldsi_div_determine_rate, + .set_rate = rzv2h_cpg_plldsi_div_set_rate, +}; + +static struct clk * __init +rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core, + struct rzv2h_cpg_priv *priv) +{ + struct rzv2h_plldsi_div_clk *clk_hw_data; + struct clk **clks = priv->clks; + struct clk_init_data init; + const struct clk *parent; + const char *parent_name; + struct clk_hw *clk_hw; + int ret; + + parent = clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->priv = priv; + clk_hw_data->ddiv = core->cfg.ddiv; + clk_hw_data->dtable = core->dtable; + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &rzv2h_cpg_plldsi_div_ops; + init.flags = core->flag; + init.parent_names = &parent_name; + init.num_parents = 1; + + clk_hw = &clk_hw_data->hw; + clk_hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, clk_hw); + if (ret) + return ERR_PTR(ret); + + return clk_hw->clk; +} + +static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct pll_clk *pll_clk = to_pll(hw); + struct rzv2h_cpg_priv *priv = pll_clk->priv; + struct rzv2h_pll_dsi_info *dsi_info; + u64 rate_millihz; + + dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance]; + /* check if the divider has already invoked the algorithm */ + if (req->rate == dsi_info->req_pll_dsi_rate) + return 0; + + /* If the req->rate doesn't match we do the calculation assuming there is no divider */ + rate_millihz = mul_u32_u32(req->rate, MILLI); + if (!rzv2h_get_pll_pars(dsi_info->pll_dsi_limits, + &dsi_info->pll_dsi_parameters.pll, rate_millihz)) { + dev_err(priv->dev, + "failed to determine rate for req->rate: %lu\n", + req->rate); + return -EINVAL; + } + + req->rate = DIV_ROUND_CLOSEST_ULL(dsi_info->pll_dsi_parameters.pll.freq_millihz, MILLI); + dsi_info->req_pll_dsi_rate = req->rate; + + return 0; +} + +static int rzv2h_cpg_pll_set_rate(struct pll_clk *pll_clk, + struct rzv2h_pll_pars *params, + bool ssc_disable) +{ + struct rzv2h_cpg_priv *priv = pll_clk->priv; + u16 offset = pll_clk->pll.offset; + u32 val; + int ret; + + /* Put PLL into standby mode */ + writel(CPG_PLL_STBY_RESETB_WEN, priv->base + CPG_PLL_STBY(offset)); + ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset), + val, !(val & CPG_PLL_MON_LOCK), + 100, 2000); + if (ret) { + dev_err(priv->dev, "Failed to put PLLDSI into standby mode"); + return ret; + } + + /* Output clock setting 1 */ + writel(FIELD_PREP(CPG_PLL_CLK1_KDIV, (u16)params->k) | + FIELD_PREP(CPG_PLL_CLK1_MDIV, params->m) | + FIELD_PREP(CPG_PLL_CLK1_PDIV, params->p), + priv->base + CPG_PLL_CLK1(offset)); + + /* Output clock setting 2 */ + val = readl(priv->base + CPG_PLL_CLK2(offset)); + writel((val & ~CPG_PLL_CLK2_SDIV) | FIELD_PREP(CPG_PLL_CLK2_SDIV, params->s), + priv->base + CPG_PLL_CLK2(offset)); + + /* Put PLL to normal mode */ + if (ssc_disable) + val = CPG_PLL_STBY_SSC_EN_WEN; + else + val = CPG_PLL_STBY_SSC_EN_WEN | CPG_PLL_STBY_SSC_EN; + writel(val | CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB, + priv->base + CPG_PLL_STBY(offset)); + + /* PLL normal mode transition, output clock stability check */ + ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset), + val, (val & CPG_PLL_MON_LOCK), + 100, 2000); + if (ret) { + dev_err(priv->dev, "Failed to put PLLDSI into normal mode"); + return ret; + } + + return 0; +} + +static int rzv2h_cpg_plldsi_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct pll_clk *pll_clk = to_pll(hw); + struct rzv2h_pll_dsi_info *dsi_info; + struct rzv2h_cpg_priv *priv = pll_clk->priv; + + dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance]; + + return rzv2h_cpg_pll_set_rate(pll_clk, &dsi_info->pll_dsi_parameters.pll, true); +} + static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw) { struct pll_clk *pll_clk = to_pll(hw); @@ -238,6 +719,12 @@ static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw, return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV, clk1)); } +static const struct clk_ops rzv2h_cpg_plldsi_ops = { + .recalc_rate = rzv2h_cpg_pll_clk_recalc_rate, + .determine_rate = rzv2h_cpg_plldsi_determine_rate, + .set_rate = rzv2h_cpg_plldsi_set_rate, +}; + static const struct clk_ops rzv2h_cpg_pll_ops = { .is_enabled = rzv2h_cpg_pll_clk_is_enabled, .enable = rzv2h_cpg_pll_clk_enable, @@ -264,6 +751,10 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core, if (!pll_clk) return ERR_PTR(-ENOMEM); + if (core->type == CLK_TYPE_PLLDSI) + priv->pll_dsi_info[core->cfg.pll.instance].pll_dsi_limits = + core->cfg.pll.limits; + parent_name = __clk_get_name(parent); init.name = core->name; init.ops = ops; @@ -588,6 +1079,12 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, case CLK_TYPE_SMUX: clk = rzv2h_cpg_mux_clk_register(core, priv); break; + case CLK_TYPE_PLLDSI: + clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_plldsi_ops); + break; + case CLK_TYPE_PLLDSI_DIV: + clk = rzv2h_cpg_plldsi_div_clk_register(core, priv); + break; default: goto fail; } diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index e2053049c29991..637803bc1e8977 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -22,15 +22,20 @@ struct pll { unsigned int offset:9; unsigned int has_clkn:1; unsigned int instance:2; + const struct rzv2h_pll_limits *limits; }; -#define PLL_PACK(_offset, _has_clkn, _instance) \ +#define PLL_PACK_LIMITS(_offset, _has_clkn, _instance, _limits) \ ((struct pll){ \ .offset = _offset, \ .has_clkn = _has_clkn, \ - .instance = _instance \ + .instance = _instance, \ + .limits = _limits \ }) +#define PLL_PACK(_offset, _has_clkn, _instance) \ + PLL_PACK_LIMITS(_offset, _has_clkn, _instance, NULL) + #define PLLCA55 PLL_PACK(0x60, 1, 0) #define PLLGPU PLL_PACK(0x120, 1, 0) @@ -191,6 +196,8 @@ enum clk_types { CLK_TYPE_PLL, CLK_TYPE_DDIV, /* Dynamic Switching Divider */ CLK_TYPE_SMUX, /* Static Mux */ + CLK_TYPE_PLLDSI, /* PLLDSI */ + CLK_TYPE_PLLDSI_DIV, /* PLLDSI divider */ }; #define DEF_TYPE(_name, _id, _type...) \ @@ -221,6 +228,14 @@ enum clk_types { .num_parents = ARRAY_SIZE(_parent_names), \ .flag = CLK_SET_RATE_PARENT, \ .mux_flags = CLK_MUX_HIWORD_MASK) +#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll = _pll_packed) +#define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \ + .cfg.ddiv = _ddiv_packed, \ + .dtable = _dtable, \ + .parent = _parent, \ + .flag = CLK_SET_RATE_PARENT) /** * struct rzv2h_mod_clk - Module Clocks definitions diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 0ebbe2f0b45e78..69d8159deee3b5 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -10,7 +10,9 @@ #ifndef __LINUX_CLK_RENESAS_H_ #define __LINUX_CLK_RENESAS_H_ +#include #include +#include struct device; struct device_node; @@ -32,4 +34,147 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev); #define cpg_mssr_attach_dev NULL #define cpg_mssr_detach_dev NULL #endif + +/** + * struct rzv2h_pll_limits - PLL parameter constraints + * + * This structure defines the minimum and maximum allowed values for + * various parameters used to configure a PLL. These limits ensure + * the PLL operates within valid and stable ranges. + * + * @fout: Output frequency range (in MHz) + * @fout.min: Minimum allowed output frequency + * @fout.max: Maximum allowed output frequency + * + * @fvco: PLL oscillation frequency range (in MHz) + * @fvco.min: Minimum allowed VCO frequency + * @fvco.max: Maximum allowed VCO frequency + * + * @m: Main-divider range + * @m.min: Minimum main-divider value + * @m.max: Maximum main-divider value + * + * @p: Pre-divider range + * @p.min: Minimum pre-divider value + * @p.max: Maximum pre-divider value + * + * @s: Divider range + * @s.min: Minimum divider value + * @s.max: Maximum divider value + * + * @k: Delta-sigma modulator range (signed) + * @k.min: Minimum delta-sigma value + * @k.max: Maximum delta-sigma value + */ +struct rzv2h_pll_limits { + struct { + u32 min; + u32 max; + } fout; + + struct { + u32 min; + u32 max; + } fvco; + + struct { + u16 min; + u16 max; + } m; + + struct { + u8 min; + u8 max; + } p; + + struct { + u8 min; + u8 max; + } s; + + struct { + s16 min; + s16 max; + } k; +}; + +/** + * struct rzv2h_pll_pars - PLL configuration parameters + * + * This structure contains the configuration parameters for the + * Phase-Locked Loop (PLL), used to achieve a specific output frequency. + * + * @m: Main divider value + * @p: Pre-divider value + * @s: Output divider value + * @k: Delta-sigma modulation value + * @freq_millihz: Calculated PLL output frequency in millihertz + * @error_millihz: Frequency error from target in millihertz (signed) + */ +struct rzv2h_pll_pars { + u16 m; + u8 p; + u8 s; + s16 k; + u64 freq_millihz; + s64 error_millihz; +}; + +/** + * struct rzv2h_pll_div_pars - PLL parameters with post-divider + * + * This structure is used for PLLs that include an additional post-divider + * stage after the main PLL block. It contains both the PLL configuration + * parameters and the resulting frequency/error values after the divider. + * + * @pll: Main PLL configuration parameters (see struct rzv2h_pll_pars) + * + * @div: Post-divider configuration and result + * @div.divider_value: Divider applied to the PLL output + * @div.freq_millihz: Output frequency after divider in millihertz + * @div.error_millihz: Frequency error from target in millihertz (signed) + */ +struct rzv2h_pll_div_pars { + struct rzv2h_pll_pars pll; + struct { + u8 divider_value; + u64 freq_millihz; + s64 error_millihz; + } div; +}; + +#define RZV2H_CPG_PLL_DSI_LIMITS(name) \ + static const struct rzv2h_pll_limits (name) = { \ + .fout = { .min = 25 * MEGA, .max = 375 * MEGA }, \ + .fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA }, \ + .m = { .min = 64, .max = 533 }, \ + .p = { .min = 1, .max = 4 }, \ + .s = { .min = 0, .max = 6 }, \ + .k = { .min = -32768, .max = 32767 }, \ + } \ + +#ifdef CONFIG_CLK_RZV2H +bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, u64 freq_millihz); + +bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, u64 freq_millihz); +#else +static inline bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, + u64 freq_millihz) +{ + return false; +} + +static inline bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, + u64 freq_millihz) +{ + return false; +} +#endif + #endif From 66a470abe950fd7ebb0cfd909581fb9573f8b629 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 15 Oct 2025 20:26:08 +0100 Subject: [PATCH 161/684] clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC Add clock and reset entries for the DSI and LCDC peripherals. Co-developed-by: Fabrizio Castro Signed-off-by: Fabrizio Castro Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251015192611.241920-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g057-cpg.c | 62 +++++++++++++++++++++++++++++ drivers/clk/renesas/rzv2h-cpg.h | 3 ++ 2 files changed, 65 insertions(+) diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index dce5755d85ec1a..c9f6d91884c39b 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,7 @@ enum clk_ids { CLK_PLLCA55, CLK_PLLVDO, CLK_PLLETH, + CLK_PLLDSI, CLK_PLLGPU, /* Internal Core Clocks */ @@ -64,6 +66,9 @@ enum clk_ids { CLK_SMUX2_GBE0_RXCLK, CLK_SMUX2_GBE1_TXCLK, CLK_SMUX2_GBE1_RXCLK, + CLK_CDIV4_PLLETH_LPCLK, + CLK_PLLETH_LPCLK_GEAR, + CLK_PLLDSI_GEAR, CLK_PLLGPU_GEAR, /* Module Clocks */ @@ -92,6 +97,26 @@ static const struct clk_div_table dtable_2_16[] = { {0, 0}, }; +static const struct clk_div_table dtable_2_32[] = { + {0, 2}, + {1, 4}, + {2, 6}, + {3, 8}, + {4, 10}, + {5, 12}, + {6, 14}, + {7, 16}, + {8, 18}, + {9, 20}, + {10, 22}, + {11, 24}, + {12, 26}, + {13, 28}, + {14, 30}, + {15, 32}, + {0, 0}, +}; + static const struct clk_div_table dtable_2_64[] = { {0, 2}, {1, 4}, @@ -108,6 +133,17 @@ static const struct clk_div_table dtable_2_100[] = { {0, 0}, }; +static const struct clk_div_table dtable_16_128[] = { + {0, 16}, + {1, 32}, + {2, 64}, + {3, 128}, + {0, 0}, +}; + +RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits); +#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2h_cpg_pll_dsi_limits) + /* Mux clock tables */ static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" }; static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" }; @@ -129,6 +165,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55), DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2), DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3), + DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI), DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU), /* Internal Core Clocks */ @@ -170,6 +207,12 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk), DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk), DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk), + DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4), + DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK, + CSDIV0_DIVCTL2, dtable_16_128), + + DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI, + CSDIV1_DIVCTL2, dtable_2_32), DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64), @@ -383,6 +426,22 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { BUS_MSTOP(9, BIT(9))), DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5, BUS_MSTOP(9, BIT(9))), + DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), + DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), + DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16, BUS_MSTOP(3, BIT(4))), DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17, @@ -464,6 +523,9 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = { DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */ DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */ DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */ + DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */ + DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */ + DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */ DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */ diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index f7b4e4785d0f78..dc957bdaf5e971 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -127,6 +127,7 @@ struct fixed_mod_conf { #define CPG_CDDIV3 (0x40C) #define CPG_CDDIV4 (0x410) #define CPG_CSDIV0 (0x500) +#define CPG_CSDIV1 (0x504) #define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1) #define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2) @@ -144,7 +145,9 @@ struct fixed_mod_conf { #define CSDIV0_DIVCTL0 DDIV_PACK(CPG_CSDIV0, 0, 2, CSDIV_NO_MON) #define CSDIV0_DIVCTL1 DDIV_PACK(CPG_CSDIV0, 4, 2, CSDIV_NO_MON) +#define CSDIV0_DIVCTL2 DDIV_PACK(CPG_CSDIV0, 8, 2, CSDIV_NO_MON) #define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON) +#define CSDIV1_DIVCTL2 DDIV_PACK(CPG_CSDIV1, 8, 4, CSDIV_NO_MON) #define SSEL0_SELCTL2 SMUX_PACK(CPG_SSEL0, 8, 1) #define SSEL0_SELCTL3 SMUX_PACK(CPG_SSEL0, 12, 1) From 79276fb06d2f7769613abeeed65d69013137cefb Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Thu, 23 Oct 2025 11:19:15 +0300 Subject: [PATCH 162/684] clk: renesas: r9a09g077: Add TSU module clock The Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs have a TSU peripheral which is controlled by a module clock. The TSU module clock is enabled in register MSTPCRD (0x30c), at bit 7, resulting in a (0x30c - 0x300) / 4 * 100 + 7 = 307 index. Add it to the list of module clocks. Signed-off-by: Cosmin Tanislav Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251023081925.2412325-2-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index 4ec6c4ddc5f5fd..8b7e84a4c307f7 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -191,6 +191,7 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH), DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH), DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM), + DEF_MOD("tsu", 307, R9A09G077_CLK_PCLKL), DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM), DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM), DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM), From d64522b54b26229ee074137135dbbcba72a4600b Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 23 Oct 2025 22:07:22 +0100 Subject: [PATCH 163/684] clk: renesas: r9a09g056: Add clocks and resets for DSI and LCDC modules Add clock and reset definitions required to support the DSI and LCDC hardware blocks on the RZ/V2N SoC. This includes new core clocks, clock dividers, module clocks, and reset entries, as well as PLL and divider configurations specific to these peripherals. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251023210724.666476-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g056-cpg.c | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/clk/renesas/r9a09g056-cpg.c b/drivers/clk/renesas/r9a09g056-cpg.c index 55f056359dd777..70b73d4101351d 100644 --- a/drivers/clk/renesas/r9a09g056-cpg.c +++ b/drivers/clk/renesas/r9a09g056-cpg.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -29,6 +30,7 @@ enum clk_ids { CLK_PLLDTY, CLK_PLLCA55, CLK_PLLETH, + CLK_PLLDSI, CLK_PLLGPU, /* Internal Core Clocks */ @@ -47,6 +49,7 @@ enum clk_ids { CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_DIV8, + CLK_PLLDTY_DIV16, CLK_PLLETH_DIV_250_FIX, CLK_PLLETH_DIV_125_FIX, CLK_CSDIV_PLLETH_GBE0, @@ -55,6 +58,9 @@ enum clk_ids { CLK_SMUX2_GBE0_RXCLK, CLK_SMUX2_GBE1_TXCLK, CLK_SMUX2_GBE1_RXCLK, + CLK_CDIV4_PLLETH_LPCLK, + CLK_PLLETH_LPCLK_GEAR, + CLK_PLLDSI_GEAR, CLK_PLLGPU_GEAR, /* Module Clocks */ @@ -77,6 +83,26 @@ static const struct clk_div_table dtable_2_16[] = { {0, 0}, }; +static const struct clk_div_table dtable_2_32[] = { + {0, 2}, + {1, 4}, + {2, 6}, + {3, 8}, + {4, 10}, + {5, 12}, + {6, 14}, + {7, 16}, + {8, 18}, + {9, 20}, + {10, 22}, + {11, 24}, + {12, 26}, + {13, 28}, + {14, 30}, + {15, 32}, + {0, 0}, +}; + static const struct clk_div_table dtable_2_64[] = { {0, 2}, {1, 4}, @@ -93,6 +119,17 @@ static const struct clk_div_table dtable_2_100[] = { {0, 0}, }; +static const struct clk_div_table dtable_16_128[] = { + {0, 16}, + {1, 32}, + {2, 64}, + {3, 128}, + {0, 0}, +}; + +RZV2H_CPG_PLL_DSI_LIMITS(rzv2n_cpg_pll_dsi_limits); +#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2n_cpg_pll_dsi_limits) + /* Mux clock tables */ static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" }; static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" }; @@ -113,6 +150,7 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3), DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55), DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3), + DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI), DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU), /* Internal Core Clocks */ @@ -134,6 +172,7 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2), DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4), DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8), + DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16), DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4), DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2), @@ -145,6 +184,12 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk), DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk), DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk), + DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4), + DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK, + CSDIV0_DIVCTL2, dtable_16_128), + + DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI, + CSDIV1_DIVCTL2, dtable_2_32), DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64), @@ -289,6 +334,22 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = { BUS_MSTOP(8, BIT(6))), DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3, BUS_MSTOP(8, BIT(6))), + DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12, + BUS_MSTOP(9, BIT(14) | BIT(15))), + DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), + DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), + DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15, + BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))), DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16, BUS_MSTOP(3, BIT(4))), DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17, @@ -335,6 +396,9 @@ static const struct rzv2h_reset r9a09g056_resets[] __initconst = { DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */ + DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */ + DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */ + DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */ DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */ From 861df8792c69d903fbb705a0d314bfdd5546d72b Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 23 Oct 2025 22:07:23 +0100 Subject: [PATCH 164/684] clk: renesas: r9a09g056: Add support for PLLVDO, CRU clocks, and resets Add support for the PLLVDO clock and its related CRU clocks and reset entries in the R9A09G056 CPG driver. Introduce `CLK_PLLVDO` and associated clocks like `CLK_PLLVDO_CRU0` and `CLK_PLLVDO_CRU1`, along with their corresponding dividers. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251023210724.666476-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g056-cpg.c | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/clk/renesas/r9a09g056-cpg.c b/drivers/clk/renesas/r9a09g056-cpg.c index 70b73d4101351d..9c536f7706ff23 100644 --- a/drivers/clk/renesas/r9a09g056-cpg.c +++ b/drivers/clk/renesas/r9a09g056-cpg.c @@ -29,6 +29,7 @@ enum clk_ids { CLK_PLLCLN, CLK_PLLDTY, CLK_PLLCA55, + CLK_PLLVDO, CLK_PLLETH, CLK_PLLDSI, CLK_PLLGPU, @@ -50,6 +51,8 @@ enum clk_ids { CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_DIV8, CLK_PLLDTY_DIV16, + CLK_PLLVDO_CRU0, + CLK_PLLVDO_CRU1, CLK_PLLETH_DIV_250_FIX, CLK_PLLETH_DIV_125_FIX, CLK_CSDIV_PLLETH_GBE0, @@ -75,6 +78,12 @@ static const struct clk_div_table dtable_1_8[] = { {0, 0}, }; +static const struct clk_div_table dtable_2_4[] = { + {0, 2}, + {1, 4}, + {0, 0}, +}; + static const struct clk_div_table dtable_2_16[] = { {0, 2}, {1, 4}, @@ -149,6 +158,7 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3), DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3), DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55), + DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2), DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3), DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI), DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU), @@ -174,6 +184,9 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8), DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16), + DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4), + DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4), + DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4), DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2), DEF_CSDIV(".plleth_gbe0", CLK_CSDIV_PLLETH_GBE0, @@ -334,6 +347,18 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = { BUS_MSTOP(8, BIT(6))), DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3, BUS_MSTOP(8, BIT(6))), + DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18, + BUS_MSTOP(9, BIT(4))), + DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19, + BUS_MSTOP(9, BIT(4))), + DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20, + BUS_MSTOP(9, BIT(4))), + DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21, + BUS_MSTOP(9, BIT(5))), + DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22, + BUS_MSTOP(9, BIT(5))), + DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23, + BUS_MSTOP(9, BIT(5))), DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8, BUS_MSTOP(9, BIT(14) | BIT(15))), DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9, @@ -396,6 +421,12 @@ static const struct rzv2h_reset r9a09g056_resets[] __initconst = { DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */ + DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */ + DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */ + DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */ + DEF_RST(12, 8, 5, 25), /* CRU_1_PRESETN */ + DEF_RST(12, 9, 5, 26), /* CRU_1_ARESETN */ + DEF_RST(12, 10, 5, 27), /* CRU_1_S_RESETN */ DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */ DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */ DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */ From 07525a693a5ff6592668a0fd647153e4b4933cae Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 23 Oct 2025 22:07:24 +0100 Subject: [PATCH 165/684] clk: renesas: r9a09g056: Add clock and reset entries for ISP Add entries detailing the clocks and resets for the ISP in the RZ/V2N SoC. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251023210724.666476-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g056-cpg.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/renesas/r9a09g056-cpg.c b/drivers/clk/renesas/r9a09g056-cpg.c index 9c536f7706ff23..e4a6dfd2bec93d 100644 --- a/drivers/clk/renesas/r9a09g056-cpg.c +++ b/drivers/clk/renesas/r9a09g056-cpg.c @@ -53,6 +53,7 @@ enum clk_ids { CLK_PLLDTY_DIV16, CLK_PLLVDO_CRU0, CLK_PLLVDO_CRU1, + CLK_PLLVDO_ISP, CLK_PLLETH_DIV_250_FIX, CLK_PLLETH_DIV_125_FIX, CLK_CSDIV_PLLETH_GBE0, @@ -186,6 +187,7 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4), DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4), + DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64), DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4), DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2), @@ -359,6 +361,14 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = { BUS_MSTOP(9, BIT(5))), DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23, BUS_MSTOP(9, BIT(5))), + DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2, + BUS_MSTOP(9, BIT(8))), + DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3, + BUS_MSTOP(9, BIT(8))), + DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4, + BUS_MSTOP(9, BIT(9))), + DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5, + BUS_MSTOP(9, BIT(9))), DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8, BUS_MSTOP(9, BIT(14) | BIT(15))), DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9, @@ -427,6 +437,10 @@ static const struct rzv2h_reset r9a09g056_resets[] __initconst = { DEF_RST(12, 8, 5, 25), /* CRU_1_PRESETN */ DEF_RST(12, 9, 5, 26), /* CRU_1_ARESETN */ DEF_RST(12, 10, 5, 27), /* CRU_1_S_RESETN */ + DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */ + DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */ + DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */ + DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */ DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */ DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */ DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */ From 2fee899c068c159e486e62623afe9e2a4975bd79 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Wed, 22 Oct 2025 12:38:35 +0200 Subject: [PATCH 166/684] perf hwmon_pmu: Fix uninitialized variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The line_len is only set on success. Check the return value instead. util/hwmon_pmu.c: In function ‘perf_pmus__read_hwmon_pmus’: util/hwmon_pmu.c:742:20: warning: ‘line_len’ may be used uninitialized [-Wmaybe-uninitialized] 742 | if (line_len > 0 && line[line_len - 1] == '\n') | ^ util/hwmon_pmu.c:719:24: note: ‘line_len’ was declared here 719 | size_t line_len; Fixes: 53cc0b351ec9 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Signed-off-by: Michal Suchanek Signed-off-by: Namhyung Kim --- tools/perf/util/hwmon_pmu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index 416dfea9ffff61..5c27256a220a51 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -742,8 +742,7 @@ int perf_pmus__read_hwmon_pmus(struct list_head *pmus) continue; } io__init(&io, name_fd, buf2, sizeof(buf2)); - io__getline(&io, &line, &line_len); - if (line_len > 0 && line[line_len - 1] == '\n') + if (io__getline(&io, &line, &line_len) > 0 && line[line_len - 1] == '\n') line[line_len - 1] = '\0'; hwmon_pmu__new(pmus, buf, class_hwmon_ent->d_name, line); close(name_fd); From 329b71cd1e9e975583d772e1741c676bb2ddad2c Mon Sep 17 00:00:00 2001 From: Gary Yang Date: Tue, 21 Oct 2025 15:04:08 +0800 Subject: [PATCH 167/684] dt-bindings: pinctrl: Add cix,sky1-pinctrl The pin-controller is used to control the Soc pins. There are two pin-controllers on Cix Sky1 platform. One is used under S0 state, the other is used under S0 and S5 state. Signed-off-by: Gary Yang Reviewed-by: Conor Dooley Signed-off-by: Linus Walleij --- .../bindings/pinctrl/cix,sky1-pinctrl.yaml | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml new file mode 100644 index 00000000000000..36977b0d745bd2 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/cix,sky1-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cix Sky1 Soc Pin Controller + +maintainers: + - Gary Yang + +description: + The pin-controller is used to control Soc pins. There are two pin-controllers + on Cix Sky1 platform. one is used under S0 state, the other one is used under + S0 and S5 state. + +properties: + compatible: + enum: + - cix,sky1-pinctrl + - cix,sky1-pinctrl-s5 + + reg: + items: + - description: gpio base + +patternProperties: + '-cfg$': + type: object + additionalProperties: false + + description: + A pinctrl node should contain at least one subnode representing the + pinctrl groups available on the machine. + + patternProperties: + 'pins$': + type: object + additionalProperties: false + + description: + Each subnode will list the pins it needs, and how they should + be configured, with regard to muxer configuration, bias pull, + and drive strength. + + allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + + properties: + pinmux: + description: + Values are constructed from pin number and mux setting, pin + number is left shifted by 8 bits, then ORed with mux setting + + bias-disable: true + + bias-pull-up: true + + bias-pull-down: true + + drive-strength: + description: + typical current when output high level. + enum: [ 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 17, 18, 20, 21, 23, + 24 ] + + + required: + - pinmux + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #define CIX_PAD_GPIO012_FUNC_GPIO012 (11 << 8 | 0x0) + pinctrl@4170000 { + compatible = "cix,sky1-pinctrl"; + reg = <0x4170000 0x1000>; + + wifi_vbat_gpio: wifi-vbat-gpio-cfg { + pins { + pinmux = ; + bias-pull-up; + drive-strength = <8>; + }; + }; + }; From 920500c5fe66168f138be7f66089e8c8547694f1 Mon Sep 17 00:00:00 2001 From: Gary Yang Date: Tue, 21 Oct 2025 15:04:09 +0800 Subject: [PATCH 168/684] pinctrl: cix: Add pin-controller support for sky1 There are two pin-controllers on Cix Sky1 platform. one is used under S0 state, the other is used under S0 and S5 state. Signed-off-by: Gary Yang [Dropped pinctrl_provide_dummies()] Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/cix/Kconfig | 14 + drivers/pinctrl/cix/Makefile | 4 + drivers/pinctrl/cix/pinctrl-sky1-base.c | 572 ++++++++++++++++++++++++ drivers/pinctrl/cix/pinctrl-sky1.c | 559 +++++++++++++++++++++++ drivers/pinctrl/cix/pinctrl-sky1.h | 48 ++ 7 files changed, 1199 insertions(+) create mode 100644 drivers/pinctrl/cix/Kconfig create mode 100644 drivers/pinctrl/cix/Makefile create mode 100644 drivers/pinctrl/cix/pinctrl-sky1-base.c create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.c create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.h diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 4ec2bb7f67cfaf..2e590913fa4417 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -702,6 +702,7 @@ source "drivers/pinctrl/aspeed/Kconfig" source "drivers/pinctrl/bcm/Kconfig" source "drivers/pinctrl/berlin/Kconfig" source "drivers/pinctrl/cirrus/Kconfig" +source "drivers/pinctrl/cix/Kconfig" source "drivers/pinctrl/freescale/Kconfig" source "drivers/pinctrl/intel/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index ea4e890766e13a..be5200c23e6017 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-y += bcm/ obj-$(CONFIG_PINCTRL_BERLIN) += berlin/ obj-y += cirrus/ +obj-y += cix/ obj-y += freescale/ obj-$(CONFIG_X86) += intel/ obj-y += mediatek/ diff --git a/drivers/pinctrl/cix/Kconfig b/drivers/pinctrl/cix/Kconfig new file mode 100644 index 00000000000000..455120dd731892 --- /dev/null +++ b/drivers/pinctrl/cix/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +config PINCTRL_SKY1_BASE + tristate + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + select GENERIC_PINCONF + select REGMAP + +config PINCTRL_SKY1 + tristate "Cix Sky1 pinctrl driver" + depends on ARCH_CIX || COMPILE_TEST + select PINCTRL_SKY1_BASE + help + Say Y here to enable the sky1 pinctrl driver diff --git a/drivers/pinctrl/cix/Makefile b/drivers/pinctrl/cix/Makefile new file mode 100644 index 00000000000000..22685d6a107b23 --- /dev/null +++ b/drivers/pinctrl/cix/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Cix Sky1 pin control drivers +obj-$(CONFIG_PINCTRL_SKY1_BASE) += pinctrl-sky1-base.o +obj-$(CONFIG_PINCTRL_SKY1) += pinctrl-sky1.o diff --git a/drivers/pinctrl/cix/pinctrl-sky1-base.c b/drivers/pinctrl/cix/pinctrl-sky1-base.c new file mode 100644 index 00000000000000..b03e10147b09fc --- /dev/null +++ b/drivers/pinctrl/cix/pinctrl-sky1-base.c @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Author: Jerry Zhu +// Author: Gary Yang + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../core.h" +#include "../pinconf.h" +#include "../pinctrl-utils.h" +#include "../pinmux.h" +#include "pinctrl-sky1.h" + +#define SKY1_PIN_SIZE (4) +#define SKY1_MUX_MASK GENMASK(8, 7) +#define SKY1_MUX_SHIFT (7) +#define SKY1_PULLCONF_MASK GENMASK(6, 5) +#define SKY1_PULLUP_BIT (6) +#define SKY1_PULLDN_BIT (5) +#define SKY1_DS_MASK GENMASK(3, 0) + +#define CIX_PIN_NO_SHIFT (8) +#define CIX_PIN_FUN_MASK GENMASK(1, 0) +#define CIX_GET_PIN_NO(x) ((x) >> CIX_PIN_NO_SHIFT) +#define CIX_GET_PIN_FUNC(x) ((x) & CIX_PIN_FUN_MASK) +#define SKY1_DEFAULT_DS_VAL (4) + +static const char * const sky1_gpio_functions[] = { + "func0", "func1", "func2", "func3", +}; + +static unsigned char sky1_ds_table[] = { + 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 17, 18, 20, 21, 23, 24, +}; + +static bool sky1_pctrl_is_function_valid(struct sky1_pinctrl *spctl, + u32 pin_num, u32 fnum) +{ + int i; + + for (i = 0; i < spctl->info->npins; i++) { + const struct sky1_pin_desc *pin = spctl->info->pins + i; + + if (pin->pin.number == pin_num) { + if (fnum < pin->nfunc) + return true; + + break; + } + } + + return false; +} + +static int sky1_pctrl_dt_node_to_map_func(struct sky1_pinctrl *spctl, + u32 pin, u32 fnum, struct sky1_pinctrl_group *grp, + struct pinctrl_map **map, unsigned int *reserved_maps, + unsigned int *num_maps) +{ + bool ret; + + if (*num_maps == *reserved_maps) + return -ENOSPC; + + (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; + (*map)[*num_maps].data.mux.group = grp->name; + + ret = sky1_pctrl_is_function_valid(spctl, pin, fnum); + if (!ret) { + dev_err(spctl->dev, "invalid function %d on pin %d .\n", + fnum, pin); + return -EINVAL; + } + + (*map)[*num_maps].data.mux.function = sky1_gpio_functions[fnum]; + (*num_maps)++; + + return 0; +} + +static struct sky1_pinctrl_group * +sky1_pctrl_find_group_by_pin(struct sky1_pinctrl *spctl, u32 pin) +{ + int i; + + for (i = 0; i < spctl->info->npins; i++) { + struct sky1_pinctrl_group *grp = + (struct sky1_pinctrl_group *)spctl->groups + i; + + if (grp->pin == pin) + return grp; + } + + return NULL; +} + +static int sky1_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *node, + struct pinctrl_map **map, + unsigned int *reserved_maps, + unsigned int *num_maps) +{ + struct property *pins; + u32 pinfunc, pin, func; + int num_pins, num_funcs, maps_per_pin; + unsigned long *configs; + unsigned int num_configs; + bool has_config = false; + int i, err; + unsigned int reserve = 0; + struct sky1_pinctrl_group *grp; + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + + pins = of_find_property(node, "pinmux", NULL); + if (!pins) { + dev_err(spctl->dev, "missing pins property in node %pOFn .\n", + node); + return -EINVAL; + } + + err = pinconf_generic_parse_dt_config(node, pctldev, &configs, + &num_configs); + if (err) + return err; + + if (num_configs) + has_config = true; + + num_pins = pins->length / sizeof(u32); + num_funcs = num_pins; + maps_per_pin = 0; + if (num_funcs) + maps_per_pin++; + if (has_config && num_pins >= 1) + maps_per_pin++; + + if (!num_pins || !maps_per_pin) { + err = -EINVAL; + goto exit; + } + + reserve = num_pins * maps_per_pin; + + err = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, num_maps, reserve); + if (err < 0) + goto exit; + + for (i = 0; i < num_pins; i++) { + err = of_property_read_u32_index(node, "pinmux", + i, &pinfunc); + if (err) + goto exit; + + pin = CIX_GET_PIN_NO(pinfunc); + func = CIX_GET_PIN_FUNC(pinfunc); + pctldev->num_functions = ARRAY_SIZE(sky1_gpio_functions); + + if (pin >= pctldev->desc->npins || + func >= pctldev->num_functions) { + dev_err(spctl->dev, "invalid pins value.\n"); + err = -EINVAL; + goto exit; + } + + grp = sky1_pctrl_find_group_by_pin(spctl, pin); + if (!grp) { + dev_err(spctl->dev, "unable to match pin %d to group\n", + pin); + err = -EINVAL; + goto exit; + } + + err = sky1_pctrl_dt_node_to_map_func(spctl, pin, func, grp, + map, reserved_maps, num_maps); + if (err < 0) + goto exit; + + if (has_config) { + err = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, grp->name, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (err < 0) + goto exit; + } + } + + err = 0; + +exit: + kfree(configs); + return err; +} + +static int sky1_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, unsigned int *num_maps) +{ + unsigned int reserved_maps; + int ret; + + *map = NULL; + *num_maps = 0; + reserved_maps = 0; + + for_each_child_of_node_scoped(np_config, np) { + ret = sky1_pctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + pinctrl_utils_free_map(pctldev, *map, *num_maps); + return ret; + } + } + + return 0; +} + +static void sky1_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, + unsigned int num_maps) +{ + kfree(map); +} + +static int sky1_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + + return spctl->info->npins; +} + +static const char *sky1_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + + return spctl->groups[group].name; +} + +static int sky1_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + + *pins = (unsigned int *)&spctl->groups[group].pin; + *num_pins = 1; + + return 0; +} + +static void sky1_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned int offset) +{ + seq_printf(s, "%s", dev_name(pctldev->dev)); +} + +static const struct pinctrl_ops sky1_pctrl_ops = { + .dt_node_to_map = sky1_pctrl_dt_node_to_map, + .dt_free_map = sky1_dt_free_map, + .get_groups_count = sky1_pctrl_get_groups_count, + .get_group_name = sky1_pctrl_get_group_name, + .get_group_pins = sky1_pctrl_get_group_pins, + .pin_dbg_show = sky1_pin_dbg_show, +}; + +static int sky1_pmx_set_one_pin(struct sky1_pinctrl *spctl, + unsigned int pin, unsigned char muxval) +{ + u32 reg_val; + void __iomem *pin_reg; + + pin_reg = spctl->base + pin * SKY1_PIN_SIZE; + reg_val = readl(pin_reg); + reg_val &= ~SKY1_MUX_MASK; + reg_val |= muxval << SKY1_MUX_SHIFT; + writel(reg_val, pin_reg); + + dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n", + pin * SKY1_PIN_SIZE, reg_val); + return 0; +} + +static int sky1_pmx_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, + unsigned int group) +{ + bool ret; + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + struct sky1_pinctrl_group *g = + (struct sky1_pinctrl_group *)spctl->groups + group; + + ret = sky1_pctrl_is_function_valid(spctl, g->pin, function); + if (!ret) { + dev_err(spctl->dev, "invalid function %d on group %d .\n", + function, group); + return -EINVAL; + } + + sky1_pmx_set_one_pin(spctl, g->pin, function); + return 0; +} + +static int sky1_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(sky1_gpio_functions); +} + +static const char *sky1_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return sky1_gpio_functions[selector]; +} + +static int sky1_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned int function, + const char * const **groups, + unsigned int * const num_groups) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + const struct sky1_pinctrl_soc_info *info = spctl->info; + + *groups = spctl->grp_names; + *num_groups = info->npins; + + return 0; +} + +static const struct pinmux_ops sky1_pmx_ops = { + .get_functions_count = sky1_pmx_get_funcs_cnt, + .get_function_groups = sky1_pmx_get_func_groups, + .get_function_name = sky1_pmx_get_func_name, + .set_mux = sky1_pmx_set_mux, +}; + +static int sky1_pconf_set_pull_select(struct sky1_pinctrl *spctl, + unsigned int pin, bool enable, bool isup) +{ + u32 reg_val, reg_pullsel = 0; + void __iomem *pin_reg; + + pin_reg = spctl->base + pin * SKY1_PIN_SIZE; + reg_val = readl(pin_reg); + reg_val &= ~SKY1_PULLCONF_MASK; + + if (!enable) + goto update; + + if (isup) + reg_pullsel = BIT(SKY1_PULLUP_BIT); + else + reg_pullsel = BIT(SKY1_PULLDN_BIT); + +update: + reg_val |= reg_pullsel; + writel(reg_val, pin_reg); + + dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n", + pin * SKY1_PIN_SIZE, reg_val); + return 0; +} + +static int sky1_ds_to_index(unsigned char driving) +{ + int i; + + for (i = 0; i < sizeof(sky1_ds_table); i++) + if (driving == sky1_ds_table[i]) + return i; + return SKY1_DEFAULT_DS_VAL; +} + +static int sky1_pconf_set_driving(struct sky1_pinctrl *spctl, + unsigned int pin, unsigned char driving) +{ + unsigned int reg_val, val; + void __iomem *pin_reg; + + if (pin >= spctl->info->npins) + return -EINVAL; + + pin_reg = spctl->base + pin * SKY1_PIN_SIZE; + reg_val = readl(pin_reg); + reg_val &= ~SKY1_DS_MASK; + val = sky1_ds_to_index(driving); + reg_val |= (val & SKY1_DS_MASK); + writel(reg_val, pin_reg); + + dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n", + pin * SKY1_PIN_SIZE, reg_val); + + return 0; +} + +static int sky1_pconf_parse_conf(struct pinctrl_dev *pctldev, + unsigned int pin, enum pin_config_param param, + enum pin_config_param arg) +{ + int ret = 0; + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + ret = sky1_pconf_set_pull_select(spctl, pin, false, false); + break; + case PIN_CONFIG_BIAS_PULL_UP: + ret = sky1_pconf_set_pull_select(spctl, pin, true, true); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = sky1_pconf_set_pull_select(spctl, pin, true, false); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + ret = sky1_pconf_set_driving(spctl, pin, arg); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int sky1_pconf_group_get(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *config) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + struct sky1_pinctrl_group *g = &spctl->groups[group]; + + *config = g->config; + + return 0; +} + +static int sky1_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int group, + unsigned long *configs, unsigned int num_configs) +{ + struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev); + struct sky1_pinctrl_group *g = &spctl->groups[group]; + int i, ret; + + for (i = 0; i < num_configs; i++) { + ret = sky1_pconf_parse_conf(pctldev, g->pin, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret < 0) + return ret; + + g->config = configs[i]; + } + + return 0; +} + +static const struct pinconf_ops sky1_pinconf_ops = { + .pin_config_group_get = sky1_pconf_group_get, + .pin_config_group_set = sky1_pconf_group_set, +}; + +static int sky1_pctrl_build_state(struct platform_device *pdev) +{ + struct sky1_pinctrl *spctl = platform_get_drvdata(pdev); + const struct sky1_pinctrl_soc_info *info = spctl->info; + int i; + + /* Allocate groups */ + spctl->groups = devm_kcalloc(&pdev->dev, info->npins, + sizeof(*spctl->groups), GFP_KERNEL); + if (!spctl->groups) + return -ENOMEM; + + /* We assume that one pin is one group, use pin name as group name. */ + spctl->grp_names = devm_kcalloc(&pdev->dev, info->npins, + sizeof(*spctl->grp_names), GFP_KERNEL); + if (!spctl->grp_names) + return -ENOMEM; + + for (i = 0; i < info->npins; i++) { + const struct sky1_pin_desc *pin = spctl->info->pins + i; + struct sky1_pinctrl_group *group = + (struct sky1_pinctrl_group *)spctl->groups + i; + + group->name = pin->pin.name; + group->pin = pin->pin.number; + spctl->grp_names[i] = pin->pin.name; + } + + return 0; +} + +int sky1_base_pinctrl_probe(struct platform_device *pdev, + const struct sky1_pinctrl_soc_info *info) +{ + struct pinctrl_desc *sky1_pinctrl_desc; + struct sky1_pinctrl *spctl; + struct pinctrl_pin_desc *pins; + int ret, i; + + if (!info || !info->pins || !info->npins) { + dev_err(&pdev->dev, "wrong pinctrl info\n"); + return -EINVAL; + } + + /* Create state holders etc for this driver */ + spctl = devm_kzalloc(&pdev->dev, sizeof(*spctl), GFP_KERNEL); + if (!spctl) + return -ENOMEM; + + spctl->info = info; + platform_set_drvdata(pdev, spctl); + + spctl->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(spctl->base)) + return PTR_ERR(spctl->base); + + sky1_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*sky1_pinctrl_desc), + GFP_KERNEL); + if (!sky1_pinctrl_desc) + return -ENOMEM; + + pins = devm_kcalloc(&pdev->dev, info->npins, sizeof(*pins), + GFP_KERNEL); + if (!pins) + return -ENOMEM; + for (i = 0; i < info->npins; i++) + pins[i] = info->pins[i].pin; + + ret = sky1_pctrl_build_state(pdev); + if (ret) + return ret; + + sky1_pinctrl_desc->name = dev_name(&pdev->dev); + sky1_pinctrl_desc->pins = pins; + sky1_pinctrl_desc->npins = info->npins; + sky1_pinctrl_desc->pctlops = &sky1_pctrl_ops; + sky1_pinctrl_desc->pmxops = &sky1_pmx_ops; + sky1_pinctrl_desc->confops = &sky1_pinconf_ops; + sky1_pinctrl_desc->owner = THIS_MODULE; + spctl->dev = &pdev->dev; + ret = devm_pinctrl_register_and_init(&pdev->dev, + sky1_pinctrl_desc, spctl, + &spctl->pctl); + if (ret) { + dev_err(&pdev->dev, "could not register SKY1 pinctrl driver\n"); + return ret; + } + + dev_dbg(&pdev->dev, "initialized SKY1 pinctrl driver\n"); + + return pinctrl_enable(spctl->pctl); +} +EXPORT_SYMBOL_GPL(sky1_base_pinctrl_probe); + + +MODULE_AUTHOR("Jerry Zhu "); +MODULE_DESCRIPTION("Cix SKy1 pinctrl base driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/cix/pinctrl-sky1.c b/drivers/pinctrl/cix/pinctrl-sky1.c new file mode 100644 index 00000000000000..5d0d8be815b2ba --- /dev/null +++ b/drivers/pinctrl/cix/pinctrl-sky1.c @@ -0,0 +1,559 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Author: Jerry Zhu +// Author: Gary Yang + +#include +#include +#include +#include +#include +#include +#include +#include "linux/stddef.h" + +#include "../core.h" +#include "pinctrl-sky1.h" + +/* Pad names for the s5 domain pinmux subsystem */ +static const char * const gpio1_group[] = {"GPIO1"}; +static const char * const gpio2_group[] = {"GPIO2"}; +static const char * const gpio3_group[] = {"GPIO3"}; +static const char * const gpio4_group[] = {"GPIO4"}; +static const char * const gpio5_group[] = {"GPIO5"}; +static const char * const gpio6_group[] = {"GPIO6"}; +static const char * const gpio7_group[] = {"GPIO7"}; +static const char * const gpio8_group[] = {"GPIO8"}; +static const char * const gpio9_group[] = {"GPIO9"}; +static const char * const gpio10_group[] = {"GPIO10"}; +static const char * const gpio11_group[] = {"GPIO11"}; +static const char * const gpio12_group[] = {"GPIO12"}; +static const char * const gpio13_group[] = {"GPIO13"}; +static const char * const gpio14_group[] = {"GPIO14"}; +static const char * const rsmrst_group[] = { }; +static const char * const srst_group[] = { }; +static const char * const slp_s3_group[] = { }; +static const char * const slp_s5_group[] = { }; +static const char * const pwrgd_group[] = { }; +static const char * const pwrok_group[] = { }; +static const char * const pwrbtn_group[] = { }; +static const char * const ddrio_gate_group[] = { }; +static const char * const jtag_gpio_group[] = { }; +static const char * const jtag_tck_group[] = { }; +static const char * const jtag_tdi_group[] = { }; +static const char * const jtag_tdo_group[] = { }; +static const char * const tms_group[] = { }; +static const char * const trsl_group[] = { }; +static const char * const sfi_i2c0_scl_group[] = {"SFI_I2C0_SCL", + "SFI_I3C0_SCL"}; +static const char * const sfi_i2c0_sda_group[] = {"SFI_I2C0_SDA", + "SFI_I3C0_SDA"}; +static const char * const sfi_i2c1_scl_group[] = {"SFI_I2C1_SCL", + "SFI_I3C1_SCL", "SFI_SPI_CS0"}; +static const char * const sfi_i2c1_sda_group[] = {"SFI_I2C1_SDA", + "SFI_I3C1_SDA", "SFI_SPI_CS1"}; +static const char * const sfi_gpio0_group[] = {"GPIO15", "SFI_SPI_SCK", + "SFI_GPIO0"}; +static const char * const sfi_gpio1_group[] = {"GPIO16", "SFI_SPI_MOSI", + "SFI_GPIO1"}; +static const char * const sfi_gpio2_group[] = {"GPIO17", "SFI_SPI_MISO", + "SFI_GPIO2"}; +static const char * const gpio18_group[] = {"SFI_GPIO3", "GPIO18"}; +static const char * const gpio19_group[] = {"SFI_GPIO4", "GPIO19"}; +static const char * const gpio20_group[] = {"SFI_GPIO5", "GPIO20"}; +static const char * const gpio21_group[] = {"SFI_GPIO6", "GPIO21"}; +static const char * const gpio22_group[] = {"SFI_GPIO7", "GPIO22"}; +static const char * const gpio23_group[] = {"SFI_GPIO8", "GPIO23", + "SFI_I3C0_PUR_EN_L"}; +static const char * const gpio24_group[] = {"SFI_GPIO9", "GPIO24", + "SFI_I3C1_PUR_EN_L"}; +static const char * const spi1_miso_group[] = {"SPI1_MISO", "GPIO25"}; +static const char * const spi1_cs0_group[] = {"SPI1_CS0", "GPIO26"}; +static const char * const spi1_cs1_group[] = {"SPI1_CS1", "GPIO27"}; +static const char * const spi1_mosi_group[] = {"SPI1_MOSI", "GPIO28"}; +static const char * const spi1_clk_group[] = {"SPI1_CLK", "GPIO29"}; +static const char * const gpio30_group[] = {"GPIO30", "USB_0C0_L"}; +static const char * const gpio31_group[] = {"GPIO31", "USB_0C1_L"}; +static const char * const gpio32_group[] = {"GPIO32", "USB_0C2_L"}; +static const char * const gpio33_group[] = {"GPIO33", "USB_0C3_L"}; +static const char * const gpio34_group[] = {"GPIO34", "USB_0C4_L"}; +static const char * const gpio35_group[] = {"GPIO35", "USB_0C5_L"}; +static const char * const gpio36_group[] = {"GPIO36", "USB_0C6_L"}; +static const char * const gpio37_group[] = {"GPIO37", "USB_0C7_L"}; +static const char * const gpio38_group[] = {"GPIO38", "USB_0C8_L"}; +static const char * const gpio39_group[] = {"GPIO39", "USB_0C9_L"}; +static const char * const gpio40_group[] = {"GPIO40", "USB_DRIVE_VBUS0"}; +static const char * const gpio41_group[] = {"GPIO41", "USB_DRIVE_VBUS4"}; +static const char * const gpio42_group[] = {"GPIO42", "USB_DRIVE_VBUS5"}; +static const char * const se_qspi_clk_group[] = {"SE_QSPI_CLK", "QSPI_CLK"}; +static const char * const se_qspi_cs_group[] = {"SE_QSPI_CS_L", "QSPI_CS_L"}; +static const char * const se_qspi_data0_group[] = {"SE_QSPI_DATA0", + "QSPI_DATA0"}; +static const char * const se_qspi_data1_group[] = {"SE_QSPI_DATA1", + "QSPI_DATA1"}; +static const char * const se_qspi_data2_group[] = {"SE_QSPI_DATA2", + "QSPI_DATA2"}; +static const char * const se_qspi_data3_group[] = {"SE_QSPI_DATA3", + "QSPI_DATA3"}; +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = { + SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"), gpio1), + SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"), gpio2), + SKY_PINFUNCTION(PINCTRL_PIN(2, "GPIO3"), gpio3), + SKY_PINFUNCTION(PINCTRL_PIN(3, "GPIO4"), gpio4), + SKY_PINFUNCTION(PINCTRL_PIN(4, "GPIO5"), gpio5), + SKY_PINFUNCTION(PINCTRL_PIN(5, "GPIO6"), gpio6), + SKY_PINFUNCTION(PINCTRL_PIN(6, "GPIO7"), gpio7), + SKY_PINFUNCTION(PINCTRL_PIN(7, "GPIO8"), gpio8), + SKY_PINFUNCTION(PINCTRL_PIN(8, "GPIO9"), gpio9), + SKY_PINFUNCTION(PINCTRL_PIN(9, "GPIO10"), gpio10), + SKY_PINFUNCTION(PINCTRL_PIN(10, "GPIO11"), gpio11), + SKY_PINFUNCTION(PINCTRL_PIN(11, "GPIO12"), gpio12), + SKY_PINFUNCTION(PINCTRL_PIN(12, "GPIO13"), gpio13), + SKY_PINFUNCTION(PINCTRL_PIN(13, "GPIO14"), gpio14), + SKY_PINFUNCTION(PINCTRL_PIN(14, "RSMRST_L"), rsmrst), + SKY_PINFUNCTION(PINCTRL_PIN(15, "SRST_L"), srst), + SKY_PINFUNCTION(PINCTRL_PIN(16, "SLP_S3_L"), slp_s3), + SKY_PINFUNCTION(PINCTRL_PIN(17, "SLP_S5_L"), slp_s5), + SKY_PINFUNCTION(PINCTRL_PIN(18, "PWRGD"), pwrgd), + SKY_PINFUNCTION(PINCTRL_PIN(19, "PWROK"), pwrok), + SKY_PINFUNCTION(PINCTRL_PIN(20, "PWRBTN_L"), pwrbtn), + SKY_PINFUNCTION(PINCTRL_PIN(21, "VDD_DDRIO_GATE"), ddrio_gate), + SKY_PINFUNCTION(PINCTRL_PIN(22, "JTAG_GPIO_L"), jtag_gpio), + SKY_PINFUNCTION(PINCTRL_PIN(23, "JTAG_TCK"), jtag_tck), + SKY_PINFUNCTION(PINCTRL_PIN(24, "JTAG_TDI"), jtag_tdi), + SKY_PINFUNCTION(PINCTRL_PIN(25, "JTAG_TDO"), jtag_tdo), + SKY_PINFUNCTION(PINCTRL_PIN(26, "TMS"), tms), + SKY_PINFUNCTION(PINCTRL_PIN(27, "TRSL_L"), trsl), + SKY_PINFUNCTION(PINCTRL_PIN(28, "SFI_I2C0_SCL"), sfi_i2c0_scl), + SKY_PINFUNCTION(PINCTRL_PIN(29, "SFI_I2C0_SDA"), sfi_i2c0_sda), + SKY_PINFUNCTION(PINCTRL_PIN(30, "SFI_I2C1_SCL"), sfi_i2c1_scl), + SKY_PINFUNCTION(PINCTRL_PIN(31, "SFI_I2C1_SDA"), sfi_i2c1_sda), + SKY_PINFUNCTION(PINCTRL_PIN(32, "SFI_GPIO0"), sfi_gpio0), + SKY_PINFUNCTION(PINCTRL_PIN(33, "SFI_GPIO1"), sfi_gpio1), + SKY_PINFUNCTION(PINCTRL_PIN(34, "SFI_GPIO2"), sfi_gpio2), + SKY_PINFUNCTION(PINCTRL_PIN(35, "GPIO18"), gpio18), + SKY_PINFUNCTION(PINCTRL_PIN(36, "GPIO19"), gpio19), + SKY_PINFUNCTION(PINCTRL_PIN(37, "GPIO20"), gpio20), + SKY_PINFUNCTION(PINCTRL_PIN(38, "GPIO21"), gpio21), + SKY_PINFUNCTION(PINCTRL_PIN(39, "GPIO22"), gpio22), + SKY_PINFUNCTION(PINCTRL_PIN(40, "GPIO23"), gpio23), + SKY_PINFUNCTION(PINCTRL_PIN(41, "GPIO24"), gpio24), + SKY_PINFUNCTION(PINCTRL_PIN(42, "SPI1_MISO"), spi1_miso), + SKY_PINFUNCTION(PINCTRL_PIN(43, "SPI1_CS0"), spi1_cs0), + SKY_PINFUNCTION(PINCTRL_PIN(44, "SPI1_CS1"), spi1_cs1), + SKY_PINFUNCTION(PINCTRL_PIN(45, "SPI1_MOSI"), spi1_mosi), + SKY_PINFUNCTION(PINCTRL_PIN(46, "SPI1_CLK"), spi1_clk), + SKY_PINFUNCTION(PINCTRL_PIN(47, "GPIO30"), gpio30), + SKY_PINFUNCTION(PINCTRL_PIN(48, "GPIO31"), gpio31), + SKY_PINFUNCTION(PINCTRL_PIN(49, "GPIO32"), gpio32), + SKY_PINFUNCTION(PINCTRL_PIN(50, "GPIO33"), gpio33), + SKY_PINFUNCTION(PINCTRL_PIN(51, "GPIO34"), gpio34), + SKY_PINFUNCTION(PINCTRL_PIN(52, "GPIO35"), gpio35), + SKY_PINFUNCTION(PINCTRL_PIN(53, "GPIO36"), gpio36), + SKY_PINFUNCTION(PINCTRL_PIN(54, "GPIO37"), gpio37), + SKY_PINFUNCTION(PINCTRL_PIN(55, "GPIO38"), gpio38), + SKY_PINFUNCTION(PINCTRL_PIN(56, "GPIO39"), gpio39), + SKY_PINFUNCTION(PINCTRL_PIN(57, "GPIO40"), gpio40), + SKY_PINFUNCTION(PINCTRL_PIN(58, "GPIO41"), gpio41), + SKY_PINFUNCTION(PINCTRL_PIN(59, "GPIO42"), gpio42), + SKY_PINFUNCTION(PINCTRL_PIN(60, "SE_QSPI_CLK"), se_qspi_clk), + SKY_PINFUNCTION(PINCTRL_PIN(61, "SE_QSPI_CS_L"), se_qspi_cs), + SKY_PINFUNCTION(PINCTRL_PIN(62, "SE_QSPI_DATA0"), se_qspi_data0), + SKY_PINFUNCTION(PINCTRL_PIN(63, "SE_QSPI_DATA1"), se_qspi_data1), + SKY_PINFUNCTION(PINCTRL_PIN(64, "SE_QSPI_DATA2"), se_qspi_data2), + SKY_PINFUNCTION(PINCTRL_PIN(65, "SE_QSPI_DATA3"), se_qspi_data3), +}; + +/* Pad names for the s0 domain pinmux subsystem */ +static const char * const gpio43_group[] = {"GPIO43"}; +static const char * const gpio44_group[] = {"GPIO44"}; +static const char * const gpio45_group[] = {"GPIO45"}; +static const char * const gpio46_group[] = {"GPIO46"}; +static const char * const reset_in_group[] = { }; +static const char * const plt_reset_group[] = { }; +static const char * const thermtrip_group[] = { }; +static const char * const prochot_group[] = { }; +static const char * const pm_i2c0_clk_group[] = { }; +static const char * const pm_i2c0_data_group[] = { }; +static const char * const pm_i2c1_clk_group[] = { }; +static const char * const pm_i2c1_data_group[] = { }; +static const char * const pm_i2c2_clk_group[] = { }; +static const char * const pm_i2c2_data_group[] = { }; +static const char * const pm_i2c3_clk_group[] = { }; +static const char * const pm_i2c3_data_group[] = { }; +static const char * const strap0_group[] = { }; +static const char * const strap1_group[] = { }; +static const char * const dp2_digon_group[] = {"DP2_DIGON"}; +static const char * const dp2_blon_group[] = {"DP2_BLON"}; +static const char * const dp2_vary_bl_group[] = {"DP2_VARY_BL"}; +static const char * const i2c7_scl_group[] = {"I2C7_SCL"}; +static const char * const i2c7_sda_group[] = {"I2C7_SDA"}; +static const char * const uart6_csu_se_txd_group[] = { }; +static const char * const clk_req1_group[] = { }; +static const char * const clk_req3_group[] = { }; +static const char * const i2c5_scl_group[] = {"I2C5_SCL", "GPIO47"}; +static const char * const i2c5_sda_group[] = {"I2C5_SDA", "GPIO48"}; +static const char * const i2c6_scl_group[] = {"I2C6_SCL", "GPIO49"}; +static const char * const i2c6_sda_group[] = {"I2C6_SDA", "GPIO50"}; +static const char * const i2c0_scl_group[] = {"I2C0_SCL", "GPIO51"}; +static const char * const i2c0_sda_group[] = {"I2C0_SDA", "GPIO52"}; +static const char * const i2c1_scl_group[] = {"I2C1_SCL", "GPIO53"}; +static const char * const i2c1_sda_group[] = {"I2C1_SDA", "GPIO54"}; +static const char * const i2c2_scl_group[] = {"I2C2_SCL", "I3C0_SCL", + "GPIO55"}; +static const char * const i2c2_sda_group[] = {"I2C2_SDA", "I3C0_SDA", + "GPIO56"}; +static const char * const gpio57_group[] = {"GPIO57", "I3C0_PUR_EN_L"}; +static const char * const i2c3_scl_group[] = {"I2C3_SCL", "I3C1_SCL", + "GPIO58"}; +static const char * const i2c3_sda_group[] = {"I2C3_SDA", "I3C1_SDA", + "GPIO59"}; +static const char * const gpio60_group[] = {"GPIO60", "I3C1_PUR_EN_L"}; +static const char * const i2c4_scl_group[] = {"I2C4_SCL", "GPIO61"}; +static const char * const i2c4_sda_group[] = {"I2C4_SDA", "GPIO62"}; +static const char * const hda_bitclk_group[] = {"HDA_BITCLK", "I2S0_SCK", + "I2S9_RSCK_DBG"}; +static const char * const hda_rst_group[] = {"HDA_RST_L", "I2S0_DATA_IN", + "I2S9_DATA_IN_DBG"}; +static const char * const hda_sdin0_group[] = {"HDA_SDIN0", "I2S0_MCLK", + "I2S9_TSCK_DBG"}; +static const char * const hda_sdout0_group[] = {"HDA_SDOUT0", "I2S0_DATA_OUT", + "I2S9_TWS_DBG"}; +static const char * const hda_sync_group[] = {"HDA_SYNC", "I2S0_WS", + "I2S9_RWS_DBG"}; +static const char * const hda_sdin1_group[] = {"HDA_SDIN1", "GPIO63", + "I2S9_DATA_IN1_DBG"}; +static const char * const hda_sdout1_group[] = {"HDA_SDOUT1", "GPIO64", + "I2S9_DATA_OUT0_DBG"}; +static const char * const i2s1_mclk_group[] = {"I2S1_MCLK", "GPIO65"}; +static const char * const i2s1_sck_group[] = {"I2S1_SCK", "GPIO66"}; +static const char * const i2s1_ws_group[] = {"I2S1_WS", "GPIO67"}; +static const char * const i2s1_data_in_group[] = {"I2S1_DATA_IN", "GPIO68"}; +static const char * const i2s1_data_out_group[] = {"I2S1_DATA_OUT", "GPIO69"}; +static const char * const i2s2_mck_group[] = {"I2S2_MCLK", "GPIO70"}; +static const char * const i2s2_rsck_group[] = {"I2S2_RSCK", "GPIO71", + "I2S5_RSCK_DBG", "I2S6_RSCK_DBG"}; +static const char * const i2s2_rws_group[] = {"I2S2_RWS", "GPIO72", + "I2S5_RWS_DBG", "I2S6_RWS_DBG"}; +static const char * const i2s2_tsck_group[] = {"I2S2_TSCK", "GPIO73", + "I2S5_TSCK_DBG", "I2S6_TSCK_DBG"}; +static const char * const i2s2_tws_group[] = {"I2S2_TWS", "GPIO74", + "I2S5_TWS_DBG", "I2S6_TWS_DBG"}; +static const char * const i2s2_data_in0_group[] = {"I2S2_DATA_IN0", "GPIO75", + "I2S5_DATA_IN0_DBG", "I2S6_DATA_IN0_DBG"}; +static const char * const i2s2_data_in1_group[] = {"I2S2_DATA_IN1", "GPIO76", + "I2S5_DATA_IN1_DBG", "I2S6_DATA_IN1_DBG"}; +static const char * const i2s2_data_out0_group[] = {"I2S2_DATA_OUT0", "GPIO77", + "I2S5_DATA_OUT0_DBG", "I2S6_DATA_OUT0_DBG"}; +static const char * const i2s2_data_out1_group[] = {"I2S2_DATA_OUT1", "GPIO78", + "I2S5_DATA_OUT1_DBG", "I2S6_DATA_OUT1_DBG"}; +static const char * const i2s2_data_out2_group[] = {"I2S2_DATA_OUT2", + "GPIO79"}; +static const char * const i2s2_data_out3_group[] = {"I2S2_DATA_OUT3", "GPIO80", + "I2S9_DATA_OUT1_DBG"}; +static const char * const i2s3_mclk_group[] = {"I2S3_MCLK", "GPIO81"}; +static const char * const i2s3_rsck_group[] = {"I2S3_RSCK", "GPIO82", + "I2S7_RSCK_DBG", "I2S8_RSCK_DBG"}; +static const char * const i2s3_rws_group[] = {"I2S3_RWS", "GPIO83", + "I2S7_RWS_DBG", "I2S8_RWS_DBG"}; +static const char * const i2s3_tsck_group[] = {"I2S3_TSCK", "GPIO84", + "I2S7_TSCK_DBG", "I2S8_TSCK_DBG"}; +static const char * const i2s3_tws_group[] = {"I2S3_TWS", "GPIO85", + "I2S7_TWS_DBG", "I2S8_TWS_DBG"}; +static const char * const i2s3_data_in0_group[] = {"I2S3_DATA_IN0", "GPIO86", + "I2S7_DATA_IN0_DBG", "I2S8_DATA_IN0_DBG"}; +static const char * const i2s3_data_in1_group[] = {"I2S3_DATA_IN1", "GPIO87", + "I2S7_DATA_IN1_DBG", "I2S8_DATA_IN1_DBG"}; +static const char * const i2s3_data_out0_group[] = {"I2S3_DATA_OUT0", "GPIO88", + "I2S7_DATA_OUT0_DBG", "I2S8_DATA_OUT0_DBG"}; +static const char * const i2s3_data_out1_group[] = {"I2S3_DATA_OUT1", "GPIO89", + "I2S7_DATA_OUT1_DBG", "I2S8_DATA_OUT1_DBG"}; +static const char * const gpio90_group[] = {"GPIO90", "I2S4_MCLK_LB"}; +static const char * const gpio91_group[] = {"GPIO91", "I2S4_SCK_LB"}; +static const char * const gpio92_group[] = {"GPIO92", "I2S4_WS_LB"}; +static const char * const gpio93_group[] = {"GPIO93", "I2S4_DATA_IN_LB"}; +static const char * const gpio94_group[] = {"GPIO94", "I2S4_DATA_OUT_LB"}; +static const char * const uart0_txd_group[] = {"UART0_TXD", "PWM0", "GPIO95"}; +static const char * const uart0_rxd_group[] = {"UART0_RXD", "PWM1", "GPIO96"}; +static const char * const uart0_cts_group[] = {"UART0_CTS", "FAN_OUT2", + "GPIO97"}; +static const char * const uart0_rts_group[] = {"UART0_RTS", "FAN_TACH2", + "GPIO98"}; +static const char * const uart1_txd_group[] = {"UART1_TXD", "FAN_OUT0", + "GPIO99"}; +static const char * const uart1_rxd_group[] = {"UART1_RXD", "FAN_TACH0", + "GPIO100"}; +static const char * const uart1_cts_group[] = {"UART1_CTS", "FAN_OUT1", + "GPIO101"}; +static const char * const uart1_rts_group[] = {"UART1_RTS", "FAN_TACH1", + "GPIO102"}; +static const char * const uart2_txd_group[] = {"UART2_TXD", "GPIO103"}; +static const char * const uart2_rxd_group[] = {"UART2_RXD", "GPIO104"}; +static const char * const uart3_txd_group[] = {"UART3_TXD", "GPIO105"}; +static const char * const uart3_rxd_group[] = {"UART3_RXD", "GPIO106"}; +static const char * const uart3_cts_group[] = {"UART3_CTS", "GPIO107", + "TRIGIN0"}; +static const char * const uart3_rts_group[] = {"UART3_RTS", "GPIO108", + "TRIGIN1"}; +static const char * const uart4_csu_pm_txd_group[] = {"UART4_CSU_PM_TXD", + "GPIO109"}; +static const char * const uart4_csu_pm_rxd_group[] = {"UART4_CSU_PM_RXD", + "GPIO110"}; +static const char * const uart5_csu_se_txd_group[] = {"UART5_CSU_SE_TXD", + "GPIO111"}; +static const char * const uart5_csu_se_rxd_group[] = {"UART5_CSU_SE_RXD", + "GPIO112"}; +static const char * const uart6_csu_se_rxd_group[] = {"UART6_CSU_SE_RXD", + "GPIO113"}; +static const char * const clk_req0_group[] = {"CLK_REQ0_L", "GPIO114"}; +static const char * const clk_req2_group[] = {"CLK_REQ2_L", "GPIO115"}; +static const char * const clk_req4_group[] = {"CLK_REQ4_L", "GPIO116"}; +static const char * const csi0_mclk0_group[] = {"CSI0_MCLK0", "GPIO117"}; +static const char * const csi0_mclk1_group[] = {"CSI0_MCLK1", "GPIO118"}; +static const char * const csi1_mclk0_group[] = {"CSI1_MCLK0", "GPIO119"}; +static const char * const csi1_mclk1_group[] = {"CSI1_MCLK1", "GPIO120"}; +static const char * const gpio121_group[] = {"GPIO121", "GMAC0_REFCLK_25M"}; +static const char * const gpio122_group[] = {"GPIO122", "GMAC0_TX_CTL"}; +static const char * const gpio123_group[] = {"GPIO123", "GMAC0_TXD0"}; +static const char * const gpio124_group[] = {"GPIO124", "GMAC0_TXD1"}; +static const char * const gpio125_group[] = {"GPIO125", "GMAC0_TXD2"}; +static const char * const gpio126_group[] = {"GPIO126", "GMAC0_TXD3"}; +static const char * const gpio127_group[] = {"GPIO127", "GMAC0_TX_CLK"}; +static const char * const gpio128_group[] = {"GPIO128", "GMAC0_RX_CTL"}; +static const char * const gpio129_group[] = {"GPIO129", "GMAC0_RXD0"}; +static const char * const gpio130_group[] = {"GPIO130", "GMAC0_RXD1"}; +static const char * const gpio131_group[] = {"GPIO131", "GMAC0_RXD2"}; +static const char * const gpio132_group[] = {"GPIO132", "GMAC0_RXD3"}; +static const char * const gpio133_group[] = {"GPIO133", "GMAC0_RX_CLK"}; +static const char * const gpio134_group[] = {"GPIO134", "GMAC0_MDC"}; +static const char * const gpio135_group[] = {"GPIO135", "GMAC0_MDIO"}; +static const char * const gpio136_group[] = {"GPIO136", "GMAC1_REFCLK_25M"}; +static const char * const gpio137_group[] = {"GPIO137", "GMAC1_TX_CTL"}; +static const char * const gpio138_group[] = {"GPIO138", "GMAC1_TXD0", + "SPI2_MISO"}; +static const char * const gpio139_group[] = {"GPIO139", "GMAC1_TXD1", + "SPI2_CS0"}; +static const char * const gpio140_group[] = {"GPIO140", "GMAC1_TXD2", + "SPI2_CS1"}; +static const char * const gpio141_group[] = {"GPIO141", "GMAC1_TXD3", + "SPI2_MOSI"}; +static const char * const gpio142_group[] = {"GPIO142", "GMAC1_TX_CLK", + "SPI2_CLK"}; +static const char * const gpio143_group[] = {"GPIO143", "GMAC1_RX_CTL"}; +static const char * const gpio144_group[] = {"GPIO144", "GMAC1_RXD0"}; +static const char * const gpio145_group[] = {"GPIO145", "GMAC1_RXD1"}; +static const char * const gpio146_group[] = {"GPIO146", "GMAC1_RXD2"}; +static const char * const gpio147_group[] = {"GPIO147", "GMAC1_RXD3"}; +static const char * const gpio148_group[] = {"GPIO148", "GMAC1_RX_CLK"}; +static const char * const gpio149_group[] = {"GPIO149", "GMAC1_MDC"}; +static const char * const gpio150_group[] = {"GPIO150", "GMAC1_MDIO"}; +static const char * const gpio151_group[] = {"GPIO151", "PM_GPIO0"}; +static const char * const gpio152_group[] = {"GPIO152", "PM_GPIO1"}; +static const char * const gpio153_group[] = {"GPIO153", "PM_GPIO2"}; +static const struct sky1_pin_desc sky1_pinctrl_pads[] = { + SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO43"), gpio43), + SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO44"), gpio44), + SKY_PINFUNCTION(PINCTRL_PIN(2, "GPIO45"), gpio45), + SKY_PINFUNCTION(PINCTRL_PIN(3, "GPIO46"), gpio46), + SKY_PINFUNCTION(PINCTRL_PIN(4, "RESET_IN_L"), reset_in), + SKY_PINFUNCTION(PINCTRL_PIN(5, "PLT_RESET_L"), plt_reset), + SKY_PINFUNCTION(PINCTRL_PIN(6, "THERMTRIP_L"), thermtrip), + SKY_PINFUNCTION(PINCTRL_PIN(7, "PROCHOT_L"), prochot), + SKY_PINFUNCTION(PINCTRL_PIN(8, "PM_I2C0_CLK"), pm_i2c0_clk), + SKY_PINFUNCTION(PINCTRL_PIN(9, "PM_I2C0_DATA"), pm_i2c0_data), + SKY_PINFUNCTION(PINCTRL_PIN(10, "PM_I2C1_CLK"), pm_i2c1_clk), + SKY_PINFUNCTION(PINCTRL_PIN(11, "PM_I2C1_DATA"), pm_i2c1_data), + SKY_PINFUNCTION(PINCTRL_PIN(12, "PM_I2C2_CLK"), pm_i2c2_clk), + SKY_PINFUNCTION(PINCTRL_PIN(13, "PM_I2C2_DATA"), pm_i2c2_data), + SKY_PINFUNCTION(PINCTRL_PIN(14, "PM_I2C3_CLK"), pm_i2c3_clk), + SKY_PINFUNCTION(PINCTRL_PIN(15, "PM_I2C3_DATA"), pm_i2c3_data), + SKY_PINFUNCTION(PINCTRL_PIN(16, "STRAP0"), strap0), + SKY_PINFUNCTION(PINCTRL_PIN(17, "STRAP1"), strap1), + SKY_PINFUNCTION(PINCTRL_PIN(18, "DP2_DIGON"), dp2_digon), + SKY_PINFUNCTION(PINCTRL_PIN(19, "DP2_BLON"), dp2_blon), + SKY_PINFUNCTION(PINCTRL_PIN(20, "DP2_VARY_BL"), dp2_vary_bl), + SKY_PINFUNCTION(PINCTRL_PIN(21, "I2C7_SCL"), i2c7_scl), + SKY_PINFUNCTION(PINCTRL_PIN(22, "I2C7_SDA"), i2c7_sda), + SKY_PINFUNCTION(PINCTRL_PIN(23, "UART6_CSU_SE_TXD"), uart6_csu_se_txd), + SKY_PINFUNCTION(PINCTRL_PIN(24, "CLK_REQ1_L"), clk_req1), + SKY_PINFUNCTION(PINCTRL_PIN(25, "CLK_REQ3_L"), clk_req3), + SKY_PINFUNCTION(PINCTRL_PIN(26, "I2C5_SCL"), i2c5_scl), + SKY_PINFUNCTION(PINCTRL_PIN(27, "I2C5_SDA"), i2c5_sda), + SKY_PINFUNCTION(PINCTRL_PIN(28, "I2C6_SCL"), i2c6_scl), + SKY_PINFUNCTION(PINCTRL_PIN(29, "I2C6_SDA"), i2c6_sda), + SKY_PINFUNCTION(PINCTRL_PIN(30, "I2C0_CLK"), i2c0_scl), + SKY_PINFUNCTION(PINCTRL_PIN(31, "I2C0_SDA"), i2c0_sda), + SKY_PINFUNCTION(PINCTRL_PIN(32, "I2C1_CLK"), i2c1_scl), + SKY_PINFUNCTION(PINCTRL_PIN(33, "I2C1_SDA"), i2c1_sda), + SKY_PINFUNCTION(PINCTRL_PIN(34, "I2C2_SCL"), i2c2_scl), + SKY_PINFUNCTION(PINCTRL_PIN(35, "I2C2_SDA"), i2c2_sda), + SKY_PINFUNCTION(PINCTRL_PIN(36, "GPIO57"), gpio57), + SKY_PINFUNCTION(PINCTRL_PIN(37, "I2C3_SCL"), i2c3_scl), + SKY_PINFUNCTION(PINCTRL_PIN(38, "I2C3_SDA"), i2c3_sda), + SKY_PINFUNCTION(PINCTRL_PIN(39, "GPIO60"), gpio60), + SKY_PINFUNCTION(PINCTRL_PIN(40, "I2C4_SCL"), i2c4_scl), + SKY_PINFUNCTION(PINCTRL_PIN(41, "I2C4_SDA"), i2c4_sda), + SKY_PINFUNCTION(PINCTRL_PIN(42, "HDA_BITCLK"), hda_bitclk), + SKY_PINFUNCTION(PINCTRL_PIN(43, "HDA_RST_L"), hda_rst), + SKY_PINFUNCTION(PINCTRL_PIN(44, "HDA_SDIN0"), hda_sdin0), + SKY_PINFUNCTION(PINCTRL_PIN(45, "HDA_SDOUT0"), hda_sdout0), + SKY_PINFUNCTION(PINCTRL_PIN(46, "HDA_SYNC"), hda_sync), + SKY_PINFUNCTION(PINCTRL_PIN(47, "HDA_SDIN1"), hda_sdin1), + SKY_PINFUNCTION(PINCTRL_PIN(48, "HDA_SDOUT1"), hda_sdout1), + SKY_PINFUNCTION(PINCTRL_PIN(49, "I2S1_MCLK"), i2s1_mclk), + SKY_PINFUNCTION(PINCTRL_PIN(50, "I2S1_SCK"), i2s1_sck), + SKY_PINFUNCTION(PINCTRL_PIN(51, "I2S1_WS"), i2s1_ws), + SKY_PINFUNCTION(PINCTRL_PIN(52, "I2S1_DATA_IN"), i2s1_data_in), + SKY_PINFUNCTION(PINCTRL_PIN(53, "I2S1_DATA_OUT"), i2s1_data_out), + SKY_PINFUNCTION(PINCTRL_PIN(54, "I2S2_MCLK"), i2s2_mck), + SKY_PINFUNCTION(PINCTRL_PIN(55, "I2S2_RSCK"), i2s2_rsck), + SKY_PINFUNCTION(PINCTRL_PIN(56, "I2S2_RWS"), i2s2_rws), + SKY_PINFUNCTION(PINCTRL_PIN(57, "I2S2_TSCK"), i2s2_tsck), + SKY_PINFUNCTION(PINCTRL_PIN(58, "I2S2_TWS"), i2s2_tws), + SKY_PINFUNCTION(PINCTRL_PIN(59, "I2S2_DATA_IN0"), i2s2_data_in0), + SKY_PINFUNCTION(PINCTRL_PIN(60, "I2S2_DATA_IN1"), i2s2_data_in1), + SKY_PINFUNCTION(PINCTRL_PIN(61, "I2S2_DATA_OUT0"), i2s2_data_out0), + SKY_PINFUNCTION(PINCTRL_PIN(62, "I2S2_DATA_OUT1"), i2s2_data_out1), + SKY_PINFUNCTION(PINCTRL_PIN(63, "I2S2_DATA_OUT2"), i2s2_data_out2), + SKY_PINFUNCTION(PINCTRL_PIN(64, "I2S2_DATA_OUT3"), i2s2_data_out3), + SKY_PINFUNCTION(PINCTRL_PIN(65, "I2S3_MCLK"), i2s3_mclk), + SKY_PINFUNCTION(PINCTRL_PIN(66, "I2S3_RSCK"), i2s3_rsck), + SKY_PINFUNCTION(PINCTRL_PIN(67, "I2S3_RWS"), i2s3_rws), + SKY_PINFUNCTION(PINCTRL_PIN(68, "I2S3_TSCK"), i2s3_tsck), + SKY_PINFUNCTION(PINCTRL_PIN(69, "I2S3_TWS"), i2s3_tws), + SKY_PINFUNCTION(PINCTRL_PIN(70, "I2S3_DATA_IN0"), i2s3_data_in0), + SKY_PINFUNCTION(PINCTRL_PIN(71, "I2S3_DATA_IN1"), i2s3_data_in1), + SKY_PINFUNCTION(PINCTRL_PIN(72, "I2S3_DATA_OUT0"), i2s3_data_out0), + SKY_PINFUNCTION(PINCTRL_PIN(73, "I2S3_DATA_OUT1"), i2s3_data_out1), + SKY_PINFUNCTION(PINCTRL_PIN(74, "GPIO90"), gpio90), + SKY_PINFUNCTION(PINCTRL_PIN(75, "GPIO91"), gpio91), + SKY_PINFUNCTION(PINCTRL_PIN(76, "GPIO92"), gpio92), + SKY_PINFUNCTION(PINCTRL_PIN(77, "GPIO93"), gpio93), + SKY_PINFUNCTION(PINCTRL_PIN(78, "GPIO94"), gpio94), + SKY_PINFUNCTION(PINCTRL_PIN(79, "UART0_TXD"), uart0_txd), + SKY_PINFUNCTION(PINCTRL_PIN(80, "UART0_RXD"), uart0_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(81, "UART0_CTS"), uart0_cts), + SKY_PINFUNCTION(PINCTRL_PIN(82, "UART0_RTS"), uart0_rts), + SKY_PINFUNCTION(PINCTRL_PIN(83, "UART1_TXD"), uart1_txd), + SKY_PINFUNCTION(PINCTRL_PIN(84, "UART1_RXD"), uart1_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(85, "UART1_CTS"), uart1_cts), + SKY_PINFUNCTION(PINCTRL_PIN(86, "UART1_RTS"), uart1_rts), + SKY_PINFUNCTION(PINCTRL_PIN(87, "UART2_TXD"), uart2_txd), + SKY_PINFUNCTION(PINCTRL_PIN(88, "UART2_RXD"), uart2_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(89, "UART3_TXD"), uart3_txd), + SKY_PINFUNCTION(PINCTRL_PIN(90, "UART3_RXD"), uart3_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(91, "UART3_CTS"), uart3_cts), + SKY_PINFUNCTION(PINCTRL_PIN(92, "UART3_RTS"), uart3_rts), + SKY_PINFUNCTION(PINCTRL_PIN(93, "UART4_CSU_PM_TXD"), uart4_csu_pm_txd), + SKY_PINFUNCTION(PINCTRL_PIN(94, "UART4_CSU_PM_RXD"), uart4_csu_pm_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(95, "UART5_CSU_SE_TXD"), uart5_csu_se_txd), + SKY_PINFUNCTION(PINCTRL_PIN(96, "UART5_CSU_SE_RXD"), uart5_csu_se_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(97, "UART6_CSU_SE_RXD"), uart6_csu_se_rxd), + SKY_PINFUNCTION(PINCTRL_PIN(98, "CLK_REQ0_L"), clk_req0), + SKY_PINFUNCTION(PINCTRL_PIN(99, "CLK_REQ2_L"), clk_req2), + SKY_PINFUNCTION(PINCTRL_PIN(100, "CLK_REQ4_L"), clk_req4), + SKY_PINFUNCTION(PINCTRL_PIN(101, "CSI0_MCLK0"), csi0_mclk0), + SKY_PINFUNCTION(PINCTRL_PIN(102, "CSI0_MCLK1"), csi0_mclk1), + SKY_PINFUNCTION(PINCTRL_PIN(103, "CSI1_MCLK0"), csi1_mclk0), + SKY_PINFUNCTION(PINCTRL_PIN(104, "CSI1_MCLK1"), csi1_mclk1), + SKY_PINFUNCTION(PINCTRL_PIN(105, "GPIO121"), gpio121), + SKY_PINFUNCTION(PINCTRL_PIN(106, "GPIO122"), gpio122), + SKY_PINFUNCTION(PINCTRL_PIN(107, "GPIO123"), gpio123), + SKY_PINFUNCTION(PINCTRL_PIN(108, "GPIO124"), gpio124), + SKY_PINFUNCTION(PINCTRL_PIN(109, "GPIO125"), gpio125), + SKY_PINFUNCTION(PINCTRL_PIN(110, "GPIO126"), gpio126), + SKY_PINFUNCTION(PINCTRL_PIN(111, "GPIO127"), gpio127), + SKY_PINFUNCTION(PINCTRL_PIN(112, "GPIO128"), gpio128), + SKY_PINFUNCTION(PINCTRL_PIN(113, "GPIO129"), gpio129), + SKY_PINFUNCTION(PINCTRL_PIN(114, "GPIO130"), gpio130), + SKY_PINFUNCTION(PINCTRL_PIN(115, "GPIO131"), gpio131), + SKY_PINFUNCTION(PINCTRL_PIN(116, "GPIO132"), gpio132), + SKY_PINFUNCTION(PINCTRL_PIN(117, "GPIO133"), gpio133), + SKY_PINFUNCTION(PINCTRL_PIN(118, "GPIO134"), gpio134), + SKY_PINFUNCTION(PINCTRL_PIN(119, "GPIO135"), gpio135), + SKY_PINFUNCTION(PINCTRL_PIN(120, "GPIO136"), gpio136), + SKY_PINFUNCTION(PINCTRL_PIN(121, "GPIO137"), gpio137), + SKY_PINFUNCTION(PINCTRL_PIN(122, "GPIO138"), gpio138), + SKY_PINFUNCTION(PINCTRL_PIN(123, "GPIO139"), gpio139), + SKY_PINFUNCTION(PINCTRL_PIN(124, "GPIO140"), gpio140), + SKY_PINFUNCTION(PINCTRL_PIN(125, "GPIO141"), gpio141), + SKY_PINFUNCTION(PINCTRL_PIN(126, "GPIO142"), gpio142), + SKY_PINFUNCTION(PINCTRL_PIN(127, "GPIO143"), gpio143), + SKY_PINFUNCTION(PINCTRL_PIN(128, "GPIO144"), gpio144), + SKY_PINFUNCTION(PINCTRL_PIN(129, "GPIO145"), gpio145), + SKY_PINFUNCTION(PINCTRL_PIN(130, "GPIO146"), gpio146), + SKY_PINFUNCTION(PINCTRL_PIN(131, "GPIO147"), gpio147), + SKY_PINFUNCTION(PINCTRL_PIN(132, "GPIO148"), gpio148), + SKY_PINFUNCTION(PINCTRL_PIN(133, "GPIO149"), gpio149), + SKY_PINFUNCTION(PINCTRL_PIN(134, "GPIO150"), gpio150), + SKY_PINFUNCTION(PINCTRL_PIN(135, "GPIO151"), gpio151), + SKY_PINFUNCTION(PINCTRL_PIN(136, "GPIO152"), gpio152), + SKY_PINFUNCTION(PINCTRL_PIN(137, "GPIO153"), gpio153), +}; + +static const struct sky1_pinctrl_soc_info sky1_pinctrl_s5_info = { + .pins = sky1_pinctrl_s5_pads, + .npins = ARRAY_SIZE(sky1_pinctrl_s5_pads), +}; + +static const struct sky1_pinctrl_soc_info sky1_pinctrl_info = { + .pins = sky1_pinctrl_pads, + .npins = ARRAY_SIZE(sky1_pinctrl_pads), +}; + +static const struct of_device_id sky1_pinctrl_of_match[] = { + { .compatible = "cix,sky1-pinctrl-s5", .data = &sky1_pinctrl_s5_info, }, + { .compatible = "cix,sky1-pinctrl", .data = &sky1_pinctrl_info, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sky1_pinctrl_of_match); + +static int __maybe_unused sky1_pinctrl_suspend(struct device *dev) +{ + struct sky1_pinctrl *spctl = dev_get_drvdata(dev); + + return pinctrl_force_sleep(spctl->pctl); +} + +static int __maybe_unused sky1_pinctrl_resume(struct device *dev) +{ + struct sky1_pinctrl *spctl = dev_get_drvdata(dev); + + return pinctrl_force_default(spctl->pctl); +} + +const struct dev_pm_ops sky1_pinctrl_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(sky1_pinctrl_suspend, + sky1_pinctrl_resume) +}; +EXPORT_SYMBOL_GPL(sky1_pinctrl_pm_ops); + +static int sky1_pinctrl_probe(struct platform_device *pdev) +{ + const struct sky1_pinctrl_soc_info *pinctrl_info; + + pinctrl_info = device_get_match_data(&pdev->dev); + if (!pinctrl_info) + return -ENODEV; + + return sky1_base_pinctrl_probe(pdev, pinctrl_info); +} + +static struct platform_driver sky1_pinctrl_driver = { + .driver = { + .name = "sky1-pinctrl", + .of_match_table = sky1_pinctrl_of_match, + .pm = &sky1_pinctrl_pm_ops, + }, + .probe = sky1_pinctrl_probe, +}; + +static int __init sky1_pinctrl_init(void) +{ + return platform_driver_register(&sky1_pinctrl_driver); +} +arch_initcall(sky1_pinctrl_init); + +MODULE_AUTHOR("Jerry Zhu "); +MODULE_DESCRIPTION("Cix Sky1 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/cix/pinctrl-sky1.h b/drivers/pinctrl/cix/pinctrl-sky1.h new file mode 100644 index 00000000000000..a8b09985296513 --- /dev/null +++ b/drivers/pinctrl/cix/pinctrl-sky1.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Author: Jerry Zhu + */ + +#ifndef __DRIVERS_PINCTRL_SKY1_H +#define __DRIVERS_PINCTRL_SKY1_H + +struct sky1_pinctrl_group { + const char *name; + unsigned long config; + unsigned int pin; +}; + +struct sky1_pin_desc { + const struct pinctrl_pin_desc pin; + const char * const *func_group; + unsigned int nfunc; +}; + +struct sky1_pinctrl_soc_info { + const struct sky1_pin_desc *pins; + unsigned int npins; +}; + +#define SKY_PINFUNCTION(_pin, _func) \ +((struct sky1_pin_desc) { \ + .pin = _pin, \ + .func_group = _func##_group, \ + .nfunc = ARRAY_SIZE(_func##_group), \ + }) +/** + * @dev: a pointer back to containing device + * @base: the offset to the controller in virtual memory + */ +struct sky1_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl; + void __iomem *base; + const struct sky1_pinctrl_soc_info *info; + struct sky1_pinctrl_group *groups; + const char **grp_names; +}; + +int sky1_base_pinctrl_probe(struct platform_device *pdev, + const struct sky1_pinctrl_soc_info *info); + +#endif /* __DRIVERS_PINCTRL_SKY1_H */ From 4a6cc9655fcc46690de5c517c9a6dbbed1a7932e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:49 +0200 Subject: [PATCH 169/684] pinctrl: pinconf-generic: Fix minor typos in comments s/specyfying/specifying/ s/propertity/property/ Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf-generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 5de6ff62c69bdb..e3d10bbcdaebc4 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -104,7 +104,7 @@ static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev, * @pctldev: Pincontrol device * @s: File to print to * @gname: Group name specifying pins - * @pin: Pin number specyfying pin + * @pin: Pin number specifying pin * * Print the pinconf configuration for the requested pin(s) to @s. Pins can be * specified either by pin using @pin or by group using @gname. Only one needs @@ -242,7 +242,7 @@ static void parse_dt_cfg(struct device_node *np, * @pmux: array with pin mux value entries * @npins: number of pins * - * pinmux propertity: mux value [0,7]bits and pin identity [8,31]bits. + * pinmux property: mux value [0,7]bits and pin identity [8,31]bits. */ int pinconf_generic_parse_dt_pinmux(struct device_node *np, struct device *dev, unsigned int **pid, unsigned int **pmux, From 90a18c512884adb49ddc2fb30e94594169aae808 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:50 +0200 Subject: [PATCH 170/684] pinctrl: pinconf-generic: Handle string values for generic properties Allow a generic pinconf property to specify its argument as one of the strings in a match list. Convert the matching string to an integer value using the index in the list, then keep using this value in the generic pinconf code. Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf-generic.c | 57 ++++++++++++++++++------- include/linux/pinctrl/pinconf-generic.h | 11 ++++- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index e3d10bbcdaebc4..72906d71ae1a2e 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -65,11 +65,12 @@ static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev, int i; for (i = 0; i < nitems; i++) { + const struct pin_config_item *item = &items[i]; unsigned long config; int ret; /* We want to check out this parameter */ - config = pinconf_to_config_packed(items[i].param, 0); + config = pinconf_to_config_packed(item->param, 0); if (gname) ret = pin_config_group_get(dev_name(pctldev->dev), gname, &config); @@ -86,15 +87,22 @@ static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev, if (*print_sep) seq_puts(s, ", "); *print_sep = 1; - seq_puts(s, items[i].display); + seq_puts(s, item->display); /* Print unit if available */ - if (items[i].has_arg) { + if (item->has_arg) { u32 val = pinconf_to_config_argument(config); - if (items[i].format) - seq_printf(s, " (%u %s)", val, items[i].format); + if (item->format) + seq_printf(s, " (%u %s)", val, item->format); else seq_printf(s, " (0x%x)", val); + + if (item->values && item->num_values) { + if (val < item->num_values) + seq_printf(s, " \"%s\"", item->values[val]); + else + seq_puts(s, " \"(unknown)\""); + } } } } @@ -205,10 +213,10 @@ static const struct pinconf_generic_params dt_params[] = { * @ncfg. @ncfg is updated to reflect the number of entries after parsing. @cfg * needs to have enough memory allocated to hold all possible entries. */ -static void parse_dt_cfg(struct device_node *np, - const struct pinconf_generic_params *params, - unsigned int count, unsigned long *cfg, - unsigned int *ncfg) +static int parse_dt_cfg(struct device_node *np, + const struct pinconf_generic_params *params, + unsigned int count, unsigned long *cfg, + unsigned int *ncfg) { int i; @@ -217,7 +225,19 @@ static void parse_dt_cfg(struct device_node *np, int ret; const struct pinconf_generic_params *par = ¶ms[i]; - ret = of_property_read_u32(np, par->property, &val); + if (par->values && par->num_values) { + ret = fwnode_property_match_property_string(of_fwnode_handle(np), + par->property, + par->values, par->num_values); + if (ret == -ENOENT) + return ret; + if (ret >= 0) { + val = ret; + ret = 0; + } + } else { + ret = of_property_read_u32(np, par->property, &val); + } /* property not found */ if (ret == -EINVAL) @@ -231,6 +251,8 @@ static void parse_dt_cfg(struct device_node *np, cfg[*ncfg] = pinconf_to_config_packed(par->param, val); (*ncfg)++; } + + return 0; } /** @@ -323,13 +345,16 @@ int pinconf_generic_parse_dt_config(struct device_node *np, if (!cfg) return -ENOMEM; - parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg); + ret = parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg); + if (ret) + return ret; if (pctldev && pctldev->desc->num_custom_params && - pctldev->desc->custom_params) - parse_dt_cfg(np, pctldev->desc->custom_params, - pctldev->desc->num_custom_params, cfg, &ncfg); - - ret = 0; + pctldev->desc->custom_params) { + ret = parse_dt_cfg(np, pctldev->desc->custom_params, + pctldev->desc->num_custom_params, cfg, &ncfg); + if (ret) + return ret; + } /* no configs found at all */ if (ncfg == 0) { diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index d9245ecec71dc6..f82add5d3302de 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -181,21 +181,28 @@ static inline unsigned long pinconf_to_config_packed(enum pin_config_param param return PIN_CONF_PACKED(param, argument); } -#define PCONFDUMP(a, b, c, d) { \ - .param = a, .display = b, .format = c, .has_arg = d \ +#define PCONFDUMP_WITH_VALUES(a, b, c, d, e, f) { \ + .param = a, .display = b, .format = c, .has_arg = d, \ + .values = e, .num_values = f \ } +#define PCONFDUMP(a, b, c, d) PCONFDUMP_WITH_VALUES(a, b, c, d, NULL, 0) + struct pin_config_item { const enum pin_config_param param; const char * const display; const char * const format; bool has_arg; + const char * const *values; + size_t num_values; }; struct pinconf_generic_params { const char * const property; enum pin_config_param param; u32 default_value; + const char * const *values; + size_t num_values; }; int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, From 55c7f5ef904fc2dcc7ef5945c5efb0cd60b46d32 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:51 +0200 Subject: [PATCH 171/684] pinctrl: pinconf-generic: Add properties 'skew-delay-{in,out}put-ps' Add the properties 'skew-delay-input-ps' and 'skew-delay-output-ps' to the generic parameters used for parsing DT files. This allows to specify the independent skew delay value for the two directions. This enables drivers that use the generic pin configuration to get the value passed through these new properties. Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf-generic.c | 4 ++++ include/linux/pinctrl/pinconf-generic.h | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 72906d71ae1a2e..366775841c6399 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -54,6 +54,8 @@ static const struct pin_config_item conf_items[] = { PCONFDUMP(PIN_CONFIG_SLEEP_HARDWARE_STATE, "sleep hardware state", NULL, false), PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true), PCONFDUMP(PIN_CONFIG_SKEW_DELAY, "skew delay", NULL, true), + PCONFDUMP(PIN_CONFIG_SKEW_DELAY_INPUT_PS, "input skew delay", "ps", true), + PCONFDUMP(PIN_CONFIG_SKEW_DELAY_OUTPUT_PS, "output skew delay", "ps", true), }; static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev, @@ -198,6 +200,8 @@ static const struct pinconf_generic_params dt_params[] = { { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 }, { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 }, { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 }, + { "skew-delay-input-ps", PIN_CONFIG_SKEW_DELAY_INPUT_PS, 0 }, + { "skew-delay-output-ps", PIN_CONFIG_SKEW_DELAY_OUTPUT_PS, 0 }, }; /** diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index f82add5d3302de..1be4032071c23b 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -112,6 +112,12 @@ struct pinctrl_map; * or latch delay (on outputs) this parameter (in a custom format) * specifies the clock skew or latch delay. It typically controls how * many double inverters are put in front of the line. + * @PIN_CONFIG_SKEW_DELAY_INPUT_PS: if the pin has independent values for the + * programmable skew rate (on inputs) and latch delay (on outputs), then + * this parameter specifies the clock skew only. The argument is in ps. + * @PIN_CONFIG_SKEW_DELAY_OUPUT_PS: if the pin has independent values for the + * programmable skew rate (on inputs) and latch delay (on outputs), then + * this parameter specifies the latch delay only. The argument is in ps. * @PIN_CONFIG_SLEEP_HARDWARE_STATE: indicate this is sleep related state. * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to * this parameter (on a custom format) tells the driver which alternative @@ -147,6 +153,8 @@ enum pin_config_param { PIN_CONFIG_PERSIST_STATE, PIN_CONFIG_POWER_SOURCE, PIN_CONFIG_SKEW_DELAY, + PIN_CONFIG_SKEW_DELAY_INPUT_PS, + PIN_CONFIG_SKEW_DELAY_OUTPUT_PS, PIN_CONFIG_SLEEP_HARDWARE_STATE, PIN_CONFIG_SLEW_RATE, PIN_CONFIG_END = 0x7F, From 5c284d086bcf3bcfe54debb44a18fb218f91c010 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:52 +0200 Subject: [PATCH 172/684] dt-bindings: pincfg-node: Add properties 'skew-delay-{in,out}put-ps' Add the properties 'skew-delay-input-ps' and 'skew-delay-output-ps' to specify independent skew delay value for the two pin's directions. Make the new properties unavailable when the existing property 'skew-delay' is selected. Signed-off-by: Antonio Borneo Acked-by: Conor Dooley Signed-off-by: Linus Walleij --- .../bindings/pinctrl/pincfg-node.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml index cbfcf215e571d9..d1bc389e0a6d18 100644 --- a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml @@ -153,4 +153,21 @@ properties: pin. Typically indicates how many double-inverters are used to delay the signal. + skew-delay-input-ps: + description: + this affects the expected clock skew in ps on an input pin. + + skew-delay-output-ps: + description: + this affects the expected delay in ps before latching a value to + an output pin. + +if: + required: + - skew-delay +then: + properties: + skew-delay-input-ps: false + skew-delay-output-ps: false + additionalProperties: true From 5a0398cc2a364e8c314a9c6361680a95d7d9b5d7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:53 +0200 Subject: [PATCH 173/684] pinctrl: stm32: Rework stm32_pconf_parse_conf() Reduce the number of parameters of the function by moving inside the function the decoding of the field 'config'. While there: - change the type of 'param' to 'unsigned int' to handle the extra values not in 'enum pin_config_param'; - change the type of 'arg' to 'u32' to avoid additional conversions and align to 'u32' the corresponding param of __stm32_gpio_set(). Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 3ebb468de830db..6c5f9e015e8e1b 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -287,7 +287,7 @@ static void stm32_gpio_rif_release_semaphore(struct stm32_gpio_bank *bank, unsig /* GPIO functions */ static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, - unsigned offset, int value) + unsigned int offset, u32 value) { stm32_gpio_backup_value(bank, offset, value); @@ -1195,10 +1195,11 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, } static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, - unsigned int pin, enum pin_config_param param, - enum pin_config_param arg) + unsigned int pin, unsigned long config) { struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + unsigned int param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); struct pinctrl_gpio_range *range; struct stm32_gpio_bank *bank; int offset, ret = 0; @@ -1267,9 +1268,7 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, for (i = 0; i < num_configs; i++) { mutex_lock(&pctldev->mutex); - ret = stm32_pconf_parse_conf(pctldev, g->pin, - pinconf_to_config_param(configs[i]), - pinconf_to_config_argument(configs[i])); + ret = stm32_pconf_parse_conf(pctldev, g->pin, configs[i]); mutex_unlock(&pctldev->mutex); if (ret < 0) return ret; @@ -1286,9 +1285,7 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, int i, ret; for (i = 0; i < num_configs; i++) { - ret = stm32_pconf_parse_conf(pctldev, pin, - pinconf_to_config_param(configs[i]), - pinconf_to_config_argument(configs[i])); + ret = stm32_pconf_parse_conf(pctldev, pin, configs[i]); if (ret < 0) return ret; } From bbd3fc34122431f5b004777c97164bc95f71228d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:54 +0200 Subject: [PATCH 174/684] pinctrl: stm32: Simplify handling of backup pin status Use C bit-field to keep the backup of the pin status, instead of explicitly handling the bit-field through shift and mask of a u32 container. Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 70 +++++++++------------------ 1 file changed, 24 insertions(+), 46 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 6c5f9e015e8e1b..66f9783fce8629 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -54,18 +54,6 @@ #define STM32_GPIO_CIDCFGR(x) (0x50 + (0x8 * (x))) #define STM32_GPIO_SEMCR(x) (0x54 + (0x8 * (x))) -/* custom bitfield to backup pin status */ -#define STM32_GPIO_BKP_MODE_SHIFT 0 -#define STM32_GPIO_BKP_MODE_MASK GENMASK(1, 0) -#define STM32_GPIO_BKP_ALT_SHIFT 2 -#define STM32_GPIO_BKP_ALT_MASK GENMASK(5, 2) -#define STM32_GPIO_BKP_SPEED_SHIFT 6 -#define STM32_GPIO_BKP_SPEED_MASK GENMASK(7, 6) -#define STM32_GPIO_BKP_PUPD_SHIFT 8 -#define STM32_GPIO_BKP_PUPD_MASK GENMASK(9, 8) -#define STM32_GPIO_BKP_TYPE 10 -#define STM32_GPIO_BKP_VAL 11 - #define STM32_GPIO_CIDCFGR_CFEN BIT(0) #define STM32_GPIO_CIDCFGR_SEMEN BIT(1) #define STM32_GPIO_CIDCFGR_SCID_MASK GENMASK(5, 4) @@ -100,6 +88,15 @@ struct stm32_pinctrl_group { unsigned pin; }; +struct stm32_pin_backup { + unsigned int alt:4; + unsigned int mode:2; + unsigned int bias:2; + unsigned int speed:2; + unsigned int drive:1; + unsigned int value:1; +}; + struct stm32_gpio_bank { void __iomem *base; struct reset_control *rstc; @@ -110,7 +107,7 @@ struct stm32_gpio_bank { struct irq_domain *domain; u32 bank_nr; u32 bank_ioport_nr; - u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; + struct stm32_pin_backup pin_backup[STM32_GPIO_PINS_PER_BANK]; u8 irq_type[STM32_GPIO_PINS_PER_BANK]; bool secure_control; bool rif_control; @@ -176,38 +173,32 @@ static inline u32 stm32_gpio_get_alt(u32 function) static void stm32_gpio_backup_value(struct stm32_gpio_bank *bank, u32 offset, u32 value) { - bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_VAL); - bank->pin_backup[offset] |= value << STM32_GPIO_BKP_VAL; + bank->pin_backup[offset].value = value; } static void stm32_gpio_backup_mode(struct stm32_gpio_bank *bank, u32 offset, u32 mode, u32 alt) { - bank->pin_backup[offset] &= ~(STM32_GPIO_BKP_MODE_MASK | - STM32_GPIO_BKP_ALT_MASK); - bank->pin_backup[offset] |= mode << STM32_GPIO_BKP_MODE_SHIFT; - bank->pin_backup[offset] |= alt << STM32_GPIO_BKP_ALT_SHIFT; + bank->pin_backup[offset].mode = mode; + bank->pin_backup[offset].alt = alt; } static void stm32_gpio_backup_driving(struct stm32_gpio_bank *bank, u32 offset, u32 drive) { - bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_TYPE); - bank->pin_backup[offset] |= drive << STM32_GPIO_BKP_TYPE; + bank->pin_backup[offset].drive = drive; } static void stm32_gpio_backup_speed(struct stm32_gpio_bank *bank, u32 offset, u32 speed) { - bank->pin_backup[offset] &= ~STM32_GPIO_BKP_SPEED_MASK; - bank->pin_backup[offset] |= speed << STM32_GPIO_BKP_SPEED_SHIFT; + bank->pin_backup[offset].speed = speed; } static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset, u32 bias) { - bank->pin_backup[offset] &= ~STM32_GPIO_BKP_PUPD_MASK; - bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT; + bank->pin_backup[offset].bias = bias; } /* RIF functions */ @@ -1798,7 +1789,7 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( struct stm32_pinctrl *pctl, u32 pin) { const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin); - u32 val, alt, mode, offset = stm32_gpio_pin(pin); + u32 mode, offset = stm32_gpio_pin(pin); struct pinctrl_gpio_range *range; struct stm32_gpio_bank *bank; bool pin_is_irq; @@ -1818,36 +1809,23 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( bank = gpiochip_get_data(range->gc); - alt = bank->pin_backup[offset] & STM32_GPIO_BKP_ALT_MASK; - alt >>= STM32_GPIO_BKP_ALT_SHIFT; - mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK; - mode >>= STM32_GPIO_BKP_MODE_SHIFT; - - ret = stm32_pmx_set_mode(bank, offset, mode, alt); + mode = bank->pin_backup[offset].mode; + ret = stm32_pmx_set_mode(bank, offset, mode, bank->pin_backup[offset].alt); if (ret) return ret; - if (mode == 1) { - val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL); - val = val >> STM32_GPIO_BKP_VAL; - __stm32_gpio_set(bank, offset, val); - } + if (mode == 1) + __stm32_gpio_set(bank, offset, bank->pin_backup[offset].value); - val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE); - val >>= STM32_GPIO_BKP_TYPE; - ret = stm32_pconf_set_driving(bank, offset, val); + ret = stm32_pconf_set_driving(bank, offset, bank->pin_backup[offset].drive); if (ret) return ret; - val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK; - val >>= STM32_GPIO_BKP_SPEED_SHIFT; - ret = stm32_pconf_set_speed(bank, offset, val); + ret = stm32_pconf_set_speed(bank, offset, bank->pin_backup[offset].speed); if (ret) return ret; - val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK; - val >>= STM32_GPIO_BKP_PUPD_SHIFT; - ret = stm32_pconf_set_bias(bank, offset, val); + ret = stm32_pconf_set_bias(bank, offset, bank->pin_backup[offset].bias); if (ret) return ret; From 701a6aa4a3b1ce7228523f696c9a1212abdd317f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:55 +0200 Subject: [PATCH 175/684] pinctrl: stm32: Drop useless spinlock save and restore There is no need to acquire a spinlock to only read a register for debugfs reporting. Drop such useless spinlock save and restore. Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 66f9783fce8629..7175328d0df0cf 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -920,9 +920,6 @@ static void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, u32 val; int alt_shift = (pin % 8) * 4; int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; - unsigned long flags; - - spin_lock_irqsave(&bank->lock, flags); val = readl_relaxed(bank->base + alt_offset); val &= GENMASK(alt_shift + 3, alt_shift); @@ -931,8 +928,6 @@ static void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, val = readl_relaxed(bank->base + STM32_GPIO_MODER); val &= GENMASK(pin * 2 + 1, pin * 2); *mode = val >> (pin * 2); - - spin_unlock_irqrestore(&bank->lock, flags); } static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, @@ -1050,16 +1045,11 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank, unsigned int offset) { - unsigned long flags; u32 val; - spin_lock_irqsave(&bank->lock, flags); - val = readl_relaxed(bank->base + STM32_GPIO_TYPER); val &= BIT(offset); - spin_unlock_irqrestore(&bank->lock, flags); - return (val >> offset); } @@ -1101,16 +1091,11 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank, unsigned int offset) { - unsigned long flags; u32 val; - spin_lock_irqsave(&bank->lock, flags); - val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); val &= GENMASK(offset * 2 + 1, offset * 2); - spin_unlock_irqrestore(&bank->lock, flags); - return (val >> (offset * 2)); } @@ -1152,27 +1137,19 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, unsigned int offset) { - unsigned long flags; u32 val; - spin_lock_irqsave(&bank->lock, flags); - val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); val &= GENMASK(offset * 2 + 1, offset * 2); - spin_unlock_irqrestore(&bank->lock, flags); - return (val >> (offset * 2)); } static bool stm32_pconf_get(struct stm32_gpio_bank *bank, unsigned int offset, bool dir) { - unsigned long flags; u32 val; - spin_lock_irqsave(&bank->lock, flags); - if (dir) val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); @@ -1180,8 +1157,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset)); - spin_unlock_irqrestore(&bank->lock, flags); - return val; } From 78a3ce945e66966832d2a8c07494163bd3c2f3ac Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:56 +0200 Subject: [PATCH 176/684] pinctrl: stm32: Avoid keeping a bool value in a u32 variable Change type of variable to avoid keeping the bool return value in a variable of u32 type. Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 7175328d0df0cf..ac64cb7f86d74e 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1148,7 +1148,7 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, static bool stm32_pconf_get(struct stm32_gpio_bank *bank, unsigned int offset, bool dir) { - u32 val; + bool val; if (dir) val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & From c0cfa3a9fbb9965c2ecc6e1f9d6087b676b3d348 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:57 +0200 Subject: [PATCH 177/684] pinctrl: stm32: Support I/O synchronization parameters Devices in the stm32mp2xx family include an I/O synchronization block on each pin that is used to fine tune and improve the I/O timing margins of high speed synchronous interfaces. It can be configured to provide independently for each pin: - skew rate on input direction or latch delay on output direction; - inversion of clock signals or re-sampling of data signals. Add support for the generic properties: - skew-delay-input-ps; - skew-delay-output-ps. Add support for the property 'st,io-sync' to configure clock inversion or data re-sampling mode. Show the new parameters on debugfs pinconf-pins. Enable it for the stm32mp257 pinctrl driver. Co-developed-by: Valentin Caron Signed-off-by: Valentin Caron Co-developed-by: Fabien Dessenne Signed-off-by: Fabien Dessenne Signed-off-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 255 +++++++++++++++++++++ drivers/pinctrl/stm32/pinctrl-stm32.h | 1 + drivers/pinctrl/stm32/pinctrl-stm32mp257.c | 2 + 3 files changed, 258 insertions(+) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index ac64cb7f86d74e..5f8829fdd98517 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -51,9 +51,23 @@ #define STM32_GPIO_AFRL 0x20 #define STM32_GPIO_AFRH 0x24 #define STM32_GPIO_SECCFGR 0x30 +#define STM32_GPIO_DELAYRL 0x40 +#define STM32_GPIO_ADVCFGRL 0x48 #define STM32_GPIO_CIDCFGR(x) (0x50 + (0x8 * (x))) #define STM32_GPIO_SEMCR(x) (0x54 + (0x8 * (x))) +/* Unitary delay for STM32_GPIO_DELAYRL */ +#define STM32_GPIO_DELAYRL_PS 250 + +#define STM32_GPIO_ADVCFGR_DLYPATH_MASK BIT(0) +#define STM32_GPIO_ADVCFGR_DE_MASK BIT(1) +#define STM32_GPIO_ADVCFGR_INVCLK_MASK BIT(2) +#define STM32_GPIO_ADVCFGR_RET_MASK BIT(3) +#define STM32_GPIO_ADVCFGR_IO_SYNC_MASK \ + (STM32_GPIO_ADVCFGR_DE_MASK \ + | STM32_GPIO_ADVCFGR_INVCLK_MASK \ + | STM32_GPIO_ADVCFGR_RET_MASK) + #define STM32_GPIO_CIDCFGR_CFEN BIT(0) #define STM32_GPIO_CIDCFGR_SEMEN BIT(1) #define STM32_GPIO_CIDCFGR_SCID_MASK GENMASK(5, 4) @@ -67,6 +81,9 @@ #define SYSCFG_IRQMUX_MASK GENMASK(3, 0) +/* Vendor specific pin configuration */ +#define STM32_GPIO_PIN_CONFIG_IO_SYNC (PIN_CONFIG_END + 1) + #define gpio_range_to_bank(chip) \ container_of(chip, struct stm32_gpio_bank, range) @@ -82,6 +99,32 @@ static const char * const stm32_gpio_functions[] = { "reserved", }; +static const char * const stm32_gpio_io_sync[] = { + "pass-through", + "clock inverted", + "data on rising edge", + "data on falling edge", + "data on both edges", +}; + +static u8 io_sync_2_advcfgr[] = { + /* data or clock GPIO pass-through */ + [0] = 0, + /* clock GPIO inverted */ + [1] = STM32_GPIO_ADVCFGR_INVCLK_MASK, + /* data GPIO re-sampled on clock rising edge */ + [2] = STM32_GPIO_ADVCFGR_RET_MASK, + /* data GPIO re-sampled on clock falling edge */ + [3] = STM32_GPIO_ADVCFGR_RET_MASK | STM32_GPIO_ADVCFGR_INVCLK_MASK, + /* data GPIO re-sampled on both clock edges */ + [4] = STM32_GPIO_ADVCFGR_RET_MASK | STM32_GPIO_ADVCFGR_DE_MASK, +}; + +static const struct pinconf_generic_params stm32_gpio_bindings[] = { + {"st,io-sync", STM32_GPIO_PIN_CONFIG_IO_SYNC, 0, + stm32_gpio_io_sync, ARRAY_SIZE(stm32_gpio_io_sync)}, +}; + struct stm32_pinctrl_group { const char *name; unsigned long config; @@ -95,6 +138,8 @@ struct stm32_pin_backup { unsigned int speed:2; unsigned int drive:1; unsigned int value:1; + unsigned int advcfg:4; + unsigned int skew_delay:4; }; struct stm32_gpio_bank { @@ -110,6 +155,7 @@ struct stm32_gpio_bank { struct stm32_pin_backup pin_backup[STM32_GPIO_PINS_PER_BANK]; u8 irq_type[STM32_GPIO_PINS_PER_BANK]; bool secure_control; + bool io_sync_control; bool rif_control; }; @@ -201,6 +247,21 @@ static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset, bank->pin_backup[offset].bias = bias; } +static void stm32_gpio_backup_advcfg(struct stm32_gpio_bank *bank, u32 offset, u32 mask, u32 value) +{ + u32 val; + + val = bank->pin_backup[offset].advcfg; + val &= ~mask; + val |= value & mask; + bank->pin_backup[offset].advcfg = val; +} + +static void stm32_gpio_backup_skew_delay(struct stm32_gpio_bank *bank, u32 offset, u32 delay) +{ + bank->pin_backup[offset].skew_delay = delay; +} + /* RIF functions */ static bool stm32_gpio_rif_valid(struct stm32_gpio_bank *bank, unsigned int gpio_nr) @@ -1145,6 +1206,155 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, return (val >> (offset * 2)); } +static void +stm32_pconf_set_advcfgr_nolock(struct stm32_gpio_bank *bank, int offset, u32 mask, u32 value) +{ + int advcfgr_offset = STM32_GPIO_ADVCFGRL + (offset / 8) * 4; + int advcfgr_shift = (offset % 8) * 4; + u32 val; + + val = readl_relaxed(bank->base + advcfgr_offset); + val &= ~(mask << advcfgr_shift); + val |= (value & mask) << advcfgr_shift; + writel_relaxed(val, bank->base + advcfgr_offset); + + stm32_gpio_backup_advcfg(bank, offset, mask, value); +} + +static int stm32_pconf_set_advcfgr(struct stm32_gpio_bank *bank, int offset, u32 mask, u32 value) +{ + struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); + unsigned long flags; + int err = 0; + + if (!bank->io_sync_control) + return -ENOTSUPP; + + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { + err = hwspin_lock_timeout_in_atomic(pctl->hwlock, HWSPNLCK_TIMEOUT); + if (err) { + dev_err(pctl->dev, "Can't get hwspinlock\n"); + goto unlock; + } + } + + stm32_pconf_set_advcfgr_nolock(bank, offset, mask, value); + + if (pctl->hwlock) + hwspin_unlock_in_atomic(pctl->hwlock); + +unlock: + spin_unlock_irqrestore(&bank->lock, flags); + + return err; +} + +static u32 stm32_pconf_get_advcfgr(struct stm32_gpio_bank *bank, int offset, u32 mask) +{ + int advcfgr_offset = STM32_GPIO_ADVCFGRL + (offset / 8) * 4; + int advcfgr_shift = (offset % 8) * 4; + u32 val; + + if (!bank->io_sync_control) + return 0; + + val = readl_relaxed(bank->base + advcfgr_offset); + val >>= advcfgr_shift; + + return val & mask; +} + +static int stm32_pconf_set_io_sync(struct stm32_gpio_bank *bank, int offset, u32 io_sync) +{ + if (io_sync >= ARRAY_SIZE(io_sync_2_advcfgr)) + return -EINVAL; + + return stm32_pconf_set_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_IO_SYNC_MASK, + io_sync_2_advcfgr[io_sync]); +} + +static const char *stm32_pconf_get_io_sync_str(struct stm32_gpio_bank *bank, int offset) +{ + u32 io_sync = stm32_pconf_get_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_IO_SYNC_MASK); + + if (io_sync & STM32_GPIO_ADVCFGR_RET_MASK) { + if (io_sync & STM32_GPIO_ADVCFGR_DE_MASK) + return "data GPIO re-sampled on both clock edges"; + + if (io_sync & STM32_GPIO_ADVCFGR_INVCLK_MASK) + return "data GPIO re-sampled on clock falling edge"; + + return "data GPIO re-sampled on clock rising edge"; + } + + if (io_sync & STM32_GPIO_ADVCFGR_INVCLK_MASK) + return "clock GPIO inverted"; + + return NULL; +} + +static int +stm32_pconf_set_skew_delay(struct stm32_gpio_bank *bank, int offset, u32 delay, bool is_dir_input) +{ + struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); + int delay_offset = STM32_GPIO_DELAYRL + (offset / 8) * 4; + int delay_shift = (offset % 8) * 4; + unsigned long flags; + int err = 0; + u32 val; + + if (!bank->io_sync_control) + return -ENOTSUPP; + + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { + err = hwspin_lock_timeout_in_atomic(pctl->hwlock, HWSPNLCK_TIMEOUT); + if (err) { + dev_err(pctl->dev, "Can't get hwspinlock\n"); + goto unlock; + } + } + + val = readl_relaxed(bank->base + delay_offset); + val &= ~GENMASK(delay_shift + 3, delay_shift); + val |= (delay << delay_shift); + writel_relaxed(val, bank->base + delay_offset); + + stm32_gpio_backup_skew_delay(bank, offset, delay); + + stm32_pconf_set_advcfgr_nolock(bank, offset, STM32_GPIO_ADVCFGR_DLYPATH_MASK, + is_dir_input ? STM32_GPIO_ADVCFGR_DLYPATH_MASK : 0); + + if (pctl->hwlock) + hwspin_unlock_in_atomic(pctl->hwlock); + +unlock: + spin_unlock_irqrestore(&bank->lock, flags); + + return err; +} + +static u32 stm32_pconf_get_skew_delay_val(struct stm32_gpio_bank *bank, int offset) +{ + int delay_offset = STM32_GPIO_DELAYRL + (offset / 8) * 4; + int delay_shift = (offset % 8) * 4; + u32 val; + + val = readl_relaxed(bank->base + delay_offset); + val &= GENMASK(delay_shift + 3, delay_shift); + + return val >> delay_shift; +} + +static const char *stm32_pconf_get_skew_dir_str(struct stm32_gpio_bank *bank, int offset) +{ + return stm32_pconf_get_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_DLYPATH_MASK) ? + "input" : "output"; +} + static bool stm32_pconf_get(struct stm32_gpio_bank *bank, unsigned int offset, bool dir) { @@ -1207,6 +1417,17 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, __stm32_gpio_set(bank, offset, arg); ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false); break; + case PIN_CONFIG_SKEW_DELAY_INPUT_PS: + arg /= STM32_GPIO_DELAYRL_PS; + ret = stm32_pconf_set_skew_delay(bank, offset, arg, true); + break; + case PIN_CONFIG_SKEW_DELAY_OUTPUT_PS: + arg /= STM32_GPIO_DELAYRL_PS; + ret = stm32_pconf_set_skew_delay(bank, offset, arg, false); + break; + case STM32_GPIO_PIN_CONFIG_IO_SYNC: + ret = stm32_pconf_set_io_sync(bank, offset, arg); + break; default: ret = -ENOTSUPP; } @@ -1349,6 +1570,22 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, case 3: break; } + + if (bank->io_sync_control) { + const char *io_sync_str, *skew_dir_str; + u32 skew_delay; + + io_sync_str = stm32_pconf_get_io_sync_str(bank, offset); + skew_dir_str = stm32_pconf_get_skew_dir_str(bank, offset); + skew_delay = stm32_pconf_get_skew_delay_val(bank, offset); + + if (io_sync_str) + seq_printf(s, " - IO-sync: %s", io_sync_str); + + if (skew_delay) + seq_printf(s, " - Skew-delay: %u (%u ps) %s", skew_delay, + skew_delay * STM32_GPIO_DELAYRL_PS, skew_dir_str); + } } static const struct pinconf_ops stm32_pconf_ops = { @@ -1441,6 +1678,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode bank->bank_nr = bank_nr; bank->bank_ioport_nr = bank_ioport_nr; bank->secure_control = pctl->match_data->secure_control; + bank->io_sync_control = pctl->match_data->io_sync_control; bank->rif_control = pctl->match_data->rif_control; spin_lock_init(&bank->lock); @@ -1683,6 +1921,8 @@ int stm32_pctl_probe(struct platform_device *pdev) pctl->pctl_desc.confops = &stm32_pconf_ops; pctl->pctl_desc.pctlops = &stm32_pctrl_ops; pctl->pctl_desc.pmxops = &stm32_pmx_ops; + pctl->pctl_desc.num_custom_params = ARRAY_SIZE(stm32_gpio_bindings); + pctl->pctl_desc.custom_params = stm32_gpio_bindings; pctl->dev = &pdev->dev; pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, @@ -1804,6 +2044,21 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( if (ret) return ret; + if (bank->io_sync_control) { + bool is_input = bank->pin_backup[offset].advcfg & STM32_GPIO_ADVCFGR_DLYPATH_MASK; + + ret = stm32_pconf_set_skew_delay(bank, offset, + bank->pin_backup[offset].skew_delay, + is_input); + if (ret) + return ret; + + ret = stm32_pconf_set_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_IO_SYNC_MASK, + bank->pin_backup[offset].advcfg); + if (ret) + return ret; + } + if (pin_is_irq) regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr); diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h index b98a4141bf2c02..d17cbdbba44826 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.h +++ b/drivers/pinctrl/stm32/pinctrl-stm32.h @@ -64,6 +64,7 @@ struct stm32_pinctrl_match_data { const struct stm32_desc_pin *pins; const unsigned int npins; bool secure_control; + bool io_sync_control; bool rif_control; }; diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c index d226de524bfc1b..6709bddd971861 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c @@ -2543,6 +2543,7 @@ static const struct stm32_desc_pin stm32mp257_z_pins[] = { static struct stm32_pinctrl_match_data stm32mp257_match_data = { .pins = stm32mp257_pins, .npins = ARRAY_SIZE(stm32mp257_pins), + .io_sync_control = true, .secure_control = true, .rif_control = true, }; @@ -2550,6 +2551,7 @@ static struct stm32_pinctrl_match_data stm32mp257_match_data = { static struct stm32_pinctrl_match_data stm32mp257_z_match_data = { .pins = stm32mp257_z_pins, .npins = ARRAY_SIZE(stm32mp257_z_pins), + .io_sync_control = true, .secure_control = true, .rif_control = true, }; From cf7a3d4d3f31ec10f595f90e23f7961d8bc57cee Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:58 +0200 Subject: [PATCH 178/684] dt-bindings: pinctrl: stm32: Use properties from pincfg-node.yaml Don't re-declare the standard pincfg properties; take them from the default schema. Signed-off-by: Antonio Borneo Acked-by: Conor Dooley Signed-off-by: Linus Walleij --- .../bindings/pinctrl/st,stm32-pinctrl.yaml | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml index 961161c2ab62b0..27c0dd7a8df01c 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -151,6 +151,8 @@ patternProperties: pinctrl group available on the machine. Each subnode will list the pins it needs, and how they should be configured, with regard to muxer configuration, pullups, drive, output high/low and output speed. + $ref: /schemas/pinctrl/pincfg-node.yaml + properties: pinmux: $ref: /schemas/types.yaml#/definitions/uint32-array @@ -195,26 +197,19 @@ patternProperties: pinmux = ; }; - bias-disable: - type: boolean + bias-disable: true - bias-pull-down: - type: boolean + bias-pull-down: true - bias-pull-up: - type: boolean + bias-pull-up: true - drive-push-pull: - type: boolean + drive-push-pull: true - drive-open-drain: - type: boolean + drive-open-drain: true - output-low: - type: boolean + output-low: true - output-high: - type: boolean + output-high: true slew-rate: description: | @@ -222,8 +217,8 @@ patternProperties: 1: Medium speed 2: Fast speed 3: High speed - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2, 3] + minimum: 0 + maximum: 3 required: - pinmux From a730bf753eae64c6e7dcaf5d4a5c5d0ac0f76f95 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 23 Oct 2025 15:26:59 +0200 Subject: [PATCH 179/684] dt-bindings: pinctrl: stm32: Support I/O synchronization parameters Document the support of the I/O synchronization parameters: - skew-delay-input-ps; - skew-delay-output-ps; - st,io-sync. Forbid 'skew-delay-input-ps' and 'skew-delay-output-ps' to be both present on the same pin. Allow the new properties only with compatibles that support them. Add an example that uses the new properties. Co-developed-by: Fabien Dessenne Signed-off-by: Fabien Dessenne Signed-off-by: Antonio Borneo Reviewed-by: Conor Dooley Signed-off-by: Linus Walleij --- .../bindings/pinctrl/st,stm32-pinctrl.yaml | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml index 27c0dd7a8df01c..76d956b4a5372d 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -220,12 +220,65 @@ patternProperties: minimum: 0 maximum: 3 + skew-delay-input-ps: + description: | + IO synchronization skew rate applied to the input path + enum: [0, 300, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250] + + skew-delay-output-ps: + description: | + IO synchronization latch delay applied to the output path + enum: [0, 300, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250] + + st,io-sync: + $ref: /schemas/types.yaml#/definitions/string + enum: + - pass-through + - clock inverted + - data on rising edge + - data on falling edge + - data on both edges + description: | + IO synchronization through re-sampling or inversion + "pass-through" - data or clock GPIO pass-through + "clock inverted" - clock GPIO inverted + "data on rising edge" - data GPIO re-sampled on clock rising edge + "data on falling edge" - data GPIO re-sampled on clock falling edge + "data on both edges" - data GPIO re-sampled on both clock edges + default: pass-through + required: - pinmux + # Not allowed both skew-delay-input-ps and skew-delay-output-ps + if: + required: + - skew-delay-input-ps + then: + properties: + skew-delay-output-ps: false + allOf: - $ref: pinctrl.yaml# + - if: + not: + properties: + compatible: + contains: + enum: + - st,stm32mp257-pinctrl + - st,stm32mp257-z-pinctrl + then: + patternProperties: + '-[0-9]*$': + patternProperties: + '^pins': + properties: + skew-delay-input-ps: false + skew-delay-output-ps: false + st,io-sync: false + required: - compatible - '#address-cells' @@ -306,4 +359,25 @@ examples: pinctrl-names = "default"; }; + - | + #include + //Example 4 skew-delay and st,io-sync + pinctrl: pinctrl@44240000 { + compatible = "st,stm32mp257-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x44240000 0xa0400>; + + eth3_rgmii_pins_a: eth3-rgmii-0 { + pins1 { + pinmux = ; + st,io-sync = "data on both edges"; + }; + pins2 { + pinmux = ; + skew-delay-output-ps = <500>; + }; + }; + }; + ... From 352864787458d31420b446154a165145f150d1f0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 28 Oct 2025 08:38:20 -0700 Subject: [PATCH 180/684] perf test workload: Add thread count argument to thloop Allow the number of threads for the thloop workload to be increased beyond the normal 2. Add error checking to the parsed time and thread count values. Signed-off-by: Ian Rogers Acked-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/tests/workloads/thloop.c | 45 ++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/tools/perf/tests/workloads/thloop.c b/tools/perf/tests/workloads/thloop.c index 457b29f91c3ee2..bd8168f883fb67 100644 --- a/tools/perf/tests/workloads/thloop.c +++ b/tools/perf/tests/workloads/thloop.c @@ -31,21 +31,52 @@ static void *thfunc(void *arg) static int thloop(int argc, const char **argv) { - int sec = 1; - pthread_t th; + int nt = 2, sec = 1, err = 1; + pthread_t *thread_list = NULL; if (argc > 0) sec = atoi(argv[0]); + if (sec <= 0) { + fprintf(stderr, "Error: seconds (%d) must be >= 1\n", sec); + return 1; + } + + if (argc > 1) + nt = atoi(argv[1]); + + if (nt <= 0) { + fprintf(stderr, "Error: thread count (%d) must be >= 1\n", nt); + return 1; + } + signal(SIGINT, sighandler); signal(SIGALRM, sighandler); - alarm(sec); - pthread_create(&th, NULL, thfunc, test_loop); - test_loop(); - pthread_join(th, NULL); + thread_list = calloc(nt, sizeof(pthread_t)); + if (thread_list == NULL) { + fprintf(stderr, "Error: malloc failed for %d threads\n", nt); + goto out; + } + for (int i = 1; i < nt; i++) { + int ret = pthread_create(&thread_list[i], NULL, thfunc, test_loop); - return 0; + if (ret) { + fprintf(stderr, "Error: failed to create thread %d\n", i); + done = 1; // Ensure started threads terminate. + goto out; + } + } + alarm(sec); + test_loop(); + err = 0; +out: + for (int i = 1; i < nt; i++) { + if (thread_list && thread_list[i]) + pthread_join(thread_list[i], /*retval=*/NULL); + } + free(thread_list); + return err; } DEFINE_WORKLOAD(thloop); From b45928845cc3997c074ee12960fdca8173c70da2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Oct 2025 18:18:20 +0300 Subject: [PATCH 181/684] pinctrl-scmi: remove unused struct members The ->pins and ->nr_pins members are not used so delete them. Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-scmi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c index d14528b9aa31ef..af3ac031e36268 100644 --- a/drivers/pinctrl/pinctrl-scmi.c +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -40,8 +40,6 @@ struct scmi_pinctrl { struct pinctrl_desc pctl_desc; struct pinfunction *functions; unsigned int nr_functions; - struct pinctrl_pin_desc *pins; - unsigned int nr_pins; }; static int pinctrl_scmi_get_groups_count(struct pinctrl_dev *pctldev) From 0820c9373369c83de5202871d02682d583a91a9c Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 29 Oct 2025 15:07:54 +0530 Subject: [PATCH 182/684] clk: qcom: gcc-qcs615: Update the SDCC clock to use shared_floor_ops Fix "gcc_sdcc2_apps_clk_src: rcg didn't update its configuration" during boot. This happens due to the floor_ops tries to update the rcg configuration even if the clock is not enabled. The shared_floor_ops ensures that the RCG is safely parked and the new parent configuration is cached in the parked_cfg when the clock is off. Ensure to use the ops for the other SDCC clock instances as well. Fixes: 39d6dcf67fe9 ("clk: qcom: gcc: Add support for QCS615 GCC clocks") Reviewed-by: Abel Vesa Signed-off-by: Taniya Das Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20251029-sdcc_rcg2_shared_ops-v3-1-ecf47d9601d1@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-qcs615.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/gcc-qcs615.c b/drivers/clk/qcom/gcc-qcs615.c index 9695446bc2a3c8..5b3b8dd4f114bd 100644 --- a/drivers/clk/qcom/gcc-qcs615.c +++ b/drivers/clk/qcom/gcc-qcs615.c @@ -784,7 +784,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { .name = "gcc_sdcc1_apps_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_shared_floor_ops, }, }; @@ -806,7 +806,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { .name = "gcc_sdcc1_ice_core_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_shared_floor_ops, }, }; @@ -830,7 +830,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { .name = "gcc_sdcc2_apps_clk_src", .parent_data = gcc_parent_data_8, .num_parents = ARRAY_SIZE(gcc_parent_data_8), - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_shared_floor_ops, }, }; From f9f4fda15e720686f1b2b436591ab11255e4e85e Mon Sep 17 00:00:00 2001 From: Maksim Kiselev Date: Mon, 27 Oct 2025 13:46:26 +0300 Subject: [PATCH 183/684] pinctrl: mcp23s08: init reg_defaults from HW at probe and switch cache type The probe function does not guarantee that chip registers are in their default state. Thus using reg_defaults for regmap is incorrect. For example, the chip may have already been configured by the bootloader before the Linux driver loads, or the mcp might not have a reset at all and not reset a state between reboots. In such cases, using reg_defaults leads to the cache values diverging from the actual registers values in the chip. Previous attempts to fix consequences of this issue were made in 'commit 3ede3f8b4b4b ("pinctrl: mcp23s08: Reset all pins to input at probe")', but this is insufficient. The OLAT register reset is also required. And there's still potential for new issues arising due to cache desynchronization of other registers. Therefore, remove reg_defaults and provide num_reg_defaults_raw. In that case the cache defaults being initialized from hardware. Also switch cache type to REGCACHE_MAPLE, which is aware of (in)valid cache entries. And remove the force reset all pins to input at probe as it is no longer required. Link: https://lore.kernel.org/all/20251009132651.649099-2-bigunclemax@gmail.com/ Suggested-by: Mike Looijmans Suggested-by: Andy Shevchenko Suggested-by: Sander Vanheule Signed-off-by: Maksim Kiselev Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-mcp23s08.c | 40 +++--------------------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index a17fcaddf490be..586f2f67c6177f 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -44,17 +44,6 @@ #define MCP_GPIO 0x09 #define MCP_OLAT 0x0a -static const struct reg_default mcp23x08_defaults[] = { - {.reg = MCP_IODIR, .def = 0xff}, - {.reg = MCP_IPOL, .def = 0x00}, - {.reg = MCP_GPINTEN, .def = 0x00}, - {.reg = MCP_DEFVAL, .def = 0x00}, - {.reg = MCP_INTCON, .def = 0x00}, - {.reg = MCP_IOCON, .def = 0x00}, - {.reg = MCP_GPPU, .def = 0x00}, - {.reg = MCP_OLAT, .def = 0x00}, -}; - static const struct regmap_range mcp23x08_volatile_range = { .range_min = MCP_INTF, .range_max = MCP_GPIO, @@ -82,25 +71,13 @@ const struct regmap_config mcp23x08_regmap = { .reg_stride = 1, .volatile_table = &mcp23x08_volatile_table, .precious_table = &mcp23x08_precious_table, - .reg_defaults = mcp23x08_defaults, - .num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults), - .cache_type = REGCACHE_FLAT, + .num_reg_defaults_raw = MCP_OLAT + 1, + .cache_type = REGCACHE_MAPLE, .max_register = MCP_OLAT, .disable_locking = true, /* mcp->lock protects the regmap */ }; EXPORT_SYMBOL_GPL(mcp23x08_regmap); -static const struct reg_default mcp23x17_defaults[] = { - {.reg = MCP_IODIR << 1, .def = 0xffff}, - {.reg = MCP_IPOL << 1, .def = 0x0000}, - {.reg = MCP_GPINTEN << 1, .def = 0x0000}, - {.reg = MCP_DEFVAL << 1, .def = 0x0000}, - {.reg = MCP_INTCON << 1, .def = 0x0000}, - {.reg = MCP_IOCON << 1, .def = 0x0000}, - {.reg = MCP_GPPU << 1, .def = 0x0000}, - {.reg = MCP_OLAT << 1, .def = 0x0000}, -}; - static const struct regmap_range mcp23x17_volatile_range = { .range_min = MCP_INTF << 1, .range_max = MCP_GPIO << 1, @@ -129,9 +106,8 @@ const struct regmap_config mcp23x17_regmap = { .max_register = MCP_OLAT << 1, .volatile_table = &mcp23x17_volatile_table, .precious_table = &mcp23x17_precious_table, - .reg_defaults = mcp23x17_defaults, - .num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults), - .cache_type = REGCACHE_FLAT, + .num_reg_defaults_raw = MCP_OLAT + 1, + .cache_type = REGCACHE_MAPLE, .val_format_endian = REGMAP_ENDIAN_LITTLE, .disable_locking = true, /* mcp->lock protects the regmap */ }; @@ -642,14 +618,6 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, mcp->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - /* - * Reset the chip - we don't really know what state it's in, so reset - * all pins to input first to prevent surprises. - */ - ret = mcp_write(mcp, MCP_IODIR, mcp->chip.ngpio == 16 ? 0xFFFF : 0xFF); - if (ret < 0) - return ret; - /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, * and MCP_IOCON.HAEN = 1, so we work with all chips. */ From 002679f79ed605e543fbace465557317cd307c9a Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Wed, 29 Oct 2025 09:42:52 +0800 Subject: [PATCH 184/684] pinctrl: stm32: fix hwspinlock resource leak in probe function In stm32_pctl_probe(), hwspin_lock_request_specific() is called to request a hwspinlock, but the acquired lock is not freed on multiple error paths after this call. This causes resource leakage when the function fails to initialize properly. Use devm_hwspin_lock_request_specific() instead of hwspin_lock_request_specific() to automatically manage the hwspinlock resource lifecycle. Fixes: 97cfb6cd34f2 ("pinctrl: stm32: protect configuration registers with a hwspinlock") Signed-off-by: Haotian Zhang Reviewed-by: Antonio Borneo Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 5f8829fdd98517..ceb9e19f2290d6 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1872,7 +1872,7 @@ int stm32_pctl_probe(struct platform_device *pdev) if (hwlock_id == -EPROBE_DEFER) return hwlock_id; } else { - pctl->hwlock = hwspin_lock_request_specific(hwlock_id); + pctl->hwlock = devm_hwspin_lock_request_specific(dev, hwlock_id); } spin_lock_init(&pctl->irqmux_lock); From 99224c151c19b74e1930d236dd348b6b22a607a5 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 29 Oct 2025 15:29:35 +0000 Subject: [PATCH 185/684] pinctrl: mpfs-iomux0: fix compile-time constant warning for LLVM prior to 17 With LLVM prior to 17.0.0: drivers/pinctrl/pinctrl-mpfs-iomux0.c:89:2: error: initializer element is not a compile-time constant MPFS_IOMUX0_GROUP(spi0), ^~~~~~~~~~~~~~~~~~~~~~~ drivers/pinctrl/pinctrl-mpfs-iomux0.c:79:10: note: expanded from macro 'MPFS_IOMUX0_GROUP' .mask = BIT(mpfs_iomux0_##_name##_pins[0]), \ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/vdso/bits.h:7:19: note: expanded from macro 'BIT' \#define BIT(nr) (UL(1) << (nr)) ^~~~~~~~~~~~~~~ This is a constant, but LLVM prior to a change from Nick to match the gcc behaviour did not allow this. The macro isn't really all that much of an idiot-proofing, just change it to the same sort that's in the gpio2 driver, where a second argument provides the mask/setting. Reported-by: Nathan Chancellor Link: https://github.com/ClangBuiltLinux/linux/issues/2140 Fixes: 46397274da22 ("pinctrl: add polarfire soc iomux0 pinmux driver") Signed-off-by: Conor Dooley Reviewed-by: Nathan Chancellor Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-mpfs-iomux0.c | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/pinctrl/pinctrl-mpfs-iomux0.c b/drivers/pinctrl/pinctrl-mpfs-iomux0.c index 49d9fcec0a162b..cf5b2e4e8f5ba7 100644 --- a/drivers/pinctrl/pinctrl-mpfs-iomux0.c +++ b/drivers/pinctrl/pinctrl-mpfs-iomux0.c @@ -73,33 +73,33 @@ static const unsigned int mpfs_iomux0_uart4_pins[] = { 11 }; static const unsigned int mpfs_iomux0_mdio0_pins[] = { 12 }; static const unsigned int mpfs_iomux0_mdio1_pins[] = { 13 }; -#define MPFS_IOMUX0_GROUP(_name) { \ +#define MPFS_IOMUX0_GROUP(_name, _mask) { \ .name = #_name "_mssio", \ .pins = mpfs_iomux0_##_name##_pins, \ - .mask = BIT(mpfs_iomux0_##_name##_pins[0]), \ + .mask = _mask, \ .setting = 0x0, \ }, { \ .name = #_name "_fabric", \ .pins = mpfs_iomux0_##_name##_pins, \ - .mask = BIT(mpfs_iomux0_##_name##_pins[0]), \ - .setting = BIT(mpfs_iomux0_##_name##_pins[0]), \ + .mask = _mask, \ + .setting = _mask, \ } static const struct mpfs_iomux0_pin_group mpfs_iomux0_pin_groups[] = { - MPFS_IOMUX0_GROUP(spi0), - MPFS_IOMUX0_GROUP(spi1), - MPFS_IOMUX0_GROUP(i2c0), - MPFS_IOMUX0_GROUP(i2c1), - MPFS_IOMUX0_GROUP(can0), - MPFS_IOMUX0_GROUP(can1), - MPFS_IOMUX0_GROUP(qspi), - MPFS_IOMUX0_GROUP(uart0), - MPFS_IOMUX0_GROUP(uart1), - MPFS_IOMUX0_GROUP(uart2), - MPFS_IOMUX0_GROUP(uart3), - MPFS_IOMUX0_GROUP(uart4), - MPFS_IOMUX0_GROUP(mdio0), - MPFS_IOMUX0_GROUP(mdio1), + MPFS_IOMUX0_GROUP(spi0, BIT(0)), + MPFS_IOMUX0_GROUP(spi1, BIT(1)), + MPFS_IOMUX0_GROUP(i2c0, BIT(2)), + MPFS_IOMUX0_GROUP(i2c1, BIT(3)), + MPFS_IOMUX0_GROUP(can0, BIT(4)), + MPFS_IOMUX0_GROUP(can1, BIT(5)), + MPFS_IOMUX0_GROUP(qspi, BIT(6)), + MPFS_IOMUX0_GROUP(uart0, BIT(7)), + MPFS_IOMUX0_GROUP(uart1, BIT(8)), + MPFS_IOMUX0_GROUP(uart2, BIT(9)), + MPFS_IOMUX0_GROUP(uart3, BIT(10)), + MPFS_IOMUX0_GROUP(uart4, BIT(11)), + MPFS_IOMUX0_GROUP(mdio0, BIT(12)), + MPFS_IOMUX0_GROUP(mdio1, BIT(13)), }; static const char * const mpfs_iomux0_spi0_groups[] = { "spi0_mssio", "spi0_fabric" }; From 9d4f219807d5ac11fb1d596e4ddb09336b040067 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 16 Oct 2025 10:38:13 -0400 Subject: [PATCH 186/684] i3c: fix refcount inconsistency in i3c_master_register In `i3c_master_register`, a possible refcount inconsistency has been identified, causing possible resource leak. Function `of_node_get` increases the refcount of `parent->of_node`. If function `i3c_bus_init` fails, the function returns immediately without a corresponding decrease, resulting in an inconsistent refcounter. Move call i3c_bus_init() after device_initialize() to let callback i3c_masterdev_release() release of_node. Reported-by: Shuhao Fu Closes: https://lore.kernel.org/linux-i3c/aO2tjp_FsV_WohPG@osx.local/T/#m2c05a982beeb14e7bf039c1d8db856734bf234c7 Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure") Signed-off-by: Frank Li Link: https://patch.msgid.link/20251016143814.2551256-1-Frank.Li@nxp.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index d946db75df7068..66513a27e6e776 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2883,10 +2883,6 @@ int i3c_master_register(struct i3c_master_controller *master, INIT_LIST_HEAD(&master->boardinfo.i2c); INIT_LIST_HEAD(&master->boardinfo.i3c); - ret = i3c_bus_init(i3cbus, master->dev.of_node); - if (ret) - return ret; - device_initialize(&master->dev); dev_set_name(&master->dev, "i3c-%d", i3cbus->id); @@ -2894,6 +2890,10 @@ int i3c_master_register(struct i3c_master_controller *master, master->dev.coherent_dma_mask = parent->coherent_dma_mask; master->dev.dma_parms = parent->dma_parms; + ret = i3c_bus_init(i3cbus, master->dev.of_node); + if (ret) + goto err_put_dev; + ret = of_populate_i3c_bus(master); if (ret) goto err_put_dev; From 3a36273e5a07dda0ccec193800f3b78c3c0380af Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 27 Oct 2025 11:47:15 +0800 Subject: [PATCH 187/684] i3c: master: svc: Prevent incomplete IBI transaction If no free IBI slot is available, svc_i3c_master_handle_ibi returns immediately. This causes the STOP condition to be missed because the EmitStop request is sent when the transfer is not complete. To resolve this, svc_i3c_master_handle_ibi must wait for the transfer to complete before returning. Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver") Signed-off-by: Stanley Chu Reviewed-by: Frank Li Reviewed-by: Miquel Raynal Link: https://patch.msgid.link/20251027034715.708243-1-yschu@nuvoton.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/svc-i3c-master.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 9641e66a4e5f2d..e70a64f2a32fa5 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -406,21 +406,27 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, int ret, val; u8 *buf; - slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); - if (!slot) - return -ENOSPC; - - slot->len = 0; - buf = slot->data; - + /* + * Wait for transfer to complete before returning. Otherwise, the EmitStop + * request might be sent when the transfer is not complete. + */ ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val, SVC_I3C_MSTATUS_COMPLETE(val), 0, 1000); if (ret) { dev_err(master->dev, "Timeout when polling for COMPLETE\n"); - i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); return ret; } + slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); + if (!slot) { + dev_dbg(master->dev, "No free ibi slot, drop the data\n"); + writel(SVC_I3C_MDATACTRL_FLUSHRB, master->regs + SVC_I3C_MDATACTRL); + return -ENOSPC; + } + + slot->len = 0; + buf = slot->data; + while (SVC_I3C_MSTATUS_RXPEND(readl(master->regs + SVC_I3C_MSTATUS)) && slot->len < SVC_I3C_FIFO_SIZE) { mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL); From 553d18c98a896094b99a01765b9698b204183d49 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 29 Oct 2025 21:01:39 -0700 Subject: [PATCH 188/684] perf lock contention: Load kernel map before lookup On some machines, it caused troubles when it tried to find kernel symbols. I think it's because kernel modules and kallsyms are messed up during load and split. Basically we want to make sure the kernel map is loaded and the code has it in the lock_contention_read(). But recently we added more lookups in the lock_contention_prepare() which is called before _read(). Also the kernel map (kallsyms) may not be the first one in the group like on ARM. Let's use machine__kernel_map() rather than just loading the first map. Reviewed-by: Ian Rogers Fixes: 688d2e8de231c54e ("perf lock contention: Add -l/--lock-addr option") Signed-off-by: Namhyung Kim --- tools/perf/util/bpf_lock_contention.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c index 60b81d586323f3..7b5671f13c5352 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -184,6 +184,9 @@ int lock_contention_prepare(struct lock_contention *con) struct evlist *evlist = con->evlist; struct target *target = con->target; + /* make sure it loads the kernel map before lookup */ + map__load(machine__kernel_map(con->machine)); + skel = lock_contention_bpf__open(); if (!skel) { pr_err("Failed to open lock-contention BPF skeleton\n"); @@ -749,9 +752,6 @@ int lock_contention_read(struct lock_contention *con) bpf_prog_test_run_opts(prog_fd, &opts); } - /* make sure it loads the kernel map */ - maps__load_first(machine->kmaps); - prev_key = NULL; while (!bpf_map_get_next_key(fd, prev_key, &key)) { s64 ls_key; From 163e5f2b96632b7fb2eaa965562aca0dbdf9f996 Mon Sep 17 00:00:00 2001 From: Shuai Xue Date: Thu, 23 Oct 2025 09:50:43 +0800 Subject: [PATCH 189/684] perf record: skip synthesize event when open evsel failed When using perf record with the `--overwrite` option, a segmentation fault occurs if an event fails to open. For example: perf record -e cycles-ct -F 1000 -a --overwrite Error: cycles-ct:H: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat' perf: Segmentation fault #0 0x6466b6 in dump_stack debug.c:366 #1 0x646729 in sighandler_dump_stack debug.c:378 #2 0x453fd1 in sigsegv_handler builtin-record.c:722 #3 0x7f8454e65090 in __restore_rt libc-2.32.so[54090] #4 0x6c5671 in __perf_event__synthesize_id_index synthetic-events.c:1862 #5 0x6c5ac0 in perf_event__synthesize_id_index synthetic-events.c:1943 #6 0x458090 in record__synthesize builtin-record.c:2075 #7 0x45a85a in __cmd_record builtin-record.c:2888 #8 0x45deb6 in cmd_record builtin-record.c:4374 #9 0x4e5e33 in run_builtin perf.c:349 #10 0x4e60bf in handle_internal_command perf.c:401 #11 0x4e6215 in run_argv perf.c:448 #12 0x4e653a in main perf.c:555 #13 0x7f8454e4fa72 in __libc_start_main libc-2.32.so[3ea72] #14 0x43a3ee in _start ??:0 The --overwrite option implies --tail-synthesize, which collects non-sample events reflecting the system status when recording finishes. However, when evsel opening fails (e.g., unsupported event 'cycles-ct'), session->evlist is not initialized and remains NULL. The code unconditionally calls record__synthesize() in the error path, which iterates through the NULL evlist pointer and causes a segfault. To fix it, move the record__synthesize() call inside the error check block, so it's only called when there was no error during recording, ensuring that evlist is properly initialized. Fixes: 4ea648aec019 ("perf record: Add --tail-synthesize option") Signed-off-by: Shuai Xue Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index cb52aea9607d46..ffb94a8339b03e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2958,11 +2958,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) rec->bytes_written += off_cpu_write(rec->session); record__read_lost_samples(rec); - record__synthesize(rec, true); /* this will be recalculated during process_buildids() */ rec->samples = 0; if (!err) { + record__synthesize(rec, true); if (!rec->timestamp_filename) { record__finish_output(rec); } else { From 1d7f783809fc5fdd60c9cc4f5c880d0c9e47857d Mon Sep 17 00:00:00 2001 From: Chu Guangqing Date: Fri, 31 Oct 2025 11:17:29 +0800 Subject: [PATCH 190/684] perf vendor events arm64: Fix typo in Ampere eMag json file Correct instruction spelling errors. Signed-off-by: Chu Guangqing Reviewed-by: James Clark Reviewed-by: Ilkka Koskinen Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json index 4cc50b7da52648..4001cc5753a775 100644 --- a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json @@ -81,7 +81,7 @@ "BriefDescription": "L2D TLB access" }, { - "PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count", + "PublicDescription": "Level 2 access to instruction TLB that caused a page table walk. This event counts on any instruction access which causes L2I_TLB_REFILL to count", "EventCode": "0x35", "EventName": "L2I_TLB_ACCESS", "BriefDescription": "L2I TLB access" From 0d1e63183d5ce63f7a57a99cbee1018f2a72d202 Mon Sep 17 00:00:00 2001 From: Chu Guangqing Date: Fri, 31 Oct 2025 10:58:10 +0800 Subject: [PATCH 191/684] perf vendor events AmpereOneX: Fix spelling typo in the metrics file The json file incorrectly used "acceses" instead of "accesses". Signed-off-by: Chu Guangqing Reviewed-by: James Clark Reviewed-by: Ilkka Koskinen Signed-off-by: Namhyung Kim --- .../arch/arm64/ampere/ampereonex/metrics.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json index 6817cac149e0bc..a29aadc9b2e39a 100644 --- a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json +++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json @@ -388,55 +388,55 @@ "MetricExpr": "L1D_CACHE_RW / L1D_CACHE", "BriefDescription": "L1D cache access - demand", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "l1d_cache_access_prefetches", "MetricExpr": "L1D_CACHE_PRFM / L1D_CACHE", "BriefDescription": "L1D cache access - prefetch", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "l1d_cache_demand_misses", "MetricExpr": "L1D_CACHE_REFILL_RW / L1D_CACHE", "BriefDescription": "L1D cache demand misses", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "l1d_cache_demand_misses_read", "MetricExpr": "L1D_CACHE_REFILL_RD / L1D_CACHE", "BriefDescription": "L1D cache demand misses - read", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "l1d_cache_demand_misses_write", "MetricExpr": "L1D_CACHE_REFILL_WR / L1D_CACHE", "BriefDescription": "L1D cache demand misses - write", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "l1d_cache_prefetch_misses", "MetricExpr": "L1D_CACHE_REFILL_PRFM / L1D_CACHE", "BriefDescription": "L1D cache prefetch misses", "MetricGroup": "Cache", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "ase_scalar_mix", "MetricExpr": "ASE_SCALAR_SPEC / OP_SPEC", "BriefDescription": "Proportion of advanced SIMD data processing operations (excluding DP_SPEC/LD_SPEC) scalar operations", "MetricGroup": "Instructions", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" }, { "MetricName": "ase_vector_mix", "MetricExpr": "ASE_VECTOR_SPEC / OP_SPEC", "BriefDescription": "Proportion of advanced SIMD data processing operations (excluding DP_SPEC/LD_SPEC) vector operations", "MetricGroup": "Instructions", - "ScaleUnit": "100percent of cache acceses" + "ScaleUnit": "100percent of cache accesses" } ] From 915c31f0e69255897225d244e04374082d36de7f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 19 May 2025 16:25:39 -0700 Subject: [PATCH 192/684] perf trace: Increase syscall handler map size to 1024 The syscalls_sys_{enter,exit} map in augmented_raw_syscalls.bpf.c has max entries of 512. Usually syscall numbers are smaller than this but x86 has x32 ABI where syscalls start from 512. That makes trace__init_syscalls_bpf_prog_array_maps() fail in the middle of the loop when it accesses those keys. As the loop iteration is not ordered by syscall numbers anymore, the failure can affect non-x32 syscalls. Let's increase the map size to 1024 so that it can handle those ABIs too. While most systems won't need this, increasing the size will be safer for potential future changes. Reviewed-by: Howard Chu Signed-off-by: Namhyung Kim --- tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c index cb86e261b4de06..2a6e61864ee015 100644 --- a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c +++ b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c @@ -45,7 +45,7 @@ struct syscalls_sys_enter { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); __type(key, __u32); __type(value, __u32); - __uint(max_entries, 512); + __uint(max_entries, 1024); } syscalls_sys_enter SEC(".maps"); /* @@ -57,7 +57,7 @@ struct syscalls_sys_exit { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); __type(key, __u32); __type(value, __u32); - __uint(max_entries, 512); + __uint(max_entries, 1024); } syscalls_sys_exit SEC(".maps"); struct syscall_enter_args { From 01bc5d2f0d7db895739fccfbdf69cf68dddb9072 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 31 Oct 2025 12:42:16 -0700 Subject: [PATCH 193/684] perf tools: Cache counter names for raw samples on s390 Searching all event names is slower now that legacy names are included. Add a cache to avoid long iterative searches. Note, the cache isn't cleaned up and is as such a memory leak, however, globally reachable leaks like this aren't treated as leaks by leak sanitizer. Reported-by: Thomas Richter Closes: https://lore.kernel.org/linux-perf-users/09943f4f-516c-4b93-877c-e4a64ed61d38@linux.ibm.com/ Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/util/s390-sample-raw.c | 55 ++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 335217bb532b42..c6ae0ae8d86a39 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -19,12 +19,14 @@ #include #include +#include #include #include "debug.h" #include "session.h" #include "evlist.h" #include "color.h" +#include "hashmap.h" #include "sample-raw.h" #include "s390-cpumcf-kernel.h" #include "util/pmu.h" @@ -132,8 +134,8 @@ static int get_counterset_start(int setnr) } struct get_counter_name_data { - int wanted; - char *result; + long wanted; + const char *result; }; static int get_counter_name_callback(void *vdata, struct pmu_event_info *info) @@ -151,12 +153,22 @@ static int get_counter_name_callback(void *vdata, struct pmu_event_info *info) rc = sscanf(event_str, "event=%x", &event_nr); if (rc == 1 && event_nr == data->wanted) { - data->result = strdup(info->name); + data->result = info->name; return 1; /* Terminate the search. */ } return 0; } +static size_t get_counter_name_hash_fn(long key, void *ctx __maybe_unused) +{ + return key; +} + +static bool get_counter_name_hashmap_equal_fn(long key1, long key2, void *ctx __maybe_unused) +{ + return key1 == key2; +} + /* Scan the PMU and extract the logical name of a counter from the event. Input * is the counter set and counter number with in the set. Construct the event * number and use this as key. If they match return the name of this counter. @@ -164,17 +176,50 @@ static int get_counter_name_callback(void *vdata, struct pmu_event_info *info) */ static char *get_counter_name(int set, int nr, struct perf_pmu *pmu) { + static struct hashmap *cache; + static struct perf_pmu *cache_pmu; + long cache_key = get_counterset_start(set) + nr; struct get_counter_name_data data = { - .wanted = get_counterset_start(set) + nr, + .wanted = cache_key, .result = NULL, }; + char *result = NULL; if (!pmu) return NULL; + if (cache_pmu == pmu && hashmap__find(cache, cache_key, &result)) + return strdup(result); + perf_pmu__for_each_event(pmu, /*skip_duplicate_pmus=*/ true, &data, get_counter_name_callback); - return data.result; + + result = strdup(data.result ?: ""); + + if (cache_pmu == NULL) { + struct hashmap *tmp = hashmap__new(get_counter_name_hash_fn, + get_counter_name_hashmap_equal_fn, + /*ctx=*/NULL); + + if (!IS_ERR(tmp)) { + cache = tmp; + cache_pmu = pmu; + } + } + + if (cache_pmu == pmu && result) { + char *old_value = NULL, *new_value = strdup(result); + + if (new_value) { + hashmap__set(cache, cache_key, new_value, /*old_key=*/NULL, &old_value); + /* + * Free in case of a race, but resizing would be broken + * in that case. + */ + free(old_value); + } + } + return result; } static void s390_cpumcfdg_dump(struct perf_pmu *pmu, struct perf_sample *sample) From a4aa1ceb89f5c0d27a55671d88699cf5eae7331b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 31 Oct 2025 15:32:25 +0530 Subject: [PATCH 194/684] clk: qcom: tcsrcc-glymur: Update register offsets for clock refs Update the register offsets for all the clock ref branches to match the new address mapping in the TCSR subsystem. Fixes: 2c1d6ce4f3da ("clk: qcom: Add TCSR clock driver for Glymur SoC") Signed-off-by: Taniya Das Reviewed-by: Abel Vesa Tested-by: Jagadeesh Kona Link: https://lore.kernel.org/r/20251031-tcsrcc_glymur-v1-1-0efb031f0ac5@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/tcsrcc-glymur.c | 54 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/clk/qcom/tcsrcc-glymur.c b/drivers/clk/qcom/tcsrcc-glymur.c index c1f8b6d10b7fd6..215bc2ac548da8 100644 --- a/drivers/clk/qcom/tcsrcc-glymur.c +++ b/drivers/clk/qcom/tcsrcc-glymur.c @@ -28,10 +28,10 @@ enum { }; static struct clk_branch tcsr_edp_clkref_en = { - .halt_reg = 0x1c, + .halt_reg = 0x60, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x1c, + .enable_reg = 0x60, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_edp_clkref_en", @@ -45,10 +45,10 @@ static struct clk_branch tcsr_edp_clkref_en = { }; static struct clk_branch tcsr_pcie_1_clkref_en = { - .halt_reg = 0x4, + .halt_reg = 0x48, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x4, + .enable_reg = 0x48, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_pcie_1_clkref_en", @@ -62,10 +62,10 @@ static struct clk_branch tcsr_pcie_1_clkref_en = { }; static struct clk_branch tcsr_pcie_2_clkref_en = { - .halt_reg = 0x8, + .halt_reg = 0x4c, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x8, + .enable_reg = 0x4c, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_pcie_2_clkref_en", @@ -79,10 +79,10 @@ static struct clk_branch tcsr_pcie_2_clkref_en = { }; static struct clk_branch tcsr_pcie_3_clkref_en = { - .halt_reg = 0x10, + .halt_reg = 0x54, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x10, + .enable_reg = 0x54, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_pcie_3_clkref_en", @@ -96,10 +96,10 @@ static struct clk_branch tcsr_pcie_3_clkref_en = { }; static struct clk_branch tcsr_pcie_4_clkref_en = { - .halt_reg = 0x14, + .halt_reg = 0x58, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x14, + .enable_reg = 0x58, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_pcie_4_clkref_en", @@ -113,10 +113,10 @@ static struct clk_branch tcsr_pcie_4_clkref_en = { }; static struct clk_branch tcsr_usb2_1_clkref_en = { - .halt_reg = 0x28, + .halt_reg = 0x6c, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x28, + .enable_reg = 0x6c, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb2_1_clkref_en", @@ -130,10 +130,10 @@ static struct clk_branch tcsr_usb2_1_clkref_en = { }; static struct clk_branch tcsr_usb2_2_clkref_en = { - .halt_reg = 0x2c, + .halt_reg = 0x70, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x2c, + .enable_reg = 0x70, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb2_2_clkref_en", @@ -147,10 +147,10 @@ static struct clk_branch tcsr_usb2_2_clkref_en = { }; static struct clk_branch tcsr_usb2_3_clkref_en = { - .halt_reg = 0x30, + .halt_reg = 0x74, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x30, + .enable_reg = 0x74, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb2_3_clkref_en", @@ -164,10 +164,10 @@ static struct clk_branch tcsr_usb2_3_clkref_en = { }; static struct clk_branch tcsr_usb2_4_clkref_en = { - .halt_reg = 0x44, + .halt_reg = 0x88, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x44, + .enable_reg = 0x88, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb2_4_clkref_en", @@ -181,10 +181,10 @@ static struct clk_branch tcsr_usb2_4_clkref_en = { }; static struct clk_branch tcsr_usb3_0_clkref_en = { - .halt_reg = 0x20, + .halt_reg = 0x64, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x20, + .enable_reg = 0x64, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb3_0_clkref_en", @@ -198,10 +198,10 @@ static struct clk_branch tcsr_usb3_0_clkref_en = { }; static struct clk_branch tcsr_usb3_1_clkref_en = { - .halt_reg = 0x24, + .halt_reg = 0x68, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x24, + .enable_reg = 0x68, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb3_1_clkref_en", @@ -215,10 +215,10 @@ static struct clk_branch tcsr_usb3_1_clkref_en = { }; static struct clk_branch tcsr_usb4_1_clkref_en = { - .halt_reg = 0x0, + .halt_reg = 0x44, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x0, + .enable_reg = 0x44, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb4_1_clkref_en", @@ -232,10 +232,10 @@ static struct clk_branch tcsr_usb4_1_clkref_en = { }; static struct clk_branch tcsr_usb4_2_clkref_en = { - .halt_reg = 0x18, + .halt_reg = 0x5c, .halt_check = BRANCH_HALT_DELAY, .clkr = { - .enable_reg = 0x18, + .enable_reg = 0x5c, .enable_mask = BIT(0), .hw.init = &(const struct clk_init_data) { .name = "tcsr_usb4_2_clkref_en", @@ -268,7 +268,7 @@ static const struct regmap_config tcsr_cc_glymur_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x44, + .max_register = 0x94, .fast_io = true, }; From eb43534ee4bbfdd0fc134ee245a773555480937b Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 29 Oct 2025 16:11:18 +0000 Subject: [PATCH 195/684] dt-bindings: clk: microchip: mpfs: remove first reg region The first reg region in this binding is not exclusively for clocks, as evidenced by the dual role of this device as a reset controller at present. The first region is however better described by a simple-mfd syscon, but this would have require a significant re-write of the devicetree for the platform, so the easy way out was chosen when reset support was first introduced. The region doesn't just contain clock and reset registers, it also contains pinctrl and interrupt controller functionality, so drop the region from the clock binding so that it can be described instead by a simple-mfd syscon rather than propagate this incorrect description of the hardware to the new pic64gx SoC. Acked-by: Rob Herring (Arm) Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20251029-unwatched-family-e47cb29ea815@spud Signed-off-by: Claudiu Beznea --- .../bindings/clock/microchip,mpfs-clkcfg.yaml | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml index e4e1c31267d2a1..ee4f31596d9788 100644 --- a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml +++ b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml @@ -22,16 +22,23 @@ properties: const: microchip,mpfs-clkcfg reg: - items: - - description: | - clock config registers: - These registers contain enable, reset & divider tables for the, cpu, - axi, ahb and rtc/mtimer reference clocks as well as enable and reset - for the peripheral clocks. - - description: | - mss pll dri registers: - Block of registers responsible for dynamic reconfiguration of the mss - pll + oneOf: + - items: + - description: | + clock config registers: + These registers contain enable, reset & divider tables for the, cpu, + axi, ahb and rtc/mtimer reference clocks as well as enable and reset + for the peripheral clocks. + - description: | + mss pll dri registers: + Block of registers responsible for dynamic reconfiguration of the mss + pll + deprecated: true + - items: + - description: | + mss pll dri registers: + Block of registers responsible for dynamic reconfiguration of the mss + pll clocks: maxItems: 1 @@ -69,11 +76,12 @@ examples: - | #include soc { - #address-cells = <2>; - #size-cells = <2>; - clkcfg: clock-controller@20002000 { + #address-cells = <1>; + #size-cells = <1>; + + clkcfg: clock-controller@3E001000 { compatible = "microchip,mpfs-clkcfg"; - reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>; + reg = <0x3E001000 0x1000>; clocks = <&ref>; #clock-cells = <1>; }; From c6f2dddfa7f9579eeab67690def4be8094b4336d Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 29 Oct 2025 16:11:19 +0000 Subject: [PATCH 196/684] clk: microchip: mpfs: use regmap for clocks Convert the PolarFire SoC clock driver to use regmaps instead of iomem addresses as a preparatory work for supporting the new binding for this device that will only provide the second of the two register regions, and will require the use of syscon regmap to access the "cfg" and "periph" clocks currently supported by the driver. This is effectively a revert of commit 4da2404bb003 ("clk: microchip: mpfs: convert cfg_clk to clk_divider") and commit d815569783e6 ("clk: microchip: mpfs: convert periph_clk to clk_gate") as it resurrects the ops structures removed in those commits, with the readl()s and writel()s replaced by regmap_read()s and regmap_writes()s. Signed-off-by: Conor Dooley Reviewed-by: Claudiu Beznea Link: https://lore.kernel.org/r/20251029-surfboard-refocus-ca9b135ab123@spud Signed-off-by: Claudiu Beznea --- drivers/clk/microchip/Kconfig | 2 + drivers/clk/microchip/clk-mpfs.c | 227 +++++++++++++++++++++++++------ 2 files changed, 186 insertions(+), 43 deletions(-) diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig index 0724ce65898f3c..1b9e43eb54976b 100644 --- a/drivers/clk/microchip/Kconfig +++ b/drivers/clk/microchip/Kconfig @@ -7,6 +7,8 @@ config MCHP_CLK_MPFS bool "Clk driver for PolarFire SoC" depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST default ARCH_MICROCHIP_POLARFIRE + depends on MFD_SYSCON select AUXILIARY_BUS + select REGMAP_MMIO help Supports Clock Configuration for PolarFire SoC diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c index c22632a7439c5d..484893e68b6772 100644 --- a/drivers/clk/microchip/clk-mpfs.c +++ b/drivers/clk/microchip/clk-mpfs.c @@ -4,10 +4,13 @@ * * Copyright (C) 2020-2022 Microchip Technology Inc. All rights reserved. */ +#include #include #include +#include #include #include +#include #include #include @@ -30,6 +33,14 @@ #define MSSPLL_POSTDIV_WIDTH 0x07u #define MSSPLL_FIXED_DIV 4u +static const struct regmap_config mpfs_clk_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .max_register = REG_SUBBLK_CLOCK_CR, +}; + /* * This clock ID is defined here, rather than the binding headers, as it is an * internal clock only, and therefore has no consumers in other peripheral @@ -39,6 +50,7 @@ struct mpfs_clock_data { struct device *dev; + struct regmap *regmap; void __iomem *base; void __iomem *msspll_base; struct clk_hw_onecell_data hw_data; @@ -67,21 +79,39 @@ struct mpfs_msspll_out_hw_clock { #define to_mpfs_msspll_out_clk(_hw) container_of(_hw, struct mpfs_msspll_out_hw_clock, hw) +struct mpfs_cfg_clock { + struct regmap *map; + const struct clk_div_table *table; + u8 map_offset; + u8 shift; + u8 width; + u8 flags; +}; + struct mpfs_cfg_hw_clock { - struct clk_divider cfg; - struct clk_init_data init; + struct clk_hw hw; + struct mpfs_cfg_clock cfg; unsigned int id; - u32 reg_offset; +}; + +#define to_mpfs_cfg_clk(_hw) container_of(_hw, struct mpfs_cfg_hw_clock, hw) + +struct mpfs_periph_clock { + struct regmap *map; + u8 map_offset; + u8 shift; }; struct mpfs_periph_hw_clock { - struct clk_gate periph; + struct clk_hw hw; + struct mpfs_periph_clock periph; unsigned int id; }; +#define to_mpfs_periph_clk(_hw) container_of(_hw, struct mpfs_periph_hw_clock, hw) + /* - * mpfs_clk_lock prevents anything else from writing to the - * mpfs clk block while a software locked register is being written. + * Protects MSSPLL outputs, since there's two to a register */ static DEFINE_SPINLOCK(mpfs_clk_lock); @@ -219,16 +249,61 @@ static int mpfs_clk_register_msspll_outs(struct device *dev, /* * "CFG" clocks */ +static unsigned long mpfs_cfg_clk_recalc_rate(struct clk_hw *hw, unsigned long prate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + u32 val; -#define CLK_CFG(_id, _name, _parent, _shift, _width, _table, _flags, _offset) { \ - .id = _id, \ - .cfg.shift = _shift, \ - .cfg.width = _width, \ - .cfg.table = _table, \ - .reg_offset = _offset, \ - .cfg.flags = _flags, \ - .cfg.hw.init = CLK_HW_INIT(_name, _parent, &clk_divider_ops, 0), \ - .cfg.lock = &mpfs_clk_lock, \ + regmap_read(cfg->map, cfg->map_offset, &val); + val >>= cfg->shift; + val &= clk_div_mask(cfg->width); + + return divider_recalc_rate(hw, prate, val, cfg->table, cfg->flags, cfg->width); +} + +static int mpfs_cfg_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + + return divider_determine_rate(hw, req, cfg->table, cfg->width, 0); +} + +static int mpfs_cfg_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + int divider_setting; + u32 val; + u32 mask; + + divider_setting = divider_get_val(rate, prate, cfg->table, cfg->width, 0); + + if (divider_setting < 0) + return divider_setting; + + mask = clk_div_mask(cfg->width) << cfg->shift; + val = divider_setting << cfg->shift; + regmap_update_bits(cfg->map, cfg->map_offset, val, mask); + + return 0; +} + +static const struct clk_ops mpfs_clk_cfg_ops = { + .recalc_rate = mpfs_cfg_clk_recalc_rate, + .determine_rate = mpfs_cfg_clk_determine_rate, + .set_rate = mpfs_cfg_clk_set_rate, +}; + +#define CLK_CFG(_id, _name, _parent, _shift, _width, _table, _flags, _offset) { \ + .id = _id, \ + .cfg.shift = _shift, \ + .cfg.width = _width, \ + .cfg.table = _table, \ + .cfg.map_offset = _offset, \ + .cfg.flags = _flags, \ + .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_cfg_ops, 0), \ } #define CLK_CPU_OFFSET 0u @@ -248,10 +323,10 @@ static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = { .cfg.shift = 0, .cfg.width = 12, .cfg.table = mpfs_div_rtcref_table, - .reg_offset = REG_RTC_CLOCK_CR, + .cfg.map_offset = REG_RTC_CLOCK_CR, .cfg.flags = CLK_DIVIDER_ONE_BASED, - .cfg.hw.init = - CLK_HW_INIT_PARENTS_DATA("clk_rtcref", mpfs_ext_ref, &clk_divider_ops, 0), + .hw.init = + CLK_HW_INIT_PARENTS_DATA("clk_rtcref", mpfs_ext_ref, &mpfs_clk_cfg_ops, 0), } }; @@ -264,14 +339,14 @@ static int mpfs_clk_register_cfgs(struct device *dev, struct mpfs_cfg_hw_clock * for (i = 0; i < num_clks; i++) { struct mpfs_cfg_hw_clock *cfg_hw = &cfg_hws[i]; - cfg_hw->cfg.reg = data->base + cfg_hw->reg_offset; - ret = devm_clk_hw_register(dev, &cfg_hw->cfg.hw); + cfg_hw->cfg.map = data->regmap; + ret = devm_clk_hw_register(dev, &cfg_hw->hw); if (ret) return dev_err_probe(dev, ret, "failed to register clock id: %d\n", cfg_hw->id); id = cfg_hw->id; - data->hw_data.hws[id] = &cfg_hw->cfg.hw; + data->hw_data.hws[id] = &cfg_hw->hw; } return 0; @@ -281,15 +356,50 @@ static int mpfs_clk_register_cfgs(struct device *dev, struct mpfs_cfg_hw_clock * * peripheral clocks - devices connected to axi or ahb buses. */ -#define CLK_PERIPH(_id, _name, _parent, _shift, _flags) { \ - .id = _id, \ - .periph.bit_idx = _shift, \ - .periph.hw.init = CLK_HW_INIT_HW(_name, _parent, &clk_gate_ops, \ - _flags), \ - .periph.lock = &mpfs_clk_lock, \ +static int mpfs_periph_clk_enable(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + + regmap_update_bits(periph->map, periph->map_offset, + BIT(periph->shift), BIT(periph->shift)); + + return 0; } -#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].cfg.hw) +static void mpfs_periph_clk_disable(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + + regmap_update_bits(periph->map, periph->map_offset, BIT(periph->shift), 0); +} + +static int mpfs_periph_clk_is_enabled(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + u32 val; + + regmap_read(periph->map, periph->map_offset, &val); + + return !!(val & BIT(periph->shift)); +} + +static const struct clk_ops mpfs_periph_clk_ops = { + .enable = mpfs_periph_clk_enable, + .disable = mpfs_periph_clk_disable, + .is_enabled = mpfs_periph_clk_is_enabled, +}; + +#define CLK_PERIPH(_id, _name, _parent, _shift, _flags) { \ + .id = _id, \ + .periph.map_offset = REG_SUBBLK_CLOCK_CR, \ + .periph.shift = _shift, \ + .hw.init = CLK_HW_INIT_HW(_name, _parent, &mpfs_periph_clk_ops, _flags), \ +} + +#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].hw) /* * Critical clocks: @@ -346,19 +456,55 @@ static int mpfs_clk_register_periphs(struct device *dev, struct mpfs_periph_hw_c for (i = 0; i < num_clks; i++) { struct mpfs_periph_hw_clock *periph_hw = &periph_hws[i]; - periph_hw->periph.reg = data->base + REG_SUBBLK_CLOCK_CR; - ret = devm_clk_hw_register(dev, &periph_hw->periph.hw); + periph_hw->periph.map = data->regmap; + ret = devm_clk_hw_register(dev, &periph_hw->hw); if (ret) return dev_err_probe(dev, ret, "failed to register clock id: %d\n", periph_hw->id); id = periph_hws[i].id; - data->hw_data.hws[id] = &periph_hw->periph.hw; + data->hw_data.hws[id] = &periph_hw->hw; } return 0; } +static inline int mpfs_clk_syscon_probe(struct mpfs_clock_data *clk_data, + struct platform_device *pdev) +{ + clk_data->regmap = syscon_regmap_lookup_by_compatible("microchip,mpfs-mss-top-sysreg"); + if (IS_ERR(clk_data->regmap)) + return PTR_ERR(clk_data->regmap); + + clk_data->msspll_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(clk_data->msspll_base)) + return PTR_ERR(clk_data->msspll_base); + + return 0; +} + +static inline int mpfs_clk_old_format_probe(struct mpfs_clock_data *clk_data, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + dev_warn(&pdev->dev, "falling back to old devicetree format"); + + clk_data->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(clk_data->base)) + return PTR_ERR(clk_data->base); + + clk_data->msspll_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(clk_data->msspll_base)) + return PTR_ERR(clk_data->msspll_base); + + clk_data->regmap = devm_regmap_init_mmio(dev, clk_data->base, &mpfs_clk_regmap_config); + if (IS_ERR(clk_data->regmap)) + return PTR_ERR(clk_data->regmap); + + return mpfs_reset_controller_register(dev, clk_data->base + REG_SUBBLK_RESET_CR); +} + static int mpfs_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -374,13 +520,12 @@ static int mpfs_clk_probe(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - clk_data->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(clk_data->base)) - return PTR_ERR(clk_data->base); - - clk_data->msspll_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(clk_data->msspll_base)) - return PTR_ERR(clk_data->msspll_base); + ret = mpfs_clk_syscon_probe(clk_data, pdev); + if (ret) { + ret = mpfs_clk_old_format_probe(clk_data, pdev); + if (ret) + return ret; + } clk_data->hw_data.num = num_clks; clk_data->dev = dev; @@ -406,11 +551,7 @@ static int mpfs_clk_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &clk_data->hw_data); - if (ret) - return ret; - - return mpfs_reset_controller_register(dev, clk_data->base + REG_SUBBLK_RESET_CR); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &clk_data->hw_data); } static const struct of_device_id mpfs_clk_of_match_table[] = { From e21d451a82f39e91b7635c4fc3ff5ac082873ec3 Mon Sep 17 00:00:00 2001 From: Pierre Barre Date: Thu, 16 Oct 2025 15:58:36 +0200 Subject: [PATCH 197/684] 9p: Use kvmalloc for message buffers on supported transports While developing a 9P server (https://github.com/Barre/ZeroFS) and testing it under high-load, I was running into allocation failures. The failures occur even with plenty of free memory available because kmalloc requires contiguous physical memory. This results in errors like: ls: page allocation failure: order:7, mode:0x40c40(GFP_NOFS|__GFP_COMP) This patch introduces a transport capability flag (supports_vmalloc) that indicates whether a transport can work with vmalloc'd buffers (non-physically contiguous memory). Transports requiring DMA should leave this flag as false. The fd-based transports (tcp, unix, fd) set this flag to true, and p9_fcall_init will use kvmalloc instead of kmalloc for these transports. This allows the allocator to fall back to vmalloc when contiguous physical memory is not available. Additionally, if kmem_cache_alloc fails, the code falls back to kvmalloc for transports that support it. Signed-off-by: Pierre Barre Reviewed-by: Christian Schoenebeck Message-ID: Signed-off-by: Dominique Martinet --- include/net/9p/transport.h | 4 ++++ net/9p/client.c | 11 +++++++++-- net/9p/trans_fd.c | 3 +++ net/9p/trans_rdma.c | 1 + net/9p/trans_usbg.c | 1 + net/9p/trans_virtio.c | 1 + net/9p/trans_xen.c | 1 + 7 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 766ec07c95999d..f0981515148d69 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -24,6 +24,9 @@ * we're less flexible when choosing the response message * size in this case * @def: set if this transport should be considered the default + * @supports_vmalloc: set if this transport can work with vmalloc'd buffers + * (non-physically contiguous memory). Transports requiring + * DMA should leave this as false. * @create: member function to create a new connection on this transport * @close: member function to discard a connection on this transport * @request: member function to issue a request to the transport @@ -44,6 +47,7 @@ struct p9_trans_module { int maxsize; /* max message size of transport */ bool pooled_rbuffers; int def; /* this transport should be default */ + bool supports_vmalloc; /* can work with vmalloc'd buffers */ struct module *owner; int (*create)(struct p9_client *client, const char *devname, char *args); diff --git a/net/9p/client.c b/net/9p/client.c index 5c1ca57ccd2853..2a4884c880c1f0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -229,8 +229,15 @@ static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc, if (likely(c->fcall_cache) && alloc_msize == c->msize) { fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS); fc->cache = c->fcall_cache; + if (!fc->sdata && c->trans_mod->supports_vmalloc) { + fc->sdata = kvmalloc(alloc_msize, GFP_NOFS); + fc->cache = NULL; + } } else { - fc->sdata = kmalloc(alloc_msize, GFP_NOFS); + if (c->trans_mod->supports_vmalloc) + fc->sdata = kvmalloc(alloc_msize, GFP_NOFS); + else + fc->sdata = kmalloc(alloc_msize, GFP_NOFS); fc->cache = NULL; } if (!fc->sdata) @@ -252,7 +259,7 @@ void p9_fcall_fini(struct p9_fcall *fc) if (fc->cache) kmem_cache_free(fc->cache, fc->sdata); else - kfree(fc->sdata); + kvfree(fc->sdata); } EXPORT_SYMBOL(p9_fcall_fini); diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a516745f732f71..e7334033eba5ae 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1101,6 +1101,7 @@ static struct p9_trans_module p9_tcp_trans = { .maxsize = MAX_SOCK_BUF, .pooled_rbuffers = false, .def = 0, + .supports_vmalloc = true, .create = p9_fd_create_tcp, .close = p9_fd_close, .request = p9_fd_request, @@ -1115,6 +1116,7 @@ static struct p9_trans_module p9_unix_trans = { .name = "unix", .maxsize = MAX_SOCK_BUF, .def = 0, + .supports_vmalloc = true, .create = p9_fd_create_unix, .close = p9_fd_close, .request = p9_fd_request, @@ -1129,6 +1131,7 @@ static struct p9_trans_module p9_fd_trans = { .name = "fd", .maxsize = MAX_SOCK_BUF, .def = 0, + .supports_vmalloc = true, .create = p9_fd_create, .close = p9_fd_close, .request = p9_fd_request, diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index b84748baf9cbe3..6c5ad232c19463 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -749,6 +749,7 @@ static struct p9_trans_module p9_rdma_trans = { .maxsize = P9_RDMA_MAXSIZE, .pooled_rbuffers = true, .def = 0, + .supports_vmalloc = false, .owner = THIS_MODULE, .create = rdma_create_trans, .close = rdma_close, diff --git a/net/9p/trans_usbg.c b/net/9p/trans_usbg.c index 468f7e8f0277b9..2542ef09923339 100644 --- a/net/9p/trans_usbg.c +++ b/net/9p/trans_usbg.c @@ -514,6 +514,7 @@ static struct p9_trans_module p9_usbg_trans = { .close = p9_usbg_close, .request = p9_usbg_request, .cancel = p9_usbg_cancel, + .supports_vmalloc = false, .owner = THIS_MODULE, }; diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0b8086f58ad55a..12806207f4f03c 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -803,6 +803,7 @@ static struct p9_trans_module p9_virtio_trans = { .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), .pooled_rbuffers = false, .def = 1, + .supports_vmalloc = false, .owner = THIS_MODULE, }; diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index b9ff69c7522a19..4b1cec0ab82977 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -258,6 +258,7 @@ static struct p9_trans_module p9_xen_trans = { .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT - 2), .pooled_rbuffers = false, .def = 1, + .supports_vmalloc = false, .create = p9_xen_create, .close = p9_xen_close, .request = p9_xen_request, From eeaf38a798aff6384983e5a0ac464d146de7ff55 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 31 Oct 2025 16:40:07 +0900 Subject: [PATCH 198/684] net/9p: cleanup: change p9_trans_module->def to bool '->def' is only ever used as a true/false flag Reported-by: Christophe JAILLET Message-ID: <20251103-v9fs_trans_def_bool-v1-1-f33dc7ed9e81@codewreck.org> Signed-off-by: Dominique Martinet --- include/net/9p/transport.h | 2 +- net/9p/trans_fd.c | 6 +++--- net/9p/trans_rdma.c | 2 +- net/9p/trans_virtio.c | 2 +- net/9p/trans_xen.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index f0981515148d69..0aedabc9b7ebe1 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -46,7 +46,7 @@ struct p9_trans_module { char *name; /* name of transport */ int maxsize; /* max message size of transport */ bool pooled_rbuffers; - int def; /* this transport should be default */ + bool def; /* this transport should be default */ bool supports_vmalloc; /* can work with vmalloc'd buffers */ struct module *owner; int (*create)(struct p9_client *client, diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index e7334033eba5ae..bd4903d6482710 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1100,7 +1100,7 @@ static struct p9_trans_module p9_tcp_trans = { .name = "tcp", .maxsize = MAX_SOCK_BUF, .pooled_rbuffers = false, - .def = 0, + .def = false, .supports_vmalloc = true, .create = p9_fd_create_tcp, .close = p9_fd_close, @@ -1115,7 +1115,7 @@ MODULE_ALIAS_9P("tcp"); static struct p9_trans_module p9_unix_trans = { .name = "unix", .maxsize = MAX_SOCK_BUF, - .def = 0, + .def = false, .supports_vmalloc = true, .create = p9_fd_create_unix, .close = p9_fd_close, @@ -1130,7 +1130,7 @@ MODULE_ALIAS_9P("unix"); static struct p9_trans_module p9_fd_trans = { .name = "fd", .maxsize = MAX_SOCK_BUF, - .def = 0, + .def = false, .supports_vmalloc = true, .create = p9_fd_create, .close = p9_fd_close, diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 6c5ad232c19463..a0bc766199dadf 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -748,7 +748,7 @@ static struct p9_trans_module p9_rdma_trans = { .name = "rdma", .maxsize = P9_RDMA_MAXSIZE, .pooled_rbuffers = true, - .def = 0, + .def = false, .supports_vmalloc = false, .owner = THIS_MODULE, .create = rdma_create_trans, diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 12806207f4f03c..b58f50b00c7237 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -802,7 +802,7 @@ static struct p9_trans_module p9_virtio_trans = { */ .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), .pooled_rbuffers = false, - .def = 1, + .def = true, .supports_vmalloc = false, .owner = THIS_MODULE, }; diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index 4b1cec0ab82977..9389c1247001e2 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -257,7 +257,7 @@ static struct p9_trans_module p9_xen_trans = { .name = "xen", .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT - 2), .pooled_rbuffers = false, - .def = 1, + .def = true, .supports_vmalloc = false, .create = p9_xen_create, .close = p9_xen_close, From a63dd8fd137933551bfd9aeeeaa942f04c7aad65 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Sun, 2 Nov 2025 23:56:30 +0000 Subject: [PATCH 199/684] fs/9p: Don't open remote file with APPEND mode when writeback cache is used When page cache is used, writebacks are done on a page granularity, and it is expected that the underlying filesystem (such as v9fs) should respect the write position. However, currently v9fs will passthrough O_APPEND to the server even on cached mode. This causes data corruption if a sync or fstat gets between two writes to the same file. This patch removes the APPEND flag from the open request we send to the server when writeback caching is involved. I believe keeping server-side APPEND is probably fine for uncached mode (even if two fds are opened, one without O_APPEND and one with it, this should still be fine since they would use separate fid for the writes). Signed-off-by: Tingmao Wang Fixes: 4eb3117888a9 ("fs/9p: Rework cache modes and add new options to Documentation") Message-ID: <20251102235631.8724-1-m@maowtm.org> Signed-off-by: Dominique Martinet --- fs/9p/vfs_file.c | 11 ++++++++--- fs/9p/vfs_inode.c | 3 +-- fs/9p/vfs_inode_dotl.c | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index eb0b083da269b4..d1db03093d4c3c 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -43,14 +43,18 @@ int v9fs_file_open(struct inode *inode, struct file *file) struct v9fs_session_info *v9ses; struct p9_fid *fid; int omode; + int o_append; p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); v9ses = v9fs_inode2v9ses(inode); - if (v9fs_proto_dotl(v9ses)) + if (v9fs_proto_dotl(v9ses)) { omode = v9fs_open_to_dotl_flags(file->f_flags); - else + o_append = P9_DOTL_APPEND; + } else { omode = v9fs_uflags2omode(file->f_flags, v9fs_proto_dotu(v9ses)); + o_append = P9_OAPPEND; + } fid = file->private_data; if (!fid) { fid = v9fs_fid_clone(file_dentry(file)); @@ -58,9 +62,10 @@ int v9fs_file_open(struct inode *inode, struct file *file) return PTR_ERR(fid); if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) { - int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR; + int writeback_omode = (omode & ~(P9_OWRITE | o_append)) | P9_ORDWR; p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n"); + err = p9_client_open(fid, writeback_omode); if (err < 0) { p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n"); diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index d0c77ec31b1dd6..0f3189a0a516af 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -786,7 +786,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses)); if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { - p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; + p9_omode = (p9_omode & ~(P9_OWRITE | P9_OAPPEND)) | P9_ORDWR; p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, creating w/ O_RDWR\n"); } @@ -1393,4 +1393,3 @@ static const struct inode_operations v9fs_symlink_inode_operations = { .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, }; - diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index be297e33546889..6312b3590f7438 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -282,7 +282,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, } if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { - p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; + p9_omode = (p9_omode & ~(P9_OWRITE | P9_DOTL_APPEND)) | P9_ORDWR; p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, creating w/ O_RDWR\n"); } From 52df783f33ec6df2d592dd12d0afc3265d9e37eb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 24 Oct 2025 14:26:00 +0300 Subject: [PATCH 200/684] fs/9p: delete unnnecessary condition We already know that "retval" is negative, so there is no need to check again. Also the statement is not indented far enough. Delete it. Signed-off-by: Dan Carpenter Fixes: 43c36a56ccf6 ("Revert "fs/9p: Refresh metadata in d_revalidate for uncached mode too"") Reviewed-by: Christian Schoenebeck Message-ID: Signed-off-by: Dominique Martinet --- fs/9p/vfs_dentry.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index c1acbc98465deb..c5bf74d547e842 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -109,7 +109,6 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) p9_debug(P9_DEBUG_VFS, "refresh inode: dentry = %pd (%p), got error %pe\n", dentry, dentry, ERR_PTR(retval)); - if (retval < 0) return retval; } } From 695f2ca1b4247724576d57eae7b74b90dc69ba3c Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 10 Oct 2025 16:36:16 -0500 Subject: [PATCH 201/684] fs/fs_parse: add back fsparam_u32hex 296b67059 removed fsparam_u32hex because there were no callers (yet) and it didn't build due to using the nonexistent symbol fs_param_is_u32_hex. fs/9p will need this parser, so add it back with the appropriate fix (use fs_param_is_u32). Signed-off-by: Eric Sandeen Message-ID: <20251010214222.1347785-2-sandeen@redhat.com> Signed-off-by: Dominique Martinet --- include/linux/fs_parser.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h index 5a0e897cae807b..5e8a3b5460331b 100644 --- a/include/linux/fs_parser.h +++ b/include/linux/fs_parser.h @@ -120,6 +120,8 @@ static inline bool fs_validate_description(const char *name, #define fsparam_u32(NAME, OPT) __fsparam(fs_param_is_u32, NAME, OPT, 0, NULL) #define fsparam_u32oct(NAME, OPT) \ __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8) +#define fsparam_u32hex(NAME, OPT) \ + __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)16) #define fsparam_s32(NAME, OPT) __fsparam(fs_param_is_s32, NAME, OPT, 0, NULL) #define fsparam_u64(NAME, OPT) __fsparam(fs_param_is_u64, NAME, OPT, 0, NULL) #define fsparam_enum(NAME, OPT, array) __fsparam(fs_param_is_enum, NAME, OPT, 0, array) From c44393d84149d6fc91d94fa39321c9657e91b388 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 10 Oct 2025 16:36:17 -0500 Subject: [PATCH 202/684] net/9p: move structures and macros to header files With the new mount API all option parsing will need to happen in fs/v9fs.c, so move some existing data structures and macros to header files to facilitate this. Rename some to reflect the transport they are used for (rdma, fd, etc), for clarity. Signed-off-by: Eric Sandeen Message-ID: <20251010214222.1347785-3-sandeen@redhat.com> Signed-off-by: Dominique Martinet --- include/net/9p/client.h | 6 ++++++ include/net/9p/transport.h | 39 ++++++++++++++++++++++++++++++++++++++ net/9p/client.c | 6 ------ net/9p/trans_fd.c | 20 ++----------------- net/9p/trans_rdma.c | 25 ++---------------------- 5 files changed, 49 insertions(+), 47 deletions(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 4f785098c67a14..2d46f8017bd579 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -16,6 +16,12 @@ /* Number of requests per row */ #define P9_ROW_MAXTAG 255 +/* DEFAULT MSIZE = 32 pages worth of payload + P9_HDRSZ + + * room for write (16 extra) or read (11 extra) operands. + */ + +#define DEFAULT_MSIZE ((128 * 1024) + P9_IOHDRSZ) + /** enum p9_proto_versions - 9P protocol versions * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u * @p9_proto_2000u: 9P2000.u extension diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 0aedabc9b7ebe1..db6ad369a171f9 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -14,6 +14,45 @@ #define P9_DEF_MIN_RESVPORT (665U) #define P9_DEF_MAX_RESVPORT (1023U) +#define P9_FD_PORT 564 + +#define P9_RDMA_PORT 5640 +#define P9_RDMA_SQ_DEPTH 32 +#define P9_RDMA_RQ_DEPTH 32 +#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ + +/** + * struct p9_fd_opts - per-transport options for fd transport + * @rfd: file descriptor for reading (trans=fd) + * @wfd: file descriptor for writing (trans=fd) + * @port: port to connect to (trans=tcp) + * @privport: port is privileged + */ + +struct p9_fd_opts { + int rfd; + int wfd; + u16 port; + bool privport; +}; + +/** + * struct p9_rdma_opts - Collection of mount options for rdma transport + * @port: port of connection + * @privport: Whether a privileged port may be used + * @sq_depth: The requested depth of the SQ. This really doesn't need + * to be any deeper than the number of threads used in the client + * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth + * @timeout: Time to wait in msecs for CM events + */ +struct p9_rdma_opts { + short port; + bool privport; + int sq_depth; + int rq_depth; + long timeout; +}; + /** * struct p9_trans_module - transport module interface * @list: used to maintain a list of currently available transports diff --git a/net/9p/client.c b/net/9p/client.c index 2a4884c880c1f0..802f548332a5cb 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -29,12 +29,6 @@ #define CREATE_TRACE_POINTS #include -/* DEFAULT MSIZE = 32 pages worth of payload + P9_HDRSZ + - * room for write (16 extra) or read (11 extra) operands. - */ - -#define DEFAULT_MSIZE ((128 * 1024) + P9_IOHDRSZ) - /* Client Option Parsing (code inspired by NFS code) * - a little lazy - parse all client options */ diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index bd4903d6482710..b7e5933c461736 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -31,28 +31,12 @@ #include /* killme */ -#define P9_PORT 564 #define MAX_SOCK_BUF (1024*1024) #define MAXPOLLWADDR 2 static struct p9_trans_module p9_tcp_trans; static struct p9_trans_module p9_fd_trans; -/** - * struct p9_fd_opts - per-transport options - * @rfd: file descriptor for reading (trans=fd) - * @wfd: file descriptor for writing (trans=fd) - * @port: port to connect to (trans=tcp) - * @privport: port is privileged - */ - -struct p9_fd_opts { - int rfd; - int wfd; - u16 port; - bool privport; -}; - /* * Option Parsing (code inspired by NFS code) * - a little lazy - parse all fd-transport options @@ -742,7 +726,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt) { if (clnt->trans_mod == &p9_tcp_trans) { - if (clnt->trans_opts.tcp.port != P9_PORT) + if (clnt->trans_opts.tcp.port != P9_FD_PORT) seq_printf(m, ",port=%u", clnt->trans_opts.tcp.port); } else if (clnt->trans_mod == &p9_fd_trans) { if (clnt->trans_opts.fd.rfd != ~0) @@ -768,7 +752,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) int option; char *options, *tmp_options; - opts->port = P9_PORT; + opts->port = P9_FD_PORT; opts->rfd = ~0; opts->wfd = ~0; opts->privport = false; diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index a0bc766199dadf..87246463a95465 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -32,14 +32,10 @@ #include #include -#define P9_PORT 5640 -#define P9_RDMA_SQ_DEPTH 32 -#define P9_RDMA_RQ_DEPTH 32 #define P9_RDMA_SEND_SGE 4 #define P9_RDMA_RECV_SGE 4 #define P9_RDMA_IRD 0 #define P9_RDMA_ORD 0 -#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ #define P9_RDMA_MAXSIZE (1024*1024) /* 1MB */ /** @@ -110,23 +106,6 @@ struct p9_rdma_context { }; }; -/** - * struct p9_rdma_opts - Collection of mount options - * @port: port of connection - * @privport: Whether a privileged port may be used - * @sq_depth: The requested depth of the SQ. This really doesn't need - * to be any deeper than the number of threads used in the client - * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth - * @timeout: Time to wait in msecs for CM events - */ -struct p9_rdma_opts { - short port; - bool privport; - int sq_depth; - int rq_depth; - long timeout; -}; - /* * Option Parsing (code inspired by NFS code) */ @@ -151,7 +130,7 @@ static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) { struct p9_trans_rdma *rdma = clnt->trans; - if (rdma->port != P9_PORT) + if (rdma->port != P9_RDMA_PORT) seq_printf(m, ",port=%u", rdma->port); if (rdma->sq_depth != P9_RDMA_SQ_DEPTH) seq_printf(m, ",sq=%u", rdma->sq_depth); @@ -178,7 +157,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) int option; char *options, *tmp_options; - opts->port = P9_PORT; + opts->port = P9_RDMA_PORT; opts->sq_depth = P9_RDMA_SQ_DEPTH; opts->rq_depth = P9_RDMA_RQ_DEPTH; opts->timeout = P9_RDMA_TIMEOUT; From 075e8bd4127f007910fc302ad5c3c471d0be4799 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 10 Oct 2025 16:36:18 -0500 Subject: [PATCH 203/684] 9p: create a v9fs_context structure to hold parsed options This patch creates a new v9fs_context structure which includes new p9_session_opts and p9_client_opts structures, as well as re-using the existing p9_fd_opts and p9_rdma_opts to store options during parsing. The new structure will be used in the next commit to pass all parsed options to the appropriate transports. Signed-off-by: Eric Sandeen Message-ID: <20251010214222.1347785-4-sandeen@redhat.com> Signed-off-by: Dominique Martinet --- include/net/9p/client.h | 90 ++++++++++++++++++++++++++++++++++++++ include/net/9p/transport.h | 32 -------------- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 2d46f8017bd579..cc18443f7d5165 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -132,6 +132,96 @@ struct p9_client { char name[__NEW_UTS_LEN + 1]; }; +/** + * struct p9_fd_opts - holds client options during parsing + * @msize: maximum data size negotiated by protocol + * @prot-Oversion: 9P protocol version to use + * @trans_mod: module API instantiated with this client + * + * These parsed options get transferred into client in + * apply_client_options() + */ +struct p9_client_opts { + unsigned int msize; + unsigned char proto_version; + struct p9_trans_module *trans_mod; +}; + +/** + * struct p9_fd_opts - per-transport options for fd transport + * @rfd: file descriptor for reading (trans=fd) + * @wfd: file descriptor for writing (trans=fd) + * @port: port to connect to (trans=tcp) + * @privport: port is privileged + */ +struct p9_fd_opts { + int rfd; + int wfd; + u16 port; + bool privport; +}; + +/** + * struct p9_rdma_opts - Collection of mount options for rdma transport + * @port: port of connection + * @privport: Whether a privileged port may be used + * @sq_depth: The requested depth of the SQ. This really doesn't need + * to be any deeper than the number of threads used in the client + * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth + * @timeout: Time to wait in msecs for CM events + */ +struct p9_rdma_opts { + short port; + bool privport; + int sq_depth; + int rq_depth; + long timeout; +}; + +/** + * struct p9_session_opts - holds parsed options for v9fs_session_info + * @flags: session options of type &p9_session_flags + * @nodev: set to 1 to disable device mapping + * @debug: debug level + * @afid: authentication handle + * @cache: cache mode of type &p9_cache_bits + * @cachetag: the tag of the cache associated with this session + * @uname: string user name to mount hierarchy as + * @aname: mount specifier for remote hierarchy + * @dfltuid: default numeric userid to mount hierarchy as + * @dfltgid: default numeric groupid to mount hierarchy as + * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy + * @session_lock_timeout: retry interval for blocking locks + * + * This strucure holds options which are parsed and will be transferred + * to the v9fs_session_info structure when mounted, and therefore largely + * duplicates struct v9fs_session_info. + */ +struct p9_session_opts { + unsigned int flags; + unsigned char nodev; + unsigned short debug; + unsigned int afid; + unsigned int cache; +#ifdef CONFIG_9P_FSCACHE + char *cachetag; +#endif + char *uname; + char *aname; + kuid_t dfltuid; + kgid_t dfltgid; + kuid_t uid; + long session_lock_timeout; +}; + +/* Used by mount API to store parsed mount options */ +struct v9fs_context { + struct p9_client_opts client_opts; + struct p9_fd_opts fd_opts; + struct p9_rdma_opts rdma_opts; + struct p9_session_opts session_opts; +}; + /** * struct p9_fid - file system entity handle * @clnt: back pointer to instantiating &p9_client diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index db6ad369a171f9..898a432a806313 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -21,38 +21,6 @@ #define P9_RDMA_RQ_DEPTH 32 #define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ -/** - * struct p9_fd_opts - per-transport options for fd transport - * @rfd: file descriptor for reading (trans=fd) - * @wfd: file descriptor for writing (trans=fd) - * @port: port to connect to (trans=tcp) - * @privport: port is privileged - */ - -struct p9_fd_opts { - int rfd; - int wfd; - u16 port; - bool privport; -}; - -/** - * struct p9_rdma_opts - Collection of mount options for rdma transport - * @port: port of connection - * @privport: Whether a privileged port may be used - * @sq_depth: The requested depth of the SQ. This really doesn't need - * to be any deeper than the number of threads used in the client - * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth - * @timeout: Time to wait in msecs for CM events - */ -struct p9_rdma_opts { - short port; - bool privport; - int sq_depth; - int rq_depth; - long timeout; -}; - /** * struct p9_trans_module - transport module interface * @list: used to maintain a list of currently available transports From 1f3e4142c0eb178089ea0cbc97506a061470ad27 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 10 Oct 2025 16:36:19 -0500 Subject: [PATCH 204/684] 9p: convert to the new mount API Convert 9p to the new mount API. This patch consolidates all parsing into fs/9p/v9fs.c, which stores all results into a filesystem context which can be passed to the various transports as needed. Some of the parsing helper functions such as get_cache_mode() have been eliminated in favor of using the new mount API's enum param type, for simplicity. Signed-off-by: Eric Sandeen Message-ID: <20251010214222.1347785-5-sandeen@redhat.com> [ Dominique: handled source explicitly as per follow-up discussion ] Signed-off-by: Dominique Martinet --- fs/9p/v9fs.c | 552 +++++++++++++++++++------------------ fs/9p/v9fs.h | 7 +- fs/9p/vfs_super.c | 130 ++++++--- include/net/9p/client.h | 2 +- include/net/9p/transport.h | 2 +- net/9p/client.c | 148 +--------- net/9p/mod.c | 2 +- net/9p/trans_fd.c | 109 +------- net/9p/trans_rdma.c | 108 +------- net/9p/trans_usbg.c | 4 +- net/9p/trans_virtio.c | 8 +- net/9p/trans_xen.c | 4 +- 12 files changed, 424 insertions(+), 652 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index a020a8f00a1ac0..05fc2ba3c5d42e 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -13,7 +13,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -33,6 +34,10 @@ struct kmem_cache *v9fs_inode_cache; */ enum { + /* Mount-point source, we need to handle this explicitly because + * the code below accepts unknown args and the vfs layer only handles + * source if we rejected it as EINVAL */ + Opt_source, /* Options that take integer arguments */ Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, /* String options */ @@ -43,55 +48,81 @@ enum { Opt_access, Opt_posixacl, /* Lock timeout option */ Opt_locktimeout, - /* Error token */ - Opt_err + + /* Client options */ + Opt_msize, Opt_trans, Opt_legacy, Opt_version, + + /* fd transport options */ + /* Options that take integer arguments */ + Opt_rfdno, Opt_wfdno, + /* Options that take no arguments */ + + /* rdma transport options */ + /* Options that take integer arguments */ + Opt_rq_depth, Opt_sq_depth, Opt_timeout, + + /* Options for both fd and rdma transports */ + Opt_port, Opt_privport, }; -static const match_table_t tokens = { - {Opt_debug, "debug=%x"}, - {Opt_dfltuid, "dfltuid=%u"}, - {Opt_dfltgid, "dfltgid=%u"}, - {Opt_afid, "afid=%u"}, - {Opt_uname, "uname=%s"}, - {Opt_remotename, "aname=%s"}, - {Opt_nodevmap, "nodevmap"}, - {Opt_noxattr, "noxattr"}, - {Opt_directio, "directio"}, - {Opt_ignoreqv, "ignoreqv"}, - {Opt_cache, "cache=%s"}, - {Opt_cachetag, "cachetag=%s"}, - {Opt_access, "access=%s"}, - {Opt_posixacl, "posixacl"}, - {Opt_locktimeout, "locktimeout=%u"}, - {Opt_err, NULL} +static const struct constant_table p9_versions[] = { + { "9p2000", p9_proto_legacy }, + { "9p2000.u", p9_proto_2000u }, + { "9p2000.L", p9_proto_2000L }, + {} }; -/* Interpret mount options for cache mode */ -static int get_cache_mode(char *s) -{ - int version = -EINVAL; - - if (!strcmp(s, "loose")) { - version = CACHE_SC_LOOSE; - p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); - } else if (!strcmp(s, "fscache")) { - version = CACHE_SC_FSCACHE; - p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); - } else if (!strcmp(s, "mmap")) { - version = CACHE_SC_MMAP; - p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n"); - } else if (!strcmp(s, "readahead")) { - version = CACHE_SC_READAHEAD; - p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n"); - } else if (!strcmp(s, "none")) { - version = CACHE_SC_NONE; - p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); - } else if (kstrtoint(s, 0, &version) != 0) { - version = -EINVAL; - pr_info("Unknown Cache mode or invalid value %s\n", s); - } - return version; -} +static const struct constant_table p9_cache_mode[] = { + { "loose", CACHE_SC_LOOSE }, + { "fscache", CACHE_SC_FSCACHE }, + { "mmap", CACHE_SC_MMAP }, + { "readahead", CACHE_SC_READAHEAD }, + { "none", CACHE_SC_NONE }, + {} +}; + +/* + * This structure contains all parameters used for the core code, + * the client, and all the transports. + */ +const struct fs_parameter_spec v9fs_param_spec[] = { + fsparam_string ("source", Opt_source), + fsparam_u32hex ("debug", Opt_debug), + fsparam_uid ("dfltuid", Opt_dfltuid), + fsparam_gid ("dfltgid", Opt_dfltgid), + fsparam_u32 ("afid", Opt_afid), + fsparam_string ("uname", Opt_uname), + fsparam_string ("aname", Opt_remotename), + fsparam_flag ("nodevmap", Opt_nodevmap), + fsparam_flag ("noxattr", Opt_noxattr), + fsparam_flag ("directio", Opt_directio), + fsparam_flag ("ignoreqv", Opt_ignoreqv), + fsparam_enum ("cache", Opt_cache, p9_cache_mode), + fsparam_string ("cachetag", Opt_cachetag), + fsparam_string ("access", Opt_access), + fsparam_flag ("posixacl", Opt_posixacl), + fsparam_u32 ("locktimeout", Opt_locktimeout), + + /* client options */ + fsparam_u32 ("msize", Opt_msize), + fsparam_flag ("noextend", Opt_legacy), + fsparam_string ("trans", Opt_trans), + fsparam_enum ("version", Opt_version, p9_versions), + + /* fd transport options */ + fsparam_u32 ("rfdno", Opt_rfdno), + fsparam_u32 ("wfdno", Opt_wfdno), + + /* rdma transport options */ + fsparam_u32 ("sq", Opt_sq_depth), + fsparam_u32 ("rq", Opt_rq_depth), + fsparam_u32 ("timeout", Opt_timeout), + + /* fd and rdma transprt options */ + fsparam_u32 ("port", Opt_port), + fsparam_flag ("privport", Opt_privport), + {} +}; /* * Display the mount options in /proc/mounts. @@ -153,267 +184,252 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root) } /** - * v9fs_parse_options - parse mount options into session structure - * @v9ses: existing v9fs session information - * @opts: The mount option string + * v9fs_parse_param - parse a mount option into the filesystem context + * @fc: the filesystem context + * @param: the parameter to parse * * Return 0 upon success, -ERRNO upon failure. */ - -static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) +int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param) { - char *options, *tmp_options; - substring_t args[MAX_OPT_ARGS]; - char *p; - int option = 0; + struct v9fs_context *ctx = fc->fs_private; + struct fs_parse_result result; char *s; - int ret = 0; - - /* setup defaults */ - v9ses->afid = ~0; - v9ses->debug = 0; - v9ses->cache = CACHE_NONE; -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = NULL; -#endif - v9ses->session_lock_timeout = P9_LOCK_TIMEOUT; - - if (!opts) - return 0; + int r; + int opt; + struct p9_client_opts *clnt = &ctx->client_opts; + struct p9_fd_opts *fd_opts = &ctx->fd_opts; + struct p9_rdma_opts *rdma_opts = &ctx->rdma_opts; + struct p9_session_opts *session_opts = &ctx->session_opts; + + opt = fs_parse(fc, v9fs_param_spec, param, &result); + if (opt < 0) { + /* + * We might like to report bad mount options here, but + * traditionally 9p has ignored unknown mount options + */ + if (opt == -ENOPARAM) + return 0; - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) { - ret = -ENOMEM; - goto fail_option_alloc; + return opt; } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - - if (!*p) - continue; - - token = match_token(p, tokens, args); - switch (token) { - case Opt_debug: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - } else { - v9ses->debug = option; + + switch (opt) { + case Opt_source: + if (fc->source) { + pr_info("p9: multiple sources not supported\n"); + return -EINVAL; + } + fc->source = param->string; + param->string = NULL; + break; + case Opt_debug: + session_opts->debug = result.uint_32; #ifdef CONFIG_NET_9P_DEBUG - p9_debug_level = option; + p9_debug_level = result.uint_32; #endif - } - break; - - case Opt_dfltuid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltuid = make_kuid(current_user_ns(), option); - if (!uid_valid(v9ses->dfltuid)) { - p9_debug(P9_DEBUG_ERROR, - "uid field, but not a uid?\n"); - ret = -EINVAL; - } - break; - case Opt_dfltgid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltgid = make_kgid(current_user_ns(), option); - if (!gid_valid(v9ses->dfltgid)) { - p9_debug(P9_DEBUG_ERROR, - "gid field, but not a gid?\n"); - ret = -EINVAL; - } - break; - case Opt_afid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - } else { - v9ses->afid = option; - } - break; - case Opt_uname: - kfree(v9ses->uname); - v9ses->uname = match_strdup(&args[0]); - if (!v9ses->uname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_remotename: - kfree(v9ses->aname); - v9ses->aname = match_strdup(&args[0]); - if (!v9ses->aname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_nodevmap: - v9ses->nodev = 1; - break; - case Opt_noxattr: - v9ses->flags |= V9FS_NO_XATTR; - break; - case Opt_directio: - v9ses->flags |= V9FS_DIRECT_IO; - break; - case Opt_ignoreqv: - v9ses->flags |= V9FS_IGNORE_QV; - break; - case Opt_cachetag: + break; + + case Opt_dfltuid: + session_opts->dfltuid = result.uid; + break; + case Opt_dfltgid: + session_opts->dfltgid = result.gid; + break; + case Opt_afid: + session_opts->afid = result.uint_32; + break; + case Opt_uname: + kfree(session_opts->uname); + session_opts->uname = param->string; + param->string = NULL; + break; + case Opt_remotename: + kfree(session_opts->aname); + session_opts->aname = param->string; + param->string = NULL; + break; + case Opt_nodevmap: + session_opts->nodev = 1; + break; + case Opt_noxattr: + session_opts->flags |= V9FS_NO_XATTR; + break; + case Opt_directio: + session_opts->flags |= V9FS_DIRECT_IO; + break; + case Opt_ignoreqv: + session_opts->flags |= V9FS_IGNORE_QV; + break; + case Opt_cachetag: #ifdef CONFIG_9P_FSCACHE - kfree(v9ses->cachetag); - v9ses->cachetag = match_strdup(&args[0]); - if (!v9ses->cachetag) { - ret = -ENOMEM; - goto free_and_return; - } + kfree(session_opts->cachetag); + session_opts->cachetag = param->string; + param->string = NULL; #endif - break; - case Opt_cache: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of cache arg\n"); - goto free_and_return; - } - r = get_cache_mode(s); - if (r < 0) - ret = r; - else - v9ses->cache = r; - - kfree(s); - break; - - case Opt_access: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of access arg\n"); - goto free_and_return; + break; + case Opt_cache: + session_opts->cache = result.uint_32; + p9_debug(P9_DEBUG_9P, "Cache mode: %s\n", param->string); + break; + case Opt_access: + s = param->string; + session_opts->flags &= ~V9FS_ACCESS_MASK; + if (strcmp(s, "user") == 0) { + session_opts->flags |= V9FS_ACCESS_USER; + } else if (strcmp(s, "any") == 0) { + session_opts->flags |= V9FS_ACCESS_ANY; + } else if (strcmp(s, "client") == 0) { + session_opts->flags |= V9FS_ACCESS_CLIENT; + } else { + uid_t uid; + + session_opts->flags |= V9FS_ACCESS_SINGLE; + r = kstrtouint(s, 10, &uid); + if (r) { + pr_info("Unknown access argument %s: %d\n", + param->string, r); + return r; } - - v9ses->flags &= ~V9FS_ACCESS_MASK; - if (strcmp(s, "user") == 0) - v9ses->flags |= V9FS_ACCESS_USER; - else if (strcmp(s, "any") == 0) - v9ses->flags |= V9FS_ACCESS_ANY; - else if (strcmp(s, "client") == 0) { - v9ses->flags |= V9FS_ACCESS_CLIENT; - } else { - uid_t uid; - - v9ses->flags |= V9FS_ACCESS_SINGLE; - r = kstrtouint(s, 10, &uid); - if (r) { - ret = r; - pr_info("Unknown access argument %s: %d\n", - s, r); - kfree(s); - continue; - } - v9ses->uid = make_kuid(current_user_ns(), uid); - if (!uid_valid(v9ses->uid)) { - ret = -EINVAL; - pr_info("Unknown uid %s\n", s); - } + session_opts->uid = make_kuid(current_user_ns(), uid); + if (!uid_valid(session_opts->uid)) { + pr_info("Unknown uid %s\n", s); + return -EINVAL; } + } + break; - kfree(s); - break; - - case Opt_posixacl: + case Opt_posixacl: #ifdef CONFIG_9P_FS_POSIX_ACL - v9ses->flags |= V9FS_POSIX_ACL; + session_opts->flags |= V9FS_POSIX_ACL; #else - p9_debug(P9_DEBUG_ERROR, - "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); + p9_debug(P9_DEBUG_ERROR, + "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); #endif - break; - - case Opt_locktimeout: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - if (option < 1) { - p9_debug(P9_DEBUG_ERROR, - "locktimeout must be a greater than zero integer.\n"); - ret = -EINVAL; - continue; - } - v9ses->session_lock_timeout = (long)option * HZ; - break; + break; + + case Opt_locktimeout: + if (result.uint_32 < 1) { + p9_debug(P9_DEBUG_ERROR, + "locktimeout must be a greater than zero integer.\n"); + return -EINVAL; + } + session_opts->session_lock_timeout = (long)result.uint_32 * HZ; + break; - default: - continue; + /* Options for client */ + case Opt_msize: + if (result.uint_32 < 4096) { + p9_debug(P9_DEBUG_ERROR, "msize should be at least 4k\n"); + return -EINVAL; + } + if (result.uint_32 > INT_MAX) { + p9_debug(P9_DEBUG_ERROR, "msize too big\n"); + return -EINVAL; } + clnt->msize = result.uint_32; + break; + case Opt_trans: + v9fs_put_trans(clnt->trans_mod); + clnt->trans_mod = v9fs_get_trans_by_name(param->string); + if (!clnt->trans_mod) { + pr_info("Could not find request transport: %s\n", + param->string); + return -EINVAL; + } + break; + case Opt_legacy: + clnt->proto_version = p9_proto_legacy; + break; + case Opt_version: + clnt->proto_version = result.uint_32; + p9_debug(P9_DEBUG_9P, "Protocol version: %s\n", param->string); + break; + /* Options for fd transport */ + case Opt_rfdno: + fd_opts->rfd = result.uint_32; + break; + case Opt_wfdno: + fd_opts->wfd = result.uint_32; + break; + /* Options for rdma transport */ + case Opt_sq_depth: + rdma_opts->sq_depth = result.uint_32; + break; + case Opt_rq_depth: + rdma_opts->rq_depth = result.uint_32; + break; + case Opt_timeout: + rdma_opts->timeout = result.uint_32; + break; + /* Options for both fd and rdma transports */ + case Opt_port: + fd_opts->port = result.uint_32; + rdma_opts->port = result.uint_32; + break; + case Opt_privport: + fd_opts->privport = true; + rdma_opts->port = true; + break; } -free_and_return: - kfree(tmp_options); -fail_option_alloc: - return ret; + return 0; +} + +static void v9fs_apply_options(struct v9fs_session_info *v9ses, + struct fs_context *fc) +{ + struct v9fs_context *ctx = fc->fs_private; + + v9ses->debug = ctx->session_opts.debug; + v9ses->dfltuid = ctx->session_opts.dfltuid; + v9ses->dfltgid = ctx->session_opts.dfltgid; + v9ses->afid = ctx->session_opts.afid; + v9ses->uname = ctx->session_opts.uname; + ctx->session_opts.uname = NULL; + v9ses->aname = ctx->session_opts.aname; + ctx->session_opts.aname = NULL; + v9ses->nodev = ctx->session_opts.nodev; + /* + * Note that we must |= flags here as session_init already + * set basic flags. This adds in flags from parsed options. + */ + v9ses->flags |= ctx->session_opts.flags; +#ifdef CONFIG_9P_FSCACHE + v9ses->cachetag = ctx->session_opts.cachetag; + ctx->session_opts.cachetag = NULL; +#endif + v9ses->cache = ctx->session_opts.cache; + v9ses->uid = ctx->session_opts.uid; + v9ses->session_lock_timeout = ctx->session_opts.session_lock_timeout; } /** * v9fs_session_init - initialize session * @v9ses: session information structure - * @dev_name: device being mounted - * @data: options + * @fc: the filesystem mount context * */ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, - const char *dev_name, char *data) + struct fs_context *fc) { struct p9_fid *fid; int rc = -ENOMEM; - v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); - if (!v9ses->uname) - goto err_names; - - v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); - if (!v9ses->aname) - goto err_names; init_rwsem(&v9ses->rename_sem); - v9ses->uid = INVALID_UID; - v9ses->dfltuid = V9FS_DEFUID; - v9ses->dfltgid = V9FS_DEFGID; - - v9ses->clnt = p9_client_create(dev_name, data); + v9ses->clnt = p9_client_create(fc); if (IS_ERR(v9ses->clnt)) { rc = PTR_ERR(v9ses->clnt); p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n"); goto err_names; } + /* + * Initialize flags on the real v9ses. v9fs_apply_options below + * will |= the additional flags from parsed options. + */ v9ses->flags = V9FS_ACCESS_USER; if (p9_is_proto_dotl(v9ses->clnt)) { @@ -423,9 +439,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->flags |= V9FS_PROTO_2000U; } - rc = v9fs_parse_options(v9ses, data); - if (rc < 0) - goto err_clnt; + v9fs_apply_options(v9ses, fc); v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; @@ -471,7 +485,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, #ifdef CONFIG_9P_FSCACHE /* register the session for caching */ if (v9ses->cache & CACHE_FSCACHE) { - rc = v9fs_cache_session_get_cookie(v9ses, dev_name); + rc = v9fs_cache_session_get_cookie(v9ses, fc->source); if (rc < 0) goto err_clnt; } diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index f28bc763847ae5..6a12445d385822 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -10,6 +10,9 @@ #include #include +#include +#include +#include /** * enum p9_session_flags - option flags for each 9P session @@ -163,11 +166,13 @@ static inline struct fscache_volume *v9fs_session_cache(struct v9fs_session_info #endif } +extern const struct fs_parameter_spec v9fs_param_spec[]; +extern int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param); extern int v9fs_show_options(struct seq_file *m, struct dentry *root); struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, - const char *dev_name, char *data); + struct fs_context *fc); extern void v9fs_session_close(struct v9fs_session_info *v9ses); extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 1581ebac5bb423..315336de6f02a5 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,32 +31,10 @@ static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; -/** - * v9fs_set_super - set the superblock - * @s: super block - * @data: file system specific data - * - */ - -static int v9fs_set_super(struct super_block *s, void *data) -{ - s->s_fs_info = data; - return set_anon_super(s, data); -} - -/** - * v9fs_fill_super - populate superblock with info - * @sb: superblock - * @v9ses: session information - * @flags: flags propagated from v9fs_mount() - * - */ - -static int -v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, - int flags) +static int v9fs_fill_super(struct super_block *sb) { int ret; + struct v9fs_session_info *v9ses = v9ses = sb->s_fs_info; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize_bits = fls(v9ses->maxdata - 1); @@ -95,16 +74,12 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, } /** - * v9fs_mount - mount a superblock - * @fs_type: file system type - * @flags: mount flags - * @dev_name: device name that was mounted - * @data: mount options + * v9fs_get_tree - create the mountable root and superblock + * @fc: the filesystem context * */ -static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int v9fs_get_tree(struct fs_context *fc) { struct super_block *sb = NULL; struct inode *inode = NULL; @@ -117,20 +92,21 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) - return ERR_PTR(-ENOMEM); + return -ENOMEM; - fid = v9fs_session_init(v9ses, dev_name, data); + fid = v9fs_session_init(v9ses, fc); if (IS_ERR(fid)) { retval = PTR_ERR(fid); goto free_session; } - sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); + fc->s_fs_info = v9ses; + sb = sget_fc(fc, NULL, set_anon_super_fc); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto clunk_fid; } - retval = v9fs_fill_super(sb, v9ses, flags); + retval = v9fs_fill_super(sb); if (retval) goto release_sb; @@ -159,14 +135,15 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, v9fs_fid_add(root, &fid); p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); - return dget(sb->s_root); + fc->root = dget(sb->s_root); + return 0; clunk_fid: p9_fid_put(fid); v9fs_session_close(v9ses); free_session: kfree(v9ses); - return ERR_PTR(retval); + return retval; release_sb: /* @@ -177,7 +154,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, */ p9_fid_put(fid); deactivate_locked_super(sb); - return ERR_PTR(retval); + return retval; } /** @@ -303,11 +280,86 @@ static const struct super_operations v9fs_super_ops_dotl = { .write_inode = v9fs_write_inode_dotl, }; +static void v9fs_free_fc(struct fs_context *fc) +{ + struct v9fs_context *ctx = fc->fs_private; + + if (!ctx) + return; + + /* These should be NULL by now but guard against leaks */ + kfree(ctx->session_opts.uname); + kfree(ctx->session_opts.aname); +#ifdef CONFIG_9P_FSCACHE + kfree(ctx->session_opts.cachetag); +#endif + if (ctx->client_opts.trans_mod) + v9fs_put_trans(ctx->client_opts.trans_mod); + kfree(ctx); +} + +static const struct fs_context_operations v9fs_context_ops = { + .parse_param = v9fs_parse_param, + .get_tree = v9fs_get_tree, + .free = v9fs_free_fc, +}; + +static int v9fs_init_fs_context(struct fs_context *fc) +{ + struct v9fs_context *ctx; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + /* initialize core options */ + ctx->session_opts.afid = ~0; + ctx->session_opts.cache = CACHE_NONE; + ctx->session_opts.session_lock_timeout = P9_LOCK_TIMEOUT; + ctx->session_opts.uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); + if (!ctx->session_opts.uname) + goto error; + + ctx->session_opts.aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); + if (!ctx->session_opts.aname) + goto error; + + ctx->session_opts.uid = INVALID_UID; + ctx->session_opts.dfltuid = V9FS_DEFUID; + ctx->session_opts.dfltgid = V9FS_DEFGID; + + /* initialize client options */ + ctx->client_opts.proto_version = p9_proto_2000L; + ctx->client_opts.msize = DEFAULT_MSIZE; + + /* initialize fd transport options */ + ctx->fd_opts.port = P9_FD_PORT; + ctx->fd_opts.rfd = ~0; + ctx->fd_opts.wfd = ~0; + ctx->fd_opts.privport = false; + + /* initialize rdma transport options */ + ctx->rdma_opts.port = P9_RDMA_PORT; + ctx->rdma_opts.sq_depth = P9_RDMA_SQ_DEPTH; + ctx->rdma_opts.rq_depth = P9_RDMA_RQ_DEPTH; + ctx->rdma_opts.timeout = P9_RDMA_TIMEOUT; + ctx->rdma_opts.privport = false; + + fc->ops = &v9fs_context_ops; + fc->fs_private = ctx; + + return 0; +error: + fc->need_free = 1; + return -ENOMEM; +} + struct file_system_type v9fs_fs_type = { .name = "9p", - .mount = v9fs_mount, .kill_sb = v9fs_kill_super, .owner = THIS_MODULE, .fs_flags = FS_RENAME_DOES_D_MOVE, + .init_fs_context = v9fs_init_fs_context, + .parameters = v9fs_param_spec, }; MODULE_ALIAS_FS("9p"); diff --git a/include/net/9p/client.h b/include/net/9p/client.h index cc18443f7d5165..838a94218b593f 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -279,7 +279,7 @@ int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, const char *name); int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, struct p9_fid *newdirfid, const char *new_name); -struct p9_client *p9_client_create(const char *dev_name, char *options); +struct p9_client *p9_client_create(struct fs_context *fc); void p9_client_destroy(struct p9_client *clnt); void p9_client_disconnect(struct p9_client *clnt); void p9_client_begin_disconnect(struct p9_client *clnt); diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 898a432a806313..a912bbaa862f9b 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -57,7 +57,7 @@ struct p9_trans_module { bool supports_vmalloc; /* can work with vmalloc'd buffers */ struct module *owner; int (*create)(struct p9_client *client, - const char *devname, char *args); + struct fs_context *fc); void (*close)(struct p9_client *client); int (*request)(struct p9_client *client, struct p9_req_t *req); int (*cancel)(struct p9_client *client, struct p9_req_t *req); diff --git a/net/9p/client.c b/net/9p/client.c index 802f548332a5cb..f60d1d041adbe8 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include #include "protocol.h" @@ -33,22 +33,6 @@ * - a little lazy - parse all client options */ -enum { - Opt_msize, - Opt_trans, - Opt_legacy, - Opt_version, - Opt_err, -}; - -static const match_table_t tokens = { - {Opt_msize, "msize=%u"}, - {Opt_legacy, "noextend"}, - {Opt_trans, "trans=%s"}, - {Opt_version, "version=%s"}, - {Opt_err, NULL}, -}; - inline int p9_is_proto_dotl(struct p9_client *clnt) { return clnt->proto_version == p9_proto_2000L; @@ -97,124 +81,16 @@ static int safe_errno(int err) return err; } -/* Interpret mount option for protocol version */ -static int get_protocol_version(char *s) +static int apply_client_options(struct p9_client *clnt, struct fs_context *fc) { - int version = -EINVAL; - - if (!strcmp(s, "9p2000")) { - version = p9_proto_legacy; - p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n"); - } else if (!strcmp(s, "9p2000.u")) { - version = p9_proto_2000u; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); - } else if (!strcmp(s, "9p2000.L")) { - version = p9_proto_2000L; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); - } else { - pr_info("Unknown protocol version %s\n", s); - } + struct v9fs_context *ctx = fc->fs_private; - return version; -} - -/** - * parse_opts - parse mount options into client structure - * @opts: options string passed from mount - * @clnt: existing v9fs client information - * - * Return 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *opts, struct p9_client *clnt) -{ - char *options, *tmp_options; - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *s; - int ret = 0; - - clnt->proto_version = p9_proto_2000L; - clnt->msize = DEFAULT_MSIZE; - - if (!opts) - return 0; + clnt->msize = ctx->client_opts.msize; + clnt->trans_mod = ctx->client_opts.trans_mod; + ctx->client_opts.trans_mod = NULL; + clnt->proto_version = ctx->client_opts.proto_version; - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) - return -ENOMEM; - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case Opt_msize: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - if (option < 4096) { - p9_debug(P9_DEBUG_ERROR, - "msize should be at least 4k\n"); - ret = -EINVAL; - continue; - } - clnt->msize = option; - break; - case Opt_trans: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of trans arg\n"); - goto free_and_return; - } - - v9fs_put_trans(clnt->trans_mod); - clnt->trans_mod = v9fs_get_trans_by_name(s); - if (!clnt->trans_mod) { - pr_info("Could not find request transport: %s\n", - s); - ret = -EINVAL; - } - kfree(s); - break; - case Opt_legacy: - clnt->proto_version = p9_proto_legacy; - break; - case Opt_version: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of version arg\n"); - goto free_and_return; - } - r = get_protocol_version(s); - if (r < 0) - ret = r; - else - clnt->proto_version = r; - kfree(s); - break; - default: - continue; - } - } - -free_and_return: - if (ret) - v9fs_put_trans(clnt->trans_mod); - kfree(tmp_options); - return ret; + return 0; } static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc, @@ -975,7 +851,7 @@ static int p9_client_version(struct p9_client *c) return err; } -struct p9_client *p9_client_create(const char *dev_name, char *options) +struct p9_client *p9_client_create(struct fs_context *fc) { int err; static atomic_t seqno = ATOMIC_INIT(0); @@ -998,8 +874,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) idr_init(&clnt->fids); idr_init(&clnt->reqs); - err = parse_opts(options, clnt); - if (err < 0) + err = apply_client_options(clnt, fc); + if (err) goto free_client; if (!clnt->trans_mod) @@ -1015,7 +891,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); - err = clnt->trans_mod->create(clnt, dev_name, options); + err = clnt->trans_mod->create(clnt, fc); if (err) goto put_trans; diff --git a/net/9p/mod.c b/net/9p/mod.c index 55576c1866fa68..85160b52da556d 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -171,6 +170,7 @@ void v9fs_put_trans(struct p9_trans_module *m) if (m) module_put(m->owner); } +EXPORT_SYMBOL(v9fs_put_trans); /** * init_p9 - Initialize module diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index b7e5933c461736..4cec4bba222d55 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,26 +37,6 @@ static struct p9_trans_module p9_tcp_trans; static struct p9_trans_module p9_fd_trans; -/* - * Option Parsing (code inspired by NFS code) - * - a little lazy - parse all fd-transport options - */ - -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, - /* Options that take no arguments */ - Opt_privport, -}; - -static const match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_rfdno, "rfdno=%u"}, - {Opt_wfdno, "wfdno=%u"}, - {Opt_privport, "privport"}, - {Opt_err, NULL}, -}; - enum { Rworksched = 1, /* read work scheduled or running */ Rpending = 2, /* can read */ @@ -737,73 +717,6 @@ static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt) return 0; } -/** - * parse_opts - parse mount options into p9_fd_opts structure - * @params: options string passed from mount - * @opts: fd transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *params, struct p9_fd_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_FD_PORT; - opts->rfd = ~0; - opts->wfd = ~0; - opts->privport = false; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - if ((token != Opt_err) && (token != Opt_privport)) { - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_rfdno: - opts->rfd = option; - break; - case Opt_wfdno: - opts->wfd = option; - break; - case Opt_privport: - opts->privport = true; - break; - default: - continue; - } - } - - kfree(tmp_options); - return 0; -} - static int p9_fd_open(struct p9_client *client, int rfd, int wfd) { struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd), @@ -958,17 +871,18 @@ static int p9_bind_privport(struct socket *sock) } static int -p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) +p9_fd_create_tcp(struct p9_client *client, struct fs_context *fc) { + const char *addr = fc->source; + struct v9fs_context *ctx = fc->fs_private; int err; char port_str[6]; struct socket *csocket; struct sockaddr_storage stor = { 0 }; struct p9_fd_opts opts; - err = parse_opts(args, &opts); - if (err < 0) - return err; + /* opts are already parsed in context */ + opts = ctx->fd_opts; if (!addr) return -EINVAL; @@ -1015,8 +929,9 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) } static int -p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) +p9_fd_create_unix(struct p9_client *client, struct fs_context *fc) { + const char *addr = fc->source; int err; struct socket *csocket; struct sockaddr_un sun_server; @@ -1055,14 +970,12 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) } static int -p9_fd_create(struct p9_client *client, const char *addr, char *args) +p9_fd_create(struct p9_client *client, struct fs_context *fc) { + struct v9fs_context *ctx = fc->fs_private; + struct p9_fd_opts opts = ctx->fd_opts; int err; - struct p9_fd_opts opts; - err = parse_opts(args, &opts); - if (err < 0) - return err; client->trans_opts.fd.rfd = opts.rfd; client->trans_opts.fd.wfd = opts.wfd; diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 87246463a95465..4d406479f83bd4 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -106,26 +106,6 @@ struct p9_rdma_context { }; }; -/* - * Option Parsing (code inspired by NFS code) - */ -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, - /* Options that take no argument */ - Opt_privport, - Opt_err, -}; - -static match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_sq_depth, "sq=%u"}, - {Opt_rq_depth, "rq=%u"}, - {Opt_timeout, "timeout=%u"}, - {Opt_privport, "privport"}, - {Opt_err, NULL}, -}; - static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) { struct p9_trans_rdma *rdma = clnt->trans; @@ -143,77 +123,6 @@ static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) return 0; } -/** - * parse_opts - parse mount options into rdma options structure - * @params: options string passed from mount - * @opts: rdma transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ -static int parse_opts(char *params, struct p9_rdma_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_RDMA_PORT; - opts->sq_depth = P9_RDMA_SQ_DEPTH; - opts->rq_depth = P9_RDMA_RQ_DEPTH; - opts->timeout = P9_RDMA_TIMEOUT; - opts->privport = false; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - if ((token != Opt_err) && (token != Opt_privport)) { - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_sq_depth: - opts->sq_depth = option; - break; - case Opt_rq_depth: - opts->rq_depth = option; - break; - case Opt_timeout: - opts->timeout = option; - break; - case Opt_privport: - opts->privport = true; - break; - default: - continue; - } - } - /* RQ must be at least as large as the SQ */ - opts->rq_depth = max(opts->rq_depth, opts->sq_depth); - kfree(tmp_options); - return 0; -} - static int p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) { @@ -607,14 +516,15 @@ static int p9_rdma_bind_privport(struct p9_trans_rdma *rdma) /** * rdma_create_trans - Transport method for creating a transport instance * @client: client instance - * @addr: IP address string - * @args: Mount options string + * @fc: The filesystem context */ static int -rdma_create_trans(struct p9_client *client, const char *addr, char *args) +rdma_create_trans(struct p9_client *client, struct fs_context *fc) { + const char *addr = fc->source; + struct v9fs_context *ctx = fc->fs_private; + struct p9_rdma_opts opts = ctx->rdma_opts; int err; - struct p9_rdma_opts opts; struct p9_trans_rdma *rdma; struct rdma_conn_param conn_param; struct ib_qp_init_attr qp_attr; @@ -622,10 +532,8 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args) if (addr == NULL) return -EINVAL; - /* Parse the transport specific mount options */ - err = parse_opts(args, &opts); - if (err < 0) - return err; + /* options are already parsed, in the fs context */ + opts = ctx->rdma_opts; /* Create and initialize the RDMA transport structure */ rdma = alloc_rdma(&opts); diff --git a/net/9p/trans_usbg.c b/net/9p/trans_usbg.c index 2542ef09923339..93547637deaedb 100644 --- a/net/9p/trans_usbg.c +++ b/net/9p/trans_usbg.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -376,8 +377,9 @@ enable_usb9pfs(struct usb_composite_dev *cdev, struct f_usb9pfs *usb9pfs) return ret; } -static int p9_usbg_create(struct p9_client *client, const char *devname, char *args) +static int p9_usbg_create(struct p9_client *client, struct fs_context *fc) { + const char *devname = fc->source; struct f_usb9pfs_dev *dev; struct f_usb9pfs *usb9pfs; int ret = -ENOENT; diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index b58f50b00c7237..10c2dd48643818 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -679,8 +679,7 @@ static int p9_virtio_probe(struct virtio_device *vdev) /** * p9_virtio_create - allocate a new virtio channel * @client: client instance invoking this transport - * @devname: string identifying the channel to connect to (unused) - * @args: args passed from sys_mount() for per-transport options (unused) + * @fc: the filesystem context * * This sets up a transport channel for 9p communication. Right now * we only match the first available channel, but eventually we could look up @@ -691,8 +690,9 @@ static int p9_virtio_probe(struct virtio_device *vdev) */ static int -p9_virtio_create(struct p9_client *client, const char *devname, char *args) +p9_virtio_create(struct p9_client *client, struct fs_context *fc) { + const char *devname = fc->source; struct virtio_chan *chan; int ret = -ENOENT; int found = 0; diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index 9389c1247001e2..12f752a9233245 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -66,8 +67,9 @@ static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req) return 1; } -static int p9_xen_create(struct p9_client *client, const char *addr, char *args) +static int p9_xen_create(struct p9_client *client, struct fs_context *fc) { + const char *addr = fc->source; struct xen_9pfs_front_priv *priv; if (addr == NULL) From 15c320b286a128131193ad270d7aac23bba4c219 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 30 Oct 2025 16:39:04 +0530 Subject: [PATCH 205/684] dt-bindings: clock: qcom-rpmhcc: Add RPMHCC for Kaanapali Update the documentation for RPMH clock controller for Kaanapali SoC. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/20251030-gcc_kaanapali-v2-v2-1-a774a587af6f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index 78fa0572668578..3f5f1336262ee6 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -18,6 +18,7 @@ properties: compatible: enum: - qcom,glymur-rpmh-clk + - qcom,kaanapali-rpmh-clk - qcom,milos-rpmh-clk - qcom,qcs615-rpmh-clk - qcom,qdu1000-rpmh-clk From 395e0e794f9a485d9a5d6af062f096b97beecc11 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 30 Oct 2025 16:39:05 +0530 Subject: [PATCH 206/684] dt-bindings: clock: qcom: Document the Kaanapali TCSR Clock Controller Add bindings documentation for TCSR Clock Controller for Kaanapali SoC. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/20251030-gcc_kaanapali-v2-v2-2-a774a587af6f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml index 2c992b3437f29b..784fef8306812c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml @@ -25,6 +25,7 @@ properties: items: - enum: - qcom,glymur-tcsr + - qcom,kaanapali-tcsr - qcom,milos-tcsr - qcom,sar2130p-tcsr - qcom,sm8550-tcsr From 342d2a607450f256105781d29aa6300921c6152e Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 30 Oct 2025 16:39:06 +0530 Subject: [PATCH 207/684] dt-bindings: clock: qcom: Add Kaanapali Global clock controller Add device tree bindings for the global clock controller on Qualcomm Kaanapali platform. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/20251030-gcc_kaanapali-v2-v2-3-a774a587af6f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/clock/qcom,sm8750-gcc.yaml | 8 +- .../dt-bindings/clock/qcom,kaanapali-gcc.h | 241 ++++++++++++++++++ 2 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/clock/qcom,kaanapali-gcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8750-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8750-gcc.yaml index aab7039fd28db2..0114d347b26ff0 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8750-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8750-gcc.yaml @@ -13,11 +13,15 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8750 - See also: include/dt-bindings/clock/qcom,sm8750-gcc.h + See also: + include/dt-bindings/clock/qcom,kaanapali-gcc.h + include/dt-bindings/clock/qcom,sm8750-gcc.h properties: compatible: - const: qcom,sm8750-gcc + enum: + - qcom,kaanapali-gcc + - qcom,sm8750-gcc clocks: items: diff --git a/include/dt-bindings/clock/qcom,kaanapali-gcc.h b/include/dt-bindings/clock/qcom,kaanapali-gcc.h new file mode 100644 index 00000000000000..890e48709f09f7 --- /dev/null +++ b/include/dt-bindings/clock/qcom,kaanapali-gcc.h @@ -0,0 +1,241 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_KAANAPALI_H +#define _DT_BINDINGS_CLK_QCOM_GCC_KAANAPALI_H + +/* GCC clocks */ +#define GCC_AGGRE_NOC_PCIE_AXI_CLK 0 +#define GCC_AGGRE_UFS_PHY_AXI_CLK 1 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 2 +#define GCC_BOOT_ROM_AHB_CLK 3 +#define GCC_CAM_BIST_MCLK_AHB_CLK 4 +#define GCC_CAMERA_AHB_CLK 5 +#define GCC_CAMERA_HF_AXI_CLK 6 +#define GCC_CAMERA_SF_AXI_CLK 7 +#define GCC_CAMERA_XO_CLK 8 +#define GCC_CFG_NOC_PCIE_ANOC_AHB_CLK 9 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 10 +#define GCC_CNOC_PCIE_SF_AXI_CLK 11 +#define GCC_DDRSS_PCIE_SF_QTB_CLK 12 +#define GCC_QMIP_CAMERA_CMD_AHB_CLK 13 +#define GCC_DISP_HF_AXI_CLK 14 +#define GCC_DISP_SF_AXI_CLK 15 +#define GCC_EVA_AHB_CLK 16 +#define GCC_EVA_AXI0_CLK 17 +#define GCC_EVA_AXI0C_CLK 18 +#define GCC_EVA_XO_CLK 19 +#define GCC_GP1_CLK 20 +#define GCC_GP1_CLK_SRC 21 +#define GCC_GP2_CLK 22 +#define GCC_GP2_CLK_SRC 23 +#define GCC_GP3_CLK 24 +#define GCC_GP3_CLK_SRC 25 +#define GCC_GPLL0 26 +#define GCC_GPLL0_OUT_EVEN 27 +#define GCC_GPLL1 28 +#define GCC_GPLL4 29 +#define GCC_GPLL7 30 +#define GCC_GPLL9 31 +#define GCC_GPU_CFG_AHB_CLK 32 +#define GCC_GPU_GEMNOC_GFX_CLK 33 +#define GCC_GPU_GPLL0_CLK_SRC 34 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 35 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 36 +#define GCC_QMIP_GPU_AHB_CLK 37 +#define GCC_PCIE_0_AUX_CLK 38 +#define GCC_PCIE_0_AUX_CLK_SRC 39 +#define GCC_PCIE_0_CFG_AHB_CLK 40 +#define GCC_PCIE_0_MSTR_AXI_CLK 41 +#define GCC_PCIE_0_PHY_AUX_CLK 42 +#define GCC_PCIE_0_PHY_AUX_CLK_SRC 43 +#define GCC_PCIE_0_PHY_RCHNG_CLK 44 +#define GCC_PCIE_0_PHY_RCHNG_CLK_SRC 45 +#define GCC_PCIE_0_PIPE_CLK 46 +#define GCC_PCIE_0_PIPE_CLK_SRC 47 +#define GCC_PCIE_0_SLV_AXI_CLK 48 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 49 +#define GCC_PCIE_RSCC_CFG_AHB_CLK 50 +#define GCC_PCIE_RSCC_XO_CLK 51 +#define GCC_PDM2_CLK 52 +#define GCC_PDM2_CLK_SRC 53 +#define GCC_PDM_AHB_CLK 54 +#define GCC_PDM_XO4_CLK 55 +#define GCC_QUPV3_I2C_CORE_CLK 56 +#define GCC_QUPV3_I2C_S0_CLK 57 +#define GCC_QUPV3_I2C_S0_CLK_SRC 58 +#define GCC_QUPV3_I2C_S1_CLK 59 +#define GCC_QUPV3_I2C_S1_CLK_SRC 60 +#define GCC_QUPV3_I2C_S2_CLK 61 +#define GCC_QUPV3_I2C_S2_CLK_SRC 62 +#define GCC_QUPV3_I2C_S3_CLK 63 +#define GCC_QUPV3_I2C_S3_CLK_SRC 64 +#define GCC_QUPV3_I2C_S4_CLK 65 +#define GCC_QUPV3_I2C_S4_CLK_SRC 66 +#define GCC_QUPV3_I2C_S_AHB_CLK 67 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 68 +#define GCC_QUPV3_WRAP1_CORE_CLK 69 +#define GCC_QUPV3_WRAP1_QSPI_REF_CLK 70 +#define GCC_QUPV3_WRAP1_QSPI_REF_CLK_SRC 71 +#define GCC_QUPV3_WRAP1_S0_CLK 72 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 73 +#define GCC_QUPV3_WRAP1_S1_CLK 74 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 75 +#define GCC_QUPV3_WRAP1_S2_CLK 76 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 77 +#define GCC_QUPV3_WRAP1_S3_CLK 78 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 79 +#define GCC_QUPV3_WRAP1_S4_CLK 80 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 81 +#define GCC_QUPV3_WRAP1_S5_CLK 82 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 83 +#define GCC_QUPV3_WRAP1_S6_CLK 84 +#define GCC_QUPV3_WRAP1_S6_CLK_SRC 85 +#define GCC_QUPV3_WRAP1_S7_CLK 86 +#define GCC_QUPV3_WRAP1_S7_CLK_SRC 87 +#define GCC_QUPV3_WRAP2_CORE_2X_CLK 88 +#define GCC_QUPV3_WRAP2_CORE_CLK 89 +#define GCC_QUPV3_WRAP2_S0_CLK 90 +#define GCC_QUPV3_WRAP2_S0_CLK_SRC 91 +#define GCC_QUPV3_WRAP2_S1_CLK 92 +#define GCC_QUPV3_WRAP2_S1_CLK_SRC 93 +#define GCC_QUPV3_WRAP2_S2_CLK 94 +#define GCC_QUPV3_WRAP2_S2_CLK_SRC 95 +#define GCC_QUPV3_WRAP2_S3_CLK 96 +#define GCC_QUPV3_WRAP2_S3_CLK_SRC 97 +#define GCC_QUPV3_WRAP2_S4_CLK 98 +#define GCC_QUPV3_WRAP2_S4_CLK_SRC 99 +#define GCC_QUPV3_WRAP3_CORE_2X_CLK 100 +#define GCC_QUPV3_WRAP3_CORE_CLK 101 +#define GCC_QUPV3_WRAP3_IBI_CTRL_0_CLK_SRC 102 +#define GCC_QUPV3_WRAP3_IBI_CTRL_1_CLK 103 +#define GCC_QUPV3_WRAP3_IBI_CTRL_2_CLK 104 +#define GCC_QUPV3_WRAP3_S0_CLK 105 +#define GCC_QUPV3_WRAP3_S0_CLK_SRC 106 +#define GCC_QUPV3_WRAP3_S1_CLK 107 +#define GCC_QUPV3_WRAP3_S1_CLK_SRC 108 +#define GCC_QUPV3_WRAP3_S2_CLK 109 +#define GCC_QUPV3_WRAP3_S2_CLK_SRC 110 +#define GCC_QUPV3_WRAP3_S3_CLK 111 +#define GCC_QUPV3_WRAP3_S3_CLK_SRC 112 +#define GCC_QUPV3_WRAP3_S4_CLK 113 +#define GCC_QUPV3_WRAP3_S4_CLK_SRC 114 +#define GCC_QUPV3_WRAP3_S5_CLK 115 +#define GCC_QUPV3_WRAP3_S5_CLK_SRC 116 +#define GCC_QUPV3_WRAP4_CORE_2X_CLK 117 +#define GCC_QUPV3_WRAP4_CORE_CLK 118 +#define GCC_QUPV3_WRAP4_S0_CLK 119 +#define GCC_QUPV3_WRAP4_S0_CLK_SRC 120 +#define GCC_QUPV3_WRAP4_S1_CLK 121 +#define GCC_QUPV3_WRAP4_S1_CLK_SRC 122 +#define GCC_QUPV3_WRAP4_S2_CLK 123 +#define GCC_QUPV3_WRAP4_S2_CLK_SRC 124 +#define GCC_QUPV3_WRAP4_S3_CLK 125 +#define GCC_QUPV3_WRAP4_S3_CLK_SRC 126 +#define GCC_QUPV3_WRAP4_S4_CLK 127 +#define GCC_QUPV3_WRAP4_S4_CLK_SRC 128 +#define GCC_QUPV3_WRAP_1_M_AXI_CLK 129 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 130 +#define GCC_QUPV3_WRAP_2_M_AHB_CLK 131 +#define GCC_QUPV3_WRAP_2_S_AHB_CLK 132 +#define GCC_QUPV3_WRAP_3_IBI_1_AHB_CLK 133 +#define GCC_QUPV3_WRAP_3_IBI_2_AHB_CLK 134 +#define GCC_QUPV3_WRAP_3_M_AHB_CLK 135 +#define GCC_QUPV3_WRAP_3_S_AHB_CLK 136 +#define GCC_QUPV3_WRAP_4_M_AHB_CLK 137 +#define GCC_QUPV3_WRAP_4_S_AHB_CLK 138 +#define GCC_SDCC2_AHB_CLK 139 +#define GCC_SDCC2_APPS_CLK 140 +#define GCC_SDCC2_APPS_CLK_SRC 141 +#define GCC_SDCC4_AHB_CLK 142 +#define GCC_SDCC4_APPS_CLK 143 +#define GCC_SDCC4_APPS_CLK_SRC 144 +#define GCC_UFS_PHY_AHB_CLK 145 +#define GCC_UFS_PHY_AXI_CLK 146 +#define GCC_UFS_PHY_AXI_CLK_SRC 147 +#define GCC_UFS_PHY_ICE_CORE_CLK 148 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 149 +#define GCC_UFS_PHY_PHY_AUX_CLK 150 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 151 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 152 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC 153 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 154 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC 155 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 156 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC 157 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 158 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 159 +#define GCC_USB30_PRIM_MASTER_CLK 160 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 161 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 162 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 163 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 164 +#define GCC_USB30_PRIM_SLEEP_CLK 165 +#define GCC_USB3_PRIM_PHY_AUX_CLK 166 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 167 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 168 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 169 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 170 +#define GCC_VIDEO_AHB_CLK 171 +#define GCC_VIDEO_AXI0_CLK 172 +#define GCC_VIDEO_AXI1_CLK 173 +#define GCC_VIDEO_XO_CLK 174 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 175 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 176 +#define GCC_QMIP_DISP_DCP_SF_AHB_CLK 177 +#define GCC_QMIP_PCIE_AHB_CLK 178 +#define GCC_QMIP_VIDEO_CV_CPU_AHB_CLK 179 +#define GCC_QMIP_VIDEO_CVP_AHB_CLK 180 +#define GCC_QMIP_VIDEO_V_CPU_AHB_CLK 181 +#define GCC_DISP_AHB_CLK 182 + +/* GCC power domains */ +#define GCC_PCIE_0_GDSC 0 +#define GCC_PCIE_0_PHY_GDSC 1 +#define GCC_UFS_MEM_PHY_GDSC 2 +#define GCC_UFS_PHY_GDSC 3 +#define GCC_USB30_PRIM_GDSC 4 +#define GCC_USB3_PHY_GDSC 5 + +/* GCC resets */ +#define GCC_CAMERA_BCR 0 +#define GCC_DISPLAY_BCR 1 +#define GCC_EVA_AXI0_CLK_ARES 2 +#define GCC_EVA_AXI0C_CLK_ARES 3 +#define GCC_EVA_BCR 4 +#define GCC_GPU_BCR 5 +#define GCC_PCIE_0_BCR 6 +#define GCC_PCIE_0_LINK_DOWN_BCR 7 +#define GCC_PCIE_0_NOCSR_COM_PHY_BCR 8 +#define GCC_PCIE_0_PHY_BCR 9 +#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR 10 +#define GCC_PCIE_PHY_BCR 11 +#define GCC_PCIE_PHY_CFG_AHB_BCR 12 +#define GCC_PCIE_PHY_COM_BCR 13 +#define GCC_PCIE_RSCC_BCR 14 +#define GCC_PDM_BCR 15 +#define GCC_QUPV3_WRAPPER_1_BCR 16 +#define GCC_QUPV3_WRAPPER_2_BCR 17 +#define GCC_QUPV3_WRAPPER_3_BCR 18 +#define GCC_QUPV3_WRAPPER_4_BCR 19 +#define GCC_QUPV3_WRAPPER_I2C_BCR 20 +#define GCC_QUSB2PHY_PRIM_BCR 21 +#define GCC_QUSB2PHY_SEC_BCR 22 +#define GCC_SDCC2_BCR 23 +#define GCC_SDCC4_BCR 24 +#define GCC_UFS_PHY_BCR 25 +#define GCC_USB30_PRIM_BCR 26 +#define GCC_USB3_DP_PHY_PRIM_BCR 27 +#define GCC_USB3_DP_PHY_SEC_BCR 28 +#define GCC_USB3_PHY_PRIM_BCR 29 +#define GCC_USB3_PHY_SEC_BCR 30 +#define GCC_USB3PHY_PHY_PRIM_BCR 31 +#define GCC_USB3PHY_PHY_SEC_BCR 32 +#define GCC_VIDEO_AXI0_CLK_ARES 33 +#define GCC_VIDEO_AXI1_CLK_ARES 34 +#define GCC_VIDEO_BCR 35 +#define GCC_VIDEO_XO_CLK_ARES 36 + +#endif From 371d32394e538a759a1a7bb475de67424c1d633b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 24 Oct 2025 10:58:36 -0700 Subject: [PATCH 208/684] perf evsel: Remove unused metric_events variable The metric_events exist in the metric_expr list and so this variable has been unused for a while. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 2 -- tools/perf/util/evsel.h | 1 - 2 files changed, 3 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ad11cbfcbff1c7..67a898cda86ab5 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -402,7 +402,6 @@ void evsel__init(struct evsel *evsel, evsel->sample_size = __evsel__sample_size(attr->sample_type); evsel__calc_id_pos(evsel); evsel->cmdline_group_boundary = false; - evsel->metric_events = NULL; evsel->per_pkg_mask = NULL; evsel->collect_stat = false; evsel->group_pmu_name = NULL; @@ -1754,7 +1753,6 @@ void evsel__exit(struct evsel *evsel) evsel__zero_per_pkg(evsel); hashmap__free(evsel->per_pkg_mask); evsel->per_pkg_mask = NULL; - zfree(&evsel->metric_events); if (evsel__priv_destructor) evsel__priv_destructor(evsel->priv); perf_evsel__object.fini(evsel); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index f8de0f9a719b02..71f74c7036efb9 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -100,7 +100,6 @@ struct evsel { * metric fields are similar, but needs more care as they can have * references to other metric (evsel). */ - struct evsel **metric_events; struct evsel *metric_leader; void *handler; From 5faa23cdab412ad2c65d18c30f78d6489ec7c9de Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 24 Oct 2025 10:58:37 -0700 Subject: [PATCH 209/684] perf metricgroup: Update comment on location of metric_event list Update comment as the stat_config no longer holds all metrics. Signed-off-by: Ian Rogers Fixes: faebee18d720 ("perf stat: Move metric list from config to evlist") Signed-off-by: Namhyung Kim --- tools/perf/util/metricgroup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 324880b2ed8f2e..4be6bfc13c467d 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -16,7 +16,7 @@ struct cgroup; /** * A node in a rblist keyed by the evsel. The global rblist of metric events - * generally exists in perf_stat_config. The evsel is looked up in the rblist + * generally exists in evlist. The evsel is looked up in the rblist * yielding a list of metric_expr. */ struct metric_event { From 3bae9228a5503f7fb6464e895c3f542221ce9395 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 24 Oct 2025 10:58:38 -0700 Subject: [PATCH 210/684] perf metricgroup: Missed free on error path If an out-of-memory occurs the expr also needs freeing. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/metricgroup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 595b83142d2cc5..c822cf5da53b3f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1455,6 +1455,7 @@ static int parse_groups(struct evlist *perf_evlist, if (!expr->metric_name) { ret = -ENOMEM; + free(expr); free(metric_events); goto out; } From 3f02cebe130260fbfe6e2028d252d63503ba99a8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 24 Oct 2025 10:58:39 -0700 Subject: [PATCH 211/684] perf metricgroup: When copy metrics copy default information When copy metrics into a group also copy default information from the original metrics. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/metricgroup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index c822cf5da53b3f..48936e5178035d 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1608,6 +1608,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, pr_debug("copying metric event for cgroup '%s': %s (idx=%d)\n", cgrp ? cgrp->name : "root", evsel->name, evsel->core.idx); + new_me->is_default = old_me->is_default; list_for_each_entry(old_expr, &old_me->head, nd) { new_expr = malloc(sizeof(*new_expr)); if (!new_expr) @@ -1621,6 +1622,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, new_expr->metric_unit = old_expr->metric_unit; new_expr->runtime = old_expr->runtime; + new_expr->default_metricgroup_name = old_expr->default_metricgroup_name; if (old_expr->metric_refs) { /* calculate number of metric_events */ From 4df43709370cc18e9b09aa8049a6ab1f780af77e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 24 Oct 2025 10:58:41 -0700 Subject: [PATCH 212/684] perf jevents: Make all tables static The tables created by jevents.py are only used within the pmu-events.c file. Change the declarations of those global variables to be static to encapsulate this. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/empty-pmu-events.c | 10 +++++----- tools/perf/pmu-events/jevents.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 336e3924ce84f7..5120fb93690edb 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -2585,7 +2585,7 @@ static const struct compact_pmu_event pmu_events__common_tool[] = { }; -const struct pmu_table_entry pmu_events__common[] = { +static const struct pmu_table_entry pmu_events__common[] = { { .entries = pmu_events__common_default_core, .num_entries = ARRAY_SIZE(pmu_events__common_default_core), @@ -2630,7 +2630,7 @@ static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_r }; -const struct pmu_table_entry pmu_events__test_soc_cpu[] = { +static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { { .entries = pmu_events__test_soc_cpu_default_core, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), @@ -2682,7 +2682,7 @@ static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = }; -const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { +static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { { .entries = pmu_metrics__test_soc_cpu_default_core, .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), @@ -2701,7 +2701,7 @@ static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pm }; -const struct pmu_table_entry pmu_events__test_soc_sys[] = { +static const struct pmu_table_entry pmu_events__test_soc_sys[] = { { .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), @@ -2751,7 +2751,7 @@ struct pmu_events_map { * Global table mapping each known CPU for the architecture to its * table of PMU events. */ -const struct pmu_events_map pmu_events_map[] = { +static const struct pmu_events_map pmu_events_map[] = { { .arch = "common", .cpuid = "common", diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 1f3917cbff8770..786a7049363fe6 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -550,7 +550,7 @@ def fix_none(s: Optional[str]) -> str: _args.output_file.write(f""" }}; -const struct pmu_table_entry {_pending_events_tblname}[] = {{ +static const struct pmu_table_entry {_pending_events_tblname}[] = {{ """) for (pmu, tbl_pmu) in sorted(pmus): pmu_name = f"{pmu}\\000" @@ -605,7 +605,7 @@ def fix_none(s: Optional[str]) -> str: _args.output_file.write(f""" }}; -const struct pmu_table_entry {_pending_metrics_tblname}[] = {{ +static const struct pmu_table_entry {_pending_metrics_tblname}[] = {{ """) for (pmu, tbl_pmu) in sorted(pmus): pmu_name = f"{pmu}\\000" @@ -730,7 +730,7 @@ def print_mapping_table(archs: Sequence[str]) -> None: * Global table mapping each known CPU for the architecture to its * table of PMU events. */ -const struct pmu_events_map pmu_events_map[] = { +static const struct pmu_events_map pmu_events_map[] = { """) for arch in archs: if arch == 'test': From cf6dd6cafdfc3844648ba52efdaec0bd4e631129 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Nov 2025 20:58:28 +0100 Subject: [PATCH 213/684] pinctrl: baytrail: Unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-baytrail.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 5fd107a00ef853..b3a5222a175fa6 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1498,9 +1498,9 @@ static int byt_gpio_add_pin_ranges(struct gpio_chip *chip) ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins); if (ret) - dev_err(dev, "failed to add GPIO pin range\n"); + return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); - return ret; + return 0; } static int byt_gpio_probe(struct intel_pinctrl *vg) @@ -1548,9 +1548,9 @@ static int byt_gpio_probe(struct intel_pinctrl *vg) ret = devm_gpiochip_add_data(vg->dev, gc, vg); if (ret) - dev_err(vg->dev, "failed adding byt-gpio chip\n"); + return dev_err_probe(vg->dev, ret, "failed to register gpiochip\n"); - return ret; + return 0; } static int byt_set_soc_data(struct intel_pinctrl *vg, @@ -1601,10 +1601,8 @@ static int byt_pinctrl_probe(struct platform_device *pdev) vg->dev = dev; ret = byt_set_soc_data(vg, soc_data); - if (ret) { - dev_err(dev, "failed to set soc data\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to set soc data\n"); vg->pctldesc = byt_pinctrl_desc; vg->pctldesc.name = dev_name(dev); @@ -1612,10 +1610,8 @@ static int byt_pinctrl_probe(struct platform_device *pdev) vg->pctldesc.npins = vg->soc->npins; vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg); - if (IS_ERR(vg->pctldev)) { - dev_err(dev, "failed to register pinctrl driver\n"); - return PTR_ERR(vg->pctldev); - } + if (IS_ERR(vg->pctldev)) + return dev_err_probe(dev, PTR_ERR(vg->pctldev), "failed to register pinctrl\n"); ret = byt_gpio_probe(vg); if (ret) From 6afe489df6b3af0851fb98f522ecdb41c75e4632 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Nov 2025 20:58:29 +0100 Subject: [PATCH 214/684] pinctrl: cherryview: Unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-cherryview.c | 24 ++++++++-------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index f81f7929cd3bd2..077fa1318aaff3 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1528,10 +1528,8 @@ static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) for (i = 0; i < community->ngpps; i++) { gpp = &community->gpps[i]; ret = gpiochip_add_pin_range(chip, dev_name(dev), gpp->base, gpp->base, gpp->size); - if (ret) { - dev_err(dev, "failed to add GPIO pin range\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); } return 0; @@ -1567,17 +1565,13 @@ static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) chip->irq.init_valid_mask = chv_init_irq_valid_mask; } else { irq_base = devm_irq_alloc_descs(dev, -1, 0, pctrl->soc->npins, NUMA_NO_NODE); - if (irq_base < 0) { - dev_err(dev, "Failed to allocate IRQ numbers\n"); - return irq_base; - } + if (irq_base < 0) + return dev_err_probe(dev, irq_base, "failed to allocate IRQ numbers\n"); } ret = devm_gpiochip_add_data(dev, chip, pctrl); - if (ret) { - dev_err(dev, "Failed to register gpiochip\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to register gpiochip\n"); if (!need_valid_mask) { for (i = 0; i < community->ngpps; i++) { @@ -1673,10 +1667,8 @@ static int chv_pinctrl_probe(struct platform_device *pdev) pctrl->pctldesc.npins = pctrl->soc->npins; pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); - if (IS_ERR(pctrl->pctldev)) { - dev_err(dev, "failed to register pinctrl driver\n"); - return PTR_ERR(pctrl->pctldev); - } + if (IS_ERR(pctrl->pctldev)) + return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n"); ret = chv_gpio_probe(pctrl, irq); if (ret) From e2620a2c44dcb00af8216afb74040bfe4dc4a211 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Nov 2025 20:58:30 +0100 Subject: [PATCH 215/684] pinctrl: intel: Unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index d68cef4ec52ac2..1e2f77d200f9f1 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1356,10 +1356,8 @@ static int intel_gpio_add_pin_ranges(struct gpio_chip *gc) ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), grp->gpio_base, grp->base, grp->size); - if (ret) { - dev_err(pctrl->dev, "failed to add GPIO pin range\n"); - return ret; - } + if (ret) + return dev_err_probe(pctrl->dev, ret, "failed to add GPIO pin range\n"); } return 0; @@ -1401,10 +1399,8 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) ret = devm_request_irq(pctrl->dev, irq, intel_gpio_irq, IRQF_SHARED | IRQF_NO_THREAD, dev_name(pctrl->dev), pctrl); - if (ret) { - dev_err(pctrl->dev, "failed to request interrupt\n"); - return ret; - } + if (ret) + return dev_err_probe(pctrl->dev, ret, "failed to request interrupt\n"); /* Setup IRQ chip */ girq = &pctrl->chip.irq; @@ -1417,10 +1413,8 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) girq->init_hw = intel_gpio_irq_init_hw; ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); - if (ret) { - dev_err(pctrl->dev, "failed to register gpiochip\n"); - return ret; - } + if (ret) + return dev_err_probe(pctrl->dev, ret, "failed to register gpiochip\n"); return 0; } @@ -1668,10 +1662,8 @@ int intel_pinctrl_probe(struct platform_device *pdev, pctrl->pctldesc.npins = pctrl->soc->npins; pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); - if (IS_ERR(pctrl->pctldev)) { - dev_err(dev, "failed to register pinctrl driver\n"); - return PTR_ERR(pctrl->pctldev); - } + if (IS_ERR(pctrl->pctldev)) + return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n"); ret = intel_gpio_probe(pctrl, irq); if (ret) From a13735785c27c0df5b51919b63fa98c1a03118f7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Nov 2025 20:19:15 +0100 Subject: [PATCH 216/684] pinctrl: lynxpoint: Unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-lynxpoint.c | 28 ++++++++--------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 3fb628309fb256..1565eefdd4bfac 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -700,9 +700,9 @@ static int lp_gpio_add_pin_ranges(struct gpio_chip *chip) ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins); if (ret) - dev_err(dev, "failed to add GPIO pin range\n"); + return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); - return ret; + return 0; } static int lp_gpio_probe(struct platform_device *pdev) @@ -739,24 +739,18 @@ static int lp_gpio_probe(struct platform_device *pdev) lg->pctldesc.npins = lg->soc->npins; lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg); - if (IS_ERR(lg->pctldev)) { - dev_err(dev, "failed to register pinctrl driver\n"); - return PTR_ERR(lg->pctldev); - } + if (IS_ERR(lg->pctldev)) + return dev_err_probe(dev, PTR_ERR(lg->pctldev), "failed to register pinctrl\n"); platform_set_drvdata(pdev, lg); io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!io_rc) { - dev_err(dev, "missing IO resources\n"); - return -EINVAL; - } + if (!io_rc) + return dev_err_probe(dev, -EINVAL, "missing IO resources\n"); regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc)); - if (!regs) { - dev_err(dev, "failed mapping IO region %pR\n", &io_rc); - return -EBUSY; - } + if (!regs) + return dev_err_probe(dev, -EBUSY, "failed mapping IO region %pR\n", &io_rc); for (i = 0; i < lg->soc->ncommunities; i++) { struct intel_community *comm = &lg->communities[i]; @@ -807,10 +801,8 @@ static int lp_gpio_probe(struct platform_device *pdev) } ret = devm_gpiochip_add_data(dev, gc, lg); - if (ret) { - dev_err(dev, "failed adding lp-gpio chip\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to register gpiochip\n"); return 0; } From 534ea60bc4809b8ec4f13d6b252c4bb8d5f243d2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Nov 2025 20:58:31 +0100 Subject: [PATCH 217/684] pinctrl: tangier: Unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-tangier.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-tangier.c b/drivers/pinctrl/intel/pinctrl-tangier.c index ac61e632b4879d..5f0b7334a4892d 100644 --- a/drivers/pinctrl/intel/pinctrl-tangier.c +++ b/drivers/pinctrl/intel/pinctrl-tangier.c @@ -562,8 +562,7 @@ static int tng_pinctrl_probe(struct platform_device *pdev, tp->pctldev = devm_pinctrl_register(dev, &tp->pctldesc, tp); if (IS_ERR(tp->pctldev)) - return dev_err_probe(dev, PTR_ERR(tp->pctldev), - "failed to register pinctrl driver\n"); + return dev_err_probe(dev, PTR_ERR(tp->pctldev), "failed to register pinctrl\n"); return 0; } From 59d2d28f2269dfb89d64828fd330bc32113fd036 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 4 Nov 2025 14:01:03 +0100 Subject: [PATCH 218/684] pinctrl: cix: sky1: Provide pin control dummy states This exports and calls the pinctrl_provide_dummies() function from the CIX SKY1 driver. The reasons are explained in a comment in the commit, in essence the two pin controllers need to go through explicit state transitions default->sleep->default despite they only handle one single state each. Reviewed-by: Hans Zhang Reviewed-by: Fugang Duan Signed-off-by: Linus Walleij --- drivers/pinctrl/cix/pinctrl-sky1-base.c | 15 +++++++++++++++ drivers/pinctrl/core.c | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/pinctrl/cix/pinctrl-sky1-base.c b/drivers/pinctrl/cix/pinctrl-sky1-base.c index b03e10147b09fc..a5b583f10441e4 100644 --- a/drivers/pinctrl/cix/pinctrl-sky1-base.c +++ b/drivers/pinctrl/cix/pinctrl-sky1-base.c @@ -560,6 +560,21 @@ int sky1_base_pinctrl_probe(struct platform_device *pdev, return ret; } + /* + * The SKY1 SoC has two pin controllers: one for normal working state + * and one for sleep state. Since one controller only has working + * states and the other only sleep states, it will seem to the + * controller is always in the first configured state, so no + * transitions between default->sleep->default are detected and no + * new pin states are applied when we go in and out of sleep state. + * + * To counter this, provide dummies, so that the sleep-only pin + * controller still get some default states, and the working state pin + * controller get some sleep states, so that state transitions occur + * and we re-configure pins for default and sleep states. + */ + pinctrl_provide_dummies(); + dev_dbg(&pdev->dev, "initialized SKY1 pinctrl driver\n"); return pinctrl_enable(spctl->pctl); diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 157510157d47aa..83254a95ef1741 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -70,6 +70,7 @@ void pinctrl_provide_dummies(void) { pinctrl_dummy_state = true; } +EXPORT_SYMBOL_GPL(pinctrl_provide_dummies); const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) { From e1a57abb3be5ca5a33b84861d4ff7ece923419b9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:35 +0100 Subject: [PATCH 219/684] pinctrl: intel: Introduce INTEL_GPP() macro A new macro will be used for the further refactoring of the drivers. Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index 4d4e1257afdf75..654af5977603d5 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -76,6 +76,15 @@ enum { INTEL_GPIO_BASE_MATCH = 0, }; +/* Initialise struct intel_padgroup */ +#define INTEL_GPP(r, s, e, g) \ + { \ + .reg_num = (r), \ + .base = (s), \ + .size = ((e) - (s) + 1), \ + .gpio_base = (g), \ + } + /** * struct intel_community - Intel pin community description * @barno: MMIO BAR number where registers for this community reside From 16b37ed0f373638c85bf9ed68d070073bd2921a5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:36 +0100 Subject: [PATCH 220/684] pinctrl: alderlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-alderlake.c | 68 ++++++++++------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-alderlake.c b/drivers/pinctrl/intel/pinctrl-alderlake.c index 108eac205aa9dc..7bf1d5c285a083 100644 --- a/drivers/pinctrl/intel/pinctrl-alderlake.c +++ b/drivers/pinctrl/intel/pinctrl-alderlake.c @@ -27,14 +27,6 @@ #define ADL_S_GPI_IS 0x200 #define ADL_S_GPI_IE 0x220 -#define ADL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define ADL_N_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, ADL_N) @@ -316,28 +308,28 @@ static const struct pinctrl_pin_desc adln_pins[] = { }; static const struct intel_padgroup adln_community0_gpps[] = { - ADL_GPP(0, 0, 25, 0), /* GPP_B */ - ADL_GPP(1, 26, 41, 32), /* GPP_T */ - ADL_GPP(2, 42, 66, 64), /* GPP_A */ + INTEL_GPP(0, 0, 25, 0), /* GPP_B */ + INTEL_GPP(1, 26, 41, 32), /* GPP_T */ + INTEL_GPP(2, 42, 66, 64), /* GPP_A */ }; static const struct intel_padgroup adln_community1_gpps[] = { - ADL_GPP(0, 67, 74, 96), /* GPP_S */ - ADL_GPP(1, 75, 94, 128), /* GPP_I */ - ADL_GPP(2, 95, 118, 160), /* GPP_H */ - ADL_GPP(3, 119, 139, 192), /* GPP_D */ - ADL_GPP(4, 140, 168, 224), /* vGPIO */ + INTEL_GPP(0, 67, 74, 96), /* GPP_S */ + INTEL_GPP(1, 75, 94, 128), /* GPP_I */ + INTEL_GPP(2, 95, 118, 160), /* GPP_H */ + INTEL_GPP(3, 119, 139, 192), /* GPP_D */ + INTEL_GPP(4, 140, 168, 224), /* vGPIO */ }; static const struct intel_padgroup adln_community4_gpps[] = { - ADL_GPP(0, 169, 192, 256), /* GPP_C */ - ADL_GPP(1, 193, 217, 288), /* GPP_F */ - ADL_GPP(2, 218, 223, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ - ADL_GPP(3, 224, 248, 320), /* GPP_E */ + INTEL_GPP(0, 169, 192, 256), /* GPP_C */ + INTEL_GPP(1, 193, 217, 288), /* GPP_F */ + INTEL_GPP(2, 218, 223, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(3, 224, 248, 320), /* GPP_E */ }; static const struct intel_padgroup adln_community5_gpps[] = { - ADL_GPP(0, 249, 256, 352), /* GPP_R */ + INTEL_GPP(0, 249, 256, 352), /* GPP_R */ }; static const struct intel_community adln_communities[] = { @@ -680,35 +672,35 @@ static const struct pinctrl_pin_desc adls_pins[] = { }; static const struct intel_padgroup adls_community0_gpps[] = { - ADL_GPP(0, 0, 24, 0), /* GPP_I */ - ADL_GPP(1, 25, 47, 32), /* GPP_R */ - ADL_GPP(2, 48, 59, 64), /* GPP_J */ - ADL_GPP(3, 60, 86, 96), /* vGPIO */ - ADL_GPP(4, 87, 94, 128), /* vGPIO_0 */ + INTEL_GPP(0, 0, 24, 0), /* GPP_I */ + INTEL_GPP(1, 25, 47, 32), /* GPP_R */ + INTEL_GPP(2, 48, 59, 64), /* GPP_J */ + INTEL_GPP(3, 60, 86, 96), /* vGPIO */ + INTEL_GPP(4, 87, 94, 128), /* vGPIO_0 */ }; static const struct intel_padgroup adls_community1_gpps[] = { - ADL_GPP(0, 95, 118, 160), /* GPP_B */ - ADL_GPP(1, 119, 126, 192), /* GPP_G */ - ADL_GPP(2, 127, 150, 224), /* GPP_H */ + INTEL_GPP(0, 95, 118, 160), /* GPP_B */ + INTEL_GPP(1, 119, 126, 192), /* GPP_G */ + INTEL_GPP(2, 127, 150, 224), /* GPP_H */ }; static const struct intel_padgroup adls_community3_gpps[] = { - ADL_GPP(0, 151, 159, INTEL_GPIO_BASE_NOMAP), /* SPI0 */ - ADL_GPP(1, 160, 175, 256), /* GPP_A */ - ADL_GPP(2, 176, 199, 288), /* GPP_C */ + INTEL_GPP(0, 151, 159, INTEL_GPIO_BASE_NOMAP), /* SPI0 */ + INTEL_GPP(1, 160, 175, 256), /* GPP_A */ + INTEL_GPP(2, 176, 199, 288), /* GPP_C */ }; static const struct intel_padgroup adls_community4_gpps[] = { - ADL_GPP(0, 200, 207, 320), /* GPP_S */ - ADL_GPP(1, 208, 230, 352), /* GPP_E */ - ADL_GPP(2, 231, 245, 384), /* GPP_K */ - ADL_GPP(3, 246, 269, 416), /* GPP_F */ + INTEL_GPP(0, 200, 207, 320), /* GPP_S */ + INTEL_GPP(1, 208, 230, 352), /* GPP_E */ + INTEL_GPP(2, 231, 245, 384), /* GPP_K */ + INTEL_GPP(3, 246, 269, 416), /* GPP_F */ }; static const struct intel_padgroup adls_community5_gpps[] = { - ADL_GPP(0, 270, 294, 448), /* GPP_D */ - ADL_GPP(1, 295, 303, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(0, 270, 294, 448), /* GPP_D */ + INTEL_GPP(1, 295, 303, INTEL_GPIO_BASE_NOMAP), /* JTAG */ }; static const struct intel_community adls_communities[] = { From 9db14f71029d9d2b23f831203d893c30b8e2a079 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:37 +0100 Subject: [PATCH 221/684] pinctrl: cannonlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-cannonlake.c | 68 ++++++++++------------ 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c index 14a5d339385d34..a3ffd19fd5bee3 100644 --- a/drivers/pinctrl/intel/pinctrl-cannonlake.c +++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c @@ -28,14 +28,6 @@ #define CNL_H_GPI_IS 0x100 #define CNL_H_GPI_IE 0x120 -#define CNL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define CNL_LP_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, CNL_LP) @@ -362,32 +354,32 @@ static const struct pinctrl_pin_desc cnlh_pins[] = { }; static const struct intel_padgroup cnlh_community0_gpps[] = { - CNL_GPP(0, 0, 24, 0), /* GPP_A */ - CNL_GPP(1, 25, 50, 32), /* GPP_B */ + INTEL_GPP(0, 0, 24, 0), /* GPP_A */ + INTEL_GPP(1, 25, 50, 32), /* GPP_B */ }; static const struct intel_padgroup cnlh_community1_gpps[] = { - CNL_GPP(0, 51, 74, 64), /* GPP_C */ - CNL_GPP(1, 75, 98, 96), /* GPP_D */ - CNL_GPP(2, 99, 106, 128), /* GPP_G */ - CNL_GPP(3, 107, 114, INTEL_GPIO_BASE_NOMAP), /* AZA */ - CNL_GPP(4, 115, 146, 160), /* vGPIO_0 */ - CNL_GPP(5, 147, 154, INTEL_GPIO_BASE_NOMAP), /* vGPIO_1 */ + INTEL_GPP(0, 51, 74, 64), /* GPP_C */ + INTEL_GPP(1, 75, 98, 96), /* GPP_D */ + INTEL_GPP(2, 99, 106, 128), /* GPP_G */ + INTEL_GPP(3, 107, 114, INTEL_GPIO_BASE_NOMAP), /* AZA */ + INTEL_GPP(4, 115, 146, 160), /* vGPIO_0 */ + INTEL_GPP(5, 147, 154, INTEL_GPIO_BASE_NOMAP), /* vGPIO_1 */ }; static const struct intel_padgroup cnlh_community3_gpps[] = { - CNL_GPP(0, 155, 178, 192), /* GPP_K */ - CNL_GPP(1, 179, 202, 224), /* GPP_H */ - CNL_GPP(2, 203, 215, 256), /* GPP_E */ - CNL_GPP(3, 216, 239, 288), /* GPP_F */ - CNL_GPP(4, 240, 248, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(0, 155, 178, 192), /* GPP_K */ + INTEL_GPP(1, 179, 202, 224), /* GPP_H */ + INTEL_GPP(2, 203, 215, 256), /* GPP_E */ + INTEL_GPP(3, 216, 239, 288), /* GPP_F */ + INTEL_GPP(4, 240, 248, INTEL_GPIO_BASE_NOMAP), /* SPI */ }; static const struct intel_padgroup cnlh_community4_gpps[] = { - CNL_GPP(0, 249, 259, INTEL_GPIO_BASE_NOMAP), /* CPU */ - CNL_GPP(1, 260, 268, INTEL_GPIO_BASE_NOMAP), /* JTAG */ - CNL_GPP(2, 269, 286, 320), /* GPP_I */ - CNL_GPP(3, 287, 298, 352), /* GPP_J */ + INTEL_GPP(0, 249, 259, INTEL_GPIO_BASE_NOMAP), /* CPU */ + INTEL_GPP(1, 260, 268, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(2, 269, 286, 320), /* GPP_I */ + INTEL_GPP(3, 287, 298, 352), /* GPP_J */ }; static const unsigned int cnlh_spi0_pins[] = { 40, 41, 42, 43 }; @@ -780,25 +772,25 @@ static const struct intel_function cnllp_functions[] = { }; static const struct intel_padgroup cnllp_community0_gpps[] = { - CNL_GPP(0, 0, 24, 0), /* GPP_A */ - CNL_GPP(1, 25, 50, 32), /* GPP_B */ - CNL_GPP(2, 51, 58, 64), /* GPP_G */ - CNL_GPP(3, 59, 67, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(0, 0, 24, 0), /* GPP_A */ + INTEL_GPP(1, 25, 50, 32), /* GPP_B */ + INTEL_GPP(2, 51, 58, 64), /* GPP_G */ + INTEL_GPP(3, 59, 67, INTEL_GPIO_BASE_NOMAP), /* SPI */ }; static const struct intel_padgroup cnllp_community1_gpps[] = { - CNL_GPP(0, 68, 92, 96), /* GPP_D */ - CNL_GPP(1, 93, 116, 128), /* GPP_F */ - CNL_GPP(2, 117, 140, 160), /* GPP_H */ - CNL_GPP(3, 141, 172, 192), /* vGPIO */ - CNL_GPP(4, 173, 180, 224), /* vGPIO */ + INTEL_GPP(0, 68, 92, 96), /* GPP_D */ + INTEL_GPP(1, 93, 116, 128), /* GPP_F */ + INTEL_GPP(2, 117, 140, 160), /* GPP_H */ + INTEL_GPP(3, 141, 172, 192), /* vGPIO */ + INTEL_GPP(4, 173, 180, 224), /* vGPIO */ }; static const struct intel_padgroup cnllp_community4_gpps[] = { - CNL_GPP(0, 181, 204, 256), /* GPP_C */ - CNL_GPP(1, 205, 228, 288), /* GPP_E */ - CNL_GPP(2, 229, 237, INTEL_GPIO_BASE_NOMAP), /* JTAG */ - CNL_GPP(3, 238, 243, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(0, 181, 204, 256), /* GPP_C */ + INTEL_GPP(1, 205, 228, 288), /* GPP_E */ + INTEL_GPP(2, 229, 237, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(3, 238, 243, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ }; static const struct intel_community cnllp_communities[] = { From 51327d683963cf2f4f4210f8275e9a522ba27dd4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:38 +0100 Subject: [PATCH 222/684] pinctrl: icelake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-icelake.c | 60 +++++++++++-------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-icelake.c b/drivers/pinctrl/intel/pinctrl-icelake.c index 7e028c61ed0ff1..1516fe7b4e4a17 100644 --- a/drivers/pinctrl/intel/pinctrl-icelake.c +++ b/drivers/pinctrl/intel/pinctrl-icelake.c @@ -28,14 +28,6 @@ #define ICL_N_GPI_IS 0x100 #define ICL_N_GPI_IE 0x120 -#define ICL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define ICL_LP_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, ICL_LP) @@ -302,29 +294,29 @@ static const struct pinctrl_pin_desc icllp_pins[] = { }; static const struct intel_padgroup icllp_community0_gpps[] = { - ICL_GPP(0, 0, 7, 0), /* GPP_G */ - ICL_GPP(1, 8, 33, 32), /* GPP_B */ - ICL_GPP(2, 34, 58, 64), /* GPP_A */ + INTEL_GPP(0, 0, 7, 0), /* GPP_G */ + INTEL_GPP(1, 8, 33, 32), /* GPP_B */ + INTEL_GPP(2, 34, 58, 64), /* GPP_A */ }; static const struct intel_padgroup icllp_community1_gpps[] = { - ICL_GPP(0, 59, 82, 96), /* GPP_H */ - ICL_GPP(1, 83, 103, 128), /* GPP_D */ - ICL_GPP(2, 104, 123, 160), /* GPP_F */ - ICL_GPP(3, 124, 152, 192), /* vGPIO */ + INTEL_GPP(0, 59, 82, 96), /* GPP_H */ + INTEL_GPP(1, 83, 103, 128), /* GPP_D */ + INTEL_GPP(2, 104, 123, 160), /* GPP_F */ + INTEL_GPP(3, 124, 152, 192), /* vGPIO */ }; static const struct intel_padgroup icllp_community4_gpps[] = { - ICL_GPP(0, 153, 176, 224), /* GPP_C */ - ICL_GPP(1, 177, 182, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ - ICL_GPP(2, 183, 206, 256), /* GPP_E */ - ICL_GPP(3, 207, 215, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(0, 153, 176, 224), /* GPP_C */ + INTEL_GPP(1, 177, 182, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(2, 183, 206, 256), /* GPP_E */ + INTEL_GPP(3, 207, 215, INTEL_GPIO_BASE_NOMAP), /* JTAG */ }; static const struct intel_padgroup icllp_community5_gpps[] = { - ICL_GPP(0, 216, 223, 288), /* GPP_R */ - ICL_GPP(1, 224, 231, 320), /* GPP_S */ - ICL_GPP(2, 232, 240, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(0, 216, 223, 288), /* GPP_R */ + INTEL_GPP(1, 224, 231, 320), /* GPP_S */ + INTEL_GPP(2, 232, 240, INTEL_GPIO_BASE_NOMAP), /* SPI */ }; static const struct intel_community icllp_communities[] = { @@ -632,27 +624,27 @@ static const struct pinctrl_pin_desc icln_pins[] = { }; static const struct intel_padgroup icln_community0_gpps[] = { - ICL_GPP(0, 0, 8, INTEL_GPIO_BASE_NOMAP), /* SPI */ - ICL_GPP(1, 9, 34, 32), /* GPP_B */ - ICL_GPP(2, 35, 55, 64), /* GPP_A */ - ICL_GPP(3, 56, 63, 96), /* GPP_S */ - ICL_GPP(4, 64, 71, 128), /* GPP_R */ + INTEL_GPP(0, 0, 8, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(1, 9, 34, 32), /* GPP_B */ + INTEL_GPP(2, 35, 55, 64), /* GPP_A */ + INTEL_GPP(3, 56, 63, 96), /* GPP_S */ + INTEL_GPP(4, 64, 71, 128), /* GPP_R */ }; static const struct intel_padgroup icln_community1_gpps[] = { - ICL_GPP(0, 72, 95, 160), /* GPP_H */ - ICL_GPP(1, 96, 121, 192), /* GPP_D */ - ICL_GPP(2, 122, 150, 224), /* vGPIO */ - ICL_GPP(3, 151, 174, 256), /* GPP_C */ + INTEL_GPP(0, 72, 95, 160), /* GPP_H */ + INTEL_GPP(1, 96, 121, 192), /* GPP_D */ + INTEL_GPP(2, 122, 150, 224), /* vGPIO */ + INTEL_GPP(3, 151, 174, 256), /* GPP_C */ }; static const struct intel_padgroup icln_community4_gpps[] = { - ICL_GPP(0, 175, 180, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ - ICL_GPP(1, 181, 204, 288), /* GPP_E */ + INTEL_GPP(0, 175, 180, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(1, 181, 204, 288), /* GPP_E */ }; static const struct intel_padgroup icln_community5_gpps[] = { - ICL_GPP(0, 205, 212, INTEL_GPIO_BASE_ZERO), /* GPP_G */ + INTEL_GPP(0, 205, 212, INTEL_GPIO_BASE_ZERO), /* GPP_G */ }; static const struct intel_community icln_communities[] = { From 29d06c2d39d054eb72f62adac1ba1b63f2d0b365 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:39 +0100 Subject: [PATCH 223/684] pinctrl: jasperlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-jasperlake.c | 34 +++++++++------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-jasperlake.c b/drivers/pinctrl/intel/pinctrl-jasperlake.c index aef0e7f921549e..c6e1836c69a7bc 100644 --- a/drivers/pinctrl/intel/pinctrl-jasperlake.c +++ b/drivers/pinctrl/intel/pinctrl-jasperlake.c @@ -21,14 +21,6 @@ #define JSL_GPI_IS 0x100 #define JSL_GPI_IE 0x120 -#define JSL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define JSL_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, JSL) @@ -283,28 +275,28 @@ static const struct pinctrl_pin_desc jsl_pins[] = { }; static const struct intel_padgroup jsl_community0_gpps[] = { - JSL_GPP(0, 0, 19, 320), /* GPP_F */ - JSL_GPP(1, 20, 28, INTEL_GPIO_BASE_NOMAP), /* SPI */ - JSL_GPP(2, 29, 54, 32), /* GPP_B */ - JSL_GPP(3, 55, 75, 64), /* GPP_A */ - JSL_GPP(4, 76, 83, 96), /* GPP_S */ - JSL_GPP(5, 84, 91, 128), /* GPP_R */ + INTEL_GPP(0, 0, 19, 320), /* GPP_F */ + INTEL_GPP(1, 20, 28, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(2, 29, 54, 32), /* GPP_B */ + INTEL_GPP(3, 55, 75, 64), /* GPP_A */ + INTEL_GPP(4, 76, 83, 96), /* GPP_S */ + INTEL_GPP(5, 84, 91, 128), /* GPP_R */ }; static const struct intel_padgroup jsl_community1_gpps[] = { - JSL_GPP(0, 92, 115, 160), /* GPP_H */ - JSL_GPP(1, 116, 141, 192), /* GPP_D */ - JSL_GPP(2, 142, 170, 224), /* vGPIO */ - JSL_GPP(3, 171, 194, 256), /* GPP_C */ + INTEL_GPP(0, 92, 115, 160), /* GPP_H */ + INTEL_GPP(1, 116, 141, 192), /* GPP_D */ + INTEL_GPP(2, 142, 170, 224), /* vGPIO */ + INTEL_GPP(3, 171, 194, 256), /* GPP_C */ }; static const struct intel_padgroup jsl_community4_gpps[] = { - JSL_GPP(0, 195, 200, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ - JSL_GPP(1, 201, 224, 288), /* GPP_E */ + INTEL_GPP(0, 195, 200, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(1, 201, 224, 288), /* GPP_E */ }; static const struct intel_padgroup jsl_community5_gpps[] = { - JSL_GPP(0, 225, 232, INTEL_GPIO_BASE_ZERO), /* GPP_G */ + INTEL_GPP(0, 225, 232, INTEL_GPIO_BASE_ZERO), /* GPP_G */ }; static const struct intel_community jsl_communities[] = { From c11e90dc9ab324cc14f90b9b26ec95710f52b846 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:40 +0100 Subject: [PATCH 224/684] pinctrl: lakefield: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-lakefield.c | 26 ++++++++--------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-lakefield.c b/drivers/pinctrl/intel/pinctrl-lakefield.c index 60281f4216085f..bfb8b565d15c1a 100644 --- a/drivers/pinctrl/intel/pinctrl-lakefield.c +++ b/drivers/pinctrl/intel/pinctrl-lakefield.c @@ -21,14 +21,6 @@ #define LKF_GPI_IS 0x100 #define LKF_GPI_IE 0x110 -#define LKF_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define LKF_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, LKF) @@ -308,24 +300,24 @@ static const struct pinctrl_pin_desc lkf_pins[] = { }; static const struct intel_padgroup lkf_community0_gpps[] = { - LKF_GPP(0, 0, 31, 0), /* EAST_0 */ - LKF_GPP(1, 32, 59, 32), /* EAST_1 */ + INTEL_GPP(0, 0, 31, 0), /* EAST_0 */ + INTEL_GPP(1, 32, 59, 32), /* EAST_1 */ }; static const struct intel_padgroup lkf_community1_gpps[] = { - LKF_GPP(0, 60, 91, 64), /* NORTHWEST_0 */ - LKF_GPP(1, 92, 123, 96), /* NORTHWEST_1 */ - LKF_GPP(2, 124, 148, 128), /* NORTHWEST_2 */ + INTEL_GPP(0, 60, 91, 64), /* NORTHWEST_0 */ + INTEL_GPP(1, 92, 123, 96), /* NORTHWEST_1 */ + INTEL_GPP(2, 124, 148, 128), /* NORTHWEST_2 */ }; static const struct intel_padgroup lkf_community2_gpps[] = { - LKF_GPP(0, 149, 180, 160), /* WEST_0 */ - LKF_GPP(1, 181, 212, 192), /* WEST_1 */ - LKF_GPP(2, 213, 237, 224), /* WEST_2 */ + INTEL_GPP(0, 149, 180, 160), /* WEST_0 */ + INTEL_GPP(1, 181, 212, 192), /* WEST_1 */ + INTEL_GPP(2, 213, 237, 224), /* WEST_2 */ }; static const struct intel_padgroup lkf_community3_gpps[] = { - LKF_GPP(0, 238, 266, 256), /* SOUTHEAST */ + INTEL_GPP(0, 238, 266, 256), /* SOUTHEAST */ }; static const struct intel_community lkf_communities[] = { From cac89a3dca3a6dbc420bf5253c2d212cb9b4b339 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:41 +0100 Subject: [PATCH 225/684] pinctrl: meteorlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-meteorlake.c | 54 +++++++++------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c index f564376ce43731..b7395947569a38 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorlake.c +++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c @@ -27,14 +27,6 @@ #define MTL_S_GPI_IS 0x200 #define MTL_S_GPI_IE 0x210 -#define MTL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define MTL_P_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_P) @@ -349,33 +341,33 @@ static const struct pinctrl_pin_desc mtlp_pins[] = { }; static const struct intel_padgroup mtlp_community0_gpps[] = { - MTL_GPP(0, 0, 4, 0), /* CPU */ - MTL_GPP(1, 5, 28, 32), /* GPP_V */ - MTL_GPP(2, 29, 52, 64), /* GPP_C */ + INTEL_GPP(0, 0, 4, 0), /* CPU */ + INTEL_GPP(1, 5, 28, 32), /* GPP_V */ + INTEL_GPP(2, 29, 52, 64), /* GPP_C */ }; static const struct intel_padgroup mtlp_community1_gpps[] = { - MTL_GPP(0, 53, 77, 96), /* GPP_A */ - MTL_GPP(1, 78, 102, 128), /* GPP_E */ + INTEL_GPP(0, 53, 77, 96), /* GPP_A */ + INTEL_GPP(1, 78, 102, 128), /* GPP_E */ }; static const struct intel_padgroup mtlp_community3_gpps[] = { - MTL_GPP(0, 103, 128, 160), /* GPP_H */ - MTL_GPP(1, 129, 154, 192), /* GPP_F */ - MTL_GPP(2, 155, 169, 224), /* SPI0 */ - MTL_GPP(3, 170, 183, 256), /* vGPIO_3 */ + INTEL_GPP(0, 103, 128, 160), /* GPP_H */ + INTEL_GPP(1, 129, 154, 192), /* GPP_F */ + INTEL_GPP(2, 155, 169, 224), /* SPI0 */ + INTEL_GPP(3, 170, 183, 256), /* vGPIO_3 */ }; static const struct intel_padgroup mtlp_community4_gpps[] = { - MTL_GPP(0, 184, 191, 288), /* GPP_S */ - MTL_GPP(1, 192, 203, 320), /* JTAG */ + INTEL_GPP(0, 184, 191, 288), /* GPP_S */ + INTEL_GPP(1, 192, 203, 320), /* JTAG */ }; static const struct intel_padgroup mtlp_community5_gpps[] = { - MTL_GPP(0, 204, 228, 352), /* GPP_B */ - MTL_GPP(1, 229, 253, 384), /* GPP_D */ - MTL_GPP(2, 254, 285, 416), /* vGPIO_0 */ - MTL_GPP(3, 286, 288, 448), /* vGPIO_1 */ + INTEL_GPP(0, 204, 228, 352), /* GPP_B */ + INTEL_GPP(1, 229, 253, 384), /* GPP_D */ + INTEL_GPP(2, 254, 285, 416), /* vGPIO_0 */ + INTEL_GPP(3, 286, 288, 448), /* vGPIO_1 */ }; static const struct intel_community mtlp_communities[] = { @@ -554,20 +546,20 @@ static const struct pinctrl_pin_desc mtls_pins[] = { }; static const struct intel_padgroup mtls_community0_gpps[] = { - MTL_GPP(0, 0, 27, 0), /* GPP_A */ - MTL_GPP(1, 28, 46, 32), /* vGPIO_0 */ - MTL_GPP(2, 47, 73, 64), /* GPP_C */ + INTEL_GPP(0, 0, 27, 0), /* GPP_A */ + INTEL_GPP(1, 28, 46, 32), /* vGPIO_0 */ + INTEL_GPP(2, 47, 73, 64), /* GPP_C */ }; static const struct intel_padgroup mtls_community1_gpps[] = { - MTL_GPP(0, 74, 93, 96), /* GPP_B */ - MTL_GPP(1, 94, 95, 128), /* vGPIO_3 */ - MTL_GPP(2, 96, 119, 160), /* GPP_D */ + INTEL_GPP(0, 74, 93, 96), /* GPP_B */ + INTEL_GPP(1, 94, 95, 128), /* vGPIO_3 */ + INTEL_GPP(2, 96, 119, 160), /* GPP_D */ }; static const struct intel_padgroup mtls_community3_gpps[] = { - MTL_GPP(0, 120, 135, 192), /* JTAG_CPU */ - MTL_GPP(1, 136, 147, 224), /* vGPIO_4 */ + INTEL_GPP(0, 120, 135, 192), /* JTAG_CPU */ + INTEL_GPP(1, 136, 147, 224), /* vGPIO_4 */ }; static const struct intel_community mtls_communities[] = { From 9151857eefbb8528690e37b07260301a58e9127d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:42 +0100 Subject: [PATCH 226/684] pinctrl: meteorpoint: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-meteorpoint.c | 46 +++++++++------------ 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-meteorpoint.c b/drivers/pinctrl/intel/pinctrl-meteorpoint.c index ab46ac5f3b159f..b7858c2b2c5cbf 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorpoint.c +++ b/drivers/pinctrl/intel/pinctrl-meteorpoint.c @@ -21,14 +21,6 @@ #define MTP_GPI_IS 0x200 #define MTP_GPI_IE 0x220 -#define MTP_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define MTP_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, MTP) @@ -395,37 +387,37 @@ static const struct pinctrl_pin_desc mtps_pins[] = { }; static const struct intel_padgroup mtps_community0_gpps[] = { - MTP_GPP(0, 0, 24, 0), /* GPP_D */ - MTP_GPP(1, 25, 38, 32), /* GPP_R */ - MTP_GPP(2, 39, 56, 64), /* GPP_J */ - MTP_GPP(3, 57, 87, 96), /* vGPIO */ + INTEL_GPP(0, 0, 24, 0), /* GPP_D */ + INTEL_GPP(1, 25, 38, 32), /* GPP_R */ + INTEL_GPP(2, 39, 56, 64), /* GPP_J */ + INTEL_GPP(3, 57, 87, 96), /* vGPIO */ }; static const struct intel_padgroup mtps_community1_gpps[] = { - MTP_GPP(0, 88, 102, 128), /* GPP_A */ - MTP_GPP(1, 103, 114, 160), /* DIR_ESPI */ - MTP_GPP(2, 115, 136, 192), /* GPP_B */ + INTEL_GPP(0, 88, 102, 128), /* GPP_A */ + INTEL_GPP(1, 103, 114, 160), /* DIR_ESPI */ + INTEL_GPP(2, 115, 136, 192), /* GPP_B */ }; static const struct intel_padgroup mtps_community3_gpps[] = { - MTP_GPP(0, 137, 145, 224), /* SPI0 */ - MTP_GPP(1, 146, 169, 256), /* GPP_C */ - MTP_GPP(2, 170, 189, 288), /* GPP_H */ - MTP_GPP(3, 190, 193, 320), /* vGPIO_3 */ - MTP_GPP(4, 194, 201, 352), /* vGPIO_0 */ - MTP_GPP(5, 202, 232, 384), /* vGPIO_4 */ + INTEL_GPP(0, 137, 145, 224), /* SPI0 */ + INTEL_GPP(1, 146, 169, 256), /* GPP_C */ + INTEL_GPP(2, 170, 189, 288), /* GPP_H */ + INTEL_GPP(3, 190, 193, 320), /* vGPIO_3 */ + INTEL_GPP(4, 194, 201, 352), /* vGPIO_0 */ + INTEL_GPP(5, 202, 232, 384), /* vGPIO_4 */ }; static const struct intel_padgroup mtps_community4_gpps[] = { - MTP_GPP(0, 233, 240, 416), /* GPP_S */ - MTP_GPP(1, 241, 263, 448), /* GPP_E */ - MTP_GPP(2, 264, 277, 480), /* GPP_K */ - MTP_GPP(3, 278, 301, 512), /* GPP_F */ + INTEL_GPP(0, 233, 240, 416), /* GPP_S */ + INTEL_GPP(1, 241, 263, 448), /* GPP_E */ + INTEL_GPP(2, 264, 277, 480), /* GPP_K */ + INTEL_GPP(3, 278, 301, 512), /* GPP_F */ }; static const struct intel_padgroup mtps_community5_gpps[] = { - MTP_GPP(0, 302, 322, 544), /* GPP_I */ - MTP_GPP(1, 323, 338, 576), /* JTAG_CPU */ + INTEL_GPP(0, 302, 322, 544), /* GPP_I */ + INTEL_GPP(1, 323, 338, 576), /* JTAG_CPU */ }; static const struct intel_community mtps_communities[] = { From ba6467787b6843dec08d16944f9d2a7757b5acfb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:43 +0100 Subject: [PATCH 227/684] pinctrl: tigerlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-tigerlake.c | 70 ++++++++++------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c index c43576e10273e0..c0887596d113a6 100644 --- a/drivers/pinctrl/intel/pinctrl-tigerlake.c +++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c @@ -28,14 +28,6 @@ #define TGL_H_GPI_IS 0x100 #define TGL_H_GPI_IE 0x120 -#define TGL_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define TGL_LP_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, TGL_LP) @@ -339,30 +331,30 @@ static const struct pinctrl_pin_desc tgllp_pins[] = { }; static const struct intel_padgroup tgllp_community0_gpps[] = { - TGL_GPP(0, 0, 25, 0), /* GPP_B */ - TGL_GPP(1, 26, 41, 32), /* GPP_T */ - TGL_GPP(2, 42, 66, 64), /* GPP_A */ + INTEL_GPP(0, 0, 25, 0), /* GPP_B */ + INTEL_GPP(1, 26, 41, 32), /* GPP_T */ + INTEL_GPP(2, 42, 66, 64), /* GPP_A */ }; static const struct intel_padgroup tgllp_community1_gpps[] = { - TGL_GPP(0, 67, 74, 96), /* GPP_S */ - TGL_GPP(1, 75, 98, 128), /* GPP_H */ - TGL_GPP(2, 99, 119, 160), /* GPP_D */ - TGL_GPP(3, 120, 143, 192), /* GPP_U */ - TGL_GPP(4, 144, 170, 224), /* vGPIO */ + INTEL_GPP(0, 67, 74, 96), /* GPP_S */ + INTEL_GPP(1, 75, 98, 128), /* GPP_H */ + INTEL_GPP(2, 99, 119, 160), /* GPP_D */ + INTEL_GPP(3, 120, 143, 192), /* GPP_U */ + INTEL_GPP(4, 144, 170, 224), /* vGPIO */ }; static const struct intel_padgroup tgllp_community4_gpps[] = { - TGL_GPP(0, 171, 194, 256), /* GPP_C */ - TGL_GPP(1, 195, 219, 288), /* GPP_F */ - TGL_GPP(2, 220, 225, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ - TGL_GPP(3, 226, 250, 320), /* GPP_E */ - TGL_GPP(4, 251, 259, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(0, 171, 194, 256), /* GPP_C */ + INTEL_GPP(1, 195, 219, 288), /* GPP_F */ + INTEL_GPP(2, 220, 225, INTEL_GPIO_BASE_NOMAP), /* HVCMOS */ + INTEL_GPP(3, 226, 250, 320), /* GPP_E */ + INTEL_GPP(4, 251, 259, INTEL_GPIO_BASE_NOMAP), /* JTAG */ }; static const struct intel_padgroup tgllp_community5_gpps[] = { - TGL_GPP(0, 260, 267, 352), /* GPP_R */ - TGL_GPP(1, 268, 276, INTEL_GPIO_BASE_NOMAP), /* SPI */ + INTEL_GPP(0, 260, 267, 352), /* GPP_R */ + INTEL_GPP(1, 268, 276, INTEL_GPIO_BASE_NOMAP), /* SPI */ }; static const struct intel_community tgllp_communities[] = { @@ -691,34 +683,34 @@ static const struct pinctrl_pin_desc tglh_pins[] = { }; static const struct intel_padgroup tglh_community0_gpps[] = { - TGL_GPP(0, 0, 24, 0), /* GPP_A */ - TGL_GPP(1, 25, 44, 32), /* GPP_R */ - TGL_GPP(2, 45, 70, 64), /* GPP_B */ - TGL_GPP(3, 71, 78, 96), /* vGPIO_0 */ + INTEL_GPP(0, 0, 24, 0), /* GPP_A */ + INTEL_GPP(1, 25, 44, 32), /* GPP_R */ + INTEL_GPP(2, 45, 70, 64), /* GPP_B */ + INTEL_GPP(3, 71, 78, 96), /* vGPIO_0 */ }; static const struct intel_padgroup tglh_community1_gpps[] = { - TGL_GPP(0, 79, 104, 128), /* GPP_D */ - TGL_GPP(1, 105, 128, 160), /* GPP_C */ - TGL_GPP(2, 129, 136, 192), /* GPP_S */ - TGL_GPP(3, 137, 153, 224), /* GPP_G */ - TGL_GPP(4, 154, 180, 256), /* vGPIO */ + INTEL_GPP(0, 79, 104, 128), /* GPP_D */ + INTEL_GPP(1, 105, 128, 160), /* GPP_C */ + INTEL_GPP(2, 129, 136, 192), /* GPP_S */ + INTEL_GPP(3, 137, 153, 224), /* GPP_G */ + INTEL_GPP(4, 154, 180, 256), /* vGPIO */ }; static const struct intel_padgroup tglh_community3_gpps[] = { - TGL_GPP(0, 181, 193, 288), /* GPP_E */ - TGL_GPP(1, 194, 217, 320), /* GPP_F */ + INTEL_GPP(0, 181, 193, 288), /* GPP_E */ + INTEL_GPP(1, 194, 217, 320), /* GPP_F */ }; static const struct intel_padgroup tglh_community4_gpps[] = { - TGL_GPP(0, 218, 241, 352), /* GPP_H */ - TGL_GPP(1, 242, 251, 384), /* GPP_J */ - TGL_GPP(2, 252, 266, 416), /* GPP_K */ + INTEL_GPP(0, 218, 241, 352), /* GPP_H */ + INTEL_GPP(1, 242, 251, 384), /* GPP_J */ + INTEL_GPP(2, 252, 266, 416), /* GPP_K */ }; static const struct intel_padgroup tglh_community5_gpps[] = { - TGL_GPP(0, 267, 281, 448), /* GPP_I */ - TGL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP), /* JTAG */ + INTEL_GPP(0, 267, 281, 448), /* GPP_I */ + INTEL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP), /* JTAG */ }; static const struct intel_community tglh_communities[] = { From d99b7a9d51ad9585c20427f99b83ea756bd84b4b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Nov 2025 15:56:44 +0100 Subject: [PATCH 228/684] pinctrl: sunrisepoint: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-sunrisepoint.c | 26 +++++++------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c index a7a5fa65fd9d04..b51befde9e8b33 100644 --- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c +++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c @@ -28,14 +28,6 @@ #define SPT_LP_GPI_IS 0x100 #define SPT_LP_GPI_IE 0x120 -#define SPT_H_GPP(r, s, e, g) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - .gpio_base = (g), \ - } - #define SPT_H_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, SPT_H) @@ -538,21 +530,21 @@ static const struct intel_function spth_functions[] = { }; static const struct intel_padgroup spth_community0_gpps[] = { - SPT_H_GPP(0, 0, 23, 0), /* GPP_A */ - SPT_H_GPP(1, 24, 47, 24), /* GPP_B */ + INTEL_GPP(0, 0, 23, 0), /* GPP_A */ + INTEL_GPP(1, 24, 47, 24), /* GPP_B */ }; static const struct intel_padgroup spth_community1_gpps[] = { - SPT_H_GPP(0, 48, 71, 48), /* GPP_C */ - SPT_H_GPP(1, 72, 95, 72), /* GPP_D */ - SPT_H_GPP(2, 96, 108, 96), /* GPP_E */ - SPT_H_GPP(3, 109, 132, 120), /* GPP_F */ - SPT_H_GPP(4, 133, 156, 144), /* GPP_G */ - SPT_H_GPP(5, 157, 180, 168), /* GPP_H */ + INTEL_GPP(0, 48, 71, 48), /* GPP_C */ + INTEL_GPP(1, 72, 95, 72), /* GPP_D */ + INTEL_GPP(2, 96, 108, 96), /* GPP_E */ + INTEL_GPP(3, 109, 132, 120), /* GPP_F */ + INTEL_GPP(4, 133, 156, 144), /* GPP_G */ + INTEL_GPP(5, 157, 180, 168), /* GPP_H */ }; static const struct intel_padgroup spth_community3_gpps[] = { - SPT_H_GPP(0, 181, 191, 192), /* GPP_I */ + INTEL_GPP(0, 181, 191, 192), /* GPP_I */ }; static const struct intel_community spth_communities[] = { From 2a42e3210d4331dddfb04b020050bd774cf99659 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Nov 2025 00:40:31 +0100 Subject: [PATCH 229/684] clk: rockchip: rk3568: Drop CLK_NR_CLKS usage In order to get rid of CLK_NR_CLKS and be able to drop it from the bindings, use rockchip_clk_find_max_clk_id helper to find the highest clock id. Reviewed-by: Sebastian Reichel Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251103234032.413563-2-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3568.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 97d279399ae84a..74eabf9b2ae2e1 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -1652,6 +1652,7 @@ CLK_OF_DECLARE(rk3568_cru_pmu, "rockchip,rk3568-pmucru", rk3568_pmu_clk_init); static void __init rk3568_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; + unsigned long clk_nr_clks; void __iomem *reg_base; reg_base = of_iomap(np, 0); @@ -1660,7 +1661,9 @@ static void __init rk3568_clk_init(struct device_node *np) return; } - ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + clk_nr_clks = rockchip_clk_find_max_clk_id(rk3568_clk_branches, + ARRAY_SIZE(rk3568_clk_branches)) + 1; + ctx = rockchip_clk_init(np, reg_base, clk_nr_clks); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); iounmap(reg_base); From ca38f0f65eefd79889b409c89c6932d7e2fe0993 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Nov 2025 00:40:32 +0100 Subject: [PATCH 230/684] dt-bindings: clock: rk3568: Drop CLK_NR_CLKS define CLK_NR_CLKS has always only be used on the driver side to calculate array sizes should never have been part of the clock-binding. Let's drop it, since the kernel code no longer uses it either and nothing else has ever used it. Acked-by: Conor Dooley Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251103234032.413563-3-heiko@sntech.de --- include/dt-bindings/clock/rk3568-cru.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/dt-bindings/clock/rk3568-cru.h b/include/dt-bindings/clock/rk3568-cru.h index 18bb8d41d74147..1e0aef8a645d3f 100644 --- a/include/dt-bindings/clock/rk3568-cru.h +++ b/include/dt-bindings/clock/rk3568-cru.h @@ -483,8 +483,6 @@ #define PCLK_CORE_PVTM 450 -#define CLK_NR_CLKS (PCLK_CORE_PVTM + 1) - /* scmi-clocks indices */ #define SCMI_CLK_CPU 0 From 6bd89ae7d14788ba15e25289479addcb98e7dc26 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 6 Nov 2025 11:00:23 -0800 Subject: [PATCH 231/684] perf record: Make sure to update build-ID cache Recent change on enabling --buildid-mmap by default brought an issue with build-id handling. With build-ID in MMAP2 records, we don't need to save the build-ID table in the header of a perf data file. But the actual file contents still need to be cached in the debug directory for annotation etc. Split the build-ID header processing and caching and make sure perf record to save hit DSOs in the build-ID cache by moving perf_session__cache_build_ids() to the end of the record__ finish_output(). Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 30 +++++++++++++++--------------- tools/perf/util/header.c | 1 - 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ffb94a8339b03e..fe10bb7f35cbea 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1890,15 +1890,14 @@ record__finish_output(struct record *rec) } /* Buildid scanning disabled or build ID in kernel and synthesized map events. */ - if (!rec->no_buildid) { + if (!rec->no_buildid || !rec->no_buildid_cache) { process_buildids(rec); if (rec->buildid_all) perf_session__dsos_hit_all(rec->session); } perf_session__write_header(rec->session, rec->evlist, fd, true); - - return; + perf_session__cache_build_ids(rec->session); } static int record__synthesize_workload(struct record *rec, bool tail) @@ -3083,7 +3082,7 @@ static int perf_record_config(const char *var, const char *value, void *cb) else if (!strcmp(value, "no-cache")) rec->no_buildid_cache = true; else if (!strcmp(value, "skip")) - rec->no_buildid = true; + rec->no_buildid = rec->no_buildid_cache = true; else if (!strcmp(value, "mmap")) rec->buildid_mmap = true; else if (!strcmp(value, "no-mmap")) @@ -4192,24 +4191,25 @@ int cmd_record(int argc, const char **argv) record.opts.record_switch_events = true; } - if (!rec->buildid_mmap) { - pr_debug("Disabling build id in synthesized mmap2 events.\n"); - symbol_conf.no_buildid_mmap2 = true; - } else if (rec->buildid_mmap_set) { - /* - * Explicitly passing --buildid-mmap disables buildid processing - * and cache generation. - */ - rec->no_buildid = true; - } if (rec->buildid_mmap && !perf_can_record_build_id()) { pr_warning("Missing support for build id in kernel mmap events.\n" "Disable this warning with --no-buildid-mmap\n"); rec->buildid_mmap = false; } + if (rec->buildid_mmap) { /* Enable perf_event_attr::build_id bit. */ rec->opts.build_id = true; + /* Disable build-ID table in the header. */ + rec->no_buildid = true; + } else { + pr_debug("Disabling build id in synthesized mmap2 events.\n"); + symbol_conf.no_buildid_mmap2 = true; + } + + if (rec->no_buildid_set && rec->no_buildid) { + /* -B implies -N for historic reasons. */ + rec->no_buildid_cache = true; } if (rec->opts.record_cgroup && !perf_can_record_cgroup()) { @@ -4306,7 +4306,7 @@ int cmd_record(int argc, const char **argv) err = -ENOMEM; - if (rec->no_buildid_cache || rec->no_buildid) { + if (rec->no_buildid_cache) { disable_buildid_cache(); } else if (rec->switch_output.enabled) { /* diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4f2a6e10ed5cc0..4de7ca16b5522c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -335,7 +335,6 @@ static int write_build_id(struct feat_fd *ff, pr_debug("failed to write buildid table\n"); return err; } - perf_session__cache_build_ids(session); return 0; } From 268a31a9f88759c2f1a85a1d81524326d0e47290 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 6 Nov 2025 13:53:50 -0800 Subject: [PATCH 232/684] perf stat: Add ScaleUnit to {cpu,task}-clock JSON description This changes the output of the event like below. In fact, that's the output it used to have before the JSON conversion. Before: $ perf stat -e task-clock true Performance counter stats for 'true': 313,848 task-clock # 0.290 CPUs utilized 0.001081223 seconds time elapsed 0.001122000 seconds user 0.000000000 seconds sys After: $ perf stat -e task-clock true Performance counter stats for 'true': 0.36 msec task-clock # 0.297 CPUs utilized 0.001225435 seconds time elapsed 0.001268000 seconds user 0.000000000 seconds sys Reviewed-by: Ian Rogers Fixes: 9957d8c801fe0cb90 ("perf jevents: Add common software event json") Signed-off-by: Namhyung Kim --- .../arch/common/common/software.json | 6 +- tools/perf/pmu-events/empty-pmu-events.c | 268 +++++++++--------- 2 files changed, 138 insertions(+), 136 deletions(-) diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json index f2551f1107fd71..e6819ae219bb58 100644 --- a/tools/perf/pmu-events/arch/common/common/software.json +++ b/tools/perf/pmu-events/arch/common/common/software.json @@ -3,13 +3,15 @@ "Unit": "software", "EventName": "cpu-clock", "BriefDescription": "Per-CPU high-resolution timer based event", - "ConfigCode": "0" + "ConfigCode": "0", + "ScaleUnit": "1e-6msec" }, { "Unit": "software", "EventName": "task-clock", "BriefDescription": "Per-task high-resolution timer based event", - "ConfigCode": "1" + "ConfigCode": "1", + "ScaleUnit": "1e-6msec" }, { "Unit": "software", diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 5120fb93690edb..2fdf4fbf36e258 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1251,73 +1251,73 @@ static const char *const big_c_string = /* offset=123247 */ "idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" /* offset=123400 */ "ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000" /* offset=123512 */ "software\000" -/* offset=123521 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000" -/* offset=123599 */ "task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000" -/* offset=123679 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=123774 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=123869 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" -/* offset=123970 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" -/* offset=124071 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=124203 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=124335 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" -/* offset=124444 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" -/* offset=124547 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" -/* offset=124639 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" -/* offset=124766 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" -/* offset=124846 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" -/* offset=124948 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" -/* offset=125051 */ "tool\000" -/* offset=125056 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" -/* offset=125132 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" -/* offset=125202 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" -/* offset=125270 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" -/* offset=125346 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" -/* offset=125491 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" -/* offset=125594 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" -/* offset=125711 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" -/* offset=125787 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" -/* offset=125873 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" -/* offset=125983 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" -/* offset=126090 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" -/* offset=126189 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" -/* offset=126251 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" -/* offset=126313 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" -/* offset=126411 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" -/* offset=126513 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" -/* offset=126646 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" -/* offset=126764 */ "hisi_sccl,ddrc\000" -/* offset=126779 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" -/* offset=126849 */ "uncore_cbox\000" -/* offset=126861 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" -/* offset=127015 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" -/* offset=127069 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" -/* offset=127127 */ "hisi_sccl,l3c\000" -/* offset=127141 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" -/* offset=127209 */ "uncore_imc_free_running\000" -/* offset=127233 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" -/* offset=127313 */ "uncore_imc\000" -/* offset=127324 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" -/* offset=127389 */ "uncore_sys_ddr_pmu\000" -/* offset=127408 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" -/* offset=127484 */ "uncore_sys_ccn_pmu\000" -/* offset=127503 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" -/* offset=127580 */ "uncore_sys_cmn_pmu\000" -/* offset=127599 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=127742 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" -/* offset=127764 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" -/* offset=127827 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" -/* offset=127993 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=128057 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=128124 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" -/* offset=128195 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" -/* offset=128289 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" -/* offset=128423 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" -/* offset=128487 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=128555 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=128625 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" -/* offset=128647 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" -/* offset=128669 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" -/* offset=128689 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" +/* offset=123521 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\000001e-6msec\000\000\000\000\000" +/* offset=123607 */ "task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000" +/* offset=123695 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123790 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123885 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" +/* offset=123986 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" +/* offset=124087 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124219 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124351 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" +/* offset=124460 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" +/* offset=124563 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" +/* offset=124655 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" +/* offset=124782 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" +/* offset=124862 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" +/* offset=124964 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" +/* offset=125067 */ "tool\000" +/* offset=125072 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" +/* offset=125148 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" +/* offset=125218 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" +/* offset=125286 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" +/* offset=125362 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" +/* offset=125507 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" +/* offset=125610 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" +/* offset=125727 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" +/* offset=125803 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" +/* offset=125889 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" +/* offset=125999 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" +/* offset=126106 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" +/* offset=126205 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" +/* offset=126267 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" +/* offset=126329 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" +/* offset=126427 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" +/* offset=126529 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" +/* offset=126662 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" +/* offset=126780 */ "hisi_sccl,ddrc\000" +/* offset=126795 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" +/* offset=126865 */ "uncore_cbox\000" +/* offset=126877 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" +/* offset=127031 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" +/* offset=127085 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" +/* offset=127143 */ "hisi_sccl,l3c\000" +/* offset=127157 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" +/* offset=127225 */ "uncore_imc_free_running\000" +/* offset=127249 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" +/* offset=127329 */ "uncore_imc\000" +/* offset=127340 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" +/* offset=127405 */ "uncore_sys_ddr_pmu\000" +/* offset=127424 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" +/* offset=127500 */ "uncore_sys_ccn_pmu\000" +/* offset=127519 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" +/* offset=127596 */ "uncore_sys_cmn_pmu\000" +/* offset=127615 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" +/* offset=127758 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" +/* offset=127780 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" +/* offset=127843 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" +/* offset=128009 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=128073 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=128140 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" +/* offset=128211 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" +/* offset=128305 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" +/* offset=128439 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" +/* offset=128503 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=128571 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=128641 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" +/* offset=128663 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" +/* offset=128685 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" +/* offset=128705 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { @@ -2553,35 +2553,35 @@ static const struct compact_pmu_event pmu_events__common_default_core[] = { { 122795 }, /* stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__common_software[] = { -{ 124547 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */ -{ 124846 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */ -{ 124948 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */ -{ 123869 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */ -{ 123521 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */ -{ 124071 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 123970 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */ -{ 124766 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */ -{ 124639 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */ -{ 123679 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 124444 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */ -{ 124203 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 124335 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */ -{ 123774 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 123599 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */ +{ 124563 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */ +{ 124862 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */ +{ 124964 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */ +{ 123885 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */ +{ 123521 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\000001e-6msec\000\000\000\000\000 */ +{ 124087 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */ +{ 123986 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */ +{ 124782 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */ +{ 124655 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */ +{ 123695 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */ +{ 124460 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */ +{ 124219 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */ +{ 124351 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */ +{ 123790 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */ +{ 123607 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__common_tool[] = { -{ 125056 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ -{ 125270 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ -{ 125346 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ -{ 125491 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ -{ 125594 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ -{ 125711 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ -{ 125787 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ -{ 125873 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ -{ 125983 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ -{ 125202 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ -{ 126090 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ -{ 125132 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ +{ 125072 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ +{ 125286 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ +{ 125362 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ +{ 125507 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ +{ 125610 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ +{ 125727 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ +{ 125803 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ +{ 125889 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ +{ 125999 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ +{ 125218 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ +{ 126106 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ +{ 125148 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ }; @@ -2599,34 +2599,34 @@ static const struct pmu_table_entry pmu_events__common[] = { { .entries = pmu_events__common_tool, .num_entries = ARRAY_SIZE(pmu_events__common_tool), - .pmu_name = { 125051 /* tool\000 */ }, + .pmu_name = { 125067 /* tool\000 */ }, }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { -{ 126189 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ -{ 126251 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ -{ 126513 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ -{ 126646 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ -{ 126313 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ -{ 126411 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ +{ 126205 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ +{ 126267 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ +{ 126529 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ +{ 126662 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ +{ 126329 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ +{ 126427 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { -{ 126779 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ +{ 126795 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { -{ 127141 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ +{ 127157 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { -{ 127015 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ -{ 127069 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ -{ 126861 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ +{ 127031 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ +{ 127085 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ +{ 126877 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { -{ 127324 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ +{ 127340 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { -{ 127233 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ +{ 127249 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ }; @@ -2639,46 +2639,46 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { { .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), - .pmu_name = { 126764 /* hisi_sccl,ddrc\000 */ }, + .pmu_name = { 126780 /* hisi_sccl,ddrc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), - .pmu_name = { 127127 /* hisi_sccl,l3c\000 */ }, + .pmu_name = { 127143 /* hisi_sccl,l3c\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_cbox, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), - .pmu_name = { 126849 /* uncore_cbox\000 */ }, + .pmu_name = { 126865 /* uncore_cbox\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), - .pmu_name = { 127313 /* uncore_imc\000 */ }, + .pmu_name = { 127329 /* uncore_imc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), - .pmu_name = { 127209 /* uncore_imc_free_running\000 */ }, + .pmu_name = { 127225 /* uncore_imc_free_running\000 */ }, }, }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 127742 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ -{ 128423 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ -{ 128195 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ -{ 128289 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ -{ 128487 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 128555 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 127827 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ -{ 127764 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ -{ 128689 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ -{ 128625 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ -{ 128647 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ -{ 128669 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ -{ 128124 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ -{ 127993 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ -{ 128057 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 127758 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ +{ 128439 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ +{ 128211 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ +{ 128305 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ +{ 128503 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 128571 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 127843 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ +{ 127780 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ +{ 128705 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ +{ 128641 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ +{ 128663 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ +{ 128685 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ +{ 128140 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ +{ 128009 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 128073 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ }; @@ -2691,13 +2691,13 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { -{ 127503 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ +{ 127519 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { -{ 127599 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ +{ 127615 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { -{ 127408 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ +{ 127424 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ }; @@ -2705,17 +2705,17 @@ static const struct pmu_table_entry pmu_events__test_soc_sys[] = { { .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), - .pmu_name = { 127484 /* uncore_sys_ccn_pmu\000 */ }, + .pmu_name = { 127500 /* uncore_sys_ccn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), - .pmu_name = { 127580 /* uncore_sys_cmn_pmu\000 */ }, + .pmu_name = { 127596 /* uncore_sys_cmn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), - .pmu_name = { 127389 /* uncore_sys_ddr_pmu\000 */ }, + .pmu_name = { 127405 /* uncore_sys_ddr_pmu\000 */ }, }, }; From fa4a527af5cddad6f13abf80105f4da79876c31e Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Thu, 21 Aug 2025 19:01:51 +0800 Subject: [PATCH 233/684] perf vendor events arm64:: Add i.MX94 DDR Performance Monitor metrics Add JSON metrics for i.MX94 DDR Performance Monitor. Reviewed-by: Peng Fan Reviewed-by: Frank Li Signed-off-by: Xu Yang Acked-by: Ian Rogers Acked-by: Conor Dooley Signed-off-by: Namhyung Kim --- .../arch/arm64/freescale/imx94/sys/ddrc.json | 9 + .../arm64/freescale/imx94/sys/metrics.json | 450 ++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100644 tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/ddrc.json create mode 100644 tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/metrics.json diff --git a/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/ddrc.json b/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/ddrc.json new file mode 100644 index 00000000000000..aa7b58721dc7e2 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/ddrc.json @@ -0,0 +1,9 @@ +[ + { + "BriefDescription": "ddr cycles event", + "EventCode": "0x00", + "EventName": "imx94_ddr.cycles", + "Unit": "imx9_ddr", + "Compat": "imx94" + } +] diff --git a/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/metrics.json b/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/metrics.json new file mode 100644 index 00000000000000..629f1f52761e22 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/freescale/imx94/sys/metrics.json @@ -0,0 +1,450 @@ +[ + { + "BriefDescription": "bandwidth usage for lpddr5 evk board", + "MetricName": "imx94_bandwidth_usage.lpddr5", + "MetricExpr": "(( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x000\\,axi_id\\=0x000@ + imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32 / duration_time) / (4266 * 1000000 * 4)", + "ScaleUnit": "1e2%", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bandwidth usage for lpddr4 evk board", + "MetricName": "imx94_bandwidth_usage.lpddr4", + "MetricExpr": "(( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x000\\,axi_id\\=0x000@ + imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32 / duration_time) / (4266 * 1000000 * 4)", + "ScaleUnit": "1e2%", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of all masters read from ddr", + "MetricName": "imx94_ddr_read.all", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of all masters write to ddr", + "MetricName": "imx94_ddr_write.all", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of all a55 read from ddr", + "MetricName": "imx94_ddr_read.a55_all", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x3fc\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of all a55 write from ddr", + "MetricName": "imx94_ddr_write.a55_all", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3fc\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 0 read from ddr", + "MetricName": "imx94_ddr_read.a55_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x3ff\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 0 write to ddr", + "MetricName": "imx94_ddr_write.a55_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3ff\\,axi_id\\=0x000@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 1 read from ddr", + "MetricName": "imx94_ddr_read.a55_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x00f\\,axi_id\\=0x001@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 1 write to ddr", + "MetricName": "imx94_ddr_write.a55_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x001@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 2 read from ddr", + "MetricName": "imx94_ddr_read.a55_2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x00f\\,axi_id\\=0x002@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 2 write to ddr", + "MetricName": "imx94_ddr_write.a55_2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x002@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 3 read from ddr", + "MetricName": "imx94_ddr_read.a55_3", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x00f\\,axi_id\\=0x003@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of a55 core 3 write to ddr", + "MetricName": "imx94_ddr_write.a55_3", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x003@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m7 core1 read from ddr", + "MetricName": "imx94_ddr_read.m7_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x00f\\,axi_id\\=0x004@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m7 core1 write to ddr", + "MetricName": "imx94_ddr_write.m7_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x004@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m33 core1 (in netc) read from ddr", + "MetricName": "imx94_ddr_read.m33_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x00f\\,axi_id\\=0x005@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m33 core1 (in netc) write to ddr", + "MetricName": "imx94_ddr_write.m33_1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x005@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pcie2 read from ddr", + "MetricName": "imx94_ddr_read.pcie2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x00f\\,axi_id\\=0x006@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pcie2 write to ddr", + "MetricName": "imx94_ddr_write.pcie2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x006@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of Cortex-A DSU L3 evicted/ACP transactions read from ddr", + "MetricName": "imx94_ddr_read.cortex_a_dsu", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x00f\\,axi_id\\=0x007@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of Cortex-A DSU L3 evicted/ACP transactions write to ddr", + "MetricName": "imx94_ddr_write.cortex_a_dsu", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x007@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m33 core0 read from ddr", + "MetricName": "imx94_ddr_read.m33_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x00f\\,axi_id\\=0x008@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m33 core0 write to ddr", + "MetricName": "imx94_ddr_write.m33_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x008@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m7 core0 read from ddr", + "MetricName": "imx94_ddr_read.m7_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x00f\\,axi_id\\=0x009@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of m7 core0 write to ddr", + "MetricName": "imx94_ddr_write.m7_0", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x009@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of sentinel read from ddr", + "MetricName": "imx94_ddr_read.sentinel", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x00f\\,axi_id\\=0x00a@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of sentinel write to ddr", + "MetricName": "imx94_ddr_write.sentinel", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x00a@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of edma1 read from ddr", + "MetricName": "imx94_ddr_read.edma1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x00f\\,axi_id\\=0x00b@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of edma1 write to ddr", + "MetricName": "imx94_ddr_write.edma1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x00b@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of edma2 read from ddr", + "MetricName": "imx94_ddr_read.edma2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x00f\\,axi_id\\=0x00c@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of edma2 write to ddr", + "MetricName": "imx94_ddr_write.edma2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x00c@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of netc read from ddr", + "MetricName": "imx94_ddr_read.netc", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x00f\\,axi_id\\=0x00d@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of netc write to ddr", + "MetricName": "imx94_ddr_write.netc", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x00d@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of aonmix read from ddr", + "MetricName": "imx94_ddr_read.aonmix", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x00f\\,axi_id\\=0x00f@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of aonmix write to ddr", + "MetricName": "imx94_ddr_write.aonmix", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x00f\\,axi_id\\=0x00f@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of npumix read from ddr", + "MetricName": "imx94_ddr_read.npumix", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x3f0\\,axi_id\\=0x010@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of npumix write to ddr", + "MetricName": "imx94_ddr_write.npumix", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x010@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc1 read from ddr", + "MetricName": "imx94_ddr_read.usdhc1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x3f0\\,axi_id\\=0x0b0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc1 write to ddr", + "MetricName": "imx94_ddr_write.usdhc1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x0b0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc2 read from ddr", + "MetricName": "imx94_ddr_read.usdhc2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x3f0\\,axi_id\\=0x0c0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc2 write to ddr", + "MetricName": "imx94_ddr_write.usdhc2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x0c0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc3 read from ddr", + "MetricName": "imx94_ddr_read.usdhc3", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x3f0\\,axi_id\\=0x0d0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usdhc3 write to ddr", + "MetricName": "imx94_ddr_write.usdhc3", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x0d0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of xspi read from ddr", + "MetricName": "imx94_ddr_read.xspi", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x3f0\\,axi_id\\=0x0f0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of xspi write to ddr", + "MetricName": "imx94_ddr_write.xspi", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x0f0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pcie1 read from ddr", + "MetricName": "imx94_ddr_read.pcie1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x3f0\\,axi_id\\=0x100@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pcie1 write to ddr", + "MetricName": "imx94_ddr_write.pcie1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x100@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usb1 read from ddr", + "MetricName": "imx94_ddr_read.usb1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x3f0\\,axi_id\\=0x140@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usb1 write to ddr", + "MetricName": "imx94_ddr_write.usb1", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x140@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usb2 read from ddr", + "MetricName": "imx94_ddr_read.usb2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt2\\,axi_mask\\=0x3f0\\,axi_id\\=0x150@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of usb2 write to ddr", + "MetricName": "imx94_ddr_write.usb2", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x150@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pxp read from ddr", + "MetricName": "imx94_ddr_read.pxp", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x3f0\\,axi_id\\=0x2a0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of pxp write to ddr", + "MetricName": "imx94_ddr_write.pxp", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x2a0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of dcif read from ddr", + "MetricName": "imx94_ddr_read.dcif", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt1\\,axi_mask\\=0x3f0\\,axi_id\\=0x2b0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + }, + { + "BriefDescription": "bytes of dcif write to ddr", + "MetricName": "imx94_ddr_write.dcif", + "MetricExpr": "( imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x3f0\\,axi_id\\=0x2b0@ ) * 32", + "ScaleUnit": "9.765625e-4KB", + "Unit": "imx9_ddr", + "Compat": "imx94" + } +] From 2308de27c03d8ed75b28dab2354eb02c5f8e69be Mon Sep 17 00:00:00 2001 From: Jiucheng Xu Date: Fri, 10 Oct 2025 10:45:50 +0000 Subject: [PATCH 234/684] f2fs: Use mapping->gfp_mask to get file cache for writing On 32-bit architectures, when GFP_NOFS is used, the file cache for write operations cannot be allocated from the highmem and CMA. Since mapping->gfp_mask is set to GFP_HIGHUSER_MOVABLE during inode allocation, using mapping_gfp_mask(mapping) as the GFP flag of getting file cache for writing is more efficient for 32-bit architectures. Additionally, use FGP_NOFS to avoid potential deadlock issues caused by GFP_FS in GFP_HIGHUSER_MOVABLE Signed-off-by: Jiucheng Xu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 775aa4f63aa303..16a71301342747 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3570,7 +3570,8 @@ static int f2fs_write_begin(const struct kiocb *iocb, * Will wait that below with our IO control. */ folio = __filemap_get_folio(mapping, index, - FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS); + FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_NOFS, + mapping_gfp_mask(mapping)); if (IS_ERR(folio)) { err = PTR_ERR(folio); goto fail; From 71062e282d6a662b75df9aff65702455563ff7c9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 7 Nov 2025 09:07:11 -0800 Subject: [PATCH 235/684] perf tool: Add the perf_tool argument to all callbacks Getting context for what a tool is doing, such as the perf_inject instance, using container_of the tool is a common pattern in the code. This isn't possible event_op2, event_op3 and event_op4 callbacks as the tool isn't passed. Add the argument and then fix function signatures to match. As tools maybe reading a tool from somewhere else, change that code to use the passed in tool. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-annotate.c | 3 ++- tools/perf/builtin-evlist.c | 3 ++- tools/perf/builtin-inject.c | 36 +++++++++++++++------------ tools/perf/builtin-report.c | 5 ++-- tools/perf/builtin-script.c | 31 +++++++++++++---------- tools/perf/builtin-stat.c | 15 ++++++------ tools/perf/util/auxtrace.c | 9 ++++--- tools/perf/util/auxtrace.h | 18 +++++++++----- tools/perf/util/header.c | 6 +++-- tools/perf/util/header.h | 6 +++-- tools/perf/util/intel-tpebs.c | 3 ++- tools/perf/util/session.c | 35 +++++++++++++------------- tools/perf/util/session.h | 3 ++- tools/perf/util/stat.c | 3 ++- tools/perf/util/stat.h | 3 ++- tools/perf/util/tool.c | 46 ++++++++++++++++++++--------------- tools/perf/util/tool.h | 10 +++++--- 17 files changed, 138 insertions(+), 97 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 112b15952016d8..9c27bb30b70899 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -313,7 +313,8 @@ static int process_sample_event(const struct perf_tool *tool, return ret; } -static int process_feature_event(struct perf_session *session, +static int process_feature_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { if (event->feat.feat_id < HEADER_LAST_FEATURE) diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index a9bd7bbef5a961..fb6e2c3c24c8e7 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c @@ -19,7 +19,8 @@ #include "util/tool.h" #include "util/util.h" -static int process_header_feature(struct perf_session *session __maybe_unused, +static int process_header_feature(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { session_done = 1; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index a114b3fa1bea1d..044074080aa53a 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -197,18 +197,20 @@ static int perf_event__drop_oe(const struct perf_tool *tool __maybe_unused, } #endif -static int perf_event__repipe_op2_synth(struct perf_session *session, +static int perf_event__repipe_op2_synth(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event) { - return perf_event__repipe_synth(session->tool, event); + return perf_event__repipe_synth(tool, event); } -static int perf_event__repipe_op4_synth(struct perf_session *session, +static int perf_event__repipe_op4_synth(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event, u64 data __maybe_unused, const char *str __maybe_unused) { - return perf_event__repipe_synth(session->tool, event); + return perf_event__repipe_synth(tool, event); } static int perf_event__repipe_attr(const struct perf_tool *tool, @@ -258,12 +260,11 @@ static int copy_bytes(struct perf_inject *inject, struct perf_data *data, off_t return 0; } -static s64 perf_event__repipe_auxtrace(struct perf_session *session, +static s64 perf_event__repipe_auxtrace(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { - const struct perf_tool *tool = session->tool; - struct perf_inject *inject = container_of(tool, struct perf_inject, - tool); + struct perf_inject *inject = container_of(tool, struct perf_inject, tool); int ret; inject->have_auxtrace = true; @@ -299,7 +300,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_session *session, #else static s64 -perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused, +perf_event__repipe_auxtrace(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { pr_err("AUX area tracing not supported\n"); @@ -661,12 +663,13 @@ static int perf_event__repipe_exit(const struct perf_tool *tool, } #ifdef HAVE_LIBTRACEEVENT -static int perf_event__repipe_tracing_data(struct perf_session *session, +static int perf_event__repipe_tracing_data(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { - perf_event__repipe_synth(session->tool, event); + perf_event__repipe_synth(tool, event); - return perf_event__process_tracing_data(session, event); + return perf_event__process_tracing_data(tool, session, event); } #endif @@ -1348,7 +1351,7 @@ static int process_build_id(const struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); - return perf_event__process_build_id(inject->session, event); + return perf_event__process_build_id(tool, inject->session, event); } static int synthesize_build_id(struct perf_inject *inject, struct dso *dso, pid_t machine_pid) @@ -1780,9 +1783,10 @@ static int host__repipe(const struct perf_tool *tool, return perf_event__repipe(tool, event, sample, machine); } -static int host__finished_init(struct perf_session *session, union perf_event *event) +static int host__finished_init(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event) { - struct perf_inject *inject = container_of(session->tool, struct perf_inject, tool); + struct perf_inject *inject = container_of(tool, struct perf_inject, tool); struct guest_session *gs = &inject->guest_session; int ret; @@ -1829,7 +1833,7 @@ static int host__finished_init(struct perf_session *session, union perf_event *e if (ret) return ret; - return perf_event__repipe_op2_synth(session, event); + return perf_event__repipe_op2_synth(tool, session, event); } /* diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 35df04dad2fd08..2bc269f5fcef80 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -240,10 +240,11 @@ static void setup_forced_leader(struct report *report, evlist__force_leader(evlist); } -static int process_feature_event(struct perf_session *session, +static int process_feature_event(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { - struct report *rep = container_of(session->tool, struct report, tool); + struct report *rep = container_of(tool, struct report, tool); if (event->feat.feat_id < HEADER_LAST_FEATURE) return perf_event__process_feature(session, event); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 8124fcb51da9c5..d813adbf988954 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2729,7 +2729,8 @@ static int process_switch_event(const struct perf_tool *tool, sample->tid); } -static int process_auxtrace_error(struct perf_session *session, +static int process_auxtrace_error(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { if (scripting_ops && scripting_ops->process_auxtrace_error) { @@ -2737,7 +2738,7 @@ static int process_auxtrace_error(struct perf_session *session, return 0; } - return perf_event__process_auxtrace_error(session, event); + return perf_event__process_auxtrace_error(tool, session, event); } static int @@ -2785,7 +2786,8 @@ process_bpf_events(const struct perf_tool *tool __maybe_unused, } static int -process_bpf_metadata_event(struct perf_session *session __maybe_unused, +process_bpf_metadata_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event) { perf_event__fprintf(event, NULL, stdout); @@ -3544,7 +3546,8 @@ static void script__setup_sample_type(struct perf_script *script) } } -static int process_stat_round_event(struct perf_session *session, +static int process_stat_round_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { struct perf_record_stat_round *round = &event->stat_round; @@ -3559,7 +3562,8 @@ static int process_stat_round_event(struct perf_session *session, return 0; } -static int process_stat_config_event(struct perf_session *session __maybe_unused, +static int process_stat_config_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event) { perf_event__read_stat_config(&stat_config, &event->stat_config); @@ -3593,10 +3597,10 @@ static int set_maps(struct perf_script *script) } static -int process_thread_map_event(struct perf_session *session, +int process_thread_map_event(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event) { - const struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); if (dump_trace) @@ -3615,10 +3619,10 @@ int process_thread_map_event(struct perf_session *session, } static -int process_cpu_map_event(struct perf_session *session, +int process_cpu_map_event(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event) { - const struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); if (dump_trace) @@ -3636,7 +3640,8 @@ int process_cpu_map_event(struct perf_session *session, return set_maps(script); } -static int process_feature_event(struct perf_session *session, +static int process_feature_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { if (event->feat.feat_id < HEADER_LAST_FEATURE) @@ -3645,13 +3650,13 @@ static int process_feature_event(struct perf_session *session, } #ifdef HAVE_AUXTRACE_SUPPORT -static int perf_script__process_auxtrace_info(struct perf_session *session, +static int perf_script__process_auxtrace_info(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { - int ret = perf_event__process_auxtrace_info(session, event); + int ret = perf_event__process_auxtrace_info(tool, session, event); if (ret == 0) { - const struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); ret = perf_script__setup_per_event_dump(script); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 886727ae8529b5..3c46b92a53ab69 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2197,7 +2197,8 @@ static int __cmd_record(const struct option stat_options[], struct opt_aggr_mode return argc; } -static int process_stat_round_event(struct perf_session *session, +static int process_stat_round_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { struct perf_record_stat_round *stat_round = &event->stat_round; @@ -2222,10 +2223,10 @@ static int process_stat_round_event(struct perf_session *session, } static -int process_stat_config_event(struct perf_session *session, +int process_stat_config_event(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event) { - const struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); perf_event__read_stat_config(&stat_config, &event->stat_config); @@ -2271,10 +2272,10 @@ static int set_maps(struct perf_stat *st) } static -int process_thread_map_event(struct perf_session *session, +int process_thread_map_event(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event) { - const struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); if (st->threads) { @@ -2290,10 +2291,10 @@ int process_thread_map_event(struct perf_session *session, } static -int process_cpu_map_event(struct perf_session *session, +int process_cpu_map_event(const struct perf_tool *tool, + struct perf_session *session __maybe_unused, union perf_event *event) { - const struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); struct perf_cpu_map *cpus; diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 35f4745f6b2bf0..a224687ffbc1b5 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1379,7 +1379,8 @@ static void unleader_auxtrace(struct perf_session *session) } } -int perf_event__process_auxtrace_info(struct perf_session *session, +int perf_event__process_auxtrace_info(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { enum auxtrace_type type = event->auxtrace_info.type; @@ -1423,7 +1424,8 @@ int perf_event__process_auxtrace_info(struct perf_session *session, return 0; } -s64 perf_event__process_auxtrace(struct perf_session *session, +s64 perf_event__process_auxtrace(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { s64 err; @@ -1820,7 +1822,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats) } } -int perf_event__process_auxtrace_error(struct perf_session *session, +int perf_event__process_auxtrace_error(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { if (auxtrace__dont_decode(session)) diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index ed3a1aaaf5d9df..b320a387464d58 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -615,11 +615,14 @@ void auxtrace_synth_error(struct perf_record_auxtrace_error *auxtrace_error, int int code, int cpu, pid_t pid, pid_t tid, u64 ip, const char *msg, u64 timestamp); -int perf_event__process_auxtrace_info(struct perf_session *session, +int perf_event__process_auxtrace_info(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); -s64 perf_event__process_auxtrace(struct perf_session *session, +s64 perf_event__process_auxtrace(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); -int perf_event__process_auxtrace_error(struct perf_session *session, +int perf_event__process_auxtrace_error(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); int itrace_do_parse_synth_opts(struct itrace_synth_opts *synth_opts, const char *str, int unset); @@ -728,21 +731,24 @@ int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused, } static inline -int perf_event__process_auxtrace_info(struct perf_session *session __maybe_unused, +int perf_event__process_auxtrace_info(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { return 0; } static inline -s64 perf_event__process_auxtrace(struct perf_session *session __maybe_unused, +s64 perf_event__process_auxtrace(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { return 0; } static inline -int perf_event__process_auxtrace_error(struct perf_session *session __maybe_unused, +int perf_event__process_auxtrace_error(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { return 0; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4de7ca16b5522c..a2f808841b33ab 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -4540,7 +4540,8 @@ int perf_event__process_event_update(const struct perf_tool *tool __maybe_unused } #ifdef HAVE_LIBTRACEEVENT -int perf_event__process_tracing_data(struct perf_session *session, +int perf_event__process_tracing_data(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { ssize_t size_read, padding, size = event->tracing_data.size; @@ -4588,7 +4589,8 @@ int perf_event__process_tracing_data(struct perf_session *session, } #endif -int perf_event__process_build_id(struct perf_session *session, +int perf_event__process_build_id(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { __event_process_build_id(&event->build_id, diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index d16dfceccd7404..c058021c3150b3 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -178,10 +178,12 @@ int perf_event__process_event_update(const struct perf_tool *tool, size_t perf_event__fprintf_attr(union perf_event *event, FILE *fp); size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp); #ifdef HAVE_LIBTRACEEVENT -int perf_event__process_tracing_data(struct perf_session *session, +int perf_event__process_tracing_data(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); #endif -int perf_event__process_build_id(struct perf_session *session, +int perf_event__process_build_id(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); bool is_perf_magic(u64 magic); diff --git a/tools/perf/util/intel-tpebs.c b/tools/perf/util/intel-tpebs.c index 8c9aee157ec48d..21359155f2a0bf 100644 --- a/tools/perf/util/intel-tpebs.c +++ b/tools/perf/util/intel-tpebs.c @@ -216,7 +216,8 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, return 0; } -static int process_feature_event(struct perf_session *session, +static int process_feature_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { if (event->feat.feat_id < HEADER_LAST_FEATURE) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 09af486c83e4ff..4b0236b2df2913 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1437,19 +1437,19 @@ static s64 perf_session__process_user_event(struct perf_session *session, */ if (!perf_data__is_pipe(session->data)) lseek(fd, file_offset, SEEK_SET); - err = tool->tracing_data(session, event); + err = tool->tracing_data(tool, session, event); break; case PERF_RECORD_HEADER_BUILD_ID: - err = tool->build_id(session, event); + err = tool->build_id(tool, session, event); break; case PERF_RECORD_FINISHED_ROUND: err = tool->finished_round(tool, event, oe); break; case PERF_RECORD_ID_INDEX: - err = tool->id_index(session, event); + err = tool->id_index(tool, session, event); break; case PERF_RECORD_AUXTRACE_INFO: - err = tool->auxtrace_info(session, event); + err = tool->auxtrace_info(tool, session, event); break; case PERF_RECORD_AUXTRACE: /* @@ -1459,45 +1459,45 @@ static s64 perf_session__process_user_event(struct perf_session *session, */ if (!perf_data__is_pipe(session->data)) lseek(fd, file_offset + event->header.size, SEEK_SET); - err = tool->auxtrace(session, event); + err = tool->auxtrace(tool, session, event); break; case PERF_RECORD_AUXTRACE_ERROR: perf_session__auxtrace_error_inc(session, event); - err = tool->auxtrace_error(session, event); + err = tool->auxtrace_error(tool, session, event); break; case PERF_RECORD_THREAD_MAP: - err = tool->thread_map(session, event); + err = tool->thread_map(tool, session, event); break; case PERF_RECORD_CPU_MAP: - err = tool->cpu_map(session, event); + err = tool->cpu_map(tool, session, event); break; case PERF_RECORD_STAT_CONFIG: - err = tool->stat_config(session, event); + err = tool->stat_config(tool, session, event); break; case PERF_RECORD_STAT: - err = tool->stat(session, event); + err = tool->stat(tool, session, event); break; case PERF_RECORD_STAT_ROUND: - err = tool->stat_round(session, event); + err = tool->stat_round(tool, session, event); break; case PERF_RECORD_TIME_CONV: session->time_conv = event->time_conv; - err = tool->time_conv(session, event); + err = tool->time_conv(tool, session, event); break; case PERF_RECORD_HEADER_FEATURE: - err = tool->feature(session, event); + err = tool->feature(tool, session, event); break; case PERF_RECORD_COMPRESSED: case PERF_RECORD_COMPRESSED2: - err = tool->compressed(session, event, file_offset, file_path); + err = tool->compressed(tool, session, event, file_offset, file_path); if (err) dump_event(session->evlist, event, file_offset, &sample, file_path); break; case PERF_RECORD_FINISHED_INIT: - err = tool->finished_init(session, event); + err = tool->finished_init(tool, session, event); break; case PERF_RECORD_BPF_METADATA: - err = tool->bpf_metadata(session, event); + err = tool->bpf_metadata(tool, session, event); break; default: err = -EINVAL; @@ -2647,7 +2647,8 @@ static int perf_session__set_guest_cpu(struct perf_session *session, pid_t pid, return 0; } -int perf_event__process_id_index(struct perf_session *session, +int perf_event__process_id_index(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { struct evlist *evlist = session->evlist; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index cf88d65a25cb63..22d3ff877e83ad 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -202,7 +202,8 @@ int perf_session__deliver_synth_attr_event(struct perf_session *session, int perf_session__dsos_hit_all(struct perf_session *session); -int perf_event__process_id_index(struct perf_session *session, +int perf_event__process_id_index(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); int perf_event__process_finished_round(const struct perf_tool *tool, diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 101ed6c497bcae..976a06e632529e 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -645,7 +645,8 @@ void perf_stat_process_percore(struct perf_stat_config *config, struct evlist *e evsel__process_percore(evsel); } -int perf_event__process_stat_event(struct perf_session *session, +int perf_event__process_stat_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event) { struct perf_counts_values count, *ptr; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 34f30a295f8917..230474f4931518 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -216,7 +216,8 @@ union perf_event; struct perf_session; struct target; -int perf_event__process_stat_event(struct perf_session *session, +int perf_event__process_stat_event(const struct perf_tool *tool, + struct perf_session *session, union perf_event *event); size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index e83c7ababc2add..c983b526b30d1b 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -13,7 +13,8 @@ #include #ifdef HAVE_ZSTD_SUPPORT -static int perf_session__process_compressed_event(struct perf_session *session, +static int perf_session__process_compressed_event(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, union perf_event *event, u64 file_offset, const char *file_path) { @@ -79,10 +80,9 @@ static int perf_session__process_compressed_event(struct perf_session *session, } #endif -static int process_event_synth_tracing_data_stub(struct perf_session *session - __maybe_unused, - union perf_event *event - __maybe_unused) +static int process_event_synth_tracing_data_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -90,8 +90,7 @@ static int process_event_synth_tracing_data_stub(struct perf_session *session static int process_event_synth_attr_stub(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct evlist **pevlist - __maybe_unused) + struct evlist **pevlist __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -99,8 +98,7 @@ static int process_event_synth_attr_stub(const struct perf_tool *tool __maybe_un static int process_event_synth_event_update_stub(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct evlist **pevlist - __maybe_unused) + struct evlist **pevlist __maybe_unused) { if (dump_trace) perf_event__fprintf_event_update(event, stdout); @@ -151,7 +149,8 @@ static int skipn(int fd, off_t n) return 0; } -static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused, +static s64 process_event_auxtrace_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event) { dump_printf(": unhandled!\n"); @@ -160,7 +159,8 @@ static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unus return event->auxtrace.size; } -static int process_event_op2_stub(struct perf_session *session __maybe_unused, +static int process_event_op2_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { dump_printf(": unhandled!\n"); @@ -169,7 +169,8 @@ static int process_event_op2_stub(struct perf_session *session __maybe_unused, static -int process_event_thread_map_stub(struct perf_session *session __maybe_unused, +int process_event_thread_map_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { if (dump_trace) @@ -180,7 +181,8 @@ int process_event_thread_map_stub(struct perf_session *session __maybe_unused, } static -int process_event_cpu_map_stub(struct perf_session *session __maybe_unused, +int process_event_cpu_map_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { if (dump_trace) @@ -191,7 +193,8 @@ int process_event_cpu_map_stub(struct perf_session *session __maybe_unused, } static -int process_event_stat_config_stub(struct perf_session *session __maybe_unused, +int process_event_stat_config_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) { if (dump_trace) @@ -201,7 +204,8 @@ int process_event_stat_config_stub(struct perf_session *session __maybe_unused, return 0; } -static int process_stat_stub(struct perf_session *perf_session __maybe_unused, +static int process_stat_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *perf_session __maybe_unused, union perf_event *event) { if (dump_trace) @@ -211,7 +215,8 @@ static int process_stat_stub(struct perf_session *perf_session __maybe_unused, return 0; } -static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused, +static int process_stat_round_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *perf_session __maybe_unused, union perf_event *event) { if (dump_trace) @@ -221,7 +226,8 @@ static int process_stat_round_stub(struct perf_session *perf_session __maybe_unu return 0; } -static int process_event_time_conv_stub(struct perf_session *perf_session __maybe_unused, +static int process_event_time_conv_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *perf_session __maybe_unused, union perf_event *event) { if (dump_trace) @@ -231,7 +237,8 @@ static int process_event_time_conv_stub(struct perf_session *perf_session __mayb return 0; } -static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused, +static int perf_session__process_compressed_event_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused, u64 file_offset __maybe_unused, const char *file_path __maybe_unused) @@ -240,7 +247,8 @@ static int perf_session__process_compressed_event_stub(struct perf_session *sess return 0; } -static int perf_event__process_bpf_metadata_stub(struct perf_session *perf_session __maybe_unused, +static int perf_event__process_bpf_metadata_stub(const struct perf_tool *tool __maybe_unused, + struct perf_session *perf_session __maybe_unused, union perf_event *event) { if (dump_trace) diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 18b76ff0f26acd..1f14618083718f 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -26,10 +26,12 @@ typedef int (*event_attr_op)(const struct perf_tool *tool, union perf_event *event, struct evlist **pevlist); -typedef int (*event_op2)(struct perf_session *session, union perf_event *event); -typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); -typedef int (*event_op4)(struct perf_session *session, union perf_event *event, u64 data, - const char *str); +typedef int (*event_op2)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event); +typedef s64 (*event_op3)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event); +typedef int (*event_op4)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event, u64 data, const char *str); typedef int (*event_oe)(const struct perf_tool *tool, union perf_event *event, struct ordered_events *oe); From 6331b266935916bf050149a55bfafb45aa3d9d9e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 7 Nov 2025 09:07:12 -0800 Subject: [PATCH 236/684] perf tool: Add a delegate_tool that just delegates actions to another tool Add an ability to be able to compose perf_tools, by having one perform an action and then calling a delegate. Currently the perf_tools have if-then-elses setting the callback and then if-then-elses within the callback. Understanding the behavior is complex as it is in two places and logic for numerous operations, within things like perf inject, is interwoven. By chaining perf_tools together based on command line options this kind of code can be avoided. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/tool.c | 171 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/tool.h | 9 +++ 2 files changed, 180 insertions(+) diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index c983b526b30d1b..22a8a4ffe05f77 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -321,3 +321,174 @@ bool perf_tool__compressed_is_stub(const struct perf_tool *tool) { return tool->compressed == perf_session__process_compressed_event_stub; } + +#define CREATE_DELEGATE_SAMPLE(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + union perf_event *event, \ + struct perf_sample *sample, \ + struct evsel *evsel, \ + struct machine *machine) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, event, sample, evsel, machine); \ + } +CREATE_DELEGATE_SAMPLE(read); +CREATE_DELEGATE_SAMPLE(sample); + +#define CREATE_DELEGATE_ATTR(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + union perf_event *event, \ + struct evlist **pevlist) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, event, pevlist); \ + } +CREATE_DELEGATE_ATTR(attr); +CREATE_DELEGATE_ATTR(event_update); + +#define CREATE_DELEGATE_OE(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + union perf_event *event, \ + struct ordered_events *oe) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, event, oe); \ + } +CREATE_DELEGATE_OE(finished_round); + +#define CREATE_DELEGATE_OP(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + union perf_event *event, \ + struct perf_sample *sample, \ + struct machine *machine) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, event, sample, machine); \ + } +CREATE_DELEGATE_OP(aux); +CREATE_DELEGATE_OP(aux_output_hw_id); +CREATE_DELEGATE_OP(bpf); +CREATE_DELEGATE_OP(cgroup); +CREATE_DELEGATE_OP(comm); +CREATE_DELEGATE_OP(context_switch); +CREATE_DELEGATE_OP(exit); +CREATE_DELEGATE_OP(fork); +CREATE_DELEGATE_OP(itrace_start); +CREATE_DELEGATE_OP(ksymbol); +CREATE_DELEGATE_OP(lost); +CREATE_DELEGATE_OP(lost_samples); +CREATE_DELEGATE_OP(mmap); +CREATE_DELEGATE_OP(mmap2); +CREATE_DELEGATE_OP(namespaces); +CREATE_DELEGATE_OP(text_poke); +CREATE_DELEGATE_OP(throttle); +CREATE_DELEGATE_OP(unthrottle); + +#define CREATE_DELEGATE_OP2(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + struct perf_session *session, \ + union perf_event *event) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, session, event); \ + } +CREATE_DELEGATE_OP2(auxtrace_error); +CREATE_DELEGATE_OP2(auxtrace_info); +CREATE_DELEGATE_OP2(bpf_metadata); +CREATE_DELEGATE_OP2(build_id); +CREATE_DELEGATE_OP2(cpu_map); +CREATE_DELEGATE_OP2(feature); +CREATE_DELEGATE_OP2(finished_init); +CREATE_DELEGATE_OP2(id_index); +CREATE_DELEGATE_OP2(stat); +CREATE_DELEGATE_OP2(stat_config); +CREATE_DELEGATE_OP2(stat_round); +CREATE_DELEGATE_OP2(thread_map); +CREATE_DELEGATE_OP2(time_conv); +CREATE_DELEGATE_OP2(tracing_data); + +#define CREATE_DELEGATE_OP3(name) \ + static s64 delegate_ ## name(const struct perf_tool *tool, \ + struct perf_session *session, \ + union perf_event *event) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, session, event); \ + } +CREATE_DELEGATE_OP3(auxtrace); + +#define CREATE_DELEGATE_OP4(name) \ + static int delegate_ ## name(const struct perf_tool *tool, \ + struct perf_session *session, \ + union perf_event *event, \ + u64 data, \ + const char *str) \ + { \ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ + struct perf_tool *delegate = del_tool->delegate; \ + return delegate->name(delegate, session, event, data, str); \ + } +CREATE_DELEGATE_OP4(compressed); + +void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate) +{ + tool->delegate = delegate; + + tool->tool.ordered_events = delegate->ordered_events; + tool->tool.ordering_requires_timestamps = delegate->ordering_requires_timestamps; + tool->tool.namespace_events = delegate->namespace_events; + tool->tool.cgroup_events = delegate->cgroup_events; + tool->tool.no_warn = delegate->no_warn; + tool->tool.show_feat_hdr = delegate->show_feat_hdr; + + tool->tool.sample = delegate_sample; + tool->tool.read = delegate_read; + + tool->tool.mmap = delegate_mmap; + tool->tool.mmap2 = delegate_mmap2; + tool->tool.comm = delegate_comm; + tool->tool.namespaces = delegate_namespaces; + tool->tool.cgroup = delegate_cgroup; + tool->tool.fork = delegate_fork; + tool->tool.exit = delegate_exit; + tool->tool.lost = delegate_lost; + tool->tool.lost_samples = delegate_lost_samples; + tool->tool.aux = delegate_aux; + tool->tool.itrace_start = delegate_itrace_start; + tool->tool.aux_output_hw_id = delegate_aux_output_hw_id; + tool->tool.context_switch = delegate_context_switch; + tool->tool.throttle = delegate_throttle; + tool->tool.unthrottle = delegate_unthrottle; + tool->tool.ksymbol = delegate_ksymbol; + tool->tool.bpf = delegate_bpf; + tool->tool.text_poke = delegate_text_poke; + + tool->tool.attr = delegate_attr; + tool->tool.event_update = delegate_event_update; + + tool->tool.tracing_data = delegate_tracing_data; + + tool->tool.finished_round = delegate_finished_round; + + tool->tool.build_id = delegate_build_id; + tool->tool.id_index = delegate_id_index; + tool->tool.auxtrace_info = delegate_auxtrace_info; + tool->tool.auxtrace_error = delegate_auxtrace_error; + tool->tool.time_conv = delegate_time_conv; + tool->tool.thread_map = delegate_thread_map; + tool->tool.cpu_map = delegate_cpu_map; + tool->tool.stat_config = delegate_stat_config; + tool->tool.stat = delegate_stat; + tool->tool.stat_round = delegate_stat_round; + tool->tool.feature = delegate_feature; + tool->tool.finished_init = delegate_finished_init; + tool->tool.bpf_metadata = delegate_bpf_metadata; + tool->tool.compressed = delegate_compressed; + tool->tool.auxtrace = delegate_auxtrace; +} diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 1f14618083718f..88337cee1e3e2b 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -102,4 +102,13 @@ int process_event_sample_stub(const struct perf_tool *tool, struct evsel *evsel, struct machine *machine); +struct delegate_tool { + /** @tool: The actual tool that calls the delegate. */ + struct perf_tool tool; + /** @delegate: The tool that is delegated to. */ + struct perf_tool *delegate; +}; + +void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate); + #endif /* __PERF_TOOL_H */ From bab55c25f2ebed2608e053183146893b63d6f078 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 24 Sep 2025 22:27:15 +0200 Subject: [PATCH 237/684] clk: lan966x: remove unused dt-bindings include In preparation for LAN969x support, all instances referring to defines in the LAN966x specific header were dropped, so its safe to drop its inclusion in the driver. Signed-off-by: Robert Marko Reviewed-by: Daniel Machon Link: https://lore.kernel.org/r/20250924202810.1641883-1-robert.marko@sartura.hr Signed-off-by: Claudiu Beznea --- drivers/clk/clk-lan966x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c index 16e0405fe28bf0..3c7a48c616bbc5 100644 --- a/drivers/clk/clk-lan966x.c +++ b/drivers/clk/clk-lan966x.c @@ -16,8 +16,6 @@ #include #include -#include - #define GCK_ENA BIT(0) #define GCK_SRC_SEL GENMASK(9, 8) #define GCK_PRESCALER GENMASK(23, 16) From 8d1d2c408cc05021970df5dd7d41133d220cf851 Mon Sep 17 00:00:00 2001 From: Adrian Ng Ho Yin Date: Tue, 4 Nov 2025 15:29:06 +0800 Subject: [PATCH 238/684] dt-bindings: i3c: snps: Add Altera SoCFPGA compatible Add the "altr,agilex5-dw-i3c-master" compatible string to the Synopsys DesignWare I3C master binding. This allow Agilex5 to use the generic DW I3C master controller while applying any required platform-specific quirks. Signed-off-by: Adrian Ng Ho Yin Reviewed-by: Krzysztof Kozlowski Reviewed-by: Frank Li Link: https://patch.msgid.link/4ef059b129e9457eaadcfa6b996b9b6b000c7dba.1762237922.git.adrianhoyin.ng@altera.com Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/i3c/snps,dw-i3c-master.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml b/Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml index 5f646737581108..e803457d3f554f 100644 --- a/Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml +++ b/Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml @@ -14,7 +14,11 @@ allOf: properties: compatible: - const: snps,dw-i3c-master-1.00a + oneOf: + - const: snps,dw-i3c-master-1.00a + - items: + - const: altr,agilex5-dw-i3c-master + - const: snps,dw-i3c-master-1.00a reg: maxItems: 1 From fba0e56ee7524995b1fc9d1e90602496fc09d80f Mon Sep 17 00:00:00 2001 From: Adrian Ng Ho Yin Date: Tue, 4 Nov 2025 15:29:08 +0800 Subject: [PATCH 239/684] i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI When running compliance tests on the Altera Agilex5 SoCFPGA platform, the I3C bus can hang when a slave issues an IBI after the DAA process completes. The DesignWare I3C master enters runtime suspend once DAA finishes and stops driving SCL, preventing the IBI transfer from completing and leaving SDA stuck low. Add a new compatible string, "altr,agilex5-dw-i3c-master" and apply a quirk that keep runtime PM always active on this platform by calling pm_runtime_get_noresume() during probe. Prevent bus hangs triggered by IBIs on Agilex5 while maintaining keep the same behavior on other platforms. Signed-off-by: Adrian Ng Ho Yin Reviewed-by: Frank Li Link: https://patch.msgid.link/482d540722a98c2809d8275445aaa544b565bf85.1762237922.git.adrianhoyin.ng@altera.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/dw-i3c-master.c | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 9ceedf09c3b6a6..276592a8222e7b 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -228,6 +228,7 @@ /* List of quirks */ #define AMD_I3C_OD_PP_TIMING BIT(1) +#define DW_I3C_DISABLE_RUNTIME_PM_QUIRK BIT(2) struct dw_i3c_cmd { u32 cmd_lo; @@ -252,6 +253,10 @@ struct dw_i3c_i2c_dev_data { struct i3c_generic_ibi_pool *ibi_pool; }; +struct dw_i3c_drvdata { + u32 flags; +}; + static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m, const struct i3c_ccc_cmd *cmd) { @@ -1535,6 +1540,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, struct platform_device *pdev) { int ret, irq; + const struct dw_i3c_drvdata *drvdata; + unsigned long quirks = 0; if (!master->platform_ops) master->platform_ops = &dw_i3c_platform_ops_default; @@ -1590,7 +1597,18 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, master->maxdevs = ret >> 16; master->free_pos = GENMASK(master->maxdevs - 1, 0); - master->quirks = (unsigned long)device_get_match_data(&pdev->dev); + if (has_acpi_companion(&pdev->dev)) { + quirks = (unsigned long)device_get_match_data(&pdev->dev); + } else if (pdev->dev.of_node) { + drvdata = device_get_match_data(&pdev->dev); + if (drvdata) + quirks = drvdata->flags; + } + master->quirks = quirks; + + /* Keep controller enabled by preventing runtime suspend */ + if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK) + pm_runtime_get_noresume(&pdev->dev); INIT_WORK(&master->hj_work, dw_i3c_hj_work); ret = i3c_master_register(&master->base, &pdev->dev, @@ -1617,6 +1635,10 @@ void dw_i3c_common_remove(struct dw_i3c_master *master) cancel_work_sync(&master->hj_work); i3c_master_unregister(&master->base); + /* Balance pm_runtime_get_noresume() from probe() */ + if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK) + pm_runtime_put_noidle(master->dev); + pm_runtime_disable(master->dev); pm_runtime_set_suspended(master->dev); pm_runtime_dont_use_autosuspend(master->dev); @@ -1759,8 +1781,15 @@ static void dw_i3c_shutdown(struct platform_device *pdev) pm_runtime_put_autosuspend(master->dev); } +static const struct dw_i3c_drvdata altr_agilex5_drvdata = { + .flags = DW_I3C_DISABLE_RUNTIME_PM_QUIRK, +}; + static const struct of_device_id dw_i3c_master_of_match[] = { { .compatible = "snps,dw-i3c-master-1.00a", }, + { .compatible = "altr,agilex5-dw-i3c-master", + .data = &altr_agilex5_drvdata, + }, {}, }; MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match); From ddb37d5b130e173090c861b4d1c20a632fb49d7a Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 7 Nov 2025 08:07:50 +0200 Subject: [PATCH 240/684] i3c: mipi-i3c-hci-pci: Add support for Intel Nova Lake-S I3C Add I3C controller PCI IDs for Intel Nova Lake-S. Signed-off-by: Jarkko Nikula Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251107060750.7995-1-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 08e6cbdf89cead..dd4484eff2f02b 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -133,6 +133,9 @@ static const struct pci_device_id mipi_i3c_hci_pci_devices[] = { /* Panther Lake-P */ { PCI_VDEVICE(INTEL, 0xe47c), (kernel_ulong_t)&intel_info}, { PCI_VDEVICE(INTEL, 0xe46f), (kernel_ulong_t)&intel_info}, + /* Nova Lake-S */ + { PCI_VDEVICE(INTEL, 0x6e2c), (kernel_ulong_t)&intel_info}, + { PCI_VDEVICE(INTEL, 0x6e2d), (kernel_ulong_t)&intel_info}, { }, }; MODULE_DEVICE_TABLE(pci, mipi_i3c_hci_pci_devices); From 0e9b51a43214f81f07813b63349b03ded35139c7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 8 Nov 2025 16:59:58 -0800 Subject: [PATCH 241/684] perf pmu: Make pmu_alias_terms weak again The terms for a json event should be weak so they don't override command line options. Before: ``` $ perf record -vv -c 1000 -e uops_issued.any -o /dev/null true 2>&1 |grep "{ sample_period, sample_freq }" { sample_period, sample_freq } 200003 { sample_period, sample_freq } 2000003 { sample_period, sample_freq } 1000 ``` After: ``` $ perf record -vv -c 1000 -e uops_issued.any -o /dev/null true 2>&1 |grep "{ sample_period, sample_freq }" { sample_period, sample_freq } 1000 { sample_period, sample_freq } 1000 { sample_period, sample_freq } 1000 ``` Fixes: 84bae3af20d0 ("perf pmu: Don't eagerly parse event terms") Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d597263fab4f7e..f14f2a12d06152 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -802,6 +802,7 @@ static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd) static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms) { struct parse_events_terms alias_terms; + struct parse_events_term *term; int ret; parse_events_terms__init(&alias_terms); @@ -812,6 +813,13 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms parse_events_terms__exit(&alias_terms); return ret; } + list_for_each_entry(term, &alias_terms.terms, list) { + /* + * Weak terms don't override command line options, + * which we don't want for implicit terms in aliases. + */ + term->weak = true; + } list_splice_init(&alias_terms.terms, terms); parse_events_terms__exit(&alias_terms); return 0; From 081006b7c8e19406dc6674c6b6d086764d415b5c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 8 Nov 2025 16:59:59 -0800 Subject: [PATCH 242/684] perf test: Add test that command line period overrides sysfs/json values The behavior of weak terms is subtle, add a test that they aren't accidentally broken. The test finds an event with a weak 'period' and then overrides it. In no such event is present then the test skips. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/record_weak_term.sh | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100755 tools/perf/tests/shell/record_weak_term.sh diff --git a/tools/perf/tests/shell/record_weak_term.sh b/tools/perf/tests/shell/record_weak_term.sh new file mode 100755 index 00000000000000..811b00ffb47a13 --- /dev/null +++ b/tools/perf/tests/shell/record_weak_term.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# record weak terms +# SPDX-License-Identifier: GPL-2.0 +# Test that command line options override weak terms from sysfs or inbuilt json. +set -e + +shelldir=$(dirname "$0") +# shellcheck source=lib/setup_python.sh +. "${shelldir}"/lib/setup_python.sh + +# Find the first event with a specified period, such as +# "cpu_core/event=0x24,period=200003,umask=0xff/" +event=$(perf list --json | $PYTHON -c ' +import json, sys +for e in json.load(sys.stdin): + if "EventName" not in e or "/modifier" in e["EventName"]: + continue + if "Encoding" in e and "period=" in e["Encoding"]: + print(e["EventName"]) + break +') +if [[ "$event" = "" ]] +then + echo "Skip: No sysfs/json events with inbuilt period." + exit 2 +fi + +echo "Testing that for $event the period is overridden with 1000" +perf list --detail "$event" +if ! perf record -c 1000 -vv -e "$event" -o /dev/null true 2>&1 | \ + grep -q -F '{ sample_period, sample_freq } 1000' +then + echo "Fail: Unexpected verbose output and sample period" + exit 1 +fi +echo "Success" +exit 0 From b737322278ffabd2766ac681c28553609a48694e Mon Sep 17 00:00:00 2001 From: Thanh Quan Date: Tue, 4 Nov 2025 17:59:43 +0100 Subject: [PATCH 243/684] pinctrl: renesas: r8a779g0: Remove AVB[01]_MII MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.1.30 of the R-Car V4H Series Hardware User’s Manual removed the "AVB[01]_MII_*" signals from the pin control register tables. As these are further unused in the pin control driver, they can be removed safely. Signed-off-by: Thanh Quan Signed-off-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Link: https://patch.msgid.link/58662f50136280532bcc8bbe94741d82425bd118.1762274384.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pfc-r8a779g0.c | 96 +++++++++----------------- 1 file changed, 32 insertions(+), 64 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c index 218c5eff9b67fe..bf34e206f6f635 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779g0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c @@ -471,55 +471,55 @@ #define IP0SR6_7_4 FM(AVB1_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR6_11_8 FM(AVB1_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR6_15_12 FM(AVB1_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR6_19_16 FM(AVB1_LINK) FM(AVB1_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR6_23_20 FM(AVB1_AVTP_MATCH) FM(AVB1_MII_RX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR6_27_24 FM(AVB1_TXC) FM(AVB1_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR6_31_28 FM(AVB1_TX_CTL) FM(AVB1_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_19_16 FM(AVB1_LINK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_23_20 FM(AVB1_AVTP_MATCH) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_27_24 FM(AVB1_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_31_28 FM(AVB1_TX_CTL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP1SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ -#define IP1SR6_3_0 FM(AVB1_RXC) FM(AVB1_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_7_4 FM(AVB1_RX_CTL) FM(AVB1_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_11_8 FM(AVB1_AVTP_PPS) FM(AVB1_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_15_12 FM(AVB1_AVTP_CAPTURE) FM(AVB1_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_19_16 FM(AVB1_TD1) FM(AVB1_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_23_20 FM(AVB1_TD0) FM(AVB1_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_27_24 FM(AVB1_RD1) FM(AVB1_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR6_31_28 FM(AVB1_RD0) FM(AVB1_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_3_0 FM(AVB1_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_7_4 FM(AVB1_RX_CTL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_11_8 FM(AVB1_AVTP_PPS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_15_12 FM(AVB1_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_19_16 FM(AVB1_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_23_20 FM(AVB1_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_27_24 FM(AVB1_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_31_28 FM(AVB1_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP2SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ -#define IP2SR6_3_0 FM(AVB1_TD2) FM(AVB1_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR6_7_4 FM(AVB1_RD2) FM(AVB1_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR6_11_8 FM(AVB1_TD3) FM(AVB1_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR6_15_12 FM(AVB1_RD3) FM(AVB1_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_3_0 FM(AVB1_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_7_4 FM(AVB1_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_11_8 FM(AVB1_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_15_12 FM(AVB1_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR6_19_16 FM(AVB1_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* SR7 */ /* IP0SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ -#define IP0SR7_3_0 FM(AVB0_AVTP_PPS) FM(AVB0_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) FM(AVB0_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_15_12 FM(AVB0_TD3) FM(AVB0_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_19_16 FM(AVB0_LINK) FM(AVB0_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_3_0 FM(AVB0_AVTP_PPS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) F_(0, 0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_15_12 FM(AVB0_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_19_16 FM(AVB0_LINK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_23_20 FM(AVB0_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_27_24 FM(AVB0_TD2) FM(AVB0_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_31_28 FM(AVB0_TD1) FM(AVB0_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_27_24 FM(AVB0_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_31_28 FM(AVB0_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP1SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ -#define IP1SR7_3_0 FM(AVB0_RD3) FM(AVB0_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_3_0 FM(AVB0_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR7_7_4 FM(AVB0_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR7_11_8 FM(AVB0_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR7_15_12 FM(AVB0_TD0) FM(AVB0_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR7_19_16 FM(AVB0_RD2) FM(AVB0_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_15_12 FM(AVB0_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_19_16 FM(AVB0_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR7_23_20 FM(AVB0_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR7_27_24 FM(AVB0_MDIO) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR7_31_28 FM(AVB0_TXC) FM(AVB0_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_31_28 FM(AVB0_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP2SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ -#define IP2SR7_3_0 FM(AVB0_TX_CTL) FM(AVB0_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR7_7_4 FM(AVB0_RD1) FM(AVB0_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR7_11_8 FM(AVB0_RD0) FM(AVB0_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR7_15_12 FM(AVB0_RXC) FM(AVB0_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR7_19_16 FM(AVB0_RX_CTL) FM(AVB0_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_3_0 FM(AVB0_TX_CTL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_7_4 FM(AVB0_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_11_8 FM(AVB0_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_15_12 FM(AVB0_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_19_16 FM(AVB0_RX_CTL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* SR8 */ /* IP0SR8 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ @@ -1076,118 +1076,86 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP0SR6_15_12, AVB1_PHY_INT), PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_LINK), - PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_MII_TX_ER), PINMUX_IPSR_GPSR(IP0SR6_23_20, AVB1_AVTP_MATCH), - PINMUX_IPSR_GPSR(IP0SR6_23_20, AVB1_MII_RX_ER), PINMUX_IPSR_GPSR(IP0SR6_27_24, AVB1_TXC), - PINMUX_IPSR_GPSR(IP0SR6_27_24, AVB1_MII_TXC), PINMUX_IPSR_GPSR(IP0SR6_31_28, AVB1_TX_CTL), - PINMUX_IPSR_GPSR(IP0SR6_31_28, AVB1_MII_TX_EN), /* IP1SR6 */ PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_RXC), - PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_MII_RXC), PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_RX_CTL), - PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_MII_RX_DV), PINMUX_IPSR_GPSR(IP1SR6_11_8, AVB1_AVTP_PPS), - PINMUX_IPSR_GPSR(IP1SR6_11_8, AVB1_MII_COL), PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_AVTP_CAPTURE), - PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_MII_CRS), PINMUX_IPSR_GPSR(IP1SR6_19_16, AVB1_TD1), - PINMUX_IPSR_GPSR(IP1SR6_19_16, AVB1_MII_TD1), PINMUX_IPSR_GPSR(IP1SR6_23_20, AVB1_TD0), - PINMUX_IPSR_GPSR(IP1SR6_23_20, AVB1_MII_TD0), PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_RD1), - PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_MII_RD1), PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_RD0), - PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_MII_RD0), /* IP2SR6 */ PINMUX_IPSR_GPSR(IP2SR6_3_0, AVB1_TD2), - PINMUX_IPSR_GPSR(IP2SR6_3_0, AVB1_MII_TD2), PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_RD2), - PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_MII_RD2), PINMUX_IPSR_GPSR(IP2SR6_11_8, AVB1_TD3), - PINMUX_IPSR_GPSR(IP2SR6_11_8, AVB1_MII_TD3), PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_RD3), - PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_MII_RD3), PINMUX_IPSR_GPSR(IP2SR6_19_16, AVB1_TXCREFCLK), /* IP0SR7 */ PINMUX_IPSR_GPSR(IP0SR7_3_0, AVB0_AVTP_PPS), - PINMUX_IPSR_GPSR(IP0SR7_3_0, AVB0_MII_COL), PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_AVTP_CAPTURE), - PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_MII_CRS), PINMUX_IPSR_GPSR(IP0SR7_11_8, AVB0_AVTP_MATCH), - PINMUX_IPSR_GPSR(IP0SR7_11_8, AVB0_MII_RX_ER), PINMUX_IPSR_GPSR(IP0SR7_11_8, CC5_OSCOUT), PINMUX_IPSR_GPSR(IP0SR7_15_12, AVB0_TD3), - PINMUX_IPSR_GPSR(IP0SR7_15_12, AVB0_MII_TD3), PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_LINK), - PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_MII_TX_ER), PINMUX_IPSR_GPSR(IP0SR7_23_20, AVB0_PHY_INT), PINMUX_IPSR_GPSR(IP0SR7_27_24, AVB0_TD2), - PINMUX_IPSR_GPSR(IP0SR7_27_24, AVB0_MII_TD2), PINMUX_IPSR_GPSR(IP0SR7_31_28, AVB0_TD1), - PINMUX_IPSR_GPSR(IP0SR7_31_28, AVB0_MII_TD1), /* IP1SR7 */ PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_RD3), - PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_MII_RD3), PINMUX_IPSR_GPSR(IP1SR7_7_4, AVB0_TXCREFCLK), PINMUX_IPSR_GPSR(IP1SR7_11_8, AVB0_MAGIC), PINMUX_IPSR_GPSR(IP1SR7_15_12, AVB0_TD0), - PINMUX_IPSR_GPSR(IP1SR7_15_12, AVB0_MII_TD0), PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_RD2), - PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_MII_RD2), PINMUX_IPSR_GPSR(IP1SR7_23_20, AVB0_MDC), PINMUX_IPSR_GPSR(IP1SR7_27_24, AVB0_MDIO), PINMUX_IPSR_GPSR(IP1SR7_31_28, AVB0_TXC), - PINMUX_IPSR_GPSR(IP1SR7_31_28, AVB0_MII_TXC), /* IP2SR7 */ PINMUX_IPSR_GPSR(IP2SR7_3_0, AVB0_TX_CTL), - PINMUX_IPSR_GPSR(IP2SR7_3_0, AVB0_MII_TX_EN), PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_RD1), - PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_MII_RD1), PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_RD0), - PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_MII_RD0), PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_RXC), - PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_MII_RXC), PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_RX_CTL), - PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_MII_RX_DV), /* IP0SR8 */ PINMUX_IPSR_MSEL(IP0SR8_3_0, SCL0, SEL_SCL0_0), From ac4e5f4ab6f367be3d5acfe2d3cfc519d149d7ac Mon Sep 17 00:00:00 2001 From: Huy Bui Date: Tue, 4 Nov 2025 17:59:44 +0100 Subject: [PATCH 244/684] pinctrl: renesas: r8a779g0: Remove CC5_OSCOUT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.1.30 of the R-Car V4H Series Hardware User’s Manual removed the "CC5_OSCOUT" signal from the pin control register tables. As this is further unused in the pin control driver, it can be removed safely. Signed-off-by: Huy Bui Signed-off-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Link: https://patch.msgid.link/77f9efe5388f2801ace945b7793d4823618eeec8.1762274384.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pfc-r8a779g0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c index bf34e206f6f635..945e4f87806db1 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779g0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c @@ -497,7 +497,7 @@ /* IP0SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ #define IP0SR7_3_0 FM(AVB0_AVTP_PPS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) F_(0, 0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_15_12 FM(AVB0_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_19_16 FM(AVB0_LINK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_23_20 FM(AVB0_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -1117,7 +1117,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_AVTP_CAPTURE), PINMUX_IPSR_GPSR(IP0SR7_11_8, AVB0_AVTP_MATCH), - PINMUX_IPSR_GPSR(IP0SR7_11_8, CC5_OSCOUT), PINMUX_IPSR_GPSR(IP0SR7_15_12, AVB0_TD3), From 87f8ed0518bd7d792948809f3bf8f789522fad74 Mon Sep 17 00:00:00 2001 From: Huy Bui Date: Tue, 4 Nov 2025 17:59:45 +0100 Subject: [PATCH 245/684] pinctrl: renesas: r8a779g0: Remove STPWT_EXTFXR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.1.30 of the R-Car V4H Series Hardware User’s Manual removed the "STPWT_EXTFXR" signal from the pin control register tables. As this is further unused in the pin control driver, it can be removed safely. Signed-off-by: Huy Bui Signed-off-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Link: https://patch.msgid.link/f6cfdbbc024d85e87583a1d57ea01582632f1216.1762274384.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pfc-r8a779g0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c index 945e4f87806db1..1c8abd68583af5 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779g0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c @@ -352,7 +352,7 @@ #define IP1SR2_3_0 FM(TPU0TO0_A) FM(CANFD6_RX) F_(0, 0) FM(TCLK1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_7_4 FM(CAN_CLK) FM(FXR_TXENA_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_11_8 FM(CANFD0_TX) FM(FXR_TXENB_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR2_15_12 FM(CANFD0_RX) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_15_12 FM(CANFD0_RX) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_19_16 FM(CANFD2_TX) FM(TPU0TO2_A) F_(0, 0) FM(TCLK3_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_23_20 FM(CANFD2_RX) FM(TPU0TO3_A) FM(PWM1_B) FM(TCLK4_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_27_24 FM(CANFD3_TX) F_(0, 0) FM(PWM2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -925,7 +925,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP1SR2_11_8, FXR_TXENB_N_B), PINMUX_IPSR_GPSR(IP1SR2_15_12, CANFD0_RX), - PINMUX_IPSR_GPSR(IP1SR2_15_12, STPWT_EXTFXR), PINMUX_IPSR_GPSR(IP1SR2_19_16, CANFD2_TX), PINMUX_IPSR_GPSR(IP1SR2_19_16, TPU0TO2_A), From 3a430f50b8ceaae345ee507abfa5e7360819db71 Mon Sep 17 00:00:00 2001 From: Huy Bui Date: Tue, 4 Nov 2025 17:59:46 +0100 Subject: [PATCH 246/684] pinctrl: renesas: r8a779h0: Remove CC5_OSCOUT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.0.71 of the R-Car V4M Series Hardware User’s Manual removed the "CC5_OSCOUT" signal from the pin control register tables. As this is further unused in the pin control driver, it can be removed safely. Signed-off-by: Huy Bui Signed-off-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Link: https://patch.msgid.link/895bb560467309706931d14aeea0e063ad0e86eb.1762274384.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pfc-r8a779h0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a779h0.c b/drivers/pinctrl/renesas/pfc-r8a779h0.c index 63b3725a0cf6ff..cee7690ea19d0d 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779h0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779h0.c @@ -478,7 +478,7 @@ /* IP0SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ #define IP0SR7_3_0 FM(AVB0_AVTP_PPS) FM(AVB0_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) FM(AVB0_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_15_12 FM(AVB0_TD3) FM(AVB0_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_19_16 FM(AVB0_LINK) FM(AVB0_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR7_23_20 FM(AVB0_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -1123,7 +1123,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP0SR7_11_8, AVB0_AVTP_MATCH), PINMUX_IPSR_GPSR(IP0SR7_11_8, AVB0_MII_RX_ER), - PINMUX_IPSR_GPSR(IP0SR7_11_8, CC5_OSCOUT), PINMUX_IPSR_GPSR(IP0SR7_15_12, AVB0_TD3), PINMUX_IPSR_GPSR(IP0SR7_15_12, AVB0_MII_TD3), From 8903597df7b6d511f81abb47708a33e9a1e6a530 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Nov 2025 17:59:47 +0100 Subject: [PATCH 247/684] pinctrl: renesas: r8a779h0: Remove STPWT_EXTFXR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.0.81 of the R-Car V4M Series Hardware User’s Manual removed the "STPWT_EXTFXR" signal from the pin control register tables. As this is further unused in the pin control driver, it can be removed safely. Signed-off-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Link: https://patch.msgid.link/f849fa3b9b516e9dd04b45462b69f52225259480.1762274384.git.geert+renesas@glider.be --- drivers/pinctrl/renesas/pfc-r8a779h0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/renesas/pfc-r8a779h0.c b/drivers/pinctrl/renesas/pfc-r8a779h0.c index cee7690ea19d0d..ec0fc1bf7a9056 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779h0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779h0.c @@ -339,7 +339,7 @@ #define IP1SR2_3_0 FM(TPU0TO0_A) F_(0, 0) F_(0, 0) FM(TCLK1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_7_4 FM(CAN_CLK) FM(FXR_TXENA_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_11_8 FM(CANFD0_TX) FM(FXR_TXENB_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR2_15_12 FM(CANFD0_RX) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_15_12 FM(CANFD0_RX) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_19_16 FM(CANFD2_TX) FM(TPU0TO2_A) F_(0, 0) FM(TCLK3_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_23_20 FM(CANFD2_RX) FM(TPU0TO3_A) FM(PWM1_B) FM(TCLK4_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR2_27_24 FM(CANFD3_TX) F_(0, 0) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -865,7 +865,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP1SR2_11_8, FXR_TXENB_N_B), PINMUX_IPSR_GPSR(IP1SR2_15_12, CANFD0_RX), - PINMUX_IPSR_GPSR(IP1SR2_15_12, STPWT_EXTFXR), PINMUX_IPSR_GPSR(IP1SR2_19_16, CANFD2_TX), PINMUX_IPSR_GPSR(IP1SR2_19_16, TPU0TO2_A), From 566ed24a0a79e23b37cc883a49d515916a245cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 6 Nov 2025 22:16:02 +0100 Subject: [PATCH 248/684] clk: renesas: rcar-gen4: Add support for clock dividers in FRQCRB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FRQCRB register on R-Car V3U, V4H and V4M do in addition to the already supported KICK bit contain settings for the frequency division ratios for the clocks ZTR, ZT, ZS and ZG. It is however not possible to use the latter when registering a Z clock with the DEF_GEN4_Z() macro. This change adds support for that by extending the existing practice of treating the bit field offsets at multiples of 32 to map to a different register. With this new mapping in palace bit offsets 0 - 31 map to FRQCRC0 bit offsets 32 - 63 map to FRQCRC1 bit offsets 64 - 95 map to FRQCRB The change also adds an error condition to return an error if an unknown offset is used. The KICK bit defined in FRQCRB and already supported covers all three registers and no addition to how it is handled are needed. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251106211604.2766465-3-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-gen4-cpg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c index fb9a876aaba5cb..215ef8e1a1156a 100644 --- a/drivers/clk/renesas/rcar-gen4-cpg.c +++ b/drivers/clk/renesas/rcar-gen4-cpg.c @@ -257,7 +257,7 @@ static struct clk * __init cpg_pll_clk_register(const char *name, } /* - * Z0 Clock & Z1 Clock + * Z0, Z1 and ZG Clock */ #define CPG_FRQCRB 0x00000804 #define CPG_FRQCRB_KICK BIT(31) @@ -389,9 +389,14 @@ static struct clk * __init cpg_z_clk_register(const char *name, if (offset < 32) { zclk->reg = reg + CPG_FRQCRC0; - } else { + } else if (offset < 64) { zclk->reg = reg + CPG_FRQCRC1; offset -= 32; + } else if (offset < 96) { + zclk->reg = reg + CPG_FRQCRB; + offset -= 64; + } else { + return ERR_PTR(-EINVAL); } zclk->kick_reg = reg + CPG_FRQCRB; zclk->hw.init = &init; From f8ea1a2760296831a45a57748ae0587751b6688f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 6 Nov 2025 22:16:03 +0100 Subject: [PATCH 249/684] clk: renesas: r8a779a0: Add ZG Core clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Describe the ZG Core clock needed to operate the PowerVR GPU. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251106211604.2766465-4-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 1be7b9592aa620..449611432059bb 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -26,7 +26,7 @@ enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R8A779A0_CLK_OSC, + LAST_DT_CORE_CLK = R8A779A0_CLK_ZG, /* External Input Clocks */ CLK_EXTAL, @@ -39,6 +39,7 @@ enum clk_ids { CLK_PLL21, CLK_PLL30, CLK_PLL31, + CLK_PLL4, CLK_PLL5, CLK_PLL1_DIV2, CLK_PLL20_DIV2, @@ -65,6 +66,7 @@ enum clk_ids { #define CPG_PLL21CR 0x0838 /* PLL21 Control Register */ #define CPG_PLL30CR 0x083c /* PLL30 Control Register */ #define CPG_PLL31CR 0x0840 /* PLL31 Control Register */ +#define CPG_PLL4CR 0x0844 /* PLL4 Control Register */ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { /* External Clock Inputs */ @@ -79,6 +81,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_PLL(".pll21", CLK_PLL21, CPG_PLL21CR), DEF_PLL(".pll30", CLK_PLL30, CPG_PLL30CR), DEF_PLL(".pll31", CLK_PLL31, CPG_PLL31CR), + DEF_PLL(".pll4", CLK_PLL4, CPG_PLL4CR), DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), DEF_FIXED(".pll20_div2", CLK_PLL20_DIV2, CLK_PLL20, 2, 1), @@ -98,6 +101,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { /* Core Clock Outputs */ DEF_GEN4_Z("z0", R8A779A0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL20, 2, 0), DEF_GEN4_Z("z1", R8A779A0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL21, 2, 8), + DEF_GEN4_Z("zg", R8A779A0_CLK_ZG, CLK_TYPE_GEN4_Z, CLK_PLL4, 2, 88), DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1), DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1), DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1), From ea2bfb853b15f01b6a24e3fb020feb1c0568873b Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 27 Oct 2025 16:26:41 -0500 Subject: [PATCH 250/684] dt-bindings: pinctrl: Convert sprd,sc9860-pinctrl to DT schema Convert the sprd,sc9860-pinctrl binding to DT schema format. What's valid for the the sleep mode child nodes wasn't well defined. The schema is based on the example (as there's no .dts with pin states) and the driver's register definitions. Signed-off-by: Rob Herring (Arm) Signed-off-by: Linus Walleij --- .../bindings/pinctrl/sprd,pinctrl.txt | 83 -------- .../bindings/pinctrl/sprd,sc9860-pinctrl.txt | 70 ------ .../bindings/pinctrl/sprd,sc9860-pinctrl.yaml | 199 ++++++++++++++++++ 3 files changed, 199 insertions(+), 153 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/sprd,pinctrl.txt delete mode 100644 Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/sprd,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/sprd,pinctrl.txt deleted file mode 100644 index 779b8ef0f6e665..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/sprd,pinctrl.txt +++ /dev/null @@ -1,83 +0,0 @@ -* Spreadtrum Pin Controller - -The Spreadtrum pin controller are organized in 3 blocks (types). - -The first block comprises some global control registers, and each -register contains several bit fields with one bit or several bits -to configure for some global common configuration, such as domain -pad driving level, system control select and so on ("domain pad -driving level": One pin can output 3.0v or 1.8v, depending on the -related domain pad driving selection, if the related domain pad -select 3.0v, then the pin can output 3.0v. "system control" is used -to choose one function (like: UART0) for which system, since we -have several systems (AP/CP/CM4) on one SoC.). - -There are too much various configuration that we can not list all -of them, so we can not make every Spreadtrum-special configuration -as one generic configuration, and maybe it will add more strange -global configuration in future. Then we add one "sprd,control" to -set these various global control configuration, and we need use -magic number for this property. - -Moreover we recognise every fields comprising one bit or several -bits in one global control register as one pin, thus we should -record every pin's bit offset, bit width and register offset to -configure this field (pin). - -The second block comprises some common registers which have unified -register definition, and each register described one pin is used -to configure the pin sleep mode, function select and sleep related -configuration. - -Now we have 4 systems for sleep mode on SC9860 SoC: AP system, -PUBCP system, TGLDSP system and AGDSP system. And the pin sleep -related configuration are: -- input-enable -- input-disable -- output-high -- output-low -- bias-pull-up -- bias-pull-down - -In some situation we need set the pin sleep mode and pin sleep related -configuration, to set the pin sleep related configuration automatically -by hardware when the system specified by sleep mode goes into deep -sleep mode. For example, if we set the pin sleep mode as PUBCP_SLEEP -and set the pin sleep related configuration as "input-enable", which -means when PUBCP system goes into deep sleep mode, this pin will be set -input enable automatically. - -Moreover we can not use the "sleep" state, since some systems (like: -PUBCP system) do not run linux kernel OS (only AP system run linux -kernel on SC9860 platform), then we can not select "sleep" state -when the PUBCP system goes into deep sleep mode. Thus we introduce -"sprd,sleep-mode" property to set pin sleep mode. - -The last block comprises some misc registers which also have unified -register definition, and each register described one pin is used to -configure drive strength, pull up/down and so on. Especially for pull -up, we have two kind pull up resistor: 20K and 4.7K. - -Required properties for Spreadtrum pin controller: -- compatible: "sprd,-pinctrl" - Please refer to each sprd,-pinctrl.txt binding doc for supported SoCs. -- reg: The register address of pin controller device. -- pins : An array of pin names. - -Optional properties: -- function: Specified the function name. -- drive-strength: Drive strength in mA. -- input-schmitt-disable: Enable schmitt-trigger mode. -- input-schmitt-enable: Disable schmitt-trigger mode. -- bias-disable: Disable pin bias. -- bias-pull-down: Pull down on pin. -- bias-pull-up: Pull up on pin. -- input-enable: Enable pin input. -- input-disable: Enable pin output. -- output-high: Set the pin as an output level high. -- output-low: Set the pin as an output level low. -- sleep-hardware-state: Indicate these configs in this state are sleep related. -- sprd,control: Control values referring to databook for global control pins. -- sprd,sleep-mode: Sleep mode selection. - -Please refer to each sprd,-pinctrl.txt binding doc for supported values. diff --git a/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.txt deleted file mode 100644 index 5a628333d52f24..00000000000000 --- a/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.txt +++ /dev/null @@ -1,70 +0,0 @@ -* Spreadtrum SC9860 Pin Controller - -Please refer to sprd,pinctrl.txt in this directory for common binding part -and usage. - -Required properties: -- compatible: Must be "sprd,sc9860-pinctrl". -- reg: The register address of pin controller device. -- pins : An array of strings, each string containing the name of a pin. - -Optional properties: -- function: A string containing the name of the function, values must be - one of: "func1", "func2", "func3" and "func4". -- drive-strength: Drive strength in mA. Supported values: 2, 4, 6, 8, 10, - 12, 14, 16, 20, 21, 24, 25, 27, 29, 31 and 33. -- input-schmitt-disable: Enable schmitt-trigger mode. -- input-schmitt-enable: Disable schmitt-trigger mode. -- bias-disable: Disable pin bias. -- bias-pull-down: Pull down on pin. -- bias-pull-up: Pull up on pin. Supported values: 20000 for pull-up resistor - is 20K and 4700 for pull-up resistor is 4.7K. -- input-enable: Enable pin input. -- input-disable: Enable pin output. -- output-high: Set the pin as an output level high. -- output-low: Set the pin as an output level low. -- sleep-hardware-state: Indicate these configs in this state are sleep related. -- sprd,control: Control values referring to databook for global control pins. -- sprd,sleep-mode: Choose the pin sleep mode, and supported values are: - AP_SLEEP, PUBCP_SLEEP, TGLDSP_SLEEP and AGDSP_SLEEP. - -Pin sleep mode definition: -enum pin_sleep_mode { - AP_SLEEP = BIT(0), - PUBCP_SLEEP = BIT(1), - TGLDSP_SLEEP = BIT(2), - AGDSP_SLEEP = BIT(3), -}; - -Example: -pin_controller: pinctrl@402a0000 { - compatible = "sprd,sc9860-pinctrl"; - reg = <0x402a0000 0x10000>; - - grp1: sd0 { - pins = "SC9860_VIO_SD2_IRTE", "SC9860_VIO_SD0_IRTE"; - sprd,control = <0x1>; - }; - - grp2: rfctl_33 { - pins = "SC9860_RFCTL33"; - function = "func2"; - sprd,sleep-mode = ; - grp2_sleep_mode: rfctl_33_sleep { - pins = "SC9860_RFCTL33"; - sleep-hardware-state; - output-low; - } - }; - - grp3: rfctl_misc_20 { - pins = "SC9860_RFCTL20_MISC"; - drive-strength = <10>; - bias-pull-up = <4700>; - grp3_sleep_mode: rfctl_misc_sleep { - pins = "SC9860_RFCTL20_MISC"; - sleep-hardware-state; - bias-pull-up; - } - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.yaml new file mode 100644 index 00000000000000..59d23eb8aa973d --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/sprd,sc9860-pinctrl.yaml @@ -0,0 +1,199 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/sprd,sc9860-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Spreadtrum SC9860 Pin Controller + +maintainers: + - Baolin Wang + +description: > + The Spreadtrum pin controller are organized in 3 blocks (types). + + The first block comprises some global control registers, and each + register contains several bit fields with one bit or several bits + to configure for some global common configuration, such as domain + pad driving level, system control select and so on ("domain pad + driving level": One pin can output 3.0v or 1.8v, depending on the + related domain pad driving selection, if the related domain pad + select 3.0v, then the pin can output 3.0v. "system control" is used + to choose one function (like: UART0) for which system, since we + have several systems (AP/CP/CM4) on one SoC.). + + There are too much various configuration that we can not list all + of them, so we can not make every Spreadtrum-special configuration + as one generic configuration, and maybe it will add more strange + global configuration in future. Then we add one "sprd,control" to + set these various global control configuration, and we need use + magic number for this property. + + Moreover we recognize every fields comprising one bit or several + bits in one global control register as one pin, thus we should + record every pin's bit offset, bit width and register offset to + configure this field (pin). + + The second block comprises some common registers which have unified + register definition, and each register described one pin is used + to configure the pin sleep mode, function select and sleep related + configuration. + + Now we have 4 systems for sleep mode on SC9860 SoC: AP system, + PUBCP system, TGLDSP system and AGDSP system. And the pin sleep + related configuration are: + - input-enable + - input-disable + - output-high + - output-low + - bias-pull-up + - bias-pull-down + + In some situation we need set the pin sleep mode and pin sleep related + configuration, to set the pin sleep related configuration automatically + by hardware when the system specified by sleep mode goes into deep + sleep mode. For example, if we set the pin sleep mode as PUBCP_SLEEP + and set the pin sleep related configuration as "input-enable", which + means when PUBCP system goes into deep sleep mode, this pin will be set + input enable automatically. + + Moreover we can not use the "sleep" state, since some systems (like: + PUBCP system) do not run linux kernel OS (only AP system run linux + kernel on SC9860 platform), then we can not select "sleep" state + when the PUBCP system goes into deep sleep mode. Thus we introduce + "sprd,sleep-mode" property to set pin sleep mode. + + The last block comprises some misc registers which also have unified + register definition, and each register described one pin is used to + configure drive strength, pull up/down and so on. Especially for pull + up, we have two kind pull up resistor: 20K and 4.7K. + +properties: + compatible: + const: sprd,sc9860-pinctrl + + reg: + maxItems: 1 + +additionalProperties: + $ref: '#/$defs/pin-node' + unevaluatedProperties: false + + properties: + function: + description: Function to assign to the pins. + enum: + - func1 + - func2 + - func3 + - func4 + + drive-strength: + description: Drive strength in mA. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [2, 4, 6, 8, 10, 12, 14, 16, 20, 21, 24, 25, 27, 29, 31, 33] + + input-schmitt-disable: true + + input-schmitt-enable: true + + bias-pull-up: + enum: [20000, 4700] + + sprd,sleep-mode: + description: Pin sleep mode selection. + $ref: /schemas/types.yaml#/definitions/uint32 + maximum: 0x1f + + sprd,control: + description: Control values referring to databook for global control pins. + $ref: /schemas/types.yaml#/definitions/uint32 + + patternProperties: + 'sleep$': + $ref: '#/$defs/pin-node' + unevaluatedProperties: false + + properties: + bias-pull-up: + type: boolean + + sleep-hardware-state: + description: Indicate these configs in sleep related state. + type: boolean + +$defs: + pin-node: + type: object + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + + properties: + pins: + description: Names of pins to configure. + $ref: /schemas/types.yaml#/definitions/string-array + + bias-disable: + description: Disable pin bias. + type: boolean + + bias-pull-down: + description: Pull down on pin. + type: boolean + + bias-pull-up: true + + input-enable: + description: Enable pin input. + type: boolean + + input-disable: + description: Enable pin output. + type: boolean + + output-high: + description: Set the pin as an output level high. + type: boolean + + output-low: + description: Set the pin as an output level low. + type: boolean + +required: + - compatible + - reg + +examples: + - | + pin_controller: pinctrl@402a0000 { + compatible = "sprd,sc9860-pinctrl"; + reg = <0x402a0000 0x10000>; + + grp1: sd0 { + pins = "SC9860_VIO_SD2_IRTE", "SC9860_VIO_SD0_IRTE"; + sprd,control = <0x1>; + }; + + grp2: rfctl_33 { + pins = "SC9860_RFCTL33"; + function = "func2"; + sprd,sleep-mode = <3>; + grp2_sleep_mode: rfctl_33_sleep { + pins = "SC9860_RFCTL33"; + sleep-hardware-state; + output-low; + }; + }; + + grp3: rfctl_misc_20 { + pins = "SC9860_RFCTL20_MISC"; + drive-strength = <10>; + bias-pull-up = <4700>; + grp3_sleep_mode: rfctl_misc_sleep { + pins = "SC9860_RFCTL20_MISC"; + sleep-hardware-state; + bias-pull-up; + }; + }; + }; From 13064950339ffc73a0e55e9b4898df861b04848e Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Tue, 4 Nov 2025 10:12:21 +0800 Subject: [PATCH 251/684] dt-bindings: pinctrl: Add rk3506 pinctrl support Add the compatible string for the rk3506 SoC. Signed-off-by: Ye Zhang Acked-by: Krzysztof Kozlowski Reviewed-by: Heiko Stuebner Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml index 125af766b99297..76e6072817160d 100644 --- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml @@ -44,6 +44,7 @@ properties: - rockchip,rk3328-pinctrl - rockchip,rk3368-pinctrl - rockchip,rk3399-pinctrl + - rockchip,rk3506-pinctrl - rockchip,rk3528-pinctrl - rockchip,rk3562-pinctrl - rockchip,rk3568-pinctrl From dbd2317d7b9f88b7b4b7de0d48173ee178f2ac97 Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Tue, 4 Nov 2025 10:12:22 +0800 Subject: [PATCH 252/684] pinctrl: rockchip: Add rk3506 pinctrl support Add support for the 5 rk3506 GPIO banks. Signed-off-by: Ye Zhang Reviewed-by: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 442 ++++++++++++++++++++++++++++- drivers/pinctrl/pinctrl-rockchip.h | 4 + 2 files changed, 438 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 7a68a6237649c1..e44ef262beec6e 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -105,6 +105,29 @@ .pull_type[3] = pull3, \ } +#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(id, pins, label, iom0, \ + iom1, iom2, iom3, \ + offset0, offset1, \ + offset2, offset3, drv0, \ + drv1, drv2, drv3) \ + { \ + .bank_num = id, \ + .nr_pins = pins, \ + .name = label, \ + .iomux = { \ + { .type = iom0, .offset = offset0 }, \ + { .type = iom1, .offset = offset1 }, \ + { .type = iom2, .offset = offset2 }, \ + { .type = iom3, .offset = offset3 }, \ + }, \ + .drv = { \ + { .drv_type = drv0, .offset = -1 }, \ + { .drv_type = drv1, .offset = -1 }, \ + { .drv_type = drv2, .offset = -1 }, \ + { .drv_type = drv3, .offset = -1 }, \ + }, \ + } + #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \ { \ .bank_num = id, \ @@ -233,6 +256,35 @@ .pull_type[3] = pull3, \ } +#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(id, pins, \ + label, iom0, iom1, \ + iom2, iom3, offset0, \ + offset1, offset2, \ + offset3, drv0, drv1, \ + drv2, drv3, pull0, \ + pull1, pull2, pull3) \ + { \ + .bank_num = id, \ + .nr_pins = pins, \ + .name = label, \ + .iomux = { \ + { .type = iom0, .offset = offset0 }, \ + { .type = iom1, .offset = offset1 }, \ + { .type = iom2, .offset = offset2 }, \ + { .type = iom3, .offset = offset3 }, \ + }, \ + .drv = { \ + { .drv_type = drv0, .offset = -1 }, \ + { .drv_type = drv1, .offset = -1 }, \ + { .drv_type = drv2, .offset = -1 }, \ + { .drv_type = drv3, .offset = -1 }, \ + }, \ + .pull_type[0] = pull0, \ + .pull_type[1] = pull1, \ + .pull_type[2] = pull2, \ + .pull_type[3] = pull3, \ + } + #define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG) \ { \ .bank_num = ID, \ @@ -1120,6 +1172,13 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) else regmap = info->regmap_base; + if (ctrl->type == RK3506) { + if (bank->bank_num == 1) + regmap = info->regmap_ioc1; + else if (bank->bank_num == 4) + return 0; + } + /* get basic quadrupel of mux registers and the correct reg inside */ mux_type = bank->iomux[iomux_num].type; reg = bank->iomux[iomux_num].offset; @@ -1239,6 +1298,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) else regmap = info->regmap_base; + if (ctrl->type == RK3506) { + if (bank->bank_num == 1) + regmap = info->regmap_ioc1; + else if (bank->bank_num == 4) + return 0; + } + /* get basic quadrupel of mux registers and the correct reg inside */ mux_type = bank->iomux[iomux_num].type; reg = bank->iomux[iomux_num].offset; @@ -2003,6 +2069,262 @@ static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, return 0; } +#define RK3506_DRV_BITS_PER_PIN 8 +#define RK3506_DRV_PINS_PER_REG 2 +#define RK3506_DRV_GPIO0_A_OFFSET 0x100 +#define RK3506_DRV_GPIO0_D_OFFSET 0x830 +#define RK3506_DRV_GPIO1_OFFSET 0x140 +#define RK3506_DRV_GPIO2_OFFSET 0x180 +#define RK3506_DRV_GPIO3_OFFSET 0x1c0 +#define RK3506_DRV_GPIO4_OFFSET 0x840 + +static int rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + int ret = 0; + + switch (bank->bank_num) { + case 0: + *regmap = info->regmap_pmu; + if (pin_num > 24) { + ret = -EINVAL; + } else if (pin_num < 24) { + *reg = RK3506_DRV_GPIO0_A_OFFSET; + } else { + *reg = RK3506_DRV_GPIO0_D_OFFSET; + *bit = 3; + + return 0; + } + break; + + case 1: + *regmap = info->regmap_ioc1; + if (pin_num < 28) + *reg = RK3506_DRV_GPIO1_OFFSET; + else + ret = -EINVAL; + break; + + case 2: + *regmap = info->regmap_base; + if (pin_num < 17) + *reg = RK3506_DRV_GPIO2_OFFSET; + else + ret = -EINVAL; + break; + + case 3: + *regmap = info->regmap_base; + if (pin_num < 15) + *reg = RK3506_DRV_GPIO3_OFFSET; + else + ret = -EINVAL; + break; + + case 4: + *regmap = info->regmap_base; + if (pin_num < 8 || pin_num > 11) { + ret = -EINVAL; + } else { + *reg = RK3506_DRV_GPIO4_OFFSET; + *bit = 10; + + return 0; + } + break; + + default: + ret = -EINVAL; + break; + } + + if (ret) { + dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num); + + return ret; + } + + *reg += ((pin_num / RK3506_DRV_PINS_PER_REG) * 4); + *bit = pin_num % RK3506_DRV_PINS_PER_REG; + *bit *= RK3506_DRV_BITS_PER_PIN; + + return 0; +} + +#define RK3506_PULL_BITS_PER_PIN 2 +#define RK3506_PULL_PINS_PER_REG 8 +#define RK3506_PULL_GPIO0_A_OFFSET 0x200 +#define RK3506_PULL_GPIO0_D_OFFSET 0x830 +#define RK3506_PULL_GPIO1_OFFSET 0x210 +#define RK3506_PULL_GPIO2_OFFSET 0x220 +#define RK3506_PULL_GPIO3_OFFSET 0x230 +#define RK3506_PULL_GPIO4_OFFSET 0x840 + +static int rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + int ret = 0; + + switch (bank->bank_num) { + case 0: + *regmap = info->regmap_pmu; + if (pin_num > 24) { + ret = -EINVAL; + } else if (pin_num < 24) { + *reg = RK3506_PULL_GPIO0_A_OFFSET; + } else { + *reg = RK3506_PULL_GPIO0_D_OFFSET; + *bit = 5; + + return 0; + } + break; + + case 1: + *regmap = info->regmap_ioc1; + if (pin_num < 28) + *reg = RK3506_PULL_GPIO1_OFFSET; + else + ret = -EINVAL; + break; + + case 2: + *regmap = info->regmap_base; + if (pin_num < 17) + *reg = RK3506_PULL_GPIO2_OFFSET; + else + ret = -EINVAL; + break; + + case 3: + *regmap = info->regmap_base; + if (pin_num < 15) + *reg = RK3506_PULL_GPIO3_OFFSET; + else + ret = -EINVAL; + break; + + case 4: + *regmap = info->regmap_base; + if (pin_num < 8 || pin_num > 11) { + ret = -EINVAL; + } else { + *reg = RK3506_PULL_GPIO4_OFFSET; + *bit = 13; + + return 0; + } + break; + + default: + ret = -EINVAL; + break; + } + + if (ret) { + dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num); + + return ret; + } + + *reg += ((pin_num / RK3506_PULL_PINS_PER_REG) * 4); + *bit = pin_num % RK3506_PULL_PINS_PER_REG; + *bit *= RK3506_PULL_BITS_PER_PIN; + + return 0; +} + +#define RK3506_SMT_BITS_PER_PIN 1 +#define RK3506_SMT_PINS_PER_REG 8 +#define RK3506_SMT_GPIO0_A_OFFSET 0x400 +#define RK3506_SMT_GPIO0_D_OFFSET 0x830 +#define RK3506_SMT_GPIO1_OFFSET 0x410 +#define RK3506_SMT_GPIO2_OFFSET 0x420 +#define RK3506_SMT_GPIO3_OFFSET 0x430 +#define RK3506_SMT_GPIO4_OFFSET 0x840 + +static int rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, + struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + int ret = 0; + + switch (bank->bank_num) { + case 0: + *regmap = info->regmap_pmu; + if (pin_num > 24) { + ret = -EINVAL; + } else if (pin_num < 24) { + *reg = RK3506_SMT_GPIO0_A_OFFSET; + } else { + *reg = RK3506_SMT_GPIO0_D_OFFSET; + *bit = 9; + + return 0; + } + break; + + case 1: + *regmap = info->regmap_ioc1; + if (pin_num < 28) + *reg = RK3506_SMT_GPIO1_OFFSET; + else + ret = -EINVAL; + break; + + case 2: + *regmap = info->regmap_base; + if (pin_num < 17) + *reg = RK3506_SMT_GPIO2_OFFSET; + else + ret = -EINVAL; + break; + + case 3: + *regmap = info->regmap_base; + if (pin_num < 15) + *reg = RK3506_SMT_GPIO3_OFFSET; + else + ret = -EINVAL; + break; + + case 4: + *regmap = info->regmap_base; + if (pin_num < 8 || pin_num > 11) { + ret = -EINVAL; + } else { + *reg = RK3506_SMT_GPIO4_OFFSET; + *bit = 8; + + return 0; + } + break; + + default: + ret = -EINVAL; + break; + } + + if (ret) { + dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num); + + return ret; + } + + *reg += ((pin_num / RK3506_SMT_PINS_PER_REG) * 4); + *bit = pin_num % RK3506_SMT_PINS_PER_REG; + *bit *= RK3506_SMT_BITS_PER_PIN; + + return 0; +} + #define RK3528_DRV_BITS_PER_PIN 8 #define RK3528_DRV_PINS_PER_REG 2 #define RK3528_DRV_GPIO0_OFFSET 0x100 @@ -2749,7 +3071,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, rmask_bits = RK3588_DRV_BITS_PER_PIN; ret = strength; goto config; - } else if (ctrl->type == RK3528 || + } else if (ctrl->type == RK3506 || + ctrl->type == RK3528 || ctrl->type == RK3562 || ctrl->type == RK3568) { rmask_bits = RK3568_DRV_BITS_PER_PIN; @@ -2828,12 +3151,37 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, case DRV_TYPE_IO_1V8_ONLY: rmask_bits = RK3288_DRV_BITS_PER_PIN; break; + case DRV_TYPE_IO_LEVEL_2_BIT: + ret = regmap_read(regmap, reg, &data); + if (ret) + return ret; + data >>= bit; + + return data & 0x3; + case DRV_TYPE_IO_LEVEL_8_BIT: + ret = regmap_read(regmap, reg, &data); + if (ret) + return ret; + data >>= bit; + data &= (1 << 8) - 1; + + ret = hweight8(data); + if (ret > 0) + return ret - 1; + else + return -EINVAL; default: dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type); return -EINVAL; } config: + if (ctrl->type == RK3506) { + if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) { + rmask_bits = 2; + ret = strength; + } + } /* enable the write to the equivalent lower bits */ data = ((1 << rmask_bits) - 1) << (bit + 16); rmask = data | (data >> 16); @@ -2957,6 +3305,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, case RK3328: case RK3368: case RK3399: + case RK3506: case RK3528: case RK3562: case RK3568: @@ -3077,6 +3426,10 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num) break; } + if (ctrl->type == RK3506) + if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) + return data & 0x3; + return data & 0x1; } @@ -3112,6 +3465,14 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank, break; } + if (ctrl->type == RK3506) { + if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) { + data = 0x3 << (bit + 16); + rmask = data | (data >> 16); + data |= ((enable ? 0x3 : 0) << bit); + } + } + return regmap_update_bits(regmap, reg, rmask, data); } @@ -3227,6 +3588,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, case RK3328: case RK3368: case RK3399: + case RK3506: case RK3528: case RK3562: case RK3568: @@ -3880,13 +4242,10 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) } /* try to find the optional reference to the pmu syscon */ - node = of_parse_phandle(np, "rockchip,pmu", 0); - if (node) { - info->regmap_pmu = syscon_node_to_regmap(node); - of_node_put(node); - if (IS_ERR(info->regmap_pmu)) - return PTR_ERR(info->regmap_pmu); - } + info->regmap_pmu = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,pmu"); + + /* try to find the optional reference to the ioc1 syscon */ + info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1"); ret = rockchip_pinctrl_register(pdev, info); if (ret) @@ -4350,6 +4709,71 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = { .drv_calc_reg = rk3399_calc_drv_reg_and_bit, }; +static struct rockchip_pin_bank rk3506_pin_banks[] = { + PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(0, 32, "gpio0", + IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, + IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, + IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, + IOMUX_WIDTH_2BIT | IOMUX_SOURCE_PMU, + 0x0, 0x8, 0x10, 0x830, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_2_BIT, + 0, 0, 0, 1), + PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(1, 32, "gpio1", + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + 0x20, 0x28, 0x30, 0x38, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT), + PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(2, 32, "gpio2", + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + 0x40, 0x48, 0x50, 0x58, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT), + PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(3, 32, "gpio3", + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + 0x60, 0x68, 0x70, 0x78, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, + DRV_TYPE_IO_LEVEL_8_BIT), + PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(4, 32, "gpio4", + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + 0x80, 0x88, 0x90, 0x98, + DRV_TYPE_IO_LEVEL_2_BIT, + DRV_TYPE_IO_LEVEL_2_BIT, + DRV_TYPE_IO_LEVEL_2_BIT, + DRV_TYPE_IO_LEVEL_2_BIT, + 1, 1, 1, 1), +}; + +static struct rockchip_pin_ctrl rk3506_pin_ctrl __maybe_unused = { + .pin_banks = rk3506_pin_banks, + .nr_banks = ARRAY_SIZE(rk3506_pin_banks), + .label = "RK3506-GPIO", + .type = RK3506, + .pull_calc_reg = rk3506_calc_pull_reg_and_bit, + .drv_calc_reg = rk3506_calc_drv_reg_and_bit, + .schmitt_calc_reg = rk3506_calc_schmitt_reg_and_bit, +}; + static struct rockchip_pin_bank rk3528_pin_banks[] = { PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_WIDTH_4BIT, @@ -4560,6 +4984,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = { .data = &rk3368_pin_ctrl }, { .compatible = "rockchip,rk3399-pinctrl", .data = &rk3399_pin_ctrl }, + { .compatible = "rockchip,rk3506-pinctrl", + .data = &rk3506_pin_ctrl }, { .compatible = "rockchip,rk3528-pinctrl", .data = &rk3528_pin_ctrl }, { .compatible = "rockchip,rk3562-pinctrl", diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 35cd38079d1e76..4f4aff42a80a9c 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -196,6 +196,7 @@ enum rockchip_pinctrl_type { RK3328, RK3368, RK3399, + RK3506, RK3528, RK3562, RK3568, @@ -260,6 +261,8 @@ enum rockchip_pin_drv_type { DRV_TYPE_IO_1V8_ONLY, DRV_TYPE_IO_1V8_3V0_AUTO, DRV_TYPE_IO_3V3_ONLY, + DRV_TYPE_IO_LEVEL_2_BIT, + DRV_TYPE_IO_LEVEL_8_BIT, DRV_TYPE_MAX }; @@ -458,6 +461,7 @@ struct rockchip_pinctrl { int reg_size; struct regmap *regmap_pull; struct regmap *regmap_pmu; + struct regmap *regmap_ioc1; struct device *dev; struct rockchip_pin_ctrl *ctrl; struct pinctrl_desc pctl; From 7959deaabea8380a318fefe9f3fffc37e5b0fc15 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Wed, 5 Nov 2025 11:50:22 +0100 Subject: [PATCH 253/684] pinctrl: stm32: handle semaphore acquisition when handling pinctrl/pinmux When a GPIO RIF configuration is in semaphore mode, and the semaphore hasn't been taken before configuring the GPIO, the write operations silently fail. To avoid a silent fail when applying a pinctrl, if the pins that are being configured are in semaphore mode, take the semaphore. Note that there is no proper release of the RIF semaphore yet for pinctrl. Signed-off-by: Gatien Chevallier Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 35 +++++++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index ceb9e19f2290d6..6a99708a5a23c6 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -362,11 +362,9 @@ static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) return -EINVAL; } - if (bank->rif_control) { - if (!stm32_gpio_rif_acquire_semaphore(bank, offset)) { - dev_err(pctl->dev, "pin %d not available.\n", pin); - return -EINVAL; - } + if (bank->rif_control && !stm32_gpio_rif_acquire_semaphore(bank, offset)) { + dev_err(pctl->dev, "pin %d not available.\n", offset); + return -EACCES; } return pinctrl_gpio_request(chip, offset); @@ -1040,7 +1038,9 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned int gpio) { struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + unsigned int offset = stm32_gpio_pin(gpio); struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio); if (!range) { @@ -1048,11 +1048,20 @@ static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned int gpio) return -EINVAL; } - if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) { + if (!gpiochip_line_is_valid(range->gc, offset)) { dev_warn(pctl->dev, "Can't access gpio %d\n", gpio); return -EACCES; } + bank = gpiochip_get_data(range->gc); + if (!bank) + return -ENODEV; + + if (bank->rif_control && !stm32_gpio_rif_acquire_semaphore(bank, offset)) { + dev_err(pctl->dev, "pin %d not available.\n", offset); + return -EACCES; + } + return 0; } @@ -1394,6 +1403,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, return -EACCES; } + if (bank->rif_control && !stm32_gpio_rif_acquire_semaphore(bank, offset)) { + dev_err(pctl->dev, "pin %d not available.\n", offset); + return -EACCES; + } + switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: ret = stm32_pconf_set_driving(bank, offset, 0); @@ -2014,16 +2028,21 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( if (!range) return 0; + bank = gpiochip_get_data(range->gc); + if (!gpiochip_line_is_valid(range->gc, offset)) return 0; + if (bank->rif_control && !stm32_gpio_rif_acquire_semaphore(bank, offset)) { + dev_err(pctl->dev, "pin %d not available.\n", offset); + return -EACCES; + } + pin_is_irq = gpiochip_line_is_irq(range->gc, offset); if (!desc || (!pin_is_irq && !desc->gpio_owner)) return 0; - bank = gpiochip_get_data(range->gc); - mode = bank->pin_backup[offset].mode; ret = stm32_pmx_set_mode(bank, offset, mode, bank->pin_backup[offset].alt); if (ret) From 9322da935c9a2db2b81a9660f650e48423ebf34d Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 27 Oct 2025 14:28:11 +0100 Subject: [PATCH 254/684] dt-bindings: pinctrl: mt7988: allow gpio-hogs Allow gpio-hogs in pinctrl node for switching pcie on Bananapi R4 Pro. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/mediatek,mt7988-pinctrl.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7988-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7988-pinctrl.yaml index 26dfe7e7735a97..1f31b520cb439b 100644 --- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7988-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7988-pinctrl.yaml @@ -61,6 +61,11 @@ required: - "#gpio-cells" patternProperties: + "-hog(-[0-9]+)?$": + type: object + required: + - gpio-hog + '-pins$': type: object additionalProperties: false From 4043b0c45f8555a079bdac69a19ed08695a47a7b Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 7 Nov 2025 00:57:04 +0100 Subject: [PATCH 255/684] pinctrl: airoha: generalize pins/group/function/confs handling In preparation for support of Airoha AN7583, generalize pins/group/function/confs handling and move them in match_data. Inner function will base the values on the pinctrl priv struct instead of relying on hardcoded struct. This permits to use different PIN data while keeping the same logic. Signed-off-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 567 ++++++++++++---------- 1 file changed, 318 insertions(+), 249 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index f1cf2578fe423e..32e5c1b32d5071 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -30,15 +30,15 @@ #include "../pinconf.h" #include "../pinmux.h" -#define PINCTRL_PIN_GROUP(id) \ - PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins)) +#define PINCTRL_PIN_GROUP(id, table) \ + PINCTRL_PINGROUP(id, table##_pins, ARRAY_SIZE(table##_pins)) -#define PINCTRL_FUNC_DESC(id) \ +#define PINCTRL_FUNC_DESC(id, table) \ { \ - .desc = PINCTRL_PINFUNCTION(#id, id##_groups, \ - ARRAY_SIZE(id##_groups)), \ - .groups = id##_func_group, \ - .group_size = ARRAY_SIZE(id##_func_group), \ + .desc = PINCTRL_PINFUNCTION(#id, table##_groups, \ + ARRAY_SIZE(table##_groups)),\ + .groups = table##_func_group, \ + .group_size = ARRAY_SIZE(table##_func_group), \ } #define PINCTRL_CONF_DESC(p, offset, mask) \ @@ -357,16 +357,46 @@ struct airoha_pinctrl_gpiochip { u32 irq_type[AIROHA_NUM_PINS]; }; +struct airoha_pinctrl_confs_info { + const struct airoha_pinctrl_conf *confs; + unsigned int num_confs; +}; + +enum airoha_pinctrl_confs_type { + AIROHA_PINCTRL_CONFS_PULLUP, + AIROHA_PINCTRL_CONFS_PULLDOWN, + AIROHA_PINCTRL_CONFS_DRIVE_E2, + AIROHA_PINCTRL_CONFS_DRIVE_E4, + AIROHA_PINCTRL_CONFS_PCIE_RST_OD, + + AIROHA_PINCTRL_CONFS_MAX, +}; + struct airoha_pinctrl { struct pinctrl_dev *ctrl; + struct pinctrl_desc desc; + const struct pingroup *grps; + const struct airoha_pinctrl_func *funcs; + const struct airoha_pinctrl_confs_info *confs_info; + struct regmap *chip_scu; struct regmap *regmap; struct airoha_pinctrl_gpiochip gpiochip; }; -static struct pinctrl_pin_desc airoha_pinctrl_pins[] = { +struct airoha_pinctrl_match_data { + const struct pinctrl_pin_desc *pins; + const unsigned int num_pins; + const struct pingroup *grps; + const unsigned int num_grps; + const struct airoha_pinctrl_func *funcs; + const unsigned int num_funcs; + const struct airoha_pinctrl_confs_info confs_info[AIROHA_PINCTRL_CONFS_MAX]; +}; + +static struct pinctrl_pin_desc en7581_pinctrl_pins[] = { PINCTRL_PIN(0, "uart1_txd"), PINCTRL_PIN(1, "uart1_rxd"), PINCTRL_PIN(2, "i2c_scl"), @@ -427,172 +457,172 @@ static struct pinctrl_pin_desc airoha_pinctrl_pins[] = { PINCTRL_PIN(63, "pcie_reset2"), }; -static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 }; -static const int pon_tod_1pps_pins[] = { 46 }; -static const int gsw_tod_1pps_pins[] = { 46 }; -static const int sipo_pins[] = { 16, 17 }; -static const int sipo_rclk_pins[] = { 16, 17, 43 }; -static const int mdio_pins[] = { 14, 15 }; -static const int uart2_pins[] = { 48, 55 }; -static const int uart2_cts_rts_pins[] = { 46, 47 }; -static const int hsuart_pins[] = { 28, 29 }; -static const int hsuart_cts_rts_pins[] = { 26, 27 }; -static const int uart4_pins[] = { 38, 39 }; -static const int uart5_pins[] = { 18, 19 }; -static const int i2c0_pins[] = { 2, 3 }; -static const int i2c1_pins[] = { 14, 15 }; -static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; -static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; -static const int i2s_pins[] = { 26, 27, 28, 29 }; -static const int pcm1_pins[] = { 22, 23, 24, 25 }; -static const int pcm2_pins[] = { 18, 19, 20, 21 }; -static const int spi_quad_pins[] = { 32, 33 }; -static const int spi_pins[] = { 4, 5, 6, 7 }; -static const int spi_cs1_pins[] = { 34 }; -static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; -static const int pcm_spi_int_pins[] = { 14 }; -static const int pcm_spi_rst_pins[] = { 15 }; -static const int pcm_spi_cs1_pins[] = { 43 }; -static const int pcm_spi_cs2_pins[] = { 40 }; -static const int pcm_spi_cs2_p128_pins[] = { 40 }; -static const int pcm_spi_cs2_p156_pins[] = { 40 }; -static const int pcm_spi_cs3_pins[] = { 41 }; -static const int pcm_spi_cs4_pins[] = { 42 }; -static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; -static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; -static const int gpio0_pins[] = { 13 }; -static const int gpio1_pins[] = { 14 }; -static const int gpio2_pins[] = { 15 }; -static const int gpio3_pins[] = { 16 }; -static const int gpio4_pins[] = { 17 }; -static const int gpio5_pins[] = { 18 }; -static const int gpio6_pins[] = { 19 }; -static const int gpio7_pins[] = { 20 }; -static const int gpio8_pins[] = { 21 }; -static const int gpio9_pins[] = { 22 }; -static const int gpio10_pins[] = { 23 }; -static const int gpio11_pins[] = { 24 }; -static const int gpio12_pins[] = { 25 }; -static const int gpio13_pins[] = { 26 }; -static const int gpio14_pins[] = { 27 }; -static const int gpio15_pins[] = { 28 }; -static const int gpio16_pins[] = { 29 }; -static const int gpio17_pins[] = { 30 }; -static const int gpio18_pins[] = { 31 }; -static const int gpio19_pins[] = { 32 }; -static const int gpio20_pins[] = { 33 }; -static const int gpio21_pins[] = { 34 }; -static const int gpio22_pins[] = { 35 }; -static const int gpio23_pins[] = { 36 }; -static const int gpio24_pins[] = { 37 }; -static const int gpio25_pins[] = { 38 }; -static const int gpio26_pins[] = { 39 }; -static const int gpio27_pins[] = { 40 }; -static const int gpio28_pins[] = { 41 }; -static const int gpio29_pins[] = { 42 }; -static const int gpio30_pins[] = { 43 }; -static const int gpio31_pins[] = { 44 }; -static const int gpio33_pins[] = { 46 }; -static const int gpio34_pins[] = { 47 }; -static const int gpio35_pins[] = { 48 }; -static const int gpio36_pins[] = { 49 }; -static const int gpio37_pins[] = { 50 }; -static const int gpio38_pins[] = { 51 }; -static const int gpio39_pins[] = { 52 }; -static const int gpio40_pins[] = { 53 }; -static const int gpio41_pins[] = { 54 }; -static const int gpio42_pins[] = { 55 }; -static const int gpio43_pins[] = { 56 }; -static const int gpio44_pins[] = { 57 }; -static const int gpio45_pins[] = { 58 }; -static const int gpio46_pins[] = { 59 }; -static const int pcie_reset0_pins[] = { 61 }; -static const int pcie_reset1_pins[] = { 62 }; -static const int pcie_reset2_pins[] = { 63 }; - -static const struct pingroup airoha_pinctrl_groups[] = { - PINCTRL_PIN_GROUP(pon), - PINCTRL_PIN_GROUP(pon_tod_1pps), - PINCTRL_PIN_GROUP(gsw_tod_1pps), - PINCTRL_PIN_GROUP(sipo), - PINCTRL_PIN_GROUP(sipo_rclk), - PINCTRL_PIN_GROUP(mdio), - PINCTRL_PIN_GROUP(uart2), - PINCTRL_PIN_GROUP(uart2_cts_rts), - PINCTRL_PIN_GROUP(hsuart), - PINCTRL_PIN_GROUP(hsuart_cts_rts), - PINCTRL_PIN_GROUP(uart4), - PINCTRL_PIN_GROUP(uart5), - PINCTRL_PIN_GROUP(i2c0), - PINCTRL_PIN_GROUP(i2c1), - PINCTRL_PIN_GROUP(jtag_udi), - PINCTRL_PIN_GROUP(jtag_dfd), - PINCTRL_PIN_GROUP(i2s), - PINCTRL_PIN_GROUP(pcm1), - PINCTRL_PIN_GROUP(pcm2), - PINCTRL_PIN_GROUP(spi), - PINCTRL_PIN_GROUP(spi_quad), - PINCTRL_PIN_GROUP(spi_cs1), - PINCTRL_PIN_GROUP(pcm_spi), - PINCTRL_PIN_GROUP(pcm_spi_int), - PINCTRL_PIN_GROUP(pcm_spi_rst), - PINCTRL_PIN_GROUP(pcm_spi_cs1), - PINCTRL_PIN_GROUP(pcm_spi_cs2_p128), - PINCTRL_PIN_GROUP(pcm_spi_cs2_p156), - PINCTRL_PIN_GROUP(pcm_spi_cs2), - PINCTRL_PIN_GROUP(pcm_spi_cs3), - PINCTRL_PIN_GROUP(pcm_spi_cs4), - PINCTRL_PIN_GROUP(emmc), - PINCTRL_PIN_GROUP(pnand), - PINCTRL_PIN_GROUP(gpio0), - PINCTRL_PIN_GROUP(gpio1), - PINCTRL_PIN_GROUP(gpio2), - PINCTRL_PIN_GROUP(gpio3), - PINCTRL_PIN_GROUP(gpio4), - PINCTRL_PIN_GROUP(gpio5), - PINCTRL_PIN_GROUP(gpio6), - PINCTRL_PIN_GROUP(gpio7), - PINCTRL_PIN_GROUP(gpio8), - PINCTRL_PIN_GROUP(gpio9), - PINCTRL_PIN_GROUP(gpio10), - PINCTRL_PIN_GROUP(gpio11), - PINCTRL_PIN_GROUP(gpio12), - PINCTRL_PIN_GROUP(gpio13), - PINCTRL_PIN_GROUP(gpio14), - PINCTRL_PIN_GROUP(gpio15), - PINCTRL_PIN_GROUP(gpio16), - PINCTRL_PIN_GROUP(gpio17), - PINCTRL_PIN_GROUP(gpio18), - PINCTRL_PIN_GROUP(gpio19), - PINCTRL_PIN_GROUP(gpio20), - PINCTRL_PIN_GROUP(gpio21), - PINCTRL_PIN_GROUP(gpio22), - PINCTRL_PIN_GROUP(gpio23), - PINCTRL_PIN_GROUP(gpio24), - PINCTRL_PIN_GROUP(gpio25), - PINCTRL_PIN_GROUP(gpio26), - PINCTRL_PIN_GROUP(gpio27), - PINCTRL_PIN_GROUP(gpio28), - PINCTRL_PIN_GROUP(gpio29), - PINCTRL_PIN_GROUP(gpio30), - PINCTRL_PIN_GROUP(gpio31), - PINCTRL_PIN_GROUP(gpio33), - PINCTRL_PIN_GROUP(gpio34), - PINCTRL_PIN_GROUP(gpio35), - PINCTRL_PIN_GROUP(gpio36), - PINCTRL_PIN_GROUP(gpio37), - PINCTRL_PIN_GROUP(gpio38), - PINCTRL_PIN_GROUP(gpio39), - PINCTRL_PIN_GROUP(gpio40), - PINCTRL_PIN_GROUP(gpio41), - PINCTRL_PIN_GROUP(gpio42), - PINCTRL_PIN_GROUP(gpio43), - PINCTRL_PIN_GROUP(gpio44), - PINCTRL_PIN_GROUP(gpio45), - PINCTRL_PIN_GROUP(gpio46), - PINCTRL_PIN_GROUP(pcie_reset0), - PINCTRL_PIN_GROUP(pcie_reset1), - PINCTRL_PIN_GROUP(pcie_reset2), +static const int en7581_pon_pins[] = { 49, 50, 51, 52, 53, 54 }; +static const int en7581_pon_tod_1pps_pins[] = { 46 }; +static const int en7581_gsw_tod_1pps_pins[] = { 46 }; +static const int en7581_sipo_pins[] = { 16, 17 }; +static const int en7581_sipo_rclk_pins[] = { 16, 17, 43 }; +static const int en7581_mdio_pins[] = { 14, 15 }; +static const int en7581_uart2_pins[] = { 48, 55 }; +static const int en7581_uart2_cts_rts_pins[] = { 46, 47 }; +static const int en7581_hsuart_pins[] = { 28, 29 }; +static const int en7581_hsuart_cts_rts_pins[] = { 26, 27 }; +static const int en7581_uart4_pins[] = { 38, 39 }; +static const int en7581_uart5_pins[] = { 18, 19 }; +static const int en7581_i2c0_pins[] = { 2, 3 }; +static const int en7581_i2c1_pins[] = { 14, 15 }; +static const int en7581_jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; +static const int en7581_jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; +static const int en7581_i2s_pins[] = { 26, 27, 28, 29 }; +static const int en7581_pcm1_pins[] = { 22, 23, 24, 25 }; +static const int en7581_pcm2_pins[] = { 18, 19, 20, 21 }; +static const int en7581_spi_quad_pins[] = { 32, 33 }; +static const int en7581_spi_pins[] = { 4, 5, 6, 7 }; +static const int en7581_spi_cs1_pins[] = { 34 }; +static const int en7581_pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; +static const int en7581_pcm_spi_int_pins[] = { 14 }; +static const int en7581_pcm_spi_rst_pins[] = { 15 }; +static const int en7581_pcm_spi_cs1_pins[] = { 43 }; +static const int en7581_pcm_spi_cs2_pins[] = { 40 }; +static const int en7581_pcm_spi_cs2_p128_pins[] = { 40 }; +static const int en7581_pcm_spi_cs2_p156_pins[] = { 40 }; +static const int en7581_pcm_spi_cs3_pins[] = { 41 }; +static const int en7581_pcm_spi_cs4_pins[] = { 42 }; +static const int en7581_emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; +static const int en7581_pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; +static const int en7581_gpio0_pins[] = { 13 }; +static const int en7581_gpio1_pins[] = { 14 }; +static const int en7581_gpio2_pins[] = { 15 }; +static const int en7581_gpio3_pins[] = { 16 }; +static const int en7581_gpio4_pins[] = { 17 }; +static const int en7581_gpio5_pins[] = { 18 }; +static const int en7581_gpio6_pins[] = { 19 }; +static const int en7581_gpio7_pins[] = { 20 }; +static const int en7581_gpio8_pins[] = { 21 }; +static const int en7581_gpio9_pins[] = { 22 }; +static const int en7581_gpio10_pins[] = { 23 }; +static const int en7581_gpio11_pins[] = { 24 }; +static const int en7581_gpio12_pins[] = { 25 }; +static const int en7581_gpio13_pins[] = { 26 }; +static const int en7581_gpio14_pins[] = { 27 }; +static const int en7581_gpio15_pins[] = { 28 }; +static const int en7581_gpio16_pins[] = { 29 }; +static const int en7581_gpio17_pins[] = { 30 }; +static const int en7581_gpio18_pins[] = { 31 }; +static const int en7581_gpio19_pins[] = { 32 }; +static const int en7581_gpio20_pins[] = { 33 }; +static const int en7581_gpio21_pins[] = { 34 }; +static const int en7581_gpio22_pins[] = { 35 }; +static const int en7581_gpio23_pins[] = { 36 }; +static const int en7581_gpio24_pins[] = { 37 }; +static const int en7581_gpio25_pins[] = { 38 }; +static const int en7581_gpio26_pins[] = { 39 }; +static const int en7581_gpio27_pins[] = { 40 }; +static const int en7581_gpio28_pins[] = { 41 }; +static const int en7581_gpio29_pins[] = { 42 }; +static const int en7581_gpio30_pins[] = { 43 }; +static const int en7581_gpio31_pins[] = { 44 }; +static const int en7581_gpio33_pins[] = { 46 }; +static const int en7581_gpio34_pins[] = { 47 }; +static const int en7581_gpio35_pins[] = { 48 }; +static const int en7581_gpio36_pins[] = { 49 }; +static const int en7581_gpio37_pins[] = { 50 }; +static const int en7581_gpio38_pins[] = { 51 }; +static const int en7581_gpio39_pins[] = { 52 }; +static const int en7581_gpio40_pins[] = { 53 }; +static const int en7581_gpio41_pins[] = { 54 }; +static const int en7581_gpio42_pins[] = { 55 }; +static const int en7581_gpio43_pins[] = { 56 }; +static const int en7581_gpio44_pins[] = { 57 }; +static const int en7581_gpio45_pins[] = { 58 }; +static const int en7581_gpio46_pins[] = { 59 }; +static const int en7581_pcie_reset0_pins[] = { 61 }; +static const int en7581_pcie_reset1_pins[] = { 62 }; +static const int en7581_pcie_reset2_pins[] = { 63 }; + +static const struct pingroup en7581_pinctrl_groups[] = { + PINCTRL_PIN_GROUP("pon", en7581_pon), + PINCTRL_PIN_GROUP("pon_tod_1pps", en7581_pon_tod_1pps), + PINCTRL_PIN_GROUP("gsw_tod_1pps", en7581_gsw_tod_1pps), + PINCTRL_PIN_GROUP("sipo", en7581_sipo), + PINCTRL_PIN_GROUP("sipo_rclk", en7581_sipo_rclk), + PINCTRL_PIN_GROUP("mdio", en7581_mdio), + PINCTRL_PIN_GROUP("uart2", en7581_uart2), + PINCTRL_PIN_GROUP("uart2_cts_rts", en7581_uart2_cts_rts), + PINCTRL_PIN_GROUP("hsuart", en7581_hsuart), + PINCTRL_PIN_GROUP("hsuart_cts_rts", en7581_hsuart_cts_rts), + PINCTRL_PIN_GROUP("uart4", en7581_uart4), + PINCTRL_PIN_GROUP("uart5", en7581_uart5), + PINCTRL_PIN_GROUP("i2c0", en7581_i2c0), + PINCTRL_PIN_GROUP("i2c1", en7581_i2c1), + PINCTRL_PIN_GROUP("jtag_udi", en7581_jtag_udi), + PINCTRL_PIN_GROUP("jtag_dfd", en7581_jtag_dfd), + PINCTRL_PIN_GROUP("i2s", en7581_i2s), + PINCTRL_PIN_GROUP("pcm1", en7581_pcm1), + PINCTRL_PIN_GROUP("pcm2", en7581_pcm2), + PINCTRL_PIN_GROUP("spi", en7581_spi), + PINCTRL_PIN_GROUP("spi_quad", en7581_spi_quad), + PINCTRL_PIN_GROUP("spi_cs1", en7581_spi_cs1), + PINCTRL_PIN_GROUP("pcm_spi", en7581_pcm_spi), + PINCTRL_PIN_GROUP("pcm_spi_int", en7581_pcm_spi_int), + PINCTRL_PIN_GROUP("pcm_spi_rst", en7581_pcm_spi_rst), + PINCTRL_PIN_GROUP("pcm_spi_cs1", en7581_pcm_spi_cs1), + PINCTRL_PIN_GROUP("pcm_spi_cs2_p128", en7581_pcm_spi_cs2_p128), + PINCTRL_PIN_GROUP("pcm_spi_cs2_p156", en7581_pcm_spi_cs2_p156), + PINCTRL_PIN_GROUP("pcm_spi_cs2", en7581_pcm_spi_cs2), + PINCTRL_PIN_GROUP("pcm_spi_cs3", en7581_pcm_spi_cs3), + PINCTRL_PIN_GROUP("pcm_spi_cs4", en7581_pcm_spi_cs4), + PINCTRL_PIN_GROUP("emmc", en7581_emmc), + PINCTRL_PIN_GROUP("pnand", en7581_pnand), + PINCTRL_PIN_GROUP("gpio0", en7581_gpio0), + PINCTRL_PIN_GROUP("gpio1", en7581_gpio1), + PINCTRL_PIN_GROUP("gpio2", en7581_gpio2), + PINCTRL_PIN_GROUP("gpio3", en7581_gpio3), + PINCTRL_PIN_GROUP("gpio4", en7581_gpio4), + PINCTRL_PIN_GROUP("gpio5", en7581_gpio5), + PINCTRL_PIN_GROUP("gpio6", en7581_gpio6), + PINCTRL_PIN_GROUP("gpio7", en7581_gpio7), + PINCTRL_PIN_GROUP("gpio8", en7581_gpio8), + PINCTRL_PIN_GROUP("gpio9", en7581_gpio9), + PINCTRL_PIN_GROUP("gpio10", en7581_gpio10), + PINCTRL_PIN_GROUP("gpio11", en7581_gpio11), + PINCTRL_PIN_GROUP("gpio12", en7581_gpio12), + PINCTRL_PIN_GROUP("gpio13", en7581_gpio13), + PINCTRL_PIN_GROUP("gpio14", en7581_gpio14), + PINCTRL_PIN_GROUP("gpio15", en7581_gpio15), + PINCTRL_PIN_GROUP("gpio16", en7581_gpio16), + PINCTRL_PIN_GROUP("gpio17", en7581_gpio17), + PINCTRL_PIN_GROUP("gpio18", en7581_gpio18), + PINCTRL_PIN_GROUP("gpio19", en7581_gpio19), + PINCTRL_PIN_GROUP("gpio20", en7581_gpio20), + PINCTRL_PIN_GROUP("gpio21", en7581_gpio21), + PINCTRL_PIN_GROUP("gpio22", en7581_gpio22), + PINCTRL_PIN_GROUP("gpio23", en7581_gpio23), + PINCTRL_PIN_GROUP("gpio24", en7581_gpio24), + PINCTRL_PIN_GROUP("gpio25", en7581_gpio25), + PINCTRL_PIN_GROUP("gpio26", en7581_gpio26), + PINCTRL_PIN_GROUP("gpio27", en7581_gpio27), + PINCTRL_PIN_GROUP("gpio28", en7581_gpio28), + PINCTRL_PIN_GROUP("gpio29", en7581_gpio29), + PINCTRL_PIN_GROUP("gpio30", en7581_gpio30), + PINCTRL_PIN_GROUP("gpio31", en7581_gpio31), + PINCTRL_PIN_GROUP("gpio33", en7581_gpio33), + PINCTRL_PIN_GROUP("gpio34", en7581_gpio34), + PINCTRL_PIN_GROUP("gpio35", en7581_gpio35), + PINCTRL_PIN_GROUP("gpio36", en7581_gpio36), + PINCTRL_PIN_GROUP("gpio37", en7581_gpio37), + PINCTRL_PIN_GROUP("gpio38", en7581_gpio38), + PINCTRL_PIN_GROUP("gpio39", en7581_gpio39), + PINCTRL_PIN_GROUP("gpio40", en7581_gpio40), + PINCTRL_PIN_GROUP("gpio41", en7581_gpio41), + PINCTRL_PIN_GROUP("gpio42", en7581_gpio42), + PINCTRL_PIN_GROUP("gpio43", en7581_gpio43), + PINCTRL_PIN_GROUP("gpio44", en7581_gpio44), + PINCTRL_PIN_GROUP("gpio45", en7581_gpio45), + PINCTRL_PIN_GROUP("gpio46", en7581_gpio46), + PINCTRL_PIN_GROUP("pcie_reset0", en7581_pcie_reset0), + PINCTRL_PIN_GROUP("pcie_reset1", en7581_pcie_reset1), + PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2), }; static const char *const pon_groups[] = { "pon" }; @@ -1955,33 +1985,33 @@ static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { }, }; -static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = { - PINCTRL_FUNC_DESC(pon), - PINCTRL_FUNC_DESC(tod_1pps), - PINCTRL_FUNC_DESC(sipo), - PINCTRL_FUNC_DESC(mdio), - PINCTRL_FUNC_DESC(uart), - PINCTRL_FUNC_DESC(i2c), - PINCTRL_FUNC_DESC(jtag), - PINCTRL_FUNC_DESC(pcm), - PINCTRL_FUNC_DESC(spi), - PINCTRL_FUNC_DESC(pcm_spi), - PINCTRL_FUNC_DESC(i2s), - PINCTRL_FUNC_DESC(emmc), - PINCTRL_FUNC_DESC(pnand), - PINCTRL_FUNC_DESC(pcie_reset), - PINCTRL_FUNC_DESC(pwm), - PINCTRL_FUNC_DESC(phy1_led0), - PINCTRL_FUNC_DESC(phy2_led0), - PINCTRL_FUNC_DESC(phy3_led0), - PINCTRL_FUNC_DESC(phy4_led0), - PINCTRL_FUNC_DESC(phy1_led1), - PINCTRL_FUNC_DESC(phy2_led1), - PINCTRL_FUNC_DESC(phy3_led1), - PINCTRL_FUNC_DESC(phy4_led1), +static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { + PINCTRL_FUNC_DESC("pon", pon), + PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), + PINCTRL_FUNC_DESC("sipo", sipo), + PINCTRL_FUNC_DESC("mdio", mdio), + PINCTRL_FUNC_DESC("uart", uart), + PINCTRL_FUNC_DESC("i2c", i2c), + PINCTRL_FUNC_DESC("jtag", jtag), + PINCTRL_FUNC_DESC("pcm", pcm), + PINCTRL_FUNC_DESC("spi", spi), + PINCTRL_FUNC_DESC("pcm_spi", pcm_spi), + PINCTRL_FUNC_DESC("i2s", i2s), + PINCTRL_FUNC_DESC("emmc", emmc), + PINCTRL_FUNC_DESC("pnand", pnand), + PINCTRL_FUNC_DESC("pcie_reset", pcie_reset), + PINCTRL_FUNC_DESC("pwm", pwm), + PINCTRL_FUNC_DESC("phy1_led0", phy1_led0), + PINCTRL_FUNC_DESC("phy2_led0", phy2_led0), + PINCTRL_FUNC_DESC("phy3_led0", phy3_led0), + PINCTRL_FUNC_DESC("phy4_led0", phy4_led0), + PINCTRL_FUNC_DESC("phy1_led1", phy1_led1), + PINCTRL_FUNC_DESC("phy2_led1", phy2_led1), + PINCTRL_FUNC_DESC("phy3_led1", phy3_led1), + PINCTRL_FUNC_DESC("phy4_led1", phy4_led1), }; -static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = { +static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), @@ -2042,7 +2072,7 @@ static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), }; -static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = { +static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), @@ -2103,7 +2133,7 @@ static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), }; -static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = { +static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), @@ -2164,7 +2194,7 @@ static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), }; -static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = { +static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), @@ -2225,7 +2255,7 @@ static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), }; -static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = { +static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = { PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), @@ -2546,12 +2576,17 @@ airoha_pinctrl_get_conf_reg(const struct airoha_pinctrl_conf *conf, } static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl, - const struct airoha_pinctrl_conf *conf, - int conf_size, int pin, u32 *val) + enum airoha_pinctrl_confs_type conf_type, + int pin, u32 *val) { + const struct airoha_pinctrl_confs_info *confs_info; const struct airoha_pinctrl_reg *reg; - reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); + confs_info = &pinctrl->confs_info[conf_type]; + + reg = airoha_pinctrl_get_conf_reg(confs_info->confs, + confs_info->num_confs, + pin); if (!reg) return -EINVAL; @@ -2564,12 +2599,17 @@ static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl, } static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, - const struct airoha_pinctrl_conf *conf, - int conf_size, int pin, u32 val) + enum airoha_pinctrl_confs_type conf_type, + int pin, u32 val) { + const struct airoha_pinctrl_confs_info *confs_info; const struct airoha_pinctrl_reg *reg = NULL; - reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); + confs_info = &pinctrl->confs_info[conf_type]; + + reg = airoha_pinctrl_get_conf_reg(confs_info->confs, + confs_info->num_confs, + pin); if (!reg) return -EINVAL; @@ -2582,44 +2622,34 @@ static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, } #define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \ - airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf, \ - ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ + airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP, \ (pin), (val)) #define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val) \ - airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ - ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ + airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN, \ (pin), (val)) #define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val) \ - airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ - ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ + airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2, \ (pin), (val)) #define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val) \ - airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ - ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ + airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4, \ (pin), (val)) #define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val) \ - airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ - ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ + airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD, \ (pin), (val)) #define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val) \ - airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf, \ - ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ + airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP, \ (pin), (val)) #define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val) \ - airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ - ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ + airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN, \ (pin), (val)) #define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val) \ - airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ - ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ + airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2, \ (pin), (val)) #define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val) \ - airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ - ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ + airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4, \ (pin), (val)) #define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val) \ - airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ - ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ + airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD, \ (pin), (val)) static int airoha_pinconf_get_direction(struct pinctrl_dev *pctrl_dev, u32 p) @@ -2796,12 +2826,13 @@ static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, unsigned int group, unsigned long *config) { + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); u32 cur_config = 0; int i; - for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { + for (i = 0; i < pinctrl->grps[group].npins; i++) { if (airoha_pinconf_get(pctrl_dev, - airoha_pinctrl_groups[group].pins[i], + pinctrl->grps[group].pins[i], config)) return -ENOTSUPP; @@ -2818,13 +2849,14 @@ static int airoha_pinconf_group_set(struct pinctrl_dev *pctrl_dev, unsigned int group, unsigned long *configs, unsigned int num_configs) { + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); int i; - for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { + for (i = 0; i < pinctrl->grps[group].npins; i++) { int err; err = airoha_pinconf_set(pctrl_dev, - airoha_pinctrl_groups[group].pins[i], + pinctrl->grps[group].pins[i], configs, num_configs); if (err) return err; @@ -2850,23 +2882,16 @@ static const struct pinctrl_ops airoha_pctlops = { .dt_free_map = pinconf_generic_dt_free_map, }; -static const struct pinctrl_desc airoha_pinctrl_desc = { - .name = KBUILD_MODNAME, - .owner = THIS_MODULE, - .pctlops = &airoha_pctlops, - .pmxops = &airoha_pmxops, - .confops = &airoha_confops, - .pins = airoha_pinctrl_pins, - .npins = ARRAY_SIZE(airoha_pinctrl_pins), -}; - static int airoha_pinctrl_probe(struct platform_device *pdev) { + const struct airoha_pinctrl_match_data *data; struct device *dev = &pdev->dev; struct airoha_pinctrl *pinctrl; struct regmap *map; int err, i; + data = device_get_match_data(dev); + pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL); if (!pinctrl) return -ENOMEM; @@ -2881,14 +2906,23 @@ static int airoha_pinctrl_probe(struct platform_device *pdev) pinctrl->chip_scu = map; - err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc, + /* Init pinctrl desc struct */ + pinctrl->desc.name = KBUILD_MODNAME; + pinctrl->desc.owner = THIS_MODULE, + pinctrl->desc.pctlops = &airoha_pctlops, + pinctrl->desc.pmxops = &airoha_pmxops, + pinctrl->desc.confops = &airoha_confops, + pinctrl->desc.pins = data->pins, + pinctrl->desc.npins = data->num_pins, + + err = devm_pinctrl_register_and_init(dev, &pinctrl->desc, pinctrl, &pinctrl->ctrl); if (err) return err; /* build pin groups */ - for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) { - const struct pingroup *grp = &airoha_pinctrl_groups[i]; + for (i = 0; i < data->num_grps; i++) { + const struct pingroup *grp = &data->grps[i]; err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name, grp->pins, grp->npins, @@ -2901,10 +2935,10 @@ static int airoha_pinctrl_probe(struct platform_device *pdev) } /* build functions */ - for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) { + for (i = 0; i < data->num_funcs; i++) { const struct airoha_pinctrl_func *func; - func = &airoha_pinctrl_funcs[i]; + func = &data->funcs[i]; err = pinmux_generic_add_pinfunction(pinctrl->ctrl, &func->desc, (void *)func); @@ -2915,6 +2949,10 @@ static int airoha_pinctrl_probe(struct platform_device *pdev) } } + pinctrl->grps = data->grps; + pinctrl->funcs = data->funcs; + pinctrl->confs_info = data->confs_info; + err = pinctrl_enable(pinctrl->ctrl); if (err) return err; @@ -2923,8 +2961,39 @@ static int airoha_pinctrl_probe(struct platform_device *pdev) return airoha_pinctrl_add_gpiochip(pinctrl, pdev); } +static const struct airoha_pinctrl_match_data en7581_pinctrl_match_data = { + .pins = en7581_pinctrl_pins, + .num_pins = ARRAY_SIZE(en7581_pinctrl_pins), + .grps = en7581_pinctrl_groups, + .num_grps = ARRAY_SIZE(en7581_pinctrl_groups), + .funcs = en7581_pinctrl_funcs, + .num_funcs = ARRAY_SIZE(en7581_pinctrl_funcs), + .confs_info = { + [AIROHA_PINCTRL_CONFS_PULLUP] = { + .confs = en7581_pinctrl_pullup_conf, + .num_confs = ARRAY_SIZE(en7581_pinctrl_pullup_conf), + }, + [AIROHA_PINCTRL_CONFS_PULLDOWN] = { + .confs = en7581_pinctrl_pulldown_conf, + .num_confs = ARRAY_SIZE(en7581_pinctrl_pulldown_conf), + }, + [AIROHA_PINCTRL_CONFS_DRIVE_E2] = { + .confs = en7581_pinctrl_drive_e2_conf, + .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e2_conf), + }, + [AIROHA_PINCTRL_CONFS_DRIVE_E4] = { + .confs = en7581_pinctrl_drive_e4_conf, + .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e4_conf), + }, + [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = { + .confs = en7581_pinctrl_pcie_rst_od_conf, + .num_confs = ARRAY_SIZE(en7581_pinctrl_pcie_rst_od_conf), + }, + }, +}; + static const struct of_device_id airoha_pinctrl_of_match[] = { - { .compatible = "airoha,en7581-pinctrl" }, + { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match); From 579839c9548cf2a85e873ad787bc2fa6610bf8ab Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 7 Nov 2025 00:57:05 +0100 Subject: [PATCH 256/684] pinctrl: airoha: convert PHY LED GPIO to macro PHY LED GPIO pinctrl struct definition is very similar across the different 4 PHY and 2 LED and it can be generelized to a macro. To reduce code size, convert them to a common macro. Signed-off-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 588 ++++------------------ 1 file changed, 100 insertions(+), 488 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index 32e5c1b32d5071..cb0edc2a66a1e6 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -1473,516 +1473,128 @@ static const struct airoha_pinctrl_func_group pwm_func_group[] = { }, }; +#define AIROHA_PINCTRL_PHY_LED0(gpio, mux_val, map_mask, map_val) \ + { \ + .name = (gpio), \ + .regmap[0] = { \ + AIROHA_FUNC_MUX, \ + REG_GPIO_2ND_I2C_MODE, \ + (mux_val), \ + (mux_val), \ + }, \ + .regmap[1] = { \ + AIROHA_FUNC_MUX, \ + REG_LAN_LED0_MAPPING, \ + (map_mask), \ + (map_val), \ + }, \ + .regmap_size = 2, \ + } + +#define AIROHA_PINCTRL_PHY_LED1(gpio, mux_val, map_mask, map_val) \ + { \ + .name = (gpio), \ + .regmap[0] = { \ + AIROHA_FUNC_MUX, \ + REG_GPIO_2ND_I2C_MODE, \ + (mux_val), \ + (mux_val), \ + }, \ + .regmap[1] = { \ + AIROHA_FUNC_MUX, \ + REG_LAN_LED1_MAPPING, \ + (map_mask), \ + (map_val), \ + }, \ + .regmap_size = 2, \ + } + static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = { - { - .name = "gpio33", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED0_MODE_MASK, - GPIO_LAN0_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio34", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED0_MODE_MASK, - GPIO_LAN1_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio35", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED0_MODE_MASK, - GPIO_LAN2_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio42", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED0_MODE_MASK, - GPIO_LAN3_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), }; static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = { - { - .name = "gpio33", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED0_MODE_MASK, - GPIO_LAN0_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio34", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED0_MODE_MASK, - GPIO_LAN1_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio35", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED0_MODE_MASK, - GPIO_LAN2_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio42", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED0_MODE_MASK, - GPIO_LAN3_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), }; static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = { - { - .name = "gpio33", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED0_MODE_MASK, - GPIO_LAN0_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio34", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED0_MODE_MASK, - GPIO_LAN1_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio35", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED0_MODE_MASK, - GPIO_LAN2_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio42", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED0_MODE_MASK, - GPIO_LAN3_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), }; static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = { - { - .name = "gpio33", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED0_MODE_MASK, - GPIO_LAN0_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio34", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED0_MODE_MASK, - GPIO_LAN1_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio35", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED0_MODE_MASK, - GPIO_LAN2_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio42", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED0_MODE_MASK, - GPIO_LAN3_LED0_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED0_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)), }; static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = { - { - .name = "gpio43", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED1_MODE_MASK, - GPIO_LAN0_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio44", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED1_MODE_MASK, - GPIO_LAN1_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio45", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED1_MODE_MASK, - GPIO_LAN2_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, { - .name = "gpio46", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED1_MODE_MASK, - GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(0) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), }; static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = { - { - .name = "gpio43", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED1_MODE_MASK, - GPIO_LAN0_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio44", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED1_MODE_MASK, - GPIO_LAN1_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio45", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED1_MODE_MASK, - GPIO_LAN2_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, { - .name = "gpio46", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED1_MODE_MASK, - GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(1) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), }; static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = { - { - .name = "gpio43", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED1_MODE_MASK, - GPIO_LAN0_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio44", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED1_MODE_MASK, - GPIO_LAN1_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio45", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED1_MODE_MASK, - GPIO_LAN2_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, { - .name = "gpio46", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED1_MODE_MASK, - GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(2) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), }; static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { - { - .name = "gpio43", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN0_LED1_MODE_MASK, - GPIO_LAN0_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN0_LED_MAPPING_MASK, - LAN0_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio44", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN1_LED1_MODE_MASK, - GPIO_LAN1_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN1_LED_MAPPING_MASK, - LAN1_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio45", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN2_LED1_MODE_MASK, - GPIO_LAN2_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN2_LED_MAPPING_MASK, - LAN2_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, { - .name = "gpio46", - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_LAN3_LED1_MODE_MASK, - GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, - REG_LAN_LED1_MAPPING, - LAN3_LED_MAPPING_MASK, - LAN3_PHY_LED_MAP(3) - }, - .regmap_size = 2, - }, + AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), }; static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { From 1552ad5d649cff9d170e5bc1d13ab1487333b4b7 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 7 Nov 2025 00:57:06 +0100 Subject: [PATCH 257/684] pinctrl: airoha: convert PWM GPIO to macro The PWM GPIO struct definition follow the same pattern for every GPIO pin hence it can be converted to a macro. Create 2 macro one for normal mux and one for ext mux and convert all the entry to these new macro to reduce code size. Signed-off-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 465 ++++------------------ 1 file changed, 68 insertions(+), 397 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index cb0edc2a66a1e6..f3cf48bdd1f83d 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -1073,404 +1073,75 @@ static const struct airoha_pinctrl_func_group pcie_reset_func_group[] = { }; /* PWM */ +#define AIROHA_PINCTRL_PWM(gpio, mux_val) \ + { \ + .name = (gpio), \ + .regmap[0] = { \ + AIROHA_FUNC_PWM_MUX, \ + REG_GPIO_FLASH_MODE_CFG, \ + (mux_val), \ + (mux_val) \ + }, \ + .regmap_size = 1, \ + } \ + +#define AIROHA_PINCTRL_PWM_EXT(gpio, mux_val) \ + { \ + .name = (gpio), \ + .regmap[0] = { \ + AIROHA_FUNC_PWM_EXT_MUX, \ + REG_GPIO_FLASH_MODE_CFG_EXT, \ + (mux_val), \ + (mux_val) \ + }, \ + .regmap_size = 1, \ + } \ + static const struct airoha_pinctrl_func_group pwm_func_group[] = { - { - .name = "gpio0", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO0_FLASH_MODE_CFG, - GPIO0_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio1", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO1_FLASH_MODE_CFG, - GPIO1_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio2", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO2_FLASH_MODE_CFG, - GPIO2_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio3", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO3_FLASH_MODE_CFG, - GPIO3_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio4", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO4_FLASH_MODE_CFG, - GPIO4_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio5", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO5_FLASH_MODE_CFG, - GPIO5_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio6", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO6_FLASH_MODE_CFG, - GPIO6_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio7", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO7_FLASH_MODE_CFG, - GPIO7_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio8", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO8_FLASH_MODE_CFG, - GPIO8_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio9", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO9_FLASH_MODE_CFG, - GPIO9_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio10", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO10_FLASH_MODE_CFG, - GPIO10_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio11", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO11_FLASH_MODE_CFG, - GPIO11_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio12", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO12_FLASH_MODE_CFG, - GPIO12_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio13", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO13_FLASH_MODE_CFG, - GPIO13_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio14", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO14_FLASH_MODE_CFG, - GPIO14_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio15", - .regmap[0] = { - AIROHA_FUNC_PWM_MUX, - REG_GPIO_FLASH_MODE_CFG, - GPIO15_FLASH_MODE_CFG, - GPIO15_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio16", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO16_FLASH_MODE_CFG, - GPIO16_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio17", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO17_FLASH_MODE_CFG, - GPIO17_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio18", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO18_FLASH_MODE_CFG, - GPIO18_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio19", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO19_FLASH_MODE_CFG, - GPIO19_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio20", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO20_FLASH_MODE_CFG, - GPIO20_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio21", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO21_FLASH_MODE_CFG, - GPIO21_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio22", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO22_FLASH_MODE_CFG, - GPIO22_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio23", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO23_FLASH_MODE_CFG, - GPIO23_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio24", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO24_FLASH_MODE_CFG, - GPIO24_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio25", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO25_FLASH_MODE_CFG, - GPIO25_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio26", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO26_FLASH_MODE_CFG, - GPIO26_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio27", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO27_FLASH_MODE_CFG, - GPIO27_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio28", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO28_FLASH_MODE_CFG, - GPIO28_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio29", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO29_FLASH_MODE_CFG, - GPIO29_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio30", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO30_FLASH_MODE_CFG, - GPIO30_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio31", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO31_FLASH_MODE_CFG, - GPIO31_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio36", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO36_FLASH_MODE_CFG, - GPIO36_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio37", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO37_FLASH_MODE_CFG, - GPIO37_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio38", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO38_FLASH_MODE_CFG, - GPIO38_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio39", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO39_FLASH_MODE_CFG, - GPIO39_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio40", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO40_FLASH_MODE_CFG, - GPIO40_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio41", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO41_FLASH_MODE_CFG, - GPIO41_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio42", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO42_FLASH_MODE_CFG, - GPIO42_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio43", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO43_FLASH_MODE_CFG, - GPIO43_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio44", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO44_FLASH_MODE_CFG, - GPIO44_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio45", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO45_FLASH_MODE_CFG, - GPIO45_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio46", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO46_FLASH_MODE_CFG, - GPIO46_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, { - .name = "gpio47", - .regmap[0] = { - AIROHA_FUNC_PWM_EXT_MUX, - REG_GPIO_FLASH_MODE_CFG_EXT, - GPIO47_FLASH_MODE_CFG, - GPIO47_FLASH_MODE_CFG - }, - .regmap_size = 1, - }, + AIROHA_PINCTRL_PWM("gpio0", GPIO0_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio1", GPIO1_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio2", GPIO2_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio3", GPIO3_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio4", GPIO4_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio5", GPIO5_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio6", GPIO6_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio7", GPIO7_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio8", GPIO8_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio9", GPIO9_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio10", GPIO10_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio11", GPIO11_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio12", GPIO12_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio13", GPIO13_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio14", GPIO14_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM("gpio15", GPIO15_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio16", GPIO16_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio17", GPIO17_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio18", GPIO18_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio19", GPIO19_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio20", GPIO20_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio21", GPIO21_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio22", GPIO22_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio23", GPIO23_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio24", GPIO24_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio25", GPIO25_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio26", GPIO26_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio27", GPIO27_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio28", GPIO28_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio29", GPIO29_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio30", GPIO30_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio31", GPIO31_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio36", GPIO36_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio37", GPIO37_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio38", GPIO38_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio39", GPIO39_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio40", GPIO40_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio41", GPIO41_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio42", GPIO42_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio43", GPIO43_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio44", GPIO44_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio45", GPIO45_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio46", GPIO46_FLASH_MODE_CFG), + AIROHA_PINCTRL_PWM_EXT("gpio47", GPIO47_FLASH_MODE_CFG), }; #define AIROHA_PINCTRL_PHY_LED0(gpio, mux_val, map_mask, map_val) \ From e6e47d31d3f80d1e9eee863f1f24d8597f3c9deb Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 7 Nov 2025 00:57:07 +0100 Subject: [PATCH 258/684] dt-bindings: pinctrl: airoha: Document AN7583 Pin Controller Document Airoha AN7583 Pin Controller based on Airoha EN7581 with some minor difference on some function group (PCM and LED gpio). To not bloat the EN7581 schema with massive if condition, use a dedicated YAML schema for Airoha AN7583. Signed-off-by: Christian Marangi Reviewed-by: Conor Dooley Signed-off-by: Linus Walleij --- .../pinctrl/airoha,an7583-pinctrl.yaml | 402 ++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/airoha,an7583-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,an7583-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,an7583-pinctrl.yaml new file mode 100644 index 00000000000000..79910214d9b5c8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/airoha,an7583-pinctrl.yaml @@ -0,0 +1,402 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/airoha,an7583-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha AN7583 Pin Controller + +maintainers: + - Lorenzo Bianconi + +description: + The Airoha's AN7583 Pin controller is used to control SoC pins. + +properties: + compatible: + const: airoha,an7583-pinctrl + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + gpio-ranges: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +allOf: + - $ref: pinctrl.yaml# + +required: + - compatible + - interrupts + - gpio-controller + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '-pins$': + type: object + + patternProperties: + '^mux(-|$)': + type: object + + description: + pinmux configuration nodes. + + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [pon, tod_1pps, sipo, mdio, uart, i2c, jtag, pcm, spi, + pcm_spi, i2s, emmc, pnand, pcie_reset, pwm, phy1_led0, + phy2_led0, phy3_led0, phy4_led0, phy1_led1, phy2_led1, + phy3_led1, phy4_led1] + + groups: + description: + An array of strings. Each string contains the name of a group. + + required: + - function + - groups + + allOf: + - if: + properties: + function: + const: pon + then: + properties: + groups: + enum: [pon] + - if: + properties: + function: + const: tod_1pps + then: + properties: + groups: + enum: [pon_tod_1pps, gsw_tod_1pps] + - if: + properties: + function: + const: sipo + then: + properties: + groups: + enum: [sipo, sipo_rclk] + - if: + properties: + function: + const: mdio + then: + properties: + groups: + enum: [mdio] + - if: + properties: + function: + const: uart + then: + properties: + groups: + items: + enum: [uart2, uart2_cts_rts, hsuart, hsuart_cts_rts, + uart4, uart5] + maxItems: 2 + - if: + properties: + function: + const: i2c + then: + properties: + groups: + enum: [i2c1] + - if: + properties: + function: + const: jtag + then: + properties: + groups: + enum: [jtag_udi, jtag_dfd] + - if: + properties: + function: + const: pcm + then: + properties: + groups: + enum: [pcm1, pcm2] + - if: + properties: + function: + const: spi + then: + properties: + groups: + items: + enum: [spi_quad, spi_cs1] + maxItems: 2 + - if: + properties: + function: + const: pcm_spi + then: + properties: + groups: + items: + enum: [pcm_spi, pcm_spi_int, pcm_spi_rst, pcm_spi_cs1, + pcm_spi_cs2, pcm_spi_cs3, pcm_spi_cs4] + maxItems: 7 + - if: + properties: + function: + const: i2c + then: + properties: + groups: + enum: [i2s] + - if: + properties: + function: + const: emmc + then: + properties: + groups: + enum: [emmc] + - if: + properties: + function: + const: pnand + then: + properties: + groups: + enum: [pnand] + - if: + properties: + function: + const: pcie_reset + then: + properties: + groups: + enum: [pcie_reset0, pcie_reset1] + - if: + properties: + function: + const: pwm + then: + properties: + groups: + enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, + gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, + gpio14, gpio15, gpio16, gpio17, gpio18, gpio19, + gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, + gpio26, gpio27, gpio28, gpio29, gpio30, gpio31, + gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, + gpio42, gpio43, gpio44, gpio45, gpio46, gpio47] + - if: + properties: + function: + const: phy1_led0 + then: + properties: + groups: + enum: [gpio1, gpio2, gpio3, gpio4] + - if: + properties: + function: + const: phy2_led0 + then: + properties: + groups: + enum: [gpio1, gpio2, gpio3, gpio4] + - if: + properties: + function: + const: phy3_led0 + then: + properties: + groups: + enum: [gpio1, gpio2, gpio3, gpio4] + - if: + properties: + function: + const: phy4_led0 + then: + properties: + groups: + enum: [gpio1, gpio2, gpio3, gpio4] + - if: + properties: + function: + const: phy1_led1 + then: + properties: + groups: + enum: [gpio8, gpio9, gpio10, gpio11] + - if: + properties: + function: + const: phy2_led1 + then: + properties: + groups: + enum: [gpio8, gpio9, gpio10, gpio11] + - if: + properties: + function: + const: phy3_led1 + then: + properties: + groups: + enum: [gpio8, gpio9, gpio10, gpio11] + - if: + properties: + function: + const: phy4_led1 + then: + properties: + groups: + enum: [gpio8, gpio9, gpio10, gpio11] + + additionalProperties: false + + '^conf(-|$)': + type: object + + description: + pinconf configuration nodes. + + $ref: /schemas/pinctrl/pincfg-node.yaml + + properties: + pins: + description: + An array of strings. Each string contains the name of a pin. + items: + enum: [uart1_txd, uart1_rxd, i2c_scl, i2c_sda, spi_cs0, spi_clk, + spi_mosi, spi_miso, gpio0, gpio1, gpio2, gpio3, gpio4, + gpio5, gpio6, gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, + gpio13, gpio14, gpio15, gpio16, gpio17, gpio18, gpio19, + gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, gpio26, + gpio27, gpio28, gpio29, gpio30, gpio31, gpio32, gpio33, + gpio34, gpio35, gpio36, gpio37, gpio38, gpio39, gpio40, + gpio41, gpio42, gpio43, gpio44, gpio45, gpio46, + pcie_reset0, pcie_reset1, pcie_reset2] + minItems: 1 + maxItems: 58 + + bias-disable: true + + bias-pull-up: true + + bias-pull-down: true + + input-enable: true + + output-enable: true + + output-low: true + + output-high: true + + drive-open-drain: true + + drive-strength: + description: + Selects the drive strength for MIO pins, in mA. + enum: [2, 4, 6, 8] + + required: + - pins + + additionalProperties: false + + additionalProperties: false + +additionalProperties: false + +examples: + - | + #include + + pinctrl { + compatible = "airoha,an7583-pinctrl"; + + interrupt-parent = <&gic>; + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + pcie1-rst-pins { + conf { + pins = "pcie_reset1"; + drive-open-drain = <1>; + }; + }; + + pwm-pins { + mux { + function = "pwm"; + groups = "gpio18"; + }; + }; + + spi-pins { + mux { + function = "spi"; + groups = "spi_quad", "spi_cs1"; + }; + }; + + uart2-pins { + mux { + function = "uart"; + groups = "uart2", "uart2_cts_rts"; + }; + }; + + uar5-pins { + mux { + function = "uart"; + groups = "uart5"; + }; + }; + + mmc-pins { + mux { + function = "emmc"; + groups = "emmc"; + }; + }; + + mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-enable; + }; + }; + }; From 3ffeb17a9a27a668efb6fbd074835e187910a9bb Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 7 Nov 2025 00:57:08 +0100 Subject: [PATCH 259/684] pinctrl: airoha: add support for Airoha AN7583 PINs Add all the required entry to add suppot for Airoha AN7583 PINs. Where possible the same function group are used from Airoha EN7581 to reduce code duplication. Signed-off-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 747 +++++++++++++++++++++- 1 file changed, 740 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index f3cf48bdd1f83d..bfcedc7f920b1e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -70,6 +70,7 @@ #define GPIO_PCM_SPI_CS3_MODE_MASK BIT(20) #define GPIO_PCM_SPI_CS2_MODE_P156_MASK BIT(19) #define GPIO_PCM_SPI_CS2_MODE_P128_MASK BIT(18) +#define AN7583_GPIO_PCM_SPI_CS2_MODE_MASK BIT(18) #define GPIO_PCM_SPI_CS1_MODE_MASK BIT(17) #define GPIO_PCM_SPI_MODE_MASK BIT(16) #define GPIO_PCM2_MODE_MASK BIT(13) @@ -127,6 +128,8 @@ /* CONF */ #define REG_I2C_SDA_E2 0x001c +#define AN7583_I2C1_SCL_E2_MASK BIT(16) +#define AN7583_I2C1_SDA_E2_MASK BIT(15) #define SPI_MISO_E2_MASK BIT(14) #define SPI_MOSI_E2_MASK BIT(13) #define SPI_CLK_E2_MASK BIT(12) @@ -134,12 +137,16 @@ #define PCIE2_RESET_E2_MASK BIT(10) #define PCIE1_RESET_E2_MASK BIT(9) #define PCIE0_RESET_E2_MASK BIT(8) +#define AN7583_MDIO_0_E2_MASK BIT(5) +#define AN7583_MDC_0_E2_MASK BIT(4) #define UART1_RXD_E2_MASK BIT(3) #define UART1_TXD_E2_MASK BIT(2) #define I2C_SCL_E2_MASK BIT(1) #define I2C_SDA_E2_MASK BIT(0) #define REG_I2C_SDA_E4 0x0020 +#define AN7583_I2C1_SCL_E4_MASK BIT(16) +#define AN7583_I2C1_SDA_E4_MASK BIT(15) #define SPI_MISO_E4_MASK BIT(14) #define SPI_MOSI_E4_MASK BIT(13) #define SPI_CLK_E4_MASK BIT(12) @@ -147,6 +154,8 @@ #define PCIE2_RESET_E4_MASK BIT(10) #define PCIE1_RESET_E4_MASK BIT(9) #define PCIE0_RESET_E4_MASK BIT(8) +#define AN7583_MDIO_0_E4_MASK BIT(5) +#define AN7583_MDC_0_E4_MASK BIT(4) #define UART1_RXD_E4_MASK BIT(3) #define UART1_TXD_E4_MASK BIT(2) #define I2C_SCL_E4_MASK BIT(1) @@ -158,6 +167,8 @@ #define REG_GPIO_H_E4 0x0030 #define REG_I2C_SDA_PU 0x0044 +#define AN7583_I2C1_SCL_PU_MASK BIT(16) +#define AN7583_I2C1_SDA_PU_MASK BIT(15) #define SPI_MISO_PU_MASK BIT(14) #define SPI_MOSI_PU_MASK BIT(13) #define SPI_CLK_PU_MASK BIT(12) @@ -165,12 +176,16 @@ #define PCIE2_RESET_PU_MASK BIT(10) #define PCIE1_RESET_PU_MASK BIT(9) #define PCIE0_RESET_PU_MASK BIT(8) +#define AN7583_MDIO_0_PU_MASK BIT(5) +#define AN7583_MDC_0_PU_MASK BIT(4) #define UART1_RXD_PU_MASK BIT(3) #define UART1_TXD_PU_MASK BIT(2) #define I2C_SCL_PU_MASK BIT(1) #define I2C_SDA_PU_MASK BIT(0) #define REG_I2C_SDA_PD 0x0048 +#define AN7583_I2C1_SDA_PD_MASK BIT(16) +#define AN7583_I2C1_SCL_PD_MASK BIT(15) #define SPI_MISO_PD_MASK BIT(14) #define SPI_MOSI_PD_MASK BIT(13) #define SPI_CLK_PD_MASK BIT(12) @@ -178,6 +193,8 @@ #define PCIE2_RESET_PD_MASK BIT(10) #define PCIE1_RESET_PD_MASK BIT(9) #define PCIE0_RESET_PD_MASK BIT(8) +#define AN7583_MDIO_0_PD_MASK BIT(5) +#define AN7583_MDC_0_PD_MASK BIT(4) #define UART1_RXD_PD_MASK BIT(3) #define UART1_TXD_PD_MASK BIT(2) #define I2C_SCL_PD_MASK BIT(1) @@ -625,10 +642,223 @@ static const struct pingroup en7581_pinctrl_groups[] = { PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2), }; +static struct pinctrl_pin_desc an7583_pinctrl_pins[] = { + PINCTRL_PIN(2, "gpio0"), + PINCTRL_PIN(3, "gpio1"), + PINCTRL_PIN(4, "gpio2"), + PINCTRL_PIN(5, "gpio3"), + PINCTRL_PIN(6, "gpio4"), + PINCTRL_PIN(7, "gpio5"), + PINCTRL_PIN(8, "gpio6"), + PINCTRL_PIN(9, "gpio7"), + PINCTRL_PIN(10, "gpio8"), + PINCTRL_PIN(11, "gpio9"), + PINCTRL_PIN(12, "gpio10"), + PINCTRL_PIN(13, "gpio11"), + PINCTRL_PIN(14, "gpio12"), + PINCTRL_PIN(15, "gpio13"), + PINCTRL_PIN(16, "gpio14"), + PINCTRL_PIN(17, "gpio15"), + PINCTRL_PIN(18, "gpio16"), + PINCTRL_PIN(19, "gpio17"), + PINCTRL_PIN(20, "gpio18"), + PINCTRL_PIN(21, "gpio19"), + PINCTRL_PIN(22, "gpio20"), + PINCTRL_PIN(23, "gpio21"), + PINCTRL_PIN(24, "gpio22"), + PINCTRL_PIN(25, "gpio23"), + PINCTRL_PIN(26, "gpio24"), + PINCTRL_PIN(27, "gpio25"), + PINCTRL_PIN(28, "gpio26"), + PINCTRL_PIN(29, "gpio27"), + PINCTRL_PIN(30, "gpio28"), + PINCTRL_PIN(31, "gpio29"), + PINCTRL_PIN(32, "gpio30"), + PINCTRL_PIN(33, "gpio31"), + PINCTRL_PIN(34, "gpio32"), + PINCTRL_PIN(35, "gpio33"), + PINCTRL_PIN(36, "gpio34"), + PINCTRL_PIN(37, "gpio35"), + PINCTRL_PIN(38, "gpio36"), + PINCTRL_PIN(39, "gpio37"), + PINCTRL_PIN(40, "gpio38"), + PINCTRL_PIN(41, "i2c0_scl"), + PINCTRL_PIN(42, "i2c0_sda"), + PINCTRL_PIN(43, "i2c1_scl"), + PINCTRL_PIN(44, "i2c1_sda"), + PINCTRL_PIN(45, "spi_clk"), + PINCTRL_PIN(46, "spi_cs"), + PINCTRL_PIN(47, "spi_mosi"), + PINCTRL_PIN(48, "spi_miso"), + PINCTRL_PIN(49, "uart_txd"), + PINCTRL_PIN(50, "uart_rxd"), + PINCTRL_PIN(51, "pcie_reset0"), + PINCTRL_PIN(52, "pcie_reset1"), + PINCTRL_PIN(53, "mdc_0"), + PINCTRL_PIN(54, "mdio_0"), +}; + +static const int an7583_pon_pins[] = { 15, 16, 17, 18, 19, 20 }; +static const int an7583_pon_tod_1pps_pins[] = { 32 }; +static const int an7583_gsw_tod_1pps_pins[] = { 32 }; +static const int an7583_sipo_pins[] = { 34, 35 }; +static const int an7583_sipo_rclk_pins[] = { 34, 35, 33 }; +static const int an7583_mdio_pins[] = { 43, 44 }; +static const int an7583_uart2_pins[] = { 34, 35 }; +static const int an7583_uart2_cts_rts_pins[] = { 32, 33 }; +static const int an7583_hsuart_pins[] = { 30, 31 }; +static const int an7583_hsuart_cts_rts_pins[] = { 28, 29 }; +static const int an7583_npu_uart_pins[] = { 7, 8 }; +static const int an7583_uart4_pins[] = { 7, 8 }; +static const int an7583_uart5_pins[] = { 23, 24 }; +static const int an7583_i2c0_pins[] = { 41, 42 }; +static const int an7583_i2c1_pins[] = { 43, 44 }; +static const int an7583_jtag_udi_pins[] = { 23, 24, 22, 25, 26 }; +static const int an7583_jtag_dfd_pins[] = { 23, 24, 22, 25, 26 }; +static const int an7583_pcm1_pins[] = { 10, 11, 12, 13, 14 }; +static const int an7583_pcm2_pins[] = { 28, 29, 30, 31, 24 }; +static const int an7583_spi_pins[] = { 28, 29, 30, 31 }; +static const int an7583_spi_quad_pins[] = { 25, 26 }; +static const int an7583_spi_cs1_pins[] = { 27 }; +static const int an7583_pcm_spi_pins[] = { 28, 29, 30, 31, 10, 11, 12, 13 }; +static const int an7583_pcm_spi_rst_pins[] = { 14 }; +static const int an7583_pcm_spi_cs1_pins[] = { 24 }; +static const int an7583_emmc_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 45, 46, 47 }; +static const int an7583_pnand_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 45, 46, 47, 48 }; +static const int an7583_gpio0_pins[] = { 2 }; +static const int an7583_gpio1_pins[] = { 3 }; +static const int an7583_gpio2_pins[] = { 4 }; +static const int an7583_gpio3_pins[] = { 5 }; +static const int an7583_gpio4_pins[] = { 6 }; +static const int an7583_gpio5_pins[] = { 7 }; +static const int an7583_gpio6_pins[] = { 8 }; +static const int an7583_gpio7_pins[] = { 9 }; +static const int an7583_gpio8_pins[] = { 10 }; +static const int an7583_gpio9_pins[] = { 11 }; +static const int an7583_gpio10_pins[] = { 12 }; +static const int an7583_gpio11_pins[] = { 13 }; +static const int an7583_gpio12_pins[] = { 14 }; +static const int an7583_gpio13_pins[] = { 15 }; +static const int an7583_gpio14_pins[] = { 16 }; +static const int an7583_gpio15_pins[] = { 17 }; +static const int an7583_gpio16_pins[] = { 18 }; +static const int an7583_gpio17_pins[] = { 19 }; +static const int an7583_gpio18_pins[] = { 20 }; +static const int an7583_gpio19_pins[] = { 21 }; +static const int an7583_gpio20_pins[] = { 22 }; +static const int an7583_gpio21_pins[] = { 24 }; +static const int an7583_gpio23_pins[] = { 25 }; +static const int an7583_gpio24_pins[] = { 26 }; +static const int an7583_gpio25_pins[] = { 27 }; +static const int an7583_gpio26_pins[] = { 28 }; +static const int an7583_gpio27_pins[] = { 29 }; +static const int an7583_gpio28_pins[] = { 30 }; +static const int an7583_gpio29_pins[] = { 31 }; +static const int an7583_gpio30_pins[] = { 32 }; +static const int an7583_gpio31_pins[] = { 33 }; +static const int an7583_gpio33_pins[] = { 35 }; +static const int an7583_gpio34_pins[] = { 36 }; +static const int an7583_gpio35_pins[] = { 37 }; +static const int an7583_gpio36_pins[] = { 38 }; +static const int an7583_gpio37_pins[] = { 39 }; +static const int an7583_gpio38_pins[] = { 40 }; +static const int an7583_gpio39_pins[] = { 41 }; +static const int an7583_gpio40_pins[] = { 42 }; +static const int an7583_gpio41_pins[] = { 43 }; +static const int an7583_gpio42_pins[] = { 44 }; +static const int an7583_gpio43_pins[] = { 45 }; +static const int an7583_gpio44_pins[] = { 46 }; +static const int an7583_gpio45_pins[] = { 47 }; +static const int an7583_gpio46_pins[] = { 48 }; +static const int an7583_gpio47_pins[] = { 49 }; +static const int an7583_gpio48_pins[] = { 50 }; +static const int an7583_pcie_reset0_pins[] = { 51 }; +static const int an7583_pcie_reset1_pins[] = { 52 }; + +static const struct pingroup an7583_pinctrl_groups[] = { + PINCTRL_PIN_GROUP("pon", an7583_pon), + PINCTRL_PIN_GROUP("pon_tod_1pps", an7583_pon_tod_1pps), + PINCTRL_PIN_GROUP("gsw_tod_1pps", an7583_gsw_tod_1pps), + PINCTRL_PIN_GROUP("sipo", an7583_sipo), + PINCTRL_PIN_GROUP("sipo_rclk", an7583_sipo_rclk), + PINCTRL_PIN_GROUP("mdio", an7583_mdio), + PINCTRL_PIN_GROUP("uart2", an7583_uart2), + PINCTRL_PIN_GROUP("uart2_cts_rts", an7583_uart2_cts_rts), + PINCTRL_PIN_GROUP("hsuart", an7583_hsuart), + PINCTRL_PIN_GROUP("hsuart_cts_rts", an7583_hsuart_cts_rts), + PINCTRL_PIN_GROUP("npu_uart", an7583_npu_uart), + PINCTRL_PIN_GROUP("uart4", an7583_uart4), + PINCTRL_PIN_GROUP("uart5", an7583_uart5), + PINCTRL_PIN_GROUP("i2c0", an7583_i2c0), + PINCTRL_PIN_GROUP("i2c1", an7583_i2c1), + PINCTRL_PIN_GROUP("jtag_udi", an7583_jtag_udi), + PINCTRL_PIN_GROUP("jtag_dfd", an7583_jtag_dfd), + PINCTRL_PIN_GROUP("pcm1", an7583_pcm1), + PINCTRL_PIN_GROUP("pcm2", an7583_pcm2), + PINCTRL_PIN_GROUP("spi", an7583_spi), + PINCTRL_PIN_GROUP("spi_quad", an7583_spi_quad), + PINCTRL_PIN_GROUP("spi_cs1", an7583_spi_cs1), + PINCTRL_PIN_GROUP("pcm_spi", an7583_pcm_spi), + PINCTRL_PIN_GROUP("pcm_spi_rst", an7583_pcm_spi_rst), + PINCTRL_PIN_GROUP("pcm_spi_cs1", an7583_pcm_spi_cs1), + PINCTRL_PIN_GROUP("emmc", an7583_emmc), + PINCTRL_PIN_GROUP("pnand", an7583_pnand), + PINCTRL_PIN_GROUP("gpio0", an7583_gpio0), + PINCTRL_PIN_GROUP("gpio1", an7583_gpio1), + PINCTRL_PIN_GROUP("gpio2", an7583_gpio2), + PINCTRL_PIN_GROUP("gpio3", an7583_gpio3), + PINCTRL_PIN_GROUP("gpio4", an7583_gpio4), + PINCTRL_PIN_GROUP("gpio5", an7583_gpio5), + PINCTRL_PIN_GROUP("gpio6", an7583_gpio6), + PINCTRL_PIN_GROUP("gpio7", an7583_gpio7), + PINCTRL_PIN_GROUP("gpio8", an7583_gpio8), + PINCTRL_PIN_GROUP("gpio9", an7583_gpio9), + PINCTRL_PIN_GROUP("gpio10", an7583_gpio10), + PINCTRL_PIN_GROUP("gpio11", an7583_gpio11), + PINCTRL_PIN_GROUP("gpio12", an7583_gpio12), + PINCTRL_PIN_GROUP("gpio13", an7583_gpio13), + PINCTRL_PIN_GROUP("gpio14", an7583_gpio14), + PINCTRL_PIN_GROUP("gpio15", an7583_gpio15), + PINCTRL_PIN_GROUP("gpio16", an7583_gpio16), + PINCTRL_PIN_GROUP("gpio17", an7583_gpio17), + PINCTRL_PIN_GROUP("gpio18", an7583_gpio18), + PINCTRL_PIN_GROUP("gpio19", an7583_gpio19), + PINCTRL_PIN_GROUP("gpio20", an7583_gpio20), + PINCTRL_PIN_GROUP("gpio21", an7583_gpio21), + PINCTRL_PIN_GROUP("gpio23", an7583_gpio23), + PINCTRL_PIN_GROUP("gpio24", an7583_gpio24), + PINCTRL_PIN_GROUP("gpio25", an7583_gpio25), + PINCTRL_PIN_GROUP("gpio26", an7583_gpio26), + PINCTRL_PIN_GROUP("gpio27", an7583_gpio27), + PINCTRL_PIN_GROUP("gpio28", an7583_gpio28), + PINCTRL_PIN_GROUP("gpio29", an7583_gpio29), + PINCTRL_PIN_GROUP("gpio30", an7583_gpio30), + PINCTRL_PIN_GROUP("gpio31", an7583_gpio31), + PINCTRL_PIN_GROUP("gpio33", an7583_gpio33), + PINCTRL_PIN_GROUP("gpio34", an7583_gpio34), + PINCTRL_PIN_GROUP("gpio35", an7583_gpio35), + PINCTRL_PIN_GROUP("gpio36", an7583_gpio36), + PINCTRL_PIN_GROUP("gpio37", an7583_gpio37), + PINCTRL_PIN_GROUP("gpio38", an7583_gpio38), + PINCTRL_PIN_GROUP("gpio39", an7583_gpio39), + PINCTRL_PIN_GROUP("gpio40", an7583_gpio40), + PINCTRL_PIN_GROUP("gpio41", an7583_gpio41), + PINCTRL_PIN_GROUP("gpio42", an7583_gpio42), + PINCTRL_PIN_GROUP("gpio43", an7583_gpio43), + PINCTRL_PIN_GROUP("gpio44", an7583_gpio44), + PINCTRL_PIN_GROUP("gpio45", an7583_gpio45), + PINCTRL_PIN_GROUP("gpio46", an7583_gpio46), + PINCTRL_PIN_GROUP("gpio47", an7583_gpio47), + PINCTRL_PIN_GROUP("gpio48", an7583_gpio48), + PINCTRL_PIN_GROUP("pcie_reset0", an7583_pcie_reset0), + PINCTRL_PIN_GROUP("pcie_reset1", an7583_pcie_reset1), +}; + static const char *const pon_groups[] = { "pon" }; static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" }; static const char *const sipo_groups[] = { "sipo", "sipo_rclk" }; static const char *const mdio_groups[] = { "mdio" }; +static const char *const an7583_mdio_groups[] = { "mdio" }; static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart", "hsuart_cts_rts", "uart4", "uart5" }; @@ -641,11 +871,16 @@ static const char *const pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int", "pcm_spi_cs2_p156", "pcm_spi_cs2_p128", "pcm_spi_cs3", "pcm_spi_cs4" }; +static const char *const an7583_pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int", + "pcm_spi_rst", "pcm_spi_cs1", + "pcm_spi_cs2", "pcm_spi_cs3", + "pcm_spi_cs4" }; static const char *const i2s_groups[] = { "i2s" }; static const char *const emmc_groups[] = { "emmc" }; static const char *const pnand_groups[] = { "pnand" }; static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1", "pcie_reset2" }; +static const char *const an7583_pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1" }; static const char *const pwm_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", @@ -684,6 +919,22 @@ static const char *const phy3_led1_groups[] = { "gpio43", "gpio44", "gpio45", "gpio46" }; static const char *const phy4_led1_groups[] = { "gpio43", "gpio44", "gpio45", "gpio46" }; +static const char *const an7583_phy1_led0_groups[] = { "gpio1", "gpio2", + "gpio3", "gpio4" }; +static const char *const an7583_phy2_led0_groups[] = { "gpio1", "gpio2", + "gpio3", "gpio4" }; +static const char *const an7583_phy3_led0_groups[] = { "gpio1", "gpio2", + "gpio3", "gpio4" }; +static const char *const an7583_phy4_led0_groups[] = { "gpio1", "gpio2", + "gpio3", "gpio4" }; +static const char *const an7583_phy1_led1_groups[] = { "gpio8", "gpio9", + "gpio10", "gpio11" }; +static const char *const an7583_phy2_led1_groups[] = { "gpio8", "gpio9", + "gpio10", "gpio11" }; +static const char *const an7583_phy3_led1_groups[] = { "gpio8", "gpio9", + "gpio10", "gpio11" }; +static const char *const an7583_phy4_led1_groups[] = { "gpio8", "gpio9", + "gpio10", "gpio11" }; static const struct airoha_pinctrl_func_group pon_func_group[] = { { @@ -761,6 +1012,25 @@ static const struct airoha_pinctrl_func_group mdio_func_group[] = { }, }; +static const struct airoha_pinctrl_func_group an7583_mdio_func_group[] = { + { + .name = "mdio", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_SGMII_MDIO_MODE_MASK, + GPIO_SGMII_MDIO_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE + }, + .regmap_size = 2, + }, +}; + static const struct airoha_pinctrl_func_group uart_func_group[] = { { .name = "uart2", @@ -1002,6 +1272,73 @@ static const struct airoha_pinctrl_func_group pcm_spi_func_group[] = { }, }; +static const struct airoha_pinctrl_func_group an7583_pcm_spi_func_group[] = { + { + .name = "pcm_spi", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_MODE_MASK, + GPIO_PCM_SPI_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_int", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_INT_MODE_MASK, + GPIO_PCM_INT_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_rst", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_RESET_MODE_MASK, + GPIO_PCM_RESET_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS1_MODE_MASK, + GPIO_PCM_SPI_CS1_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs2", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + AN7583_GPIO_PCM_SPI_CS2_MODE_MASK, + AN7583_GPIO_PCM_SPI_CS2_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs3", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS3_MODE_MASK, + GPIO_PCM_SPI_CS3_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs4", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS4_MODE_MASK, + GPIO_PCM_SPI_CS4_MODE_MASK + }, + .regmap_size = 1, + }, +}; + static const struct airoha_pinctrl_func_group i2s_func_group[] = { { .name = "i2s", @@ -1072,6 +1409,28 @@ static const struct airoha_pinctrl_func_group pcie_reset_func_group[] = { }, }; +static const struct airoha_pinctrl_func_group an7583_pcie_reset_func_group[] = { + { + .name = "pcie_reset0", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PCIE_RESET0_MASK, + GPIO_PCIE_RESET0_MASK + }, + .regmap_size = 1, + }, { + .name = "pcie_reset1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PCIE_RESET1_MASK, + GPIO_PCIE_RESET1_MASK + }, + .regmap_size = 1, + }, +}; + /* PWM */ #define AIROHA_PINCTRL_PWM(gpio, mux_val) \ { \ @@ -1268,6 +1627,94 @@ static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), }; +static const struct airoha_pinctrl_func_group an7583_phy1_led0_func_group[] = { + AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy2_led0_func_group[] = { + AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy3_led0_func_group[] = { + AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy4_led0_func_group[] = { + AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)), + AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy1_led1_func_group[] = { + AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), + AIROHA_PINCTRL_PHY_LED1("gpio1", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy2_led1_func_group[] = { + AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), + AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy3_led1_func_group[] = { + AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), +}; + +static const struct airoha_pinctrl_func_group an7583_phy4_led1_func_group[] = { + AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, + LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, + LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, + LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), + AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), +}; + static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { PINCTRL_FUNC_DESC("pon", pon), PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), @@ -1294,6 +1741,31 @@ static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { PINCTRL_FUNC_DESC("phy4_led1", phy4_led1), }; +static const struct airoha_pinctrl_func an7583_pinctrl_funcs[] = { + PINCTRL_FUNC_DESC("pon", pon), + PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), + PINCTRL_FUNC_DESC("sipo", sipo), + PINCTRL_FUNC_DESC("mdio", an7583_mdio), + PINCTRL_FUNC_DESC("uart", uart), + PINCTRL_FUNC_DESC("i2c", i2c), + PINCTRL_FUNC_DESC("jtag", jtag), + PINCTRL_FUNC_DESC("pcm", pcm), + PINCTRL_FUNC_DESC("spi", spi), + PINCTRL_FUNC_DESC("pcm_spi", an7583_pcm_spi), + PINCTRL_FUNC_DESC("emmc", emmc), + PINCTRL_FUNC_DESC("pnand", pnand), + PINCTRL_FUNC_DESC("pcie_reset", an7583_pcie_reset), + PINCTRL_FUNC_DESC("pwm", pwm), + PINCTRL_FUNC_DESC("phy1_led0", an7583_phy1_led0), + PINCTRL_FUNC_DESC("phy2_led0", an7583_phy2_led0), + PINCTRL_FUNC_DESC("phy3_led0", an7583_phy3_led0), + PINCTRL_FUNC_DESC("phy4_led0", an7583_phy4_led0), + PINCTRL_FUNC_DESC("phy1_led1", an7583_phy1_led1), + PINCTRL_FUNC_DESC("phy2_led1", an7583_phy2_led1), + PINCTRL_FUNC_DESC("phy3_led1", an7583_phy3_led1), + PINCTRL_FUNC_DESC("phy4_led1", an7583_phy4_led1), +}; + static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), @@ -1355,6 +1827,62 @@ static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), }; +static const struct airoha_pinctrl_conf an7583_pinctrl_pullup_conf[] = { + PINCTRL_CONF_DESC(2, REG_GPIO_L_PU, BIT(0)), + PINCTRL_CONF_DESC(3, REG_GPIO_L_PU, BIT(1)), + PINCTRL_CONF_DESC(4, REG_GPIO_L_PU, BIT(2)), + PINCTRL_CONF_DESC(5, REG_GPIO_L_PU, BIT(3)), + PINCTRL_CONF_DESC(6, REG_GPIO_L_PU, BIT(4)), + PINCTRL_CONF_DESC(7, REG_GPIO_L_PU, BIT(5)), + PINCTRL_CONF_DESC(8, REG_GPIO_L_PU, BIT(6)), + PINCTRL_CONF_DESC(9, REG_GPIO_L_PU, BIT(7)), + PINCTRL_CONF_DESC(10, REG_GPIO_L_PU, BIT(8)), + PINCTRL_CONF_DESC(11, REG_GPIO_L_PU, BIT(9)), + PINCTRL_CONF_DESC(12, REG_GPIO_L_PU, BIT(10)), + PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(11)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(12)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(13)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(14)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(15)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(16)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(17)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(18)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(18)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(20)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(21)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(22)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(23)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(24)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(25)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(26)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(27)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(28)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(29)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(30)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(31)), + PINCTRL_CONF_DESC(34, REG_GPIO_H_PU, BIT(0)), + PINCTRL_CONF_DESC(35, REG_GPIO_H_PU, BIT(1)), + PINCTRL_CONF_DESC(36, REG_GPIO_H_PU, BIT(2)), + PINCTRL_CONF_DESC(37, REG_GPIO_H_PU, BIT(3)), + PINCTRL_CONF_DESC(38, REG_GPIO_H_PU, BIT(4)), + PINCTRL_CONF_DESC(39, REG_GPIO_H_PU, BIT(5)), + PINCTRL_CONF_DESC(40, REG_GPIO_H_PU, BIT(6)), + PINCTRL_CONF_DESC(41, REG_I2C_SDA_PU, I2C_SCL_PU_MASK), + PINCTRL_CONF_DESC(42, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), + PINCTRL_CONF_DESC(43, REG_I2C_SDA_PU, AN7583_I2C1_SCL_PU_MASK), + PINCTRL_CONF_DESC(44, REG_I2C_SDA_PU, AN7583_I2C1_SDA_PU_MASK), + PINCTRL_CONF_DESC(45, REG_I2C_SDA_PU, SPI_CLK_PU_MASK), + PINCTRL_CONF_DESC(46, REG_I2C_SDA_PU, SPI_CS0_PU_MASK), + PINCTRL_CONF_DESC(47, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK), + PINCTRL_CONF_DESC(48, REG_I2C_SDA_PU, SPI_MISO_PU_MASK), + PINCTRL_CONF_DESC(49, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), + PINCTRL_CONF_DESC(50, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), + PINCTRL_CONF_DESC(51, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK), + PINCTRL_CONF_DESC(52, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK), + PINCTRL_CONF_DESC(53, REG_I2C_SDA_PU, AN7583_MDC_0_PU_MASK), + PINCTRL_CONF_DESC(54, REG_I2C_SDA_PU, AN7583_MDIO_0_PU_MASK), +}; + static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), @@ -1416,6 +1944,62 @@ static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), }; +static const struct airoha_pinctrl_conf an7583_pinctrl_pulldown_conf[] = { + PINCTRL_CONF_DESC(2, REG_GPIO_L_PD, BIT(0)), + PINCTRL_CONF_DESC(3, REG_GPIO_L_PD, BIT(1)), + PINCTRL_CONF_DESC(4, REG_GPIO_L_PD, BIT(2)), + PINCTRL_CONF_DESC(5, REG_GPIO_L_PD, BIT(3)), + PINCTRL_CONF_DESC(6, REG_GPIO_L_PD, BIT(4)), + PINCTRL_CONF_DESC(7, REG_GPIO_L_PD, BIT(5)), + PINCTRL_CONF_DESC(8, REG_GPIO_L_PD, BIT(6)), + PINCTRL_CONF_DESC(9, REG_GPIO_L_PD, BIT(7)), + PINCTRL_CONF_DESC(10, REG_GPIO_L_PD, BIT(8)), + PINCTRL_CONF_DESC(11, REG_GPIO_L_PD, BIT(9)), + PINCTRL_CONF_DESC(12, REG_GPIO_L_PD, BIT(10)), + PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(11)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(12)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(13)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(14)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(15)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(16)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(17)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(18)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(18)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(20)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(21)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(22)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(23)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(24)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(25)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(26)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(27)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(28)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(29)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(30)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(31)), + PINCTRL_CONF_DESC(34, REG_GPIO_H_PD, BIT(0)), + PINCTRL_CONF_DESC(35, REG_GPIO_H_PD, BIT(1)), + PINCTRL_CONF_DESC(36, REG_GPIO_H_PD, BIT(2)), + PINCTRL_CONF_DESC(37, REG_GPIO_H_PD, BIT(3)), + PINCTRL_CONF_DESC(38, REG_GPIO_H_PD, BIT(4)), + PINCTRL_CONF_DESC(39, REG_GPIO_H_PD, BIT(5)), + PINCTRL_CONF_DESC(40, REG_GPIO_H_PD, BIT(6)), + PINCTRL_CONF_DESC(41, REG_I2C_SDA_PD, I2C_SCL_PD_MASK), + PINCTRL_CONF_DESC(42, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), + PINCTRL_CONF_DESC(43, REG_I2C_SDA_PD, AN7583_I2C1_SCL_PD_MASK), + PINCTRL_CONF_DESC(44, REG_I2C_SDA_PD, AN7583_I2C1_SDA_PD_MASK), + PINCTRL_CONF_DESC(45, REG_I2C_SDA_PD, SPI_CLK_PD_MASK), + PINCTRL_CONF_DESC(46, REG_I2C_SDA_PD, SPI_CS0_PD_MASK), + PINCTRL_CONF_DESC(47, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK), + PINCTRL_CONF_DESC(48, REG_I2C_SDA_PD, SPI_MISO_PD_MASK), + PINCTRL_CONF_DESC(49, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), + PINCTRL_CONF_DESC(50, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), + PINCTRL_CONF_DESC(51, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK), + PINCTRL_CONF_DESC(52, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK), + PINCTRL_CONF_DESC(53, REG_I2C_SDA_PD, AN7583_MDC_0_PD_MASK), + PINCTRL_CONF_DESC(54, REG_I2C_SDA_PD, AN7583_MDIO_0_PD_MASK), +}; + static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), @@ -1477,6 +2061,62 @@ static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), }; +static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e2_conf[] = { + PINCTRL_CONF_DESC(2, REG_GPIO_L_E2, BIT(0)), + PINCTRL_CONF_DESC(3, REG_GPIO_L_E2, BIT(1)), + PINCTRL_CONF_DESC(4, REG_GPIO_L_E2, BIT(2)), + PINCTRL_CONF_DESC(5, REG_GPIO_L_E2, BIT(3)), + PINCTRL_CONF_DESC(6, REG_GPIO_L_E2, BIT(4)), + PINCTRL_CONF_DESC(7, REG_GPIO_L_E2, BIT(5)), + PINCTRL_CONF_DESC(8, REG_GPIO_L_E2, BIT(6)), + PINCTRL_CONF_DESC(9, REG_GPIO_L_E2, BIT(7)), + PINCTRL_CONF_DESC(10, REG_GPIO_L_E2, BIT(8)), + PINCTRL_CONF_DESC(11, REG_GPIO_L_E2, BIT(9)), + PINCTRL_CONF_DESC(12, REG_GPIO_L_E2, BIT(10)), + PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(11)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(12)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(13)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(14)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(15)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(16)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(17)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(18)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(18)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(20)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(21)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(22)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(23)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(24)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(25)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(26)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(27)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(28)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(29)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(30)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(31)), + PINCTRL_CONF_DESC(34, REG_GPIO_H_E2, BIT(0)), + PINCTRL_CONF_DESC(35, REG_GPIO_H_E2, BIT(1)), + PINCTRL_CONF_DESC(36, REG_GPIO_H_E2, BIT(2)), + PINCTRL_CONF_DESC(37, REG_GPIO_H_E2, BIT(3)), + PINCTRL_CONF_DESC(38, REG_GPIO_H_E2, BIT(4)), + PINCTRL_CONF_DESC(39, REG_GPIO_H_E2, BIT(5)), + PINCTRL_CONF_DESC(40, REG_GPIO_H_E2, BIT(6)), + PINCTRL_CONF_DESC(41, REG_I2C_SDA_E2, I2C_SCL_E2_MASK), + PINCTRL_CONF_DESC(42, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), + PINCTRL_CONF_DESC(43, REG_I2C_SDA_E2, AN7583_I2C1_SCL_E2_MASK), + PINCTRL_CONF_DESC(44, REG_I2C_SDA_E2, AN7583_I2C1_SDA_E2_MASK), + PINCTRL_CONF_DESC(45, REG_I2C_SDA_E2, SPI_CLK_E2_MASK), + PINCTRL_CONF_DESC(46, REG_I2C_SDA_E2, SPI_CS0_E2_MASK), + PINCTRL_CONF_DESC(47, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK), + PINCTRL_CONF_DESC(48, REG_I2C_SDA_E2, SPI_MISO_E2_MASK), + PINCTRL_CONF_DESC(49, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), + PINCTRL_CONF_DESC(50, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), + PINCTRL_CONF_DESC(51, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK), + PINCTRL_CONF_DESC(52, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK), + PINCTRL_CONF_DESC(53, REG_I2C_SDA_E2, AN7583_MDC_0_E2_MASK), + PINCTRL_CONF_DESC(54, REG_I2C_SDA_E2, AN7583_MDIO_0_E2_MASK), +}; + static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = { PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), @@ -1538,12 +2178,73 @@ static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = { PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), }; +static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e4_conf[] = { + PINCTRL_CONF_DESC(2, REG_GPIO_L_E4, BIT(0)), + PINCTRL_CONF_DESC(3, REG_GPIO_L_E4, BIT(1)), + PINCTRL_CONF_DESC(4, REG_GPIO_L_E4, BIT(2)), + PINCTRL_CONF_DESC(5, REG_GPIO_L_E4, BIT(3)), + PINCTRL_CONF_DESC(6, REG_GPIO_L_E4, BIT(4)), + PINCTRL_CONF_DESC(7, REG_GPIO_L_E4, BIT(5)), + PINCTRL_CONF_DESC(8, REG_GPIO_L_E4, BIT(6)), + PINCTRL_CONF_DESC(9, REG_GPIO_L_E4, BIT(7)), + PINCTRL_CONF_DESC(10, REG_GPIO_L_E4, BIT(8)), + PINCTRL_CONF_DESC(11, REG_GPIO_L_E4, BIT(9)), + PINCTRL_CONF_DESC(12, REG_GPIO_L_E4, BIT(10)), + PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(11)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(12)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(13)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(14)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(15)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(16)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(17)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(18)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(18)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(20)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(21)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(22)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(23)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(24)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(25)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(26)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(27)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(28)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(29)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(30)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(31)), + PINCTRL_CONF_DESC(34, REG_GPIO_H_E4, BIT(0)), + PINCTRL_CONF_DESC(35, REG_GPIO_H_E4, BIT(1)), + PINCTRL_CONF_DESC(36, REG_GPIO_H_E4, BIT(2)), + PINCTRL_CONF_DESC(37, REG_GPIO_H_E4, BIT(3)), + PINCTRL_CONF_DESC(38, REG_GPIO_H_E4, BIT(4)), + PINCTRL_CONF_DESC(39, REG_GPIO_H_E4, BIT(5)), + PINCTRL_CONF_DESC(40, REG_GPIO_H_E4, BIT(6)), + PINCTRL_CONF_DESC(41, REG_I2C_SDA_E4, I2C_SCL_E4_MASK), + PINCTRL_CONF_DESC(42, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), + PINCTRL_CONF_DESC(43, REG_I2C_SDA_E4, AN7583_I2C1_SCL_E4_MASK), + PINCTRL_CONF_DESC(44, REG_I2C_SDA_E4, AN7583_I2C1_SDA_E4_MASK), + PINCTRL_CONF_DESC(45, REG_I2C_SDA_E4, SPI_CLK_E4_MASK), + PINCTRL_CONF_DESC(46, REG_I2C_SDA_E4, SPI_CS0_E4_MASK), + PINCTRL_CONF_DESC(47, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK), + PINCTRL_CONF_DESC(48, REG_I2C_SDA_E4, SPI_MISO_E4_MASK), + PINCTRL_CONF_DESC(49, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), + PINCTRL_CONF_DESC(50, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), + PINCTRL_CONF_DESC(51, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK), + PINCTRL_CONF_DESC(52, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK), + PINCTRL_CONF_DESC(53, REG_I2C_SDA_E4, AN7583_MDC_0_E4_MASK), + PINCTRL_CONF_DESC(54, REG_I2C_SDA_E4, AN7583_MDIO_0_E4_MASK), +}; + static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = { PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), }; +static const struct airoha_pinctrl_conf an7583_pinctrl_pcie_rst_od_conf[] = { + PINCTRL_CONF_DESC(51, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), + PINCTRL_CONF_DESC(52, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), +}; + static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev, struct pinctrl_gpio_range *range, int pin) @@ -1708,7 +2409,7 @@ static const struct irq_chip airoha_gpio_irq_chip = { }; static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, - struct platform_device *pdev) + struct platform_device *pdev) { struct airoha_pinctrl_gpiochip *chip = &pinctrl->gpiochip; struct gpio_chip *gc = &chip->chip; @@ -1743,7 +2444,7 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, return irq; err = devm_request_irq(dev, irq, airoha_irq_handler, IRQF_SHARED, - dev_name(dev), pinctrl); + dev_name(dev), pinctrl); if (err) { dev_err(dev, "error requesting irq %d: %d\n", irq, err); return err; @@ -1807,8 +2508,8 @@ static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, } static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev, - struct pinctrl_gpio_range *range, - unsigned int p, bool input) + struct pinctrl_gpio_range *range, + unsigned int p, bool input) { struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); u32 mask, index; @@ -1898,7 +2599,7 @@ static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, if (regmap_update_bits(pinctrl->chip_scu, reg->offset, reg->mask, - val << __ffs(reg->mask))) + val << __ffs(reg->mask))) return -EINVAL; return 0; @@ -2115,8 +2816,8 @@ static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, for (i = 0; i < pinctrl->grps[group].npins; i++) { if (airoha_pinconf_get(pctrl_dev, - pinctrl->grps[group].pins[i], - config)) + pinctrl->grps[group].pins[i], + config)) return -ENOTSUPP; if (i && cur_config != *config) @@ -2275,8 +2976,40 @@ static const struct airoha_pinctrl_match_data en7581_pinctrl_match_data = { }, }; +static const struct airoha_pinctrl_match_data an7583_pinctrl_match_data = { + .pins = an7583_pinctrl_pins, + .num_pins = ARRAY_SIZE(an7583_pinctrl_pins), + .grps = an7583_pinctrl_groups, + .num_grps = ARRAY_SIZE(an7583_pinctrl_groups), + .funcs = an7583_pinctrl_funcs, + .num_funcs = ARRAY_SIZE(an7583_pinctrl_funcs), + .confs_info = { + [AIROHA_PINCTRL_CONFS_PULLUP] = { + .confs = an7583_pinctrl_pullup_conf, + .num_confs = ARRAY_SIZE(an7583_pinctrl_pullup_conf), + }, + [AIROHA_PINCTRL_CONFS_PULLDOWN] = { + .confs = an7583_pinctrl_pulldown_conf, + .num_confs = ARRAY_SIZE(an7583_pinctrl_pulldown_conf), + }, + [AIROHA_PINCTRL_CONFS_DRIVE_E2] = { + .confs = en7581_pinctrl_drive_e2_conf, + .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e2_conf), + }, + [AIROHA_PINCTRL_CONFS_DRIVE_E4] = { + .confs = an7583_pinctrl_drive_e4_conf, + .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e4_conf), + }, + [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = { + .confs = an7583_pinctrl_pcie_rst_od_conf, + .num_confs = ARRAY_SIZE(an7583_pinctrl_pcie_rst_od_conf), + }, + }, +}; + static const struct of_device_id airoha_pinctrl_of_match[] = { { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data }, + { .compatible = "airoha,an7583-pinctrl", .data = &an7583_pinctrl_match_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match); From 79d022dcad375c6ba95e78e9035c8a0630164300 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 6 Nov 2025 18:06:08 +0100 Subject: [PATCH 260/684] clk: sprd: sc9860: Simplify with of_device_get_match_data() Driver's probe function matches against driver's of_device_id table, where each entry has non-NULL match data, so of_match_node() can be simplified with of_device_get_match_data(). Signed-off-by: Krzysztof Kozlowski [sboyd@kernel.org: Use device_get_match_data() instead, drop printk noise] Signed-off-by: Stephen Boyd --- drivers/clk/sprd/sc9860-clk.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c index cc5ed2dd826703..d7fe924fbe9717 100644 --- a/drivers/clk/sprd/sc9860-clk.c +++ b/drivers/clk/sprd/sc9860-clk.c @@ -2021,17 +2021,13 @@ MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids); static int sc9860_clk_probe(struct platform_device *pdev) { - const struct of_device_id *match; const struct sprd_clk_desc *desc; int ret; - match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node); - if (!match) { - pr_err("%s: of_match_node() failed", __func__); + desc = device_get_match_data(&pdev->dev); + if (!desc) return -ENODEV; - } - desc = match->data; ret = sprd_clk_regmap_init(pdev, desc); if (ret) return ret; From e279039c3ec3708707961daa7234e4a5fd645ad3 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 11 Nov 2025 13:44:15 +0800 Subject: [PATCH 261/684] perf symbol: Remove unneeded semicolon Remove unnecessary semicolons reported by Coccinelle/coccicheck and the semantic patch at scripts/coccinelle/misc/semicolon.cocci. Signed-off-by: Chen Ni Signed-off-by: Namhyung Kim --- tools/perf/util/synthetic-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index fcd1fd13c30e6e..5aa44c4aba6259 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -389,7 +389,7 @@ static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event, dso_id.ino_generation = event->ino_generation; dso_id.mmap2_valid = true; dso_id.mmap2_ino_generation_valid = true; - }; + } dso = dsos__findnew_id(&machine->dsos, event->filename, &dso_id); if (dso && dso__has_build_id(dso)) { From 25b47635f8729e9536d2652774bd509532eaa522 Mon Sep 17 00:00:00 2001 From: Jacky Bai Date: Fri, 1 Aug 2025 15:21:53 +0800 Subject: [PATCH 262/684] clk: imx: Add some delay before deassert the reset Some of the PCCs on i.MX8ULP have a sw_rst bit to control the peripheral reset through SW method. For peripherals like GPU that need sync reset, some delay is necessary befere & after release the reset to make sure the HW is reset into a known status. So add some delay before & after release reset. Signed-off-by: Jacky Bai Reviewed-by: Peng Fan Link: https://lore.kernel.org/r/20250801072153.1974428-1-ping.bai@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-composite-7ulp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/clk/imx/clk-composite-7ulp.c b/drivers/clk/imx/clk-composite-7ulp.c index 8ed2e0ad2769c6..37d2fc197be672 100644 --- a/drivers/clk/imx/clk-composite-7ulp.c +++ b/drivers/clk/imx/clk-composite-7ulp.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,9 @@ static int pcc_gate_enable(struct clk_hw *hw) if (ret) return ret; + /* Make sure the IP's clock is ready before release reset */ + udelay(1); + spin_lock_irqsave(gate->lock, flags); /* * release the sw reset for peripherals associated with @@ -47,6 +51,15 @@ static int pcc_gate_enable(struct clk_hw *hw) spin_unlock_irqrestore(gate->lock, flags); + /* + * Read back the register to make sure the previous write has been + * done in the target HW register. For IP like GPU, after deassert + * the reset, need to wait for a while to make sure the sync reset + * is done + */ + readl(gate->reg); + udelay(1); + return 0; } From 9d97a2fe48ae77976baff441edd5b30ea4e179c0 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Oct 2025 09:45:51 +0800 Subject: [PATCH 263/684] clk: imx: imx8mp-audiomix: use devm_auxiliary_device_create() to simple code Use helper function devm_auxiliary_device_create() to remove some boilerplate code. Reviewed-by: Abel Vesa Reviewed-by: Frank Li Signed-off-by: Peng Fan Reviewed-by: Shengjiu Wang Link: https://lore.kernel.org/r/20251024-auxiliary-v2-1-a353dc9e6b1a@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mp-audiomix.c | 39 +++------------------------ 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c index 775f62dddb11d8..131702f2c9ecfd 100644 --- a/drivers/clk/imx/clk-imx8mp-audiomix.c +++ b/drivers/clk/imx/clk-imx8mp-audiomix.c @@ -230,50 +230,19 @@ struct clk_imx8mp_audiomix_priv { #if IS_ENABLED(CONFIG_RESET_CONTROLLER) -static void clk_imx8mp_audiomix_reset_unregister_adev(void *_adev) -{ - struct auxiliary_device *adev = _adev; - - auxiliary_device_delete(adev); - auxiliary_device_uninit(adev); -} - -static void clk_imx8mp_audiomix_reset_adev_release(struct device *dev) -{ - struct auxiliary_device *adev = to_auxiliary_dev(dev); - - kfree(adev); -} - static int clk_imx8mp_audiomix_reset_controller_register(struct device *dev, struct clk_imx8mp_audiomix_priv *priv) { - struct auxiliary_device *adev __free(kfree) = NULL; - int ret; + struct auxiliary_device *adev; if (!of_property_present(dev->of_node, "#reset-cells")) return 0; - adev = kzalloc(sizeof(*adev), GFP_KERNEL); + adev = devm_auxiliary_device_create(dev, "reset", NULL); if (!adev) - return -ENOMEM; - - adev->name = "reset"; - adev->dev.parent = dev; - adev->dev.release = clk_imx8mp_audiomix_reset_adev_release; - - ret = auxiliary_device_init(adev); - if (ret) - return ret; + return -ENODEV; - ret = auxiliary_device_add(adev); - if (ret) { - auxiliary_device_uninit(adev); - return ret; - } - - return devm_add_action_or_reset(dev, clk_imx8mp_audiomix_reset_unregister_adev, - no_free_ptr(adev)); + return 0; } #else /* !CONFIG_RESET_CONTROLLER */ From 3b521bf8c51246466e2c337f1f2b60acfdfe82d6 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 4 Nov 2025 04:02:55 -0800 Subject: [PATCH 264/684] dt-bindings: clock: document 8ULP's SIM LPAV Add documentation for i.MX8ULP's SIM LPAV module. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Daniel Baluta Signed-off-by: Laurentiu Mihalcea Link: https://lore.kernel.org/r/20251104120301.913-3-laurentiumihalcea111@gmail.com Signed-off-by: Abel Vesa --- .../bindings/clock/fsl,imx8ulp-sim-lpav.yaml | 72 +++++++++++++++++++ include/dt-bindings/clock/imx8ulp-clock.h | 5 ++ .../dt-bindings/reset/fsl,imx8ulp-sim-lpav.h | 16 +++++ 3 files changed, 93 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml create mode 100644 include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h diff --git a/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml b/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml new file mode 100644 index 00000000000000..662e07528d768d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/fsl,imx8ulp-sim-lpav.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX8ULP LPAV System Integration Module (SIM) + +maintainers: + - Laurentiu Mihalcea + +description: + The i.MX8ULP LPAV subsystem contains a block control module known as + SIM LPAV, which offers functionalities such as clock gating or reset + line assertion/de-assertion. + +properties: + compatible: + const: fsl,imx8ulp-sim-lpav + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + + clock-names: + items: + - const: bus + - const: core + - const: plat + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + mux-controller: + $ref: /schemas/mux/reg-mux.yaml# + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - mux-controller + +additionalProperties: false + +examples: + - | + #include + + clock-controller@2da50000 { + compatible = "fsl,imx8ulp-sim-lpav"; + reg = <0x2da50000 0x10000>; + clocks = <&cgc2 IMX8ULP_CLK_LPAV_BUS_DIV>, + <&cgc2 IMX8ULP_CLK_HIFI_DIVCORE>, + <&cgc2 IMX8ULP_CLK_HIFI_DIVPLAT>; + clock-names = "bus", "core", "plat"; + #clock-cells = <1>; + #reset-cells = <1>; + + mux-controller { + compatible = "reg-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x8 0x00000200>; + }; + }; diff --git a/include/dt-bindings/clock/imx8ulp-clock.h b/include/dt-bindings/clock/imx8ulp-clock.h index 827404fadf5c7c..c62d84d093a9d5 100644 --- a/include/dt-bindings/clock/imx8ulp-clock.h +++ b/include/dt-bindings/clock/imx8ulp-clock.h @@ -255,4 +255,9 @@ #define IMX8ULP_CLK_PCC5_END 56 +/* LPAV SIM */ +#define IMX8ULP_CLK_SIM_LPAV_HIFI_CORE 0 +#define IMX8ULP_CLK_SIM_LPAV_HIFI_PBCLK 1 +#define IMX8ULP_CLK_SIM_LPAV_HIFI_PLAT 2 + #endif diff --git a/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h b/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h new file mode 100644 index 00000000000000..adf95bb26d213c --- /dev/null +++ b/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright 2025 NXP + */ + +#ifndef DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H +#define DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H + +#define IMX8ULP_SIM_LPAV_HIFI4_DSP_DBG_RST 0 +#define IMX8ULP_SIM_LPAV_HIFI4_DSP_RST 1 +#define IMX8ULP_SIM_LPAV_HIFI4_DSP_STALL 2 +#define IMX8ULP_SIM_LPAV_DSI_RST_BYTE_N 3 +#define IMX8ULP_SIM_LPAV_DSI_RST_ESC_N 4 +#define IMX8ULP_SIM_LPAV_DSI_RST_DPI_N 5 + +#endif /* DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H */ From fdc1dc7dd53b95805d3943ed36785c1ec812915e Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 4 Nov 2025 04:02:56 -0800 Subject: [PATCH 265/684] clk: imx: add driver for imx8ulp's sim lpav The i.MX8ULP System Integration Module (SIM) LPAV module is a block control module found inside the LPAV subsystem, which offers some clock gating options and reset line assertion/de-assertion capabilities. Therefore, the clock gate management is supported by registering the module's driver as a clock provider, while the reset capabilities are managed via the auxiliary device API to allow the DT node to act as a reset and clock provider. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Daniel Baluta Reviewed-by: Peng Fan Link: https://lore.kernel.org/r/20251104120301.913-4-laurentiumihalcea111@gmail.com Signed-off-by: Abel Vesa --- drivers/clk/imx/Kconfig | 1 + drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-imx8ulp-sim-lpav.c | 156 +++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8ulp-sim-lpav.c diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index 6ff6d934848a3b..b292e7ca5c248a 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -105,6 +105,7 @@ config CLK_IMX8ULP tristate "IMX8ULP CCM Clock Driver" depends on ARCH_MXC || COMPILE_TEST select MXC_CLK + select AUXILIARY_BUS help Build the driver for i.MX8ULP CCM Clock Driver diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 03f2b2a1ab6318..208b46873a18c1 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -41,6 +41,7 @@ clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o clk-imx-acm-$(CONFIG_CLK_IMX8QXP) = clk-imx8-acm.o obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o +obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp-sim-lpav.o obj-$(CONFIG_CLK_IMX1) += clk-imx1.o obj-$(CONFIG_CLK_IMX25) += clk-imx25.o diff --git a/drivers/clk/imx/clk-imx8ulp-sim-lpav.c b/drivers/clk/imx/clk-imx8ulp-sim-lpav.c new file mode 100644 index 00000000000000..990c95b89b75c6 --- /dev/null +++ b/drivers/clk/imx/clk-imx8ulp-sim-lpav.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2025 NXP + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSCTRL0 0x8 + +#define IMX8ULP_HIFI_CLK_GATE(gname, cname, pname, bidx) \ + { \ + .name = gname "_cg", \ + .id = IMX8ULP_CLK_SIM_LPAV_HIFI_##cname, \ + .parent = { .fw_name = pname }, \ + .bit = bidx, \ + } + +struct clk_imx8ulp_sim_lpav_data { + spinlock_t lock; /* shared by MUX, clock gate and reset */ + unsigned long flags; /* for spinlock usage */ + struct clk_hw_onecell_data clk_data; /* keep last */ +}; + +struct clk_imx8ulp_sim_lpav_gate { + const char *name; + int id; + const struct clk_parent_data parent; + u8 bit; +}; + +static struct clk_imx8ulp_sim_lpav_gate gates[] = { + IMX8ULP_HIFI_CLK_GATE("hifi_core", CORE, "core", 17), + IMX8ULP_HIFI_CLK_GATE("hifi_pbclk", PBCLK, "bus", 18), + IMX8ULP_HIFI_CLK_GATE("hifi_plat", PLAT, "plat", 19) +}; + +static void clk_imx8ulp_sim_lpav_lock(void *arg) __acquires(&data->lock) +{ + struct clk_imx8ulp_sim_lpav_data *data = dev_get_drvdata(arg); + + spin_lock_irqsave(&data->lock, data->flags); +} + +static void clk_imx8ulp_sim_lpav_unlock(void *arg) __releases(&data->lock) +{ + struct clk_imx8ulp_sim_lpav_data *data = dev_get_drvdata(arg); + + spin_unlock_irqrestore(&data->lock, data->flags); +} + +static int clk_imx8ulp_sim_lpav_probe(struct platform_device *pdev) +{ + const struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .lock = clk_imx8ulp_sim_lpav_lock, + .unlock = clk_imx8ulp_sim_lpav_unlock, + .lock_arg = &pdev->dev, + }; + struct clk_imx8ulp_sim_lpav_data *data; + struct auxiliary_device *adev; + struct regmap *regmap; + void __iomem *base; + struct clk_hw *hw; + int i, ret; + + data = devm_kzalloc(&pdev->dev, + struct_size(data, clk_data.hws, ARRAY_SIZE(gates)), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, data); + + /* + * this lock is used directly by the clock gate and indirectly + * by the reset and mux controller via the regmap API + */ + spin_lock_init(&data->lock); + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(&pdev->dev, PTR_ERR(base), + "failed to ioremap base\n"); + /* + * although the clock gate doesn't use the regmap API to modify the + * registers, we still need the regmap because of the reset auxiliary + * driver and the MUX drivers, which use the parent device's regmap + */ + regmap = devm_regmap_init_mmio(&pdev->dev, base, ®map_config); + if (IS_ERR(regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(regmap), + "failed to initialize regmap\n"); + + data->clk_data.num = ARRAY_SIZE(gates); + + for (i = 0; i < ARRAY_SIZE(gates); i++) { + hw = devm_clk_hw_register_gate_parent_data(&pdev->dev, + gates[i].name, + &gates[i].parent, + CLK_SET_RATE_PARENT, + base + SYSCTRL0, + gates[i].bit, + 0x0, &data->lock); + if (IS_ERR(hw)) + return dev_err_probe(&pdev->dev, PTR_ERR(hw), + "failed to register %s gate\n", + gates[i].name); + + data->clk_data.hws[i] = hw; + } + + adev = devm_auxiliary_device_create(&pdev->dev, "reset", NULL); + if (!adev) + return dev_err_probe(&pdev->dev, -ENODEV, + "failed to register aux reset\n"); + + ret = devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &data->clk_data); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register clk hw provider\n"); + + /* used to probe MUX child device */ + return devm_of_platform_populate(&pdev->dev); +} + +static const struct of_device_id clk_imx8ulp_sim_lpav_of_match[] = { + { .compatible = "fsl,imx8ulp-sim-lpav" }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_imx8ulp_sim_lpav_of_match); + +static struct platform_driver clk_imx8ulp_sim_lpav_driver = { + .probe = clk_imx8ulp_sim_lpav_probe, + .driver = { + .name = "clk-imx8ulp-sim-lpav", + .of_match_table = clk_imx8ulp_sim_lpav_of_match, + }, +}; +module_platform_driver(clk_imx8ulp_sim_lpav_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("i.MX8ULP LPAV System Integration Module (SIM) clock driver"); +MODULE_AUTHOR("Laurentiu Mihalcea "); From 781f60e45bdfe351aad692ac0fa89e36f8bf4a36 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Mon, 10 Nov 2025 11:23:50 +0000 Subject: [PATCH 266/684] reset: mpfs: add non-auxiliary bus probing While the auxiliary bus was a nice bandaid, and meant that re-writing the representation of the clock regions in devicetree was not required, it has run its course. The "mss_top_sysreg" region that contains the clock and reset regions, also contains pinctrl and an interrupt controller, so the time has come rewrite the devicetree and probe the reset controller from an mfd devicetree node, rather than implement those drivers using the auxiliary bus. Wanting to avoid propagating this naive/incorrect description of the hardware to the new pic64gx SoC is a major motivating factor here. Reviewed-by: Philipp Zabel Acked-by: Philipp Zabel Signed-off-by: Conor Dooley --- drivers/clk/microchip/clk-mpfs.c | 4 +- drivers/reset/Kconfig | 1 + drivers/reset/reset-mpfs.c | 91 +++++++++++++++++++------------- include/soc/microchip/mpfs.h | 3 +- 4 files changed, 60 insertions(+), 39 deletions(-) diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c index 484893e68b6772..ee58304913ef1d 100644 --- a/drivers/clk/microchip/clk-mpfs.c +++ b/drivers/clk/microchip/clk-mpfs.c @@ -38,7 +38,7 @@ static const struct regmap_config mpfs_clk_regmap_config = { .reg_stride = 4, .val_bits = 32, .val_format_endian = REGMAP_ENDIAN_LITTLE, - .max_register = REG_SUBBLK_CLOCK_CR, + .max_register = REG_SUBBLK_RESET_CR, }; /* @@ -502,7 +502,7 @@ static inline int mpfs_clk_old_format_probe(struct mpfs_clock_data *clk_data, if (IS_ERR(clk_data->regmap)) return PTR_ERR(clk_data->regmap); - return mpfs_reset_controller_register(dev, clk_data->base + REG_SUBBLK_RESET_CR); + return mpfs_reset_controller_register(dev, clk_data->regmap); } static int mpfs_clk_probe(struct platform_device *pdev) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 78b7078478d46d..0ec4b7cd08d652 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -200,6 +200,7 @@ config RESET_PISTACHIO config RESET_POLARFIRE_SOC bool "Microchip PolarFire SoC (MPFS) Reset Driver" depends on MCHP_CLK_MPFS + depends on MFD_SYSCON select AUXILIARY_BUS default MCHP_CLK_MPFS help diff --git a/drivers/reset/reset-mpfs.c b/drivers/reset/reset-mpfs.c index f6fa10e03ea889..8ffcc54ee6f696 100644 --- a/drivers/reset/reset-mpfs.c +++ b/drivers/reset/reset-mpfs.c @@ -9,11 +9,13 @@ #include #include #include +#include #include #include #include -#include +#include #include +#include #include #include @@ -27,11 +29,10 @@ #define MPFS_SLEEP_MIN_US 100 #define MPFS_SLEEP_MAX_US 200 -/* block concurrent access to the soft reset register */ -static DEFINE_SPINLOCK(mpfs_reset_lock); +#define REG_SUBBLK_RESET_CR 0x88u struct mpfs_reset { - void __iomem *base; + struct regmap *regmap; struct reset_controller_dev rcdev; }; @@ -46,41 +47,25 @@ static inline struct mpfs_reset *to_mpfs_reset(struct reset_controller_dev *rcde static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id) { struct mpfs_reset *rst = to_mpfs_reset(rcdev); - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&mpfs_reset_lock, flags); - - reg = readl(rst->base); - reg |= BIT(id); - writel(reg, rst->base); - spin_unlock_irqrestore(&mpfs_reset_lock, flags); + return regmap_set_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id)); - return 0; } static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id) { struct mpfs_reset *rst = to_mpfs_reset(rcdev); - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&mpfs_reset_lock, flags); - reg = readl(rst->base); - reg &= ~BIT(id); - writel(reg, rst->base); + return regmap_clear_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id)); - spin_unlock_irqrestore(&mpfs_reset_lock, flags); - - return 0; } static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id) { struct mpfs_reset *rst = to_mpfs_reset(rcdev); - u32 reg = readl(rst->base); + u32 reg; + + regmap_read(rst->regmap, REG_SUBBLK_RESET_CR, ®); /* * It is safe to return here as MPFS_NUM_RESETS makes sure the sign bit @@ -130,23 +115,58 @@ static int mpfs_reset_xlate(struct reset_controller_dev *rcdev, return index - MPFS_PERIPH_OFFSET; } -static int mpfs_reset_probe(struct auxiliary_device *adev, - const struct auxiliary_device_id *id) +static int mpfs_reset_mfd_probe(struct platform_device *pdev) +{ + struct reset_controller_dev *rcdev; + struct device *dev = &pdev->dev; + struct mpfs_reset *rst; + + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); + if (!rst) + return -ENOMEM; + + rcdev = &rst->rcdev; + rcdev->dev = dev; + rcdev->ops = &mpfs_reset_ops; + + rcdev->of_node = pdev->dev.parent->of_node; + rcdev->of_reset_n_cells = 1; + rcdev->of_xlate = mpfs_reset_xlate; + rcdev->nr_resets = MPFS_NUM_RESETS; + + rst->regmap = device_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(rst->regmap)) + return dev_err_probe(dev, PTR_ERR(rst->regmap), + "Failed to find syscon regmap\n"); + + return devm_reset_controller_register(dev, rcdev); +} + +static struct platform_driver mpfs_reset_mfd_driver = { + .probe = mpfs_reset_mfd_probe, + .driver = { + .name = "mpfs-reset", + }, +}; +module_platform_driver(mpfs_reset_mfd_driver); + +static int mpfs_reset_adev_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) { - struct device *dev = &adev->dev; struct reset_controller_dev *rcdev; + struct device *dev = &adev->dev; struct mpfs_reset *rst; rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); if (!rst) return -ENOMEM; - rst->base = (void __iomem *)adev->dev.platform_data; + rst->regmap = (struct regmap *)adev->dev.platform_data; rcdev = &rst->rcdev; rcdev->dev = dev; - rcdev->dev->parent = dev->parent; rcdev->ops = &mpfs_reset_ops; + rcdev->of_node = dev->parent->of_node; rcdev->of_reset_n_cells = 1; rcdev->of_xlate = mpfs_reset_xlate; @@ -155,12 +175,11 @@ static int mpfs_reset_probe(struct auxiliary_device *adev, return devm_reset_controller_register(dev, rcdev); } -int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) +int mpfs_reset_controller_register(struct device *clk_dev, struct regmap *map) { struct auxiliary_device *adev; - adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs", - (__force void *)base); + adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs", (void *)map); if (!adev) return -ENODEV; @@ -176,12 +195,12 @@ static const struct auxiliary_device_id mpfs_reset_ids[] = { }; MODULE_DEVICE_TABLE(auxiliary, mpfs_reset_ids); -static struct auxiliary_driver mpfs_reset_driver = { - .probe = mpfs_reset_probe, +static struct auxiliary_driver mpfs_reset_aux_driver = { + .probe = mpfs_reset_adev_probe, .id_table = mpfs_reset_ids, }; -module_auxiliary_driver(mpfs_reset_driver); +module_auxiliary_driver(mpfs_reset_aux_driver); MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver"); MODULE_AUTHOR("Conor Dooley "); diff --git a/include/soc/microchip/mpfs.h b/include/soc/microchip/mpfs.h index 0bd67e10b7049b..ec04c98a8b63bd 100644 --- a/include/soc/microchip/mpfs.h +++ b/include/soc/microchip/mpfs.h @@ -14,6 +14,7 @@ #include #include +#include struct mpfs_sys_controller; @@ -44,7 +45,7 @@ struct mtd_info *mpfs_sys_controller_get_flash(struct mpfs_sys_controller *mpfs_ #if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) #if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) -int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base); +int mpfs_reset_controller_register(struct device *clk_dev, struct regmap *map); #else static inline int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) { return 0; } #endif /* if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) */ From 367377f45c0b568882567f797b7b18b263505be7 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 10 Nov 2025 23:59:44 -0800 Subject: [PATCH 267/684] perf tools: Fix missing feature check for inherit + SAMPLE_READ It should also have PERF_SAMPLE_TID to enable inherit and PERF_SAMPLE_READ on recent kernels. Not having _TID makes the feature check wrongly detect the inherit and _READ support. It was reported that the following command failed due to the error in the missing feature check on Intel SPR machines. $ perf record -e '{cpu/mem-loads-aux/S,cpu/mem-loads,ldlat=3/PS}' -- ls Error: Failure to open event 'cpu/mem-loads,ldlat=3/PS' on PMU 'cpu' which will be removed. Invalid event (cpu/mem-loads,ldlat=3/PS) in per-thread mode, enable system wide with '-a'. Reviewed-by: Ian Rogers Fixes: 3b193a57baf15c468 ("perf tools: Detect missing kernel features properly") Reported-and-tested-by: Chen, Zide Closes: https://lore.kernel.org/lkml/20251022220802.1335131-1-zide.chen@intel.com/ Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 67a898cda86ab5..989c56d4a23f74 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2474,7 +2474,7 @@ static bool evsel__detect_missing_features(struct evsel *evsel, struct perf_cpu /* Please add new feature detection here. */ attr.inherit = true; - attr.sample_type = PERF_SAMPLE_READ; + attr.sample_type = PERF_SAMPLE_READ | PERF_SAMPLE_TID; if (has_attr_feature(&attr, /*flags=*/0)) goto found; perf_missing_features.inherit_sample_read = true; From c8035a496141b9c05dc3ce034c7a1d4b64f4eccb Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:49 -0800 Subject: [PATCH 268/684] perf metricgroup: Add care to picking the evsel for displaying a metric Rather than using the first evsel in the matched events, try to find the least shared non-tool evsel. The aim is to pick the first evsel that typifies the metric within the list of metrics. This addresses an issue where Default metric group metrics may lose their counter value due to how the stat displaying hides counters for default event/metric output. For a metricgroup like TopdownL1 on an Intel Alderlake the change is, before there are 4 events with metrics: ``` $ perf stat -M topdownL1 -a sleep 1 Performance counter stats for 'system wide': 7,782,334,296 cpu_core/TOPDOWN.SLOTS/ # 10.4 % tma_bad_speculation # 19.7 % tma_frontend_bound 2,668,927,977 cpu_core/topdown-retiring/ # 35.7 % tma_backend_bound # 34.1 % tma_retiring 803,623,987 cpu_core/topdown-bad-spec/ 167,514,386 cpu_core/topdown-heavy-ops/ 1,555,265,776 cpu_core/topdown-fe-bound/ 2,792,733,013 cpu_core/topdown-be-bound/ 279,769,310 cpu_atom/TOPDOWN_RETIRING.ALL/ # 12.2 % tma_retiring # 15.1 % tma_bad_speculation 457,917,232 cpu_atom/CPU_CLK_UNHALTED.CORE/ # 38.4 % tma_backend_bound # 34.2 % tma_frontend_bound 783,519,226 cpu_atom/TOPDOWN_FE_BOUND.ALL/ 10,790,192 cpu_core/INT_MISC.UOP_DROPPING/ 879,845,633 cpu_atom/TOPDOWN_BE_BOUND.ALL/ ``` After there are 6 events with metrics: ``` $ perf stat -M topdownL1 -a sleep 1 Performance counter stats for 'system wide': 2,377,551,258 cpu_core/TOPDOWN.SLOTS/ # 7.9 % tma_bad_speculation # 36.4 % tma_frontend_bound 480,791,142 cpu_core/topdown-retiring/ # 35.5 % tma_backend_bound 186,323,991 cpu_core/topdown-bad-spec/ 65,070,590 cpu_core/topdown-heavy-ops/ # 20.1 % tma_retiring 871,733,444 cpu_core/topdown-fe-bound/ 848,286,598 cpu_core/topdown-be-bound/ 260,936,456 cpu_atom/TOPDOWN_RETIRING.ALL/ # 12.4 % tma_retiring # 17.6 % tma_bad_speculation 419,576,513 cpu_atom/CPU_CLK_UNHALTED.CORE/ 797,132,597 cpu_atom/TOPDOWN_FE_BOUND.ALL/ # 38.0 % tma_frontend_bound 3,055,447 cpu_core/INT_MISC.UOP_DROPPING/ 671,014,164 cpu_atom/TOPDOWN_BE_BOUND.ALL/ # 32.0 % tma_backend_bound ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/metricgroup.c | 48 ++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 48936e5178035d..76092ee2676161 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1323,6 +1323,51 @@ static int parse_ids(bool metric_no_merge, bool fake_pmu, return ret; } +/* How many times will a given evsel be used in a set of metrics? */ +static int count_uses(struct list_head *metric_list, struct evsel *evsel) +{ + const char *metric_id = evsel__metric_id(evsel); + struct metric *m; + int uses = 0; + + list_for_each_entry(m, metric_list, nd) { + if (hashmap__find(m->pctx->ids, metric_id, NULL)) + uses++; + } + return uses; +} + +/* + * Select the evsel that stat-display will use to trigger shadow/metric + * printing. Pick the least shared non-tool evsel, encouraging metrics to be + * with a hardware counter that is specific to them. + */ +static struct evsel *pick_display_evsel(struct list_head *metric_list, + struct evsel **metric_events) +{ + struct evsel *selected = metric_events[0]; + size_t selected_uses; + bool selected_is_tool; + + if (!selected) + return NULL; + + selected_uses = count_uses(metric_list, selected); + selected_is_tool = evsel__is_tool(selected); + for (int i = 1; metric_events[i]; i++) { + struct evsel *candidate = metric_events[i]; + size_t candidate_uses = count_uses(metric_list, candidate); + + if ((selected_is_tool && !evsel__is_tool(candidate)) || + (candidate_uses < selected_uses)) { + selected = candidate; + selected_uses = candidate_uses; + selected_is_tool = evsel__is_tool(selected); + } + } + return selected; +} + static int parse_groups(struct evlist *perf_evlist, const char *pmu, const char *str, bool metric_no_group, @@ -1430,7 +1475,8 @@ static int parse_groups(struct evlist *perf_evlist, goto out; } - me = metricgroup__lookup(&perf_evlist->metric_events, metric_events[0], + me = metricgroup__lookup(&perf_evlist->metric_events, + pick_display_evsel(&metric_list, metric_events), /*create=*/true); expr = malloc(sizeof(struct metric_expr)); From 2e5140849b021889cf4dd8df5d2352e508213607 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:50 -0800 Subject: [PATCH 269/684] perf expr: Add #target_cpu literal For CPU nanoseconds a lot of the stat-shadow metrics use either task-clock or cpu-clock, the latter being used when target__has_cpu. Add a #target_cpu literal so that json metrics can perform the same test. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 7fda0ff89c168b..4df56f2b283d6f 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -409,6 +409,9 @@ double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx } else if (!strcmp("#core_wide", literal)) { result = core_wide(ctx->system_wide, ctx->user_requested_cpu_list) ? 1.0 : 0.0; + } else if (!strcmp("#target_cpu", literal)) { + result = (ctx->system_wide || ctx->user_requested_cpu_list) + ? 1.0 : 0.0; } else { pr_err("Unrecognized literal '%s'", literal); } From c7adeb0974f18da4828338ae75f1c1ebe6c03c7a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:51 -0800 Subject: [PATCH 270/684] perf jevents: Add set of common metrics based on default ones Add support to getting a common set of metrics from a default table. It simplifies the generation to add json metrics at the same time. The metrics added are CPUs_utilized, cs_per_second, migrations_per_second, page_faults_per_second, insn_per_cycle, stalled_cycles_per_instruction, frontend_cycles_idle, backend_cycles_idle, cycles_frequency, branch_frequency and branch_miss_rate based on the shadow metric definitions. Following this change the default perf stat output on an alderlake looks like: ``` $ perf stat -a -- sleep 2 Performance counter stats for 'system wide': 0.00 msec cpu-clock # 0.000 CPUs utilized 77,739 context-switches 15,033 cpu-migrations 321,313 page-faults 14,355,634,225 cpu_atom/instructions/ # 1.40 insn per cycle (35.37%) 134,561,560,583 cpu_core/instructions/ # 3.44 insn per cycle (57.85%) 10,263,836,145 cpu_atom/cycles/ (35.42%) 39,138,632,894 cpu_core/cycles/ (57.60%) 2,989,658,777 cpu_atom/branches/ (42.60%) 32,170,570,388 cpu_core/branches/ (57.39%) 29,789,870 cpu_atom/branch-misses/ # 1.00% of all branches (42.69%) 165,991,152 cpu_core/branch-misses/ # 0.52% of all branches (57.19%) (software) # nan cs/sec cs_per_second TopdownL1 (cpu_core) # 11.9 % tma_bad_speculation # 19.6 % tma_frontend_bound (63.97%) TopdownL1 (cpu_core) # 18.8 % tma_backend_bound # 49.7 % tma_retiring (63.97%) (software) # nan faults/sec page_faults_per_second # nan GHz cycles_frequency (42.88%) # nan GHz cycles_frequency (69.88%) TopdownL1 (cpu_atom) # 11.7 % tma_bad_speculation # 29.9 % tma_retiring (50.07%) TopdownL1 (cpu_atom) # 31.3 % tma_frontend_bound (43.09%) (cpu_atom) # nan M/sec branch_frequency (43.09%) # nan M/sec branch_frequency (70.07%) # nan migrations/sec migrations_per_second TopdownL1 (cpu_atom) # 27.1 % tma_backend_bound (43.08%) (software) # 0.0 CPUs CPUs_utilized # 1.4 instructions insn_per_cycle (43.04%) # 3.5 instructions insn_per_cycle (69.99%) # 1.0 % branch_miss_rate (35.46%) # 0.5 % branch_miss_rate (65.02%) 2.005626564 seconds time elapsed ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- .../arch/common/common/metrics.json | 86 +++++++++++++ tools/perf/pmu-events/empty-pmu-events.c | 115 +++++++++++++----- tools/perf/pmu-events/jevents.py | 21 +++- tools/perf/pmu-events/pmu-events.h | 1 + tools/perf/util/metricgroup.c | 31 +++-- 5 files changed, 212 insertions(+), 42 deletions(-) create mode 100644 tools/perf/pmu-events/arch/common/common/metrics.json diff --git a/tools/perf/pmu-events/arch/common/common/metrics.json b/tools/perf/pmu-events/arch/common/common/metrics.json new file mode 100644 index 00000000000000..d915be51e300bc --- /dev/null +++ b/tools/perf/pmu-events/arch/common/common/metrics.json @@ -0,0 +1,86 @@ +[ + { + "BriefDescription": "Average CPU utilization", + "MetricExpr": "(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)", + "MetricGroup": "Default", + "MetricName": "CPUs_utilized", + "ScaleUnit": "1CPUs", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Context switches per CPU second", + "MetricExpr": "(software@context\\-switches\\,name\\=context\\-switches@ * 1e9) / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)", + "MetricGroup": "Default", + "MetricName": "cs_per_second", + "ScaleUnit": "1cs/sec", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Process migrations to a new CPU per CPU second", + "MetricExpr": "(software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9) / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)", + "MetricGroup": "Default", + "MetricName": "migrations_per_second", + "ScaleUnit": "1migrations/sec", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Page faults per CPU second", + "MetricExpr": "(software@page\\-faults\\,name\\=page\\-faults@ * 1e9) / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)", + "MetricGroup": "Default", + "MetricName": "page_faults_per_second", + "ScaleUnit": "1faults/sec", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Instructions Per Cycle", + "MetricExpr": "instructions / cpu\\-cycles", + "MetricGroup": "Default", + "MetricName": "insn_per_cycle", + "MetricThreshold": "insn_per_cycle < 1", + "ScaleUnit": "1instructions" + }, + { + "BriefDescription": "Max front or backend stalls per instruction", + "MetricExpr": "max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions", + "MetricGroup": "Default", + "MetricName": "stalled_cycles_per_instruction" + }, + { + "BriefDescription": "Frontend stalls per cycle", + "MetricExpr": "stalled\\-cycles\\-frontend / cpu\\-cycles", + "MetricGroup": "Default", + "MetricName": "frontend_cycles_idle", + "MetricThreshold": "frontend_cycles_idle > 0.1" + }, + { + "BriefDescription": "Backend stalls per cycle", + "MetricExpr": "stalled\\-cycles\\-backend / cpu\\-cycles", + "MetricGroup": "Default", + "MetricName": "backend_cycles_idle", + "MetricThreshold": "backend_cycles_idle > 0.2" + }, + { + "BriefDescription": "Cycles per CPU second", + "MetricExpr": "cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)", + "MetricGroup": "Default", + "MetricName": "cycles_frequency", + "ScaleUnit": "1GHz", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Branches per CPU second", + "MetricExpr": "branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)", + "MetricGroup": "Default", + "MetricName": "branch_frequency", + "ScaleUnit": "1000M/sec", + "MetricConstraint": "NO_GROUP_EVENTS" + }, + { + "BriefDescription": "Branch miss rate", + "MetricExpr": "branch\\-misses / branches", + "MetricGroup": "Default", + "MetricName": "branch_miss_rate", + "MetricThreshold": "branch_miss_rate > 0.05", + "ScaleUnit": "100%" + } +] diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 2fdf4fbf36e258..e4d00f6b2b5d98 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1303,21 +1303,32 @@ static const char *const big_c_string = /* offset=127519 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" /* offset=127596 */ "uncore_sys_cmn_pmu\000" /* offset=127615 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=127758 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" -/* offset=127780 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" -/* offset=127843 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" -/* offset=128009 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=128073 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=128140 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" -/* offset=128211 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" -/* offset=128305 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" -/* offset=128439 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" -/* offset=128503 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=128571 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=128641 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" -/* offset=128663 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" -/* offset=128685 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" -/* offset=128705 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" +/* offset=127758 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\00001" +/* offset=127943 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\00001" +/* offset=128175 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\00001" +/* offset=128434 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\00001" +/* offset=128664 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\00000" +/* offset=128776 */ "stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\00000" +/* offset=128939 */ "frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\00000" +/* offset=129068 */ "backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\00000" +/* offset=129193 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\00001" +/* offset=129368 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\00001" +/* offset=129547 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\00000" +/* offset=129650 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" +/* offset=129672 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" +/* offset=129735 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" +/* offset=129901 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=129965 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" +/* offset=130032 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" +/* offset=130103 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" +/* offset=130197 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" +/* offset=130331 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" +/* offset=130395 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=130463 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" +/* offset=130533 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" +/* offset=130555 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" +/* offset=130577 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" +/* offset=130597 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { @@ -2603,6 +2614,29 @@ static const struct pmu_table_entry pmu_events__common[] = { }, }; +static const struct compact_pmu_event pmu_metrics__common_default_core[] = { +{ 127758 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\00001 */ +{ 129068 }, /* backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\00000 */ +{ 129368 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\00001 */ +{ 129547 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\00000 */ +{ 127943 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\00001 */ +{ 129193 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\00001 */ +{ 128939 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\00000 */ +{ 128664 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\00000 */ +{ 128175 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\00001 */ +{ 128434 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\00001 */ +{ 128776 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\00000 */ + +}; + +static const struct pmu_table_entry pmu_metrics__common[] = { +{ + .entries = pmu_metrics__common_default_core, + .num_entries = ARRAY_SIZE(pmu_metrics__common_default_core), + .pmu_name = { 0 /* default_core\000 */ }, +}, +}; + static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { { 126205 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ { 126267 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ @@ -2664,21 +2698,21 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 127758 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ -{ 128439 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ -{ 128211 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ -{ 128305 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ -{ 128503 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 128571 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 127843 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ -{ 127780 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ -{ 128705 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ -{ 128641 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ -{ 128663 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ -{ 128685 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ -{ 128140 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ -{ 128009 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ -{ 128073 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 129650 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ +{ 130331 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ +{ 130103 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ +{ 130197 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ +{ 130395 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 130463 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ +{ 129735 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ +{ 129672 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ +{ 130597 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ +{ 130533 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ +{ 130555 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ +{ 130577 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ +{ 130032 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ +{ 129901 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 129965 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ }; @@ -2759,7 +2793,10 @@ static const struct pmu_events_map pmu_events_map[] = { .pmus = pmu_events__common, .num_pmus = ARRAY_SIZE(pmu_events__common), }, - .metric_table = {}, + .metric_table = { + .pmus = pmu_metrics__common, + .num_pmus = ARRAY_SIZE(pmu_metrics__common), + }, }, { .arch = "testarch", @@ -3208,6 +3245,22 @@ const struct pmu_metrics_table *pmu_metrics_table__find(void) return map ? &map->metric_table : NULL; } +const struct pmu_metrics_table *pmu_metrics_table__default(void) +{ + int i = 0; + + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; + + if (!map->arch) + break; + + if (!strcmp(map->cpuid, "common")) + return &map->metric_table; + } + return NULL; +} + const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) { for (const struct pmu_events_map *tables = &pmu_events_map[0]; diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 786a7049363fe6..5d3f4b44cfb7f8 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -755,7 +755,10 @@ def print_mapping_table(archs: Sequence[str]) -> None: \t\t.pmus = pmu_events__common, \t\t.num_pmus = ARRAY_SIZE(pmu_events__common), \t}, -\t.metric_table = {}, +\t.metric_table = { +\t\t.pmus = pmu_metrics__common, +\t\t.num_pmus = ARRAY_SIZE(pmu_metrics__common), +\t}, }, """) else: @@ -1237,6 +1240,22 @@ def print_system_mapping_table() -> None: return map ? &map->metric_table : NULL; } +const struct pmu_metrics_table *pmu_metrics_table__default(void) +{ + int i = 0; + + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; + + if (!map->arch) + break; + + if (!strcmp(map->cpuid, "common")) + return &map->metric_table; + } + return NULL; +} + const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) { for (const struct pmu_events_map *tables = &pmu_events_map[0]; diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index e0535380c0b29d..559265a903c85f 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -127,6 +127,7 @@ int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu); const struct pmu_events_table *perf_pmu__default_core_events_table(void); const struct pmu_metrics_table *pmu_metrics_table__find(void); +const struct pmu_metrics_table *pmu_metrics_table__default(void); const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid); const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid); int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data); diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 76092ee2676161..e67e04ce01c99f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -424,10 +424,18 @@ int metricgroup__for_each_metric(const struct pmu_metrics_table *table, pmu_metr .fn = fn, .data = data, }; + const struct pmu_metrics_table *tables[2] = { + table, + pmu_metrics_table__default(), + }; + + for (size_t i = 0; i < ARRAY_SIZE(tables); i++) { + int ret; - if (table) { - int ret = pmu_metrics_table__for_each_metric(table, fn, data); + if (!tables[i]) + continue; + ret = pmu_metrics_table__for_each_metric(tables[i], fn, data); if (ret) return ret; } @@ -1581,19 +1589,22 @@ static int metricgroup__has_metric_or_groups_callback(const struct pmu_metric *p bool metricgroup__has_metric_or_groups(const char *pmu, const char *metric_or_groups) { - const struct pmu_metrics_table *table = pmu_metrics_table__find(); + const struct pmu_metrics_table *tables[2] = { + pmu_metrics_table__find(), + pmu_metrics_table__default(), + }; struct metricgroup__has_metric_data data = { .pmu = pmu, .metric_or_groups = metric_or_groups, }; - if (!table) - return false; - - return pmu_metrics_table__for_each_metric(table, - metricgroup__has_metric_or_groups_callback, - &data) - ? true : false; + for (size_t i = 0; i < ARRAY_SIZE(tables); i++) { + if (pmu_metrics_table__for_each_metric(tables[i], + metricgroup__has_metric_or_groups_callback, + &data)) + return true; + } + return false; } static int metricgroup__topdown_max_level_callback(const struct pmu_metric *pm, From a3248b5b5427dc2126c19aa9c32f1e840b65024f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:52 -0800 Subject: [PATCH 271/684] perf jevents: Add metric DefaultShowEvents Some Default group metrics require their events showing for consistency with perf's previous behavior. Add a flag to indicate when this is the case and use it in stat-display. As events are coming from Default metrics remove that default hardware and software events from perf stat. Following this change the default perf stat output on an alderlake looks like: ``` $ perf stat -a -- sleep 1 Performance counter stats for 'system wide': 20,550 context-switches # nan cs/sec cs_per_second TopdownL1 (cpu_core) # 9.0 % tma_bad_speculation # 28.1 % tma_frontend_bound TopdownL1 (cpu_core) # 29.2 % tma_backend_bound # 33.7 % tma_retiring 6,685 page-faults # nan faults/sec page_faults_per_second 790,091,064 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (49.83%) 2,563,918,366 cpu_core/cpu-cycles/ # nan GHz cycles_frequency # 12.3 % tma_bad_speculation # 14.5 % tma_retiring (50.20%) # 33.8 % tma_frontend_bound (50.24%) 76,390,322 cpu_atom/branches/ # nan M/sec branch_frequency (60.20%) 1,015,173,047 cpu_core/branches/ # nan M/sec branch_frequency 1,325 cpu-migrations # nan migrations/sec migrations_per_second # 39.3 % tma_backend_bound (60.17%) 0.00 msec cpu-clock # 0.000 CPUs utilized # 0.0 CPUs CPUs_utilized 554,347,072 cpu_atom/instructions/ # 0.64 insn per cycle # 0.6 instructions insn_per_cycle (60.14%) 5,228,931,991 cpu_core/instructions/ # 2.04 insn per cycle # 2.0 instructions insn_per_cycle 4,308,874 cpu_atom/branch-misses/ # 5.65% of all branches # 5.6 % branch_miss_rate (49.76%) 9,890,606 cpu_core/branch-misses/ # 0.97% of all branches # 1.0 % branch_miss_rate 1.005477803 seconds time elapsed ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 42 +------ .../arch/common/common/metrics.json | 33 ++++-- tools/perf/pmu-events/empty-pmu-events.c | 106 +++++++++--------- tools/perf/pmu-events/jevents.py | 7 +- tools/perf/pmu-events/pmu-events.h | 1 + tools/perf/util/evsel.h | 1 + tools/perf/util/metricgroup.c | 13 +++ tools/perf/util/stat-display.c | 4 +- tools/perf/util/stat-shadow.c | 2 +- 9 files changed, 102 insertions(+), 107 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3c46b92a53ab69..31c762695d4b03 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1857,16 +1857,6 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) return 0; } -/* Add given software event to evlist without wildcarding. */ -static int parse_software_event(struct evlist *evlist, const char *event, - struct parse_events_error *err) -{ - char buf[256]; - - snprintf(buf, sizeof(buf), "software/%s,name=%s/", event, event); - return parse_events(evlist, buf, err); -} - /* Add legacy hardware/hardware-cache event to evlist for all core PMUs without wildcarding. */ static int parse_hardware_event(struct evlist *evlist, const char *event, struct parse_events_error *err) @@ -2011,36 +2001,10 @@ static int add_default_events(void) stat_config.topdown_level = 1; if (!evlist->core.nr_entries && !evsel_list->core.nr_entries) { - /* No events so add defaults. */ - const char *sw_events[] = { - target__has_cpu(&target) ? "cpu-clock" : "task-clock", - "context-switches", - "cpu-migrations", - "page-faults", - }; - const char *hw_events[] = { - "instructions", - "cycles", - "stalled-cycles-frontend", - "stalled-cycles-backend", - "branches", - "branch-misses", - }; - - for (size_t i = 0; i < ARRAY_SIZE(sw_events); i++) { - ret = parse_software_event(evlist, sw_events[i], &err); - if (ret) - goto out; - } - for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { - ret = parse_hardware_event(evlist, hw_events[i], &err); - if (ret) - goto out; - } - /* - * Add TopdownL1 metrics if they exist. To minimize - * multiplexing, don't request threshold computation. + * Add Default metrics. To minimize multiplexing, don't request + * threshold computation, but it will be computed if the events + * are present. */ if (metricgroup__has_metric_or_groups(pmu, "Default")) { struct evlist *metric_evlist = evlist__new(); diff --git a/tools/perf/pmu-events/arch/common/common/metrics.json b/tools/perf/pmu-events/arch/common/common/metrics.json index d915be51e300bc..d6ea967a404539 100644 --- a/tools/perf/pmu-events/arch/common/common/metrics.json +++ b/tools/perf/pmu-events/arch/common/common/metrics.json @@ -5,7 +5,8 @@ "MetricGroup": "Default", "MetricName": "CPUs_utilized", "ScaleUnit": "1CPUs", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Context switches per CPU second", @@ -13,7 +14,8 @@ "MetricGroup": "Default", "MetricName": "cs_per_second", "ScaleUnit": "1cs/sec", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Process migrations to a new CPU per CPU second", @@ -21,7 +23,8 @@ "MetricGroup": "Default", "MetricName": "migrations_per_second", "ScaleUnit": "1migrations/sec", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Page faults per CPU second", @@ -29,7 +32,8 @@ "MetricGroup": "Default", "MetricName": "page_faults_per_second", "ScaleUnit": "1faults/sec", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Instructions Per Cycle", @@ -37,27 +41,31 @@ "MetricGroup": "Default", "MetricName": "insn_per_cycle", "MetricThreshold": "insn_per_cycle < 1", - "ScaleUnit": "1instructions" + "ScaleUnit": "1instructions", + "DefaultShowEvents": "1" }, { "BriefDescription": "Max front or backend stalls per instruction", "MetricExpr": "max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions", "MetricGroup": "Default", - "MetricName": "stalled_cycles_per_instruction" + "MetricName": "stalled_cycles_per_instruction", + "DefaultShowEvents": "1" }, { "BriefDescription": "Frontend stalls per cycle", "MetricExpr": "stalled\\-cycles\\-frontend / cpu\\-cycles", "MetricGroup": "Default", "MetricName": "frontend_cycles_idle", - "MetricThreshold": "frontend_cycles_idle > 0.1" + "MetricThreshold": "frontend_cycles_idle > 0.1", + "DefaultShowEvents": "1" }, { "BriefDescription": "Backend stalls per cycle", "MetricExpr": "stalled\\-cycles\\-backend / cpu\\-cycles", "MetricGroup": "Default", "MetricName": "backend_cycles_idle", - "MetricThreshold": "backend_cycles_idle > 0.2" + "MetricThreshold": "backend_cycles_idle > 0.2", + "DefaultShowEvents": "1" }, { "BriefDescription": "Cycles per CPU second", @@ -65,7 +73,8 @@ "MetricGroup": "Default", "MetricName": "cycles_frequency", "ScaleUnit": "1GHz", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Branches per CPU second", @@ -73,7 +82,8 @@ "MetricGroup": "Default", "MetricName": "branch_frequency", "ScaleUnit": "1000M/sec", - "MetricConstraint": "NO_GROUP_EVENTS" + "MetricConstraint": "NO_GROUP_EVENTS", + "DefaultShowEvents": "1" }, { "BriefDescription": "Branch miss rate", @@ -81,6 +91,7 @@ "MetricGroup": "Default", "MetricName": "branch_miss_rate", "MetricThreshold": "branch_miss_rate > 0.05", - "ScaleUnit": "100%" + "ScaleUnit": "100%", + "DefaultShowEvents": "1" } ] diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index e4d00f6b2b5d98..333a4493091032 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1303,32 +1303,32 @@ static const char *const big_c_string = /* offset=127519 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" /* offset=127596 */ "uncore_sys_cmn_pmu\000" /* offset=127615 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=127758 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\00001" -/* offset=127943 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\00001" -/* offset=128175 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\00001" -/* offset=128434 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\00001" -/* offset=128664 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\00000" -/* offset=128776 */ "stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\00000" -/* offset=128939 */ "frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\00000" -/* offset=129068 */ "backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\00000" -/* offset=129193 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\00001" -/* offset=129368 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\00001" -/* offset=129547 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\00000" -/* offset=129650 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" -/* offset=129672 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" -/* offset=129735 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" -/* offset=129901 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=129965 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" -/* offset=130032 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" -/* offset=130103 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" -/* offset=130197 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" -/* offset=130331 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" -/* offset=130395 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=130463 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" -/* offset=130533 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" -/* offset=130555 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" -/* offset=130577 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" -/* offset=130597 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" +/* offset=127758 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011" +/* offset=127944 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011" +/* offset=128177 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011" +/* offset=128437 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011" +/* offset=128668 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001" +/* offset=128781 */ "stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001" +/* offset=128945 */ "frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001" +/* offset=129075 */ "backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001" +/* offset=129201 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" +/* offset=129377 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" +/* offset=129557 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" +/* offset=129661 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" +/* offset=129684 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" +/* offset=129748 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" +/* offset=129915 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=129980 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=130048 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" +/* offset=130120 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" +/* offset=130215 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" +/* offset=130350 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" +/* offset=130415 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=130484 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=130555 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" +/* offset=130578 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" +/* offset=130601 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" +/* offset=130622 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { @@ -2615,17 +2615,17 @@ static const struct pmu_table_entry pmu_events__common[] = { }; static const struct compact_pmu_event pmu_metrics__common_default_core[] = { -{ 127758 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\00001 */ -{ 129068 }, /* backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\00000 */ -{ 129368 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\00001 */ -{ 129547 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\00000 */ -{ 127943 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\00001 */ -{ 129193 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\00001 */ -{ 128939 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\00000 */ -{ 128664 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\00000 */ -{ 128175 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\00001 */ -{ 128434 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\00001 */ -{ 128776 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\00000 */ +{ 127758 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011 */ +{ 129075 }, /* backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001 */ +{ 129377 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011 */ +{ 129557 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001 */ +{ 127944 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011 */ +{ 129201 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011 */ +{ 128945 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001 */ +{ 128668 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001 */ +{ 128177 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011 */ +{ 128437 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011 */ +{ 128781 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001 */ }; @@ -2698,21 +2698,21 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 129650 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ -{ 130331 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ -{ 130103 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ -{ 130197 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ -{ 130395 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 130463 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ -{ 129735 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ -{ 129672 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ -{ 130597 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ -{ 130533 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ -{ 130555 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ -{ 130577 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ -{ 130032 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ -{ 129901 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ -{ 129965 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ +{ 129661 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ +{ 130350 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ +{ 130120 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ +{ 130215 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ +{ 130415 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 130484 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 129748 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ +{ 129684 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ +{ 130622 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ +{ 130555 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ +{ 130578 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ +{ 130601 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ +{ 130048 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ +{ 129915 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ +{ 129980 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ }; @@ -2894,6 +2894,8 @@ static void decompress_metric(int offset, struct pmu_metric *pm) pm->aggr_mode = *p - '0'; p++; pm->event_grouping = *p - '0'; + p++; + pm->default_show_events = *p - '0'; } static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table, diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 5d3f4b44cfb7f8..3413ee5d022741 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -58,10 +58,12 @@ _json_metric_attributes = [ 'metric_name', 'metric_group', 'metric_expr', 'metric_threshold', 'desc', 'long_desc', 'unit', 'compat', 'metricgroup_no_group', - 'default_metricgroup_name', 'aggr_mode', 'event_grouping' + 'default_metricgroup_name', 'aggr_mode', 'event_grouping', + 'default_show_events' ] # Attributes that are bools or enum int values, encoded as '0', '1',... -_json_enum_attributes = ['aggr_mode', 'deprecated', 'event_grouping', 'perpkg'] +_json_enum_attributes = ['aggr_mode', 'deprecated', 'event_grouping', 'perpkg', + 'default_show_events'] def removesuffix(s: str, suffix: str) -> str: """Remove the suffix from a string @@ -356,6 +358,7 @@ def canonicalize_value(val: str) -> str: self.metricgroup_no_group = jd.get('MetricgroupNoGroup') self.default_metricgroup_name = jd.get('DefaultMetricgroupName') self.event_grouping = convert_metric_constraint(jd.get('MetricConstraint')) + self.default_show_events = jd.get('DefaultShowEvents') self.metric_expr = None if 'MetricExpr' in jd: self.metric_expr = metric.ParsePerfJson(jd['MetricExpr']).Simplify() diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index 559265a903c85f..d3b24014c6ff18 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -74,6 +74,7 @@ struct pmu_metric { const char *default_metricgroup_name; enum aggr_mode_class aggr_mode; enum metric_event_groups event_grouping; + bool default_show_events; }; struct pmu_events_table; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 71f74c7036efb9..3ae4ac8f9a37e0 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -122,6 +122,7 @@ struct evsel { bool reset_group; bool needs_auxtrace_mmap; bool default_metricgroup; /* A member of the Default metricgroup */ + bool default_show_events; /* If a default group member, show the event */ bool needs_uniquify; struct hashmap *per_pkg_mask; int err; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index e67e04ce01c99f..25c75fdbfc525f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -152,6 +152,8 @@ struct metric { * Should events of the metric be grouped? */ bool group_events; + /** Show events even if in the Default metric group. */ + bool default_show_events; /** * Parsed events for the metric. Optional as events may be taken from a * different metric whose group contains all the IDs necessary for this @@ -255,6 +257,7 @@ static struct metric *metric__new(const struct pmu_metric *pm, m->pctx->sctx.runtime = runtime; m->pctx->sctx.system_wide = system_wide; m->group_events = !metric_no_group && metric__group_events(pm, metric_no_threshold); + m->default_show_events = pm->default_show_events; m->metric_refs = NULL; m->evlist = NULL; @@ -1513,6 +1516,16 @@ static int parse_groups(struct evlist *perf_evlist, free(metric_events); goto out; } + if (m->default_show_events) { + struct evsel *pos; + + for (int i = 0; metric_events[i]; i++) + metric_events[i]->default_show_events = true; + evlist__for_each_entry(metric_evlist, pos) { + if (pos->metric_leader && pos->metric_leader->default_show_events) + pos->default_show_events = true; + } + } expr->metric_threshold = m->metric_threshold; expr->metric_unit = m->metric_unit; expr->metric_events = metric_events; diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index a67b991f4e8103..4d0e353846ead0 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -872,7 +872,7 @@ static void printout(struct perf_stat_config *config, struct outstate *os, out.ctx = os; out.force_header = false; - if (!config->metric_only && !counter->default_metricgroup) { + if (!config->metric_only && (!counter->default_metricgroup || counter->default_show_events)) { abs_printout(config, os, os->id, os->aggr_nr, counter, uval, ok); print_noise(config, os, counter, noise, /*before_metric=*/true); @@ -880,7 +880,7 @@ static void printout(struct perf_stat_config *config, struct outstate *os, } if (ok) { - if (!config->metric_only && counter->default_metricgroup) { + if (!config->metric_only && counter->default_metricgroup && !counter->default_show_events) { void *from = NULL; aggr_printout(config, os, os->evsel, os->id, os->aggr_nr); diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index abaf6b579bfc22..4df614f8e20054 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -665,7 +665,7 @@ void *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config, if (strcmp(name, mexp->default_metricgroup_name)) return (void *)mexp; /* Only print the name of the metricgroup once */ - if (!header_printed) { + if (!header_printed && !evsel->default_show_events) { header_printed = true; perf_stat__print_metricgroup_header(config, evsel, ctxp, name, out); From 2dfc0cab3da4a2054468489cc140b2bd539ce626 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:53 -0800 Subject: [PATCH 272/684] perf stat: Add detail -d,-dd,-ddd metrics Add metrics for the stat-shadow -d, -dd and -ddd events and hard coded metrics. Remove the events as these now come from the metrics. Following this change a detailed perf stat output looks like: ``` $ perf stat -a -ddd -- sleep 1 Performance counter stats for 'system wide': 21,089 context-switches # nan cs/sec cs_per_second TopdownL1 (cpu_core) # 14.1 % tma_bad_speculation # 27.3 % tma_frontend_bound (30.56%) TopdownL1 (cpu_core) # 31.5 % tma_backend_bound # 27.2 % tma_retiring (30.56%) 6,302 page-faults # nan faults/sec page_faults_per_second 928,495,163 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (28.41%) 1,841,409,834 cpu_core/cpu-cycles/ # nan GHz cycles_frequency (38.51%) # 14.5 % tma_bad_speculation # 16.0 % tma_retiring (28.41%) # 36.8 % tma_frontend_bound (35.57%) 100,859,118 cpu_atom/branches/ # nan M/sec branch_frequency (42.73%) 572,657,734 cpu_core/branches/ # nan M/sec branch_frequency (54.43%) 1,527 cpu-migrations # nan migrations/sec migrations_per_second # 32.7 % tma_backend_bound (42.73%) 0.00 msec cpu-clock # 0.000 CPUs utilized # 0.0 CPUs CPUs_utilized 498,668,509 cpu_atom/instructions/ # 0.57 insn per cycle # 0.6 instructions insn_per_cycle (42.97%) 3,281,762,225 cpu_core/instructions/ # 1.84 insn per cycle # 1.8 instructions insn_per_cycle (62.20%) 4,919,511 cpu_atom/branch-misses/ # 5.43% of all branches # 5.4 % branch_miss_rate (35.80%) 7,431,776 cpu_core/branch-misses/ # 1.39% of all branches # 1.4 % branch_miss_rate (62.20%) 2,517,007 cpu_atom/LLC-loads/ # 0.1 % llc_miss_rate (28.62%) 3,931,318 cpu_core/LLC-loads/ # 40.4 % llc_miss_rate (45.98%) 14,918,674 cpu_core/L1-dcache-load-misses/ # 2.25% of all L1-dcache accesses # nan % l1d_miss_rate (37.80%) 27,067,264 cpu_atom/L1-icache-load-misses/ # 15.92% of all L1-icache accesses # 15.9 % l1i_miss_rate (21.47%) 116,848,994 cpu_atom/dTLB-loads/ # 0.8 % dtlb_miss_rate (21.47%) 764,870,407 cpu_core/dTLB-loads/ # 0.1 % dtlb_miss_rate (15.12%) 1.006181526 seconds time elapsed ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 100 +++--------------- .../arch/common/common/metrics.json | 54 ++++++++++ tools/perf/pmu-events/empty-pmu-events.c | 72 +++++++------ 3 files changed, 113 insertions(+), 113 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 31c762695d4b03..7862094b93c88f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1857,28 +1857,6 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) return 0; } -/* Add legacy hardware/hardware-cache event to evlist for all core PMUs without wildcarding. */ -static int parse_hardware_event(struct evlist *evlist, const char *event, - struct parse_events_error *err) -{ - char buf[256]; - struct perf_pmu *pmu = NULL; - - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { - int ret; - - if (perf_pmus__num_core_pmus() == 1) - snprintf(buf, sizeof(buf), "%s/%s,name=%s/", pmu->name, event, event); - else - snprintf(buf, sizeof(buf), "%s/%s/", pmu->name, event); - - ret = parse_events(evlist, buf, err); - if (ret) - return ret; - } - return 0; -} - /* * Add default events, if there were no attributes specified or * if -d/--detailed, -d -d or -d -d -d is used: @@ -2006,22 +1984,34 @@ static int add_default_events(void) * threshold computation, but it will be computed if the events * are present. */ - if (metricgroup__has_metric_or_groups(pmu, "Default")) { - struct evlist *metric_evlist = evlist__new(); + const char *default_metricgroup_names[] = { + "Default", "Default2", "Default3", "Default4", + }; + + for (size_t i = 0; i < ARRAY_SIZE(default_metricgroup_names); i++) { + struct evlist *metric_evlist; + + if (!metricgroup__has_metric_or_groups(pmu, default_metricgroup_names[i])) + continue; + + if ((int)i > detailed_run) + break; + metric_evlist = evlist__new(); if (!metric_evlist) { ret = -ENOMEM; - goto out; + break; } - if (metricgroup__parse_groups(metric_evlist, pmu, "Default", + if (metricgroup__parse_groups(metric_evlist, pmu, default_metricgroup_names[i], /*metric_no_group=*/false, /*metric_no_merge=*/false, /*metric_no_threshold=*/true, stat_config.user_requested_cpu_list, stat_config.system_wide, stat_config.hardware_aware_grouping) < 0) { + evlist__delete(metric_evlist); ret = -1; - goto out; + break; } evlist__for_each_entry(metric_evlist, evsel) @@ -2034,62 +2024,6 @@ static int add_default_events(void) evlist__delete(metric_evlist); } } - - /* Detailed events get appended to the event list: */ - - if (!ret && detailed_run >= 1) { - /* - * Detailed stats (-d), covering the L1 and last level data - * caches: - */ - const char *hw_events[] = { - "L1-dcache-loads", - "L1-dcache-load-misses", - "LLC-loads", - "LLC-load-misses", - }; - - for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { - ret = parse_hardware_event(evlist, hw_events[i], &err); - if (ret) - goto out; - } - } - if (!ret && detailed_run >= 2) { - /* - * Very detailed stats (-d -d), covering the instruction cache - * and the TLB caches: - */ - const char *hw_events[] = { - "L1-icache-loads", - "L1-icache-load-misses", - "dTLB-loads", - "dTLB-load-misses", - "iTLB-loads", - "iTLB-load-misses", - }; - - for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { - ret = parse_hardware_event(evlist, hw_events[i], &err); - if (ret) - goto out; - } - } - if (!ret && detailed_run >= 3) { - /* - * Very, very detailed stats (-d -d -d), adding prefetch events: - */ - const char *hw_events[] = { - "L1-dcache-prefetches", - "L1-dcache-prefetch-misses", - }; - - for (size_t i = 0; i < ARRAY_SIZE(hw_events); i++) { - ret = parse_hardware_event(evlist, hw_events[i], &err); - if (ret) - goto out; - } - } out: if (!ret) { evlist__for_each_entry(evlist, evsel) { diff --git a/tools/perf/pmu-events/arch/common/common/metrics.json b/tools/perf/pmu-events/arch/common/common/metrics.json index d6ea967a404539..0d010b3ebc6d66 100644 --- a/tools/perf/pmu-events/arch/common/common/metrics.json +++ b/tools/perf/pmu-events/arch/common/common/metrics.json @@ -93,5 +93,59 @@ "MetricThreshold": "branch_miss_rate > 0.05", "ScaleUnit": "100%", "DefaultShowEvents": "1" + }, + { + "BriefDescription": "L1D miss rate", + "MetricExpr": "L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads", + "MetricGroup": "Default2", + "MetricName": "l1d_miss_rate", + "MetricThreshold": "l1d_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" + }, + { + "BriefDescription": "LLC miss rate", + "MetricExpr": "LLC\\-load\\-misses / LLC\\-loads", + "MetricGroup": "Default2", + "MetricName": "llc_miss_rate", + "MetricThreshold": "llc_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" + }, + { + "BriefDescription": "L1I miss rate", + "MetricExpr": "L1\\-icache\\-load\\-misses / L1\\-icache\\-loads", + "MetricGroup": "Default3", + "MetricName": "l1i_miss_rate", + "MetricThreshold": "l1i_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" + }, + { + "BriefDescription": "dTLB miss rate", + "MetricExpr": "dTLB\\-load\\-misses / dTLB\\-loads", + "MetricGroup": "Default3", + "MetricName": "dtlb_miss_rate", + "MetricThreshold": "dtlb_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" + }, + { + "BriefDescription": "iTLB miss rate", + "MetricExpr": "iTLB\\-load\\-misses / iTLB\\-loads", + "MetricGroup": "Default3", + "MetricName": "itlb_miss_rate", + "MetricThreshold": "itlb_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" + }, + { + "BriefDescription": "L1 prefetch miss rate", + "MetricExpr": "L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches", + "MetricGroup": "Default4", + "MetricName": "l1_prefetch_miss_rate", + "MetricThreshold": "l1_prefetch_miss_rate > 0.05", + "ScaleUnit": "100%", + "DefaultShowEvents": "1" } ] diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 333a4493091032..7fa42f13300f9a 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1314,21 +1314,27 @@ static const char *const big_c_string = /* offset=129201 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" /* offset=129377 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" /* offset=129557 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" -/* offset=129661 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" -/* offset=129684 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" -/* offset=129748 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" -/* offset=129915 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=129980 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=130048 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" -/* offset=130120 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" -/* offset=130215 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" -/* offset=130350 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" -/* offset=130415 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=130484 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=130555 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" -/* offset=130578 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" -/* offset=130601 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" -/* offset=130622 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" +/* offset=129661 */ "l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001" +/* offset=129777 */ "llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001" +/* offset=129878 */ "l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001" +/* offset=129993 */ "dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130099 */ "itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130205 */ "l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001" +/* offset=130353 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" +/* offset=130376 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" +/* offset=130440 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" +/* offset=130607 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=130672 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=130740 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" +/* offset=130812 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" +/* offset=130907 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" +/* offset=131042 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" +/* offset=131107 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131176 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131247 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" +/* offset=131270 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" +/* offset=131293 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" +/* offset=131314 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { @@ -2621,8 +2627,14 @@ static const struct compact_pmu_event pmu_metrics__common_default_core[] = { { 129557 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001 */ { 127944 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011 */ { 129201 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011 */ +{ 129993 }, /* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001 */ { 128945 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001 */ { 128668 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001 */ +{ 130099 }, /* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001 */ +{ 130205 }, /* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001 */ +{ 129661 }, /* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001 */ +{ 129878 }, /* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001 */ +{ 129777 }, /* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001 */ { 128177 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011 */ { 128437 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011 */ { 128781 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001 */ @@ -2698,21 +2710,21 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 129661 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ -{ 130350 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ -{ 130120 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ -{ 130215 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ -{ 130415 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 130484 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 129748 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ -{ 129684 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ -{ 130622 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ -{ 130555 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ -{ 130578 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ -{ 130601 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ -{ 130048 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ -{ 129915 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ -{ 129980 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ +{ 130353 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ +{ 131042 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ +{ 130812 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ +{ 130907 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ +{ 131107 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 131176 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 130440 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ +{ 130376 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ +{ 131314 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ +{ 131247 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ +{ 131270 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ +{ 131293 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ +{ 130740 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ +{ 130607 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ +{ 130672 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ }; From 3622990efaab066897a2c570b6e90f4b9f30b200 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:54 -0800 Subject: [PATCH 273/684] perf script: Change metric format to use json metrics The metric format option isn't properly supported. This change improves that by making the sample events update the counts of an evsel, where the shadow metric code expects to read the values. To support printing metrics, metrics need to be found. This is done on the first attempt to print a metric. Every metric is parsed and then the evsels in the metric's evlist compared to those in perf script using the perf_event_attr type and config. If the metric matches then it is added for printing. As an event in the perf script's evlist may have >1 metric id, or different leader for aggregation, the first metric matched will be displayed in those cases. An example use is: ``` $ perf record -a -e '{instructions,cpu-cycles}:S' -a -- sleep 1 $ perf script -F period,metric ... 867817 metric: 0.30 insn per cycle 125394 metric: 0.04 insn per cycle 313516 metric: 0.11 insn per cycle metric: 1.00 insn per cycle ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-script.c | 252 ++++++++++++++++++++++++++++++++---- 1 file changed, 230 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index d813adbf988954..8bab5b264f6136 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -33,6 +33,7 @@ #include "util/path.h" #include "util/event.h" #include "util/mem-info.h" +#include "util/metricgroup.h" #include "ui/ui.h" #include "print_binary.h" #include "print_insn.h" @@ -341,9 +342,6 @@ struct evsel_script { char *filename; FILE *fp; u64 samples; - /* For metric output */ - u64 val; - int gnum; }; static inline struct evsel_script *evsel_script(struct evsel *evsel) @@ -2132,13 +2130,161 @@ static void script_new_line(struct perf_stat_config *config __maybe_unused, fputs("\tmetric: ", mctx->fp); } -static void perf_sample__fprint_metric(struct perf_script *script, - struct thread *thread, +struct script_find_metrics_args { + struct evlist *evlist; + bool system_wide; +}; + +static struct evsel *map_metric_evsel_to_script_evsel(struct evlist *script_evlist, + struct evsel *metric_evsel) +{ + struct evsel *script_evsel; + + evlist__for_each_entry(script_evlist, script_evsel) { + /* Skip if perf_event_attr differ. */ + if (metric_evsel->core.attr.type != script_evsel->core.attr.type) + continue; + if (metric_evsel->core.attr.config != script_evsel->core.attr.config) + continue; + /* Skip if the script event has a metric_id that doesn't match. */ + if (script_evsel->metric_id && + strcmp(evsel__metric_id(metric_evsel), evsel__metric_id(script_evsel))) { + pr_debug("Skipping matching evsel due to differing metric ids '%s' vs '%s'\n", + evsel__metric_id(metric_evsel), evsel__metric_id(script_evsel)); + continue; + } + return script_evsel; + } + return NULL; +} + +static int script_find_metrics(const struct pmu_metric *pm, + const struct pmu_metrics_table *table __maybe_unused, + void *data) +{ + struct script_find_metrics_args *args = data; + struct evlist *script_evlist = args->evlist; + struct evlist *metric_evlist = evlist__new(); + struct evsel *metric_evsel; + int ret = metricgroup__parse_groups(metric_evlist, + /*pmu=*/"all", + pm->metric_name, + /*metric_no_group=*/false, + /*metric_no_merge=*/false, + /*metric_no_threshold=*/true, + /*user_requested_cpu_list=*/NULL, + args->system_wide, + /*hardware_aware_grouping=*/false); + + if (ret) { + /* Metric parsing failed but continue the search. */ + goto out; + } + + /* + * Check the script_evlist has an entry for each metric_evlist entry. If + * the script evsel was already set up avoid changing data that may + * break it. + */ + evlist__for_each_entry(metric_evlist, metric_evsel) { + struct evsel *script_evsel = + map_metric_evsel_to_script_evsel(script_evlist, metric_evsel); + struct evsel *new_metric_leader; + + if (!script_evsel) { + pr_debug("Skipping metric '%s' as evsel '%s' / '%s' is missing\n", + pm->metric_name, evsel__name(metric_evsel), + evsel__metric_id(metric_evsel)); + goto out; + } + + if (script_evsel->metric_leader == NULL) + continue; + + if (metric_evsel->metric_leader == metric_evsel) { + new_metric_leader = script_evsel; + } else { + new_metric_leader = + map_metric_evsel_to_script_evsel(script_evlist, + metric_evsel->metric_leader); + } + /* Mismatching evsel leaders. */ + if (script_evsel->metric_leader != new_metric_leader) { + pr_debug("Skipping metric '%s' due to mismatching evsel metric leaders '%s' vs '%s'\n", + pm->metric_name, evsel__metric_id(metric_evsel), + evsel__metric_id(script_evsel)); + goto out; + } + } + /* + * Metric events match those in the script evlist, copy metric evsel + * data into the script evlist. + */ + evlist__for_each_entry(metric_evlist, metric_evsel) { + struct evsel *script_evsel = + map_metric_evsel_to_script_evsel(script_evlist, metric_evsel); + struct metric_event *metric_me = metricgroup__lookup(&metric_evlist->metric_events, + metric_evsel, + /*create=*/false); + + if (script_evsel->metric_id == NULL) { + script_evsel->metric_id = metric_evsel->metric_id; + metric_evsel->metric_id = NULL; + } + + if (script_evsel->metric_leader == NULL) { + if (metric_evsel->metric_leader == metric_evsel) { + script_evsel->metric_leader = script_evsel; + } else { + script_evsel->metric_leader = + map_metric_evsel_to_script_evsel(script_evlist, + metric_evsel->metric_leader); + } + } + + if (metric_me) { + struct metric_expr *expr; + struct metric_event *script_me = + metricgroup__lookup(&script_evlist->metric_events, + script_evsel, + /*create=*/true); + + if (!script_me) { + /* + * As the metric_expr is created, the only + * failure is a lack of memory. + */ + goto out; + } + list_splice_init(&metric_me->head, &script_me->head); + list_for_each_entry(expr, &script_me->head, nd) { + for (int i = 0; expr->metric_events[i]; i++) { + expr->metric_events[i] = + map_metric_evsel_to_script_evsel(script_evlist, + expr->metric_events[i]); + } + } + } + } + pr_debug("Found metric '%s' whose evsels match those of in the perf data\n", + pm->metric_name); + evlist__delete(metric_evlist); +out: + return 0; +} + +static struct aggr_cpu_id script_aggr_cpu_id_get(struct perf_stat_config *config __maybe_unused, + struct perf_cpu cpu) +{ + return aggr_cpu_id__global(cpu, /*data=*/NULL); +} + +static void perf_sample__fprint_metric(struct thread *thread, struct evsel *evsel, struct perf_sample *sample, FILE *fp) { - struct evsel *leader = evsel__leader(evsel); + static bool init_metrics; struct perf_stat_output_ctx ctx = { .print_metric = script_print_metric, .new_line = script_new_line, @@ -2150,23 +2296,85 @@ static void perf_sample__fprint_metric(struct perf_script *script, }, .force_header = false, }; - struct evsel *ev2; - u64 val; + struct perf_counts_values *count, *old_count; + int cpu_map_idx, thread_map_idx, aggr_idx; + struct evsel *pos; + + if (!init_metrics) { + /* One time initialization of stat_config and metric data. */ + struct script_find_metrics_args args = { + .evlist = evsel->evlist, + .system_wide = perf_thread_map__pid(evsel->core.threads, /*idx=*/0) == -1, + + }; + if (!stat_config.output) + stat_config.output = stdout; + + if (!stat_config.aggr_map) { + /* TODO: currently only global aggregation is supported. */ + assert(stat_config.aggr_mode == AGGR_GLOBAL); + stat_config.aggr_get_id = script_aggr_cpu_id_get; + stat_config.aggr_map = + cpu_aggr_map__new(evsel->evlist->core.user_requested_cpus, + aggr_cpu_id__global, /*data=*/NULL, + /*needs_sort=*/false); + } + + metricgroup__for_each_metric(pmu_metrics_table__find(), script_find_metrics, &args); + init_metrics = true; + } + + if (!evsel->stats) { + if (evlist__alloc_stats(&stat_config, evsel->evlist, /*alloc_raw=*/true) < 0) + return; + } + if (!evsel->stats->aggr) { + if (evlist__alloc_aggr_stats(evsel->evlist, stat_config.aggr_map->nr) < 0) + return; + } - if (!evsel->stats) - evlist__alloc_stats(&stat_config, script->session->evlist, /*alloc_raw=*/false); - if (evsel_script(leader)->gnum++ == 0) - perf_stat__reset_shadow_stats(); - val = sample->period * evsel->scale; - evsel_script(evsel)->val = val; - if (evsel_script(leader)->gnum == leader->core.nr_members) { - for_each_group_member (ev2, leader) { - perf_stat__print_shadow_stats(&stat_config, ev2, - evsel_script(ev2)->val, - sample->cpu, - &ctx); + /* Update the evsel's count using the sample's data. */ + cpu_map_idx = perf_cpu_map__idx(evsel->core.cpus, (struct perf_cpu){sample->cpu}); + if (cpu_map_idx < 0) { + /* Missing CPU, check for any CPU. */ + if (perf_cpu_map__cpu(evsel->core.cpus, /*idx=*/0).cpu == -1 || + sample->cpu == (u32)-1) { + /* Place the counts in the which ever CPU is first in the map. */ + cpu_map_idx = 0; + } else { + pr_info("Missing CPU map entry for CPU %d\n", sample->cpu); + return; + } + } + thread_map_idx = perf_thread_map__idx(evsel->core.threads, sample->tid); + if (thread_map_idx < 0) { + /* Missing thread, check for any thread. */ + if (perf_thread_map__pid(evsel->core.threads, /*idx=*/0) == -1 || + sample->tid == (u32)-1) { + /* Place the counts in the which ever thread is first in the map. */ + thread_map_idx = 0; + } else { + pr_info("Missing thread map entry for thread %d\n", sample->tid); + return; + } + } + count = perf_counts(evsel->counts, cpu_map_idx, thread_map_idx); + old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread_map_idx); + count->val = old_count->val + sample->period; + count->run = old_count->run + 1; + count->ena = old_count->ena + 1; + + /* Update the aggregated stats. */ + perf_stat_process_counter(&stat_config, evsel); + + /* Display all metrics. */ + evlist__for_each_entry(evsel->evlist, pos) { + cpu_aggr_map__for_each_idx(aggr_idx, stat_config.aggr_map) { + perf_stat__print_shadow_stats(&stat_config, pos, + count->val, + aggr_idx, + &ctx); } - evsel_script(leader)->gnum = 0; } } @@ -2348,7 +2556,7 @@ static void process_event(struct perf_script *script, } if (PRINT_FIELD(METRIC)) - perf_sample__fprint_metric(script, thread, evsel, sample, fp); + perf_sample__fprint_metric(thread, evsel, sample, fp); if (verbose > 0) fflush(fp); From b71f46a6a708617502faa1be915feb7dd6ecf603 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:55 -0800 Subject: [PATCH 274/684] perf stat: Remove hard coded shadow metrics Now that the metrics are encoded in common json the hard coded printing means the metrics are shown twice. Remove the hard coded version. This means that when specifying events, and those events correspond to a hard coded metric, the metric will no longer be displayed. The metric will be displayed if the metric is requested. Due to the adhoc printing in the previous approach it was often found frustrating, the new approach avoids this. The default perf stat output on an alderlake now looks like: ``` $ perf stat -a -- sleep 1 Performance counter stats for 'system wide': 19,697 context-switches # nan cs/sec cs_per_second TopdownL1 (cpu_core) # 10.7 % tma_bad_speculation # 24.9 % tma_frontend_bound TopdownL1 (cpu_core) # 34.3 % tma_backend_bound # 30.1 % tma_retiring 6,593 page-faults # nan faults/sec page_faults_per_second 729,065,658 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (49.79%) 1,605,131,101 cpu_core/cpu-cycles/ # nan GHz cycles_frequency # 19.7 % tma_bad_speculation # 14.2 % tma_retiring (50.14%) # 37.3 % tma_frontend_bound (50.31%) 87,302,268 cpu_atom/branches/ # nan M/sec branch_frequency (60.27%) 512,046,956 cpu_core/branches/ # nan M/sec branch_frequency 1,111 cpu-migrations # nan migrations/sec migrations_per_second # 28.8 % tma_backend_bound (60.26%) 0.00 msec cpu-clock # 0.0 CPUs CPUs_utilized 392,509,323 cpu_atom/instructions/ # 0.6 instructions insn_per_cycle (60.19%) 2,990,369,310 cpu_core/instructions/ # 1.9 instructions insn_per_cycle 3,493,478 cpu_atom/branch-misses/ # 5.9 % branch_miss_rate (49.69%) 7,297,531 cpu_core/branch-misses/ # 1.4 % branch_miss_rate 1.006621701 seconds time elapsed ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-script.c | 1 - tools/perf/util/stat-display.c | 4 +- tools/perf/util/stat-shadow.c | 392 +-------------------------------- tools/perf/util/stat.h | 2 +- 4 files changed, 6 insertions(+), 393 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 8bab5b264f6136..cf0040bbaba9cb 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2371,7 +2371,6 @@ static void perf_sample__fprint_metric(struct thread *thread, evlist__for_each_entry(evsel->evlist, pos) { cpu_aggr_map__for_each_idx(aggr_idx, stat_config.aggr_map) { perf_stat__print_shadow_stats(&stat_config, pos, - count->val, aggr_idx, &ctx); } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 4d0e353846ead0..eabeab5e661459 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -902,7 +902,7 @@ static void printout(struct perf_stat_config *config, struct outstate *os, &num, from, &out); } while (from != NULL); } else { - perf_stat__print_shadow_stats(config, counter, uval, aggr_idx, &out); + perf_stat__print_shadow_stats(config, counter, aggr_idx, &out); } } else { pm(config, os, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, /*unit=*/NULL, /*val=*/0); @@ -1274,7 +1274,7 @@ static void print_metric_headers(struct perf_stat_config *config, os.evsel = counter; - perf_stat__print_shadow_stats(config, counter, 0, 0, &out); + perf_stat__print_shadow_stats(config, counter, /*aggr_idx=*/0, &out); } if (!config->json_output) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 4df614f8e20054..afbc49e8cb3143 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -20,357 +20,12 @@ struct stats walltime_nsecs_stats; struct rusage_stats ru_stats; -enum { - CTX_BIT_USER = 1 << 0, - CTX_BIT_KERNEL = 1 << 1, - CTX_BIT_HV = 1 << 2, - CTX_BIT_HOST = 1 << 3, - CTX_BIT_IDLE = 1 << 4, - CTX_BIT_MAX = 1 << 5, -}; - -enum stat_type { - STAT_NONE = 0, - STAT_NSECS, - STAT_CYCLES, - STAT_INSTRUCTIONS, - STAT_STALLED_CYCLES_FRONT, - STAT_STALLED_CYCLES_BACK, - STAT_BRANCHES, - STAT_BRANCH_MISS, - STAT_CACHE_REFS, - STAT_CACHE_MISSES, - STAT_L1_DCACHE, - STAT_L1_ICACHE, - STAT_LL_CACHE, - STAT_ITLB_CACHE, - STAT_DTLB_CACHE, - STAT_L1D_MISS, - STAT_L1I_MISS, - STAT_LL_MISS, - STAT_DTLB_MISS, - STAT_ITLB_MISS, - STAT_MAX -}; - -static int evsel_context(const struct evsel *evsel) -{ - int ctx = 0; - - if (evsel->core.attr.exclude_kernel) - ctx |= CTX_BIT_KERNEL; - if (evsel->core.attr.exclude_user) - ctx |= CTX_BIT_USER; - if (evsel->core.attr.exclude_hv) - ctx |= CTX_BIT_HV; - if (evsel->core.attr.exclude_host) - ctx |= CTX_BIT_HOST; - if (evsel->core.attr.exclude_idle) - ctx |= CTX_BIT_IDLE; - - return ctx; -} - void perf_stat__reset_shadow_stats(void) { memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); memset(&ru_stats, 0, sizeof(ru_stats)); } -static enum stat_type evsel__stat_type(struct evsel *evsel) -{ - /* Fake perf_hw_cache_op_id values for use with evsel__match. */ - u64 PERF_COUNT_hw_cache_l1d_miss = PERF_COUNT_HW_CACHE_L1D | - ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); - u64 PERF_COUNT_hw_cache_l1i_miss = PERF_COUNT_HW_CACHE_L1I | - ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); - u64 PERF_COUNT_hw_cache_ll_miss = PERF_COUNT_HW_CACHE_LL | - ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); - u64 PERF_COUNT_hw_cache_dtlb_miss = PERF_COUNT_HW_CACHE_DTLB | - ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); - u64 PERF_COUNT_hw_cache_itlb_miss = PERF_COUNT_HW_CACHE_ITLB | - ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | - ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); - - if (evsel__is_clock(evsel)) - return STAT_NSECS; - else if (evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) - return STAT_CYCLES; - else if (evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) - return STAT_INSTRUCTIONS; - else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) - return STAT_STALLED_CYCLES_FRONT; - else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) - return STAT_STALLED_CYCLES_BACK; - else if (evsel__match(evsel, HARDWARE, HW_BRANCH_INSTRUCTIONS)) - return STAT_BRANCHES; - else if (evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) - return STAT_BRANCH_MISS; - else if (evsel__match(evsel, HARDWARE, HW_CACHE_REFERENCES)) - return STAT_CACHE_REFS; - else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) - return STAT_CACHE_MISSES; - else if (evsel__match(evsel, HW_CACHE, HW_CACHE_L1D)) - return STAT_L1_DCACHE; - else if (evsel__match(evsel, HW_CACHE, HW_CACHE_L1I)) - return STAT_L1_ICACHE; - else if (evsel__match(evsel, HW_CACHE, HW_CACHE_LL)) - return STAT_LL_CACHE; - else if (evsel__match(evsel, HW_CACHE, HW_CACHE_DTLB)) - return STAT_DTLB_CACHE; - else if (evsel__match(evsel, HW_CACHE, HW_CACHE_ITLB)) - return STAT_ITLB_CACHE; - else if (evsel__match(evsel, HW_CACHE, hw_cache_l1d_miss)) - return STAT_L1D_MISS; - else if (evsel__match(evsel, HW_CACHE, hw_cache_l1i_miss)) - return STAT_L1I_MISS; - else if (evsel__match(evsel, HW_CACHE, hw_cache_ll_miss)) - return STAT_LL_MISS; - else if (evsel__match(evsel, HW_CACHE, hw_cache_dtlb_miss)) - return STAT_DTLB_MISS; - else if (evsel__match(evsel, HW_CACHE, hw_cache_itlb_miss)) - return STAT_ITLB_MISS; - return STAT_NONE; -} - -static enum metric_threshold_classify get_ratio_thresh(const double ratios[3], double val) -{ - assert(ratios[0] > ratios[1]); - assert(ratios[1] > ratios[2]); - - return val > ratios[1] - ? (val > ratios[0] ? METRIC_THRESHOLD_BAD : METRIC_THRESHOLD_NEARLY_BAD) - : (val > ratios[2] ? METRIC_THRESHOLD_LESS_GOOD : METRIC_THRESHOLD_GOOD); -} - -static double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type type) -{ - struct evsel *cur; - int evsel_ctx = evsel_context(evsel); - struct perf_pmu *evsel_pmu = evsel__find_pmu(evsel); - - evlist__for_each_entry(evsel->evlist, cur) { - struct perf_stat_aggr *aggr; - - /* Ignore the evsel that is being searched from. */ - if (evsel == cur) - continue; - - /* Ignore evsels that are part of different groups. */ - if (evsel->core.leader->nr_members > 1 && - evsel->core.leader != cur->core.leader) - continue; - /* Ignore evsels with mismatched modifiers. */ - if (evsel_ctx != evsel_context(cur)) - continue; - /* Ignore if not the cgroup we're looking for. */ - if (evsel->cgrp != cur->cgrp) - continue; - /* Ignore if not the stat we're looking for. */ - if (type != evsel__stat_type(cur)) - continue; - - /* - * Except the SW CLOCK events, - * ignore if not the PMU we're looking for. - */ - if ((type != STAT_NSECS) && (evsel_pmu != evsel__find_pmu(cur))) - continue; - - aggr = &cur->stats->aggr[aggr_idx]; - if (type == STAT_NSECS) - return aggr->counts.val; - return aggr->counts.val * cur->scale; - } - return 0.0; -} - -static void print_ratio(struct perf_stat_config *config, - const struct evsel *evsel, int aggr_idx, - double numerator, struct perf_stat_output_ctx *out, - enum stat_type denominator_type, - const double thresh_ratios[3], const char *_unit) -{ - double denominator = find_stat(evsel, aggr_idx, denominator_type); - double ratio = 0; - enum metric_threshold_classify thresh = METRIC_THRESHOLD_UNKNOWN; - const char *fmt = NULL; - const char *unit = NULL; - - if (numerator && denominator) { - ratio = numerator / denominator * 100.0; - thresh = get_ratio_thresh(thresh_ratios, ratio); - fmt = "%7.2f%%"; - unit = _unit; - } - out->print_metric(config, out->ctx, thresh, fmt, unit, ratio); -} - -static void print_stalled_cycles_front(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double stalled, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {50.0, 30.0, 10.0}; - - print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios, - "frontend cycles idle"); -} - -static void print_stalled_cycles_back(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double stalled, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {75.0, 50.0, 20.0}; - - print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios, - "backend cycles idle"); -} - -static void print_branch_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, thresh_ratios, - "of all branches"); -} - -static void print_l1d_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, thresh_ratios, - "of all L1-dcache accesses"); -} - -static void print_l1i_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, thresh_ratios, - "of all L1-icache accesses"); -} - -static void print_ll_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, thresh_ratios, - "of all LL-cache accesses"); -} - -static void print_dtlb_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, thresh_ratios, - "of all dTLB cache accesses"); -} - -static void print_itlb_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, thresh_ratios, - "of all iTLB cache accesses"); -} - -static void print_cache_miss(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out) -{ - const double thresh_ratios[3] = {20.0, 10.0, 5.0}; - - print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, thresh_ratios, - "of all cache refs"); -} - -static void print_instructions(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double instructions, - struct perf_stat_output_ctx *out) -{ - print_metric_t print_metric = out->print_metric; - void *ctxp = out->ctx; - double cycles = find_stat(evsel, aggr_idx, STAT_CYCLES); - double max_stalled = max(find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_FRONT), - find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_BACK)); - - if (cycles) { - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ", - "insn per cycle", instructions / cycles); - } else { - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, - "insn per cycle", 0); - } - if (max_stalled && instructions) { - if (out->new_line) - out->new_line(config, ctxp); - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ", - "stalled cycles per insn", max_stalled / instructions); - } -} - -static void print_cycles(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double cycles, - struct perf_stat_output_ctx *out) -{ - double nsecs = find_stat(evsel, aggr_idx, STAT_NSECS); - - if (cycles && nsecs) { - double ratio = cycles / nsecs; - - out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, "%8.3f", - "GHz", ratio); - } else { - out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, - "GHz", 0); - } -} - -static void print_nsecs(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx __maybe_unused, double nsecs, - struct perf_stat_output_ctx *out) -{ - print_metric_t print_metric = out->print_metric; - void *ctxp = out->ctx; - double wall_time = avg_stats(&walltime_nsecs_stats); - - if (wall_time) { - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f", "CPUs utilized", - nsecs / (wall_time * evsel->scale)); - } else { - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, - "CPUs utilized", 0); - } -} - static int prepare_metric(const struct metric_expr *mexp, const struct evsel *evsel, struct expr_parse_ctx *pctx, @@ -682,56 +337,15 @@ void *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config, void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, - double avg, int aggr_idx, + int aggr_idx, struct perf_stat_output_ctx *out) { - typedef void (*stat_print_function_t)(struct perf_stat_config *config, - const struct evsel *evsel, - int aggr_idx, double misses, - struct perf_stat_output_ctx *out); - static const stat_print_function_t stat_print_function[STAT_MAX] = { - [STAT_INSTRUCTIONS] = print_instructions, - [STAT_BRANCH_MISS] = print_branch_miss, - [STAT_L1D_MISS] = print_l1d_miss, - [STAT_L1I_MISS] = print_l1i_miss, - [STAT_DTLB_MISS] = print_dtlb_miss, - [STAT_ITLB_MISS] = print_itlb_miss, - [STAT_LL_MISS] = print_ll_miss, - [STAT_CACHE_MISSES] = print_cache_miss, - [STAT_STALLED_CYCLES_FRONT] = print_stalled_cycles_front, - [STAT_STALLED_CYCLES_BACK] = print_stalled_cycles_back, - [STAT_CYCLES] = print_cycles, - [STAT_NSECS] = print_nsecs, - }; print_metric_t print_metric = out->print_metric; void *ctxp = out->ctx; - int num = 1; + int num = 0; - if (config->iostat_run) { + if (config->iostat_run) iostat_print_metric(config, evsel, out); - } else { - stat_print_function_t fn = stat_print_function[evsel__stat_type(evsel)]; - - if (fn) - fn(config, evsel, aggr_idx, avg, out); - else { - double nsecs = find_stat(evsel, aggr_idx, STAT_NSECS); - - if (nsecs) { - char unit = ' '; - char unit_buf[10] = "/sec"; - double ratio = convert_unit_double(1000000000.0 * avg / nsecs, - &unit); - - if (unit != ' ') - snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); - print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f", - unit_buf, ratio); - } else { - num = 0; - } - } - } perf_stat__print_shadow_stats_metricgroup(config, evsel, aggr_idx, &num, NULL, out); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 230474f4931518..b42da4a29c442c 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -184,7 +184,7 @@ struct perf_stat_output_ctx { void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, - double avg, int aggr_idx, + int aggr_idx, struct perf_stat_output_ctx *out); bool perf_stat__skip_metric_event(struct evsel *evsel, u64 ena, u64 run); void *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config, From 19df87d9ed7072d08b80a2aae58ac971716c2c18 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:56 -0800 Subject: [PATCH 275/684] perf stat: Fix default metricgroup display on hybrid The logic to skip output of a default metric line was firing on Alderlake and not displaying 'TopdownL1 (cpu_atom)'. Remove the need_full_name check as it is equivalent to the different PMU test in the cases we care about, merge the 'if's and flip the evsel of the PMU test. The 'if' is now basically saying, if the output matches the last printed output then skip the output. Before: ``` TopdownL1 (cpu_core) # 11.3 % tma_bad_speculation # 24.3 % tma_frontend_bound TopdownL1 (cpu_core) # 33.9 % tma_backend_bound # 30.6 % tma_retiring # 42.2 % tma_backend_bound # 25.0 % tma_frontend_bound (49.81%) # 12.8 % tma_bad_speculation # 20.0 % tma_retiring (59.46%) ``` After: ``` TopdownL1 (cpu_core) # 8.3 % tma_bad_speculation # 43.7 % tma_frontend_bound # 30.7 % tma_backend_bound # 17.2 % tma_retiring TopdownL1 (cpu_atom) # 31.9 % tma_backend_bound # 37.6 % tma_frontend_bound (49.66%) # 18.0 % tma_bad_speculation # 12.6 % tma_retiring (59.58%) ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/stat-shadow.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index afbc49e8cb3143..c1547128c39623 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -256,11 +256,9 @@ static void perf_stat__print_metricgroup_header(struct perf_stat_config *config, * event. Only align with other metics from * different metric events. */ - if (last_name && !strcmp(last_name, name)) { - if (!need_full_name || last_pmu != evsel->pmu) { - out->print_metricgroup_header(config, ctxp, NULL); - return; - } + if (last_name && !strcmp(last_name, name) && last_pmu == evsel->pmu) { + out->print_metricgroup_header(config, ctxp, NULL); + return; } if (need_full_name && evsel->pmu) From a745c0831c15cd93daf9651149cb54e557e54956 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:57 -0800 Subject: [PATCH 276/684] perf stat: Sort default events/metrics To improve the readability of default events/metrics, sort the evsels after the Default metric groups have be parsed. Before: ``` $ perf stat -a sleep 1 Performance counter stats for 'system wide': 22,087 context-switches # nan cs/sec cs_per_second TopdownL1 (cpu_core) # 10.3 % tma_bad_speculation # 25.8 % tma_frontend_bound # 34.5 % tma_backend_bound # 29.3 % tma_retiring 7,829 page-faults # nan faults/sec page_faults_per_second 880,144,270 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (50.10%) 1,693,081,235 cpu_core/cpu-cycles/ # nan GHz cycles_frequency TopdownL1 (cpu_atom) # 20.5 % tma_bad_speculation # 13.8 % tma_retiring (50.26%) # 34.6 % tma_frontend_bound (50.23%) 89,326,916 cpu_atom/branches/ # nan M/sec branch_frequency (60.19%) 538,123,088 cpu_core/branches/ # nan M/sec branch_frequency 1,368 cpu-migrations # nan migrations/sec migrations_per_second # 31.1 % tma_backend_bound (60.19%) 0.00 msec cpu-clock # 0.0 CPUs CPUs_utilized 485,744,856 cpu_atom/instructions/ # 0.6 instructions insn_per_cycle (59.87%) 3,093,112,283 cpu_core/instructions/ # 1.8 instructions insn_per_cycle 4,939,427 cpu_atom/branch-misses/ # 5.0 % branch_miss_rate (49.77%) 7,632,248 cpu_core/branch-misses/ # 1.4 % branch_miss_rate 1.005084693 seconds time elapsed ``` After: ``` $ perf stat -a sleep 1 Performance counter stats for 'system wide': 22,165 context-switches # nan cs/sec cs_per_second 0.00 msec cpu-clock # 0.0 CPUs CPUs_utilized 2,260 cpu-migrations # nan migrations/sec migrations_per_second 20,476 page-faults # nan faults/sec page_faults_per_second 17,052,357 cpu_core/branch-misses/ # 1.5 % branch_miss_rate 1,120,090,590 cpu_core/branches/ # nan M/sec branch_frequency 3,402,892,275 cpu_core/cpu-cycles/ # nan GHz cycles_frequency 6,129,236,701 cpu_core/instructions/ # 1.8 instructions insn_per_cycle 6,159,523 cpu_atom/branch-misses/ # 3.1 % branch_miss_rate (49.86%) 222,158,812 cpu_atom/branches/ # nan M/sec branch_frequency (50.25%) 1,547,610,244 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (50.40%) 1,304,901,260 cpu_atom/instructions/ # 0.8 instructions insn_per_cycle (50.41%) TopdownL1 (cpu_core) # 13.7 % tma_bad_speculation # 23.5 % tma_frontend_bound # 33.3 % tma_backend_bound # 29.6 % tma_retiring TopdownL1 (cpu_atom) # 32.1 % tma_backend_bound (59.65%) # 30.1 % tma_frontend_bound (59.51%) # 22.3 % tma_bad_speculation # 15.5 % tma_retiring (59.53%) 1.008405429 seconds time elapsed ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7862094b93c88f..095016b2209e92 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -74,6 +74,7 @@ #include "util/intel-tpebs.h" #include "asm/bug.h" +#include #include #include #include @@ -1857,6 +1858,35 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) return 0; } +static int default_evlist_evsel_cmp(void *priv __maybe_unused, + const struct list_head *l, + const struct list_head *r) +{ + const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node); + const struct evsel *lhs = container_of(lhs_core, struct evsel, core); + const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node); + const struct evsel *rhs = container_of(rhs_core, struct evsel, core); + + if (evsel__leader(lhs) == evsel__leader(rhs)) { + /* Within the same group, respect the original order. */ + return lhs_core->idx - rhs_core->idx; + } + + /* Sort default metrics evsels first, and default show events before those. */ + if (lhs->default_metricgroup != rhs->default_metricgroup) + return lhs->default_metricgroup ? -1 : 1; + + if (lhs->default_show_events != rhs->default_show_events) + return lhs->default_show_events ? -1 : 1; + + /* Sort by PMU type (prefers legacy types first). */ + if (lhs->pmu != rhs->pmu) + return lhs->pmu->type - rhs->pmu->type; + + /* Sort by name. */ + return strcmp(evsel__name((struct evsel *)lhs), evsel__name((struct evsel *)rhs)); +} + /* * Add default events, if there were no attributes specified or * if -d/--detailed, -d -d or -d -d -d is used: @@ -2023,6 +2053,8 @@ static int add_default_events(void) &metric_evlist->metric_events); evlist__delete(metric_evlist); } + list_sort(/*priv=*/NULL, &evlist->core.entries, default_evlist_evsel_cmp); + } out: if (!ret) { From 1bcd6271651e55329664e38446ab0288b64fb326 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:58 -0800 Subject: [PATCH 277/684] perf stat: Remove "unit" workarounds for metric-only Remove code that tested the "unit" as in KB/sec for certain hard coded metric values and did workarounds. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/stat-display.c | 47 ++++++---------------------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index eabeab5e661459..b3596f9f5cdd81 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -592,42 +592,18 @@ static void print_metricgroup_header_std(struct perf_stat_config *config, fprintf(config->output, "%*s", MGROUP_LEN - n - 1, ""); } -/* Filter out some columns that don't work well in metrics only mode */ - -static bool valid_only_metric(const char *unit) -{ - if (!unit) - return false; - if (strstr(unit, "/sec") || - strstr(unit, "CPUs utilized")) - return false; - return true; -} - -static const char *fixunit(char *buf, struct evsel *evsel, - const char *unit) -{ - if (!strncmp(unit, "of all", 6)) { - snprintf(buf, 1024, "%s %s", evsel__name(evsel), - unit); - return buf; - } - return unit; -} - static void print_metric_only(struct perf_stat_config *config, void *ctx, enum metric_threshold_classify thresh, const char *fmt, const char *unit, double val) { struct outstate *os = ctx; FILE *out = os->fh; - char buf[1024], str[1024]; + char str[1024]; unsigned mlen = config->metric_only_len; const char *color = metric_threshold_classify__color(thresh); - if (!valid_only_metric(unit)) - return; - unit = fixunit(buf, os->evsel, unit); + if (!unit) + unit = ""; if (mlen < strlen(unit)) mlen = strlen(unit) + 1; @@ -643,16 +619,15 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused void *ctx, enum metric_threshold_classify thresh __maybe_unused, const char *fmt, - const char *unit, double val) + const char *unit __maybe_unused, double val) { struct outstate *os = ctx; FILE *out = os->fh; char buf[64], *vals, *ends; - char tbuf[1024]; - if (!valid_only_metric(unit)) + if (!unit) return; - unit = fixunit(tbuf, os->evsel, unit); + snprintf(buf, sizeof(buf), fmt ?: "", val); ends = vals = skip_spaces(buf); while (isdigit(*ends) || *ends == '.') @@ -670,13 +645,9 @@ static void print_metric_only_json(struct perf_stat_config *config __maybe_unuse { struct outstate *os = ctx; char buf[64], *ends; - char tbuf[1024]; const char *vals; - if (!valid_only_metric(unit)) - return; - unit = fixunit(tbuf, os->evsel, unit); - if (!unit[0]) + if (!unit || !unit[0]) return; snprintf(buf, sizeof(buf), fmt ?: "", val); vals = ends = skip_spaces(buf); @@ -695,7 +666,6 @@ static void print_metric_header(struct perf_stat_config *config, const char *unit, double val __maybe_unused) { struct outstate *os = ctx; - char tbuf[1024]; /* In case of iostat, print metric header for first root port only */ if (config->iostat_run && @@ -705,9 +675,8 @@ static void print_metric_header(struct perf_stat_config *config, if (os->evsel->cgrp != os->cgrp) return; - if (!valid_only_metric(unit)) + if (!unit) return; - unit = fixunit(tbuf, os->evsel, unit); if (config->json_output) return; From 2c240484cf52da3c2ca14cfb70e8cf9179197ced Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:21:59 -0800 Subject: [PATCH 278/684] perf test stat+json: Improve metric-only testing When testing metric-only, pass a metric to perf rather than expecting a hard coded metric value to be generated. Remove keys that were really metric-only units and instead don't expect metric only to have a matching json key as it encodes metrics as {"metric_name", "metric_value"}. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/lib/perf_json_output_lint.py | 4 ++-- tools/perf/tests/shell/stat+json_output.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/shell/lib/perf_json_output_lint.py b/tools/perf/tests/shell/lib/perf_json_output_lint.py index c6750ef06c0f8c..1369baaa0361bd 100644 --- a/tools/perf/tests/shell/lib/perf_json_output_lint.py +++ b/tools/perf/tests/shell/lib/perf_json_output_lint.py @@ -65,8 +65,6 @@ def check_json_output(expected_items): 'socket': lambda x: True, 'thread': lambda x: True, 'unit': lambda x: True, - 'insn per cycle': lambda x: isfloat(x), - 'GHz': lambda x: True, # FIXME: it seems unintended for --metric-only } input = '[\n' + ','.join(Lines) + '\n]' for item in json.loads(input): @@ -88,6 +86,8 @@ def check_json_output(expected_items): f' in \'{item}\'') for key, value in item.items(): if key not in checks: + if args.metric_only: + continue raise RuntimeError(f'Unexpected key: key={key} value={value}') if not checks[key](value): raise RuntimeError(f'Check failed for: key={key} value={value}') diff --git a/tools/perf/tests/shell/stat+json_output.sh b/tools/perf/tests/shell/stat+json_output.sh index 98fb65274ac4f7..85d1ad7186c6e0 100755 --- a/tools/perf/tests/shell/stat+json_output.sh +++ b/tools/perf/tests/shell/stat+json_output.sh @@ -181,7 +181,7 @@ check_metric_only() echo "[Skip] CPU-measurement counter facility not installed" return fi - perf stat -j --metric-only -e instructions,cycles -o "${stat_output}" true + perf stat -j --metric-only -M page_faults_per_second -o "${stat_output}" true $PYTHON $pythonchecker --metric-only --file "${stat_output}" echo "[Success]" } From b1cb2b76bd16d5399fa7d21b2909134687f021b0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:00 -0800 Subject: [PATCH 279/684] perf test stat: Ignore failures in Default[234] metricgroups The Default[234] metric groups may contain unsupported legacy events. Allow those metric groups to fail. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat_all_metricgroups.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/tests/shell/stat_all_metricgroups.sh b/tools/perf/tests/shell/stat_all_metricgroups.sh index c6d61a4ac3e7d3..1400880ec01f82 100755 --- a/tools/perf/tests/shell/stat_all_metricgroups.sh +++ b/tools/perf/tests/shell/stat_all_metricgroups.sh @@ -37,6 +37,9 @@ do then err=2 # Skip fi + elif [[ "$m" == @(Default2|Default3|Default4) ]] + then + echo "Ignoring failures in $m that may contain unsupported legacy events" else echo "Metric group $m failed" echo $result From 083ae6c1fbf69a56f638aa9a477d35afdea2ab3f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:01 -0800 Subject: [PATCH 280/684] perf test stat: Update std_output testing metric expectations Make the expectations match json metrics rather than the previous hard coded ones. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat+std_output.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/shell/stat+std_output.sh b/tools/perf/tests/shell/stat+std_output.sh index ec41f24299d9a7..9c4b92ecf4485c 100755 --- a/tools/perf/tests/shell/stat+std_output.sh +++ b/tools/perf/tests/shell/stat+std_output.sh @@ -12,8 +12,8 @@ set -e stat_output=$(mktemp /tmp/__perf_test.stat_output.std.XXXXX) event_name=(cpu-clock task-clock context-switches cpu-migrations page-faults stalled-cycles-frontend stalled-cycles-backend cycles instructions branches branch-misses) -event_metric=("CPUs utilized" "CPUs utilized" "/sec" "/sec" "/sec" "frontend cycles idle" "backend cycles idle" "GHz" "insn per cycle" "/sec" "of all branches") -skip_metric=("stalled cycles per insn" "tma_" "retiring" "frontend_bound" "bad_speculation" "backend_bound" "TopdownL1" "percent of slots") +event_metric=("CPUs_utilized" "CPUs_utilized" "cs/sec" "migrations/sec" "faults/sec" "frontend_cycles_idle" "backend_cycles_idle" "GHz" "insn_per_cycle" "/sec" "branch_miss_rate") +skip_metric=("tma_" "TopdownL1") cleanup() { rm -f "${stat_output}" From 91c1949d768520d9befa7761eb97c3826997da25 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:02 -0800 Subject: [PATCH 281/684] perf test metrics: Update all metrics for possibly failing default metrics Default metrics may use unsupported events and be ignored. These metrics shouldn't cause metric testing to fail. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat_all_metrics.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/stat_all_metrics.sh b/tools/perf/tests/shell/stat_all_metrics.sh index 6fa585a1e34c9f..a7edf01b394336 100755 --- a/tools/perf/tests/shell/stat_all_metrics.sh +++ b/tools/perf/tests/shell/stat_all_metrics.sh @@ -25,8 +25,13 @@ for m in $(perf list --raw-dump metrics); do # No error result and metric shown. continue fi - if [[ "$result" =~ "Cannot resolve IDs for" ]] + if [[ "$result" =~ "Cannot resolve IDs for" || "$result" =~ "No supported events found" ]] then + if [[ "$m" == @(l1_prefetch_miss_rate|stalled_cycles_per_instruction) ]] + then + # Default metrics that may use unsupported events. + continue + fi echo "Metric contains missing events" echo $result err=1 # Fail From 6b76f0678b245a9d59ae6a4b69a7bdd8cae89476 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:03 -0800 Subject: [PATCH 282/684] perf test stat: Update shadow test to use metrics Previously '-e cycles,instructions' would implicitly create an IPC metric. This now has to be explicit with '-M insn_per_cycle'. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat+shadow_stat.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/shell/stat+shadow_stat.sh b/tools/perf/tests/shell/stat+shadow_stat.sh index 8824f445d34308..cabbbf17c662df 100755 --- a/tools/perf/tests/shell/stat+shadow_stat.sh +++ b/tools/perf/tests/shell/stat+shadow_stat.sh @@ -14,7 +14,7 @@ perf stat -a -e cycles sleep 1 2>&1 | grep -e cpu_core && exit 2 test_global_aggr() { - perf stat -a --no-big-num -e cycles,instructions sleep 1 2>&1 | \ + perf stat -a --no-big-num -M insn_per_cycle sleep 1 2>&1 | \ grep -e cycles -e instructions | \ while read num evt _ ipc rest do @@ -53,7 +53,7 @@ test_global_aggr() test_no_aggr() { - perf stat -a -A --no-big-num -e cycles,instructions sleep 1 2>&1 | \ + perf stat -a -A --no-big-num -M insn_per_cycle sleep 1 2>&1 | \ grep ^CPU | \ while read cpu num evt _ ipc rest do From a48cd551d7436be3b1bd65c63a6d00163f7e7706 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:04 -0800 Subject: [PATCH 283/684] perf test stat: Update test expectations and events test_stat_record_report and test_stat_record_script used default output which triggers a bug when sending metrics. As this isn't relevant to the test switch to using named software events. Update the match in test_hybrid as the cycles event is now cpu-cycles to workaround potential ARM issues. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh index 8a100a7f2dc17f..985adc02749e2c 100755 --- a/tools/perf/tests/shell/stat.sh +++ b/tools/perf/tests/shell/stat.sh @@ -18,7 +18,7 @@ test_default_stat() { test_stat_record_report() { echo "stat record and report test" - if ! perf stat record -o - true | perf stat report -i - 2>&1 | \ + if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \ grep -E -q "Performance counter stats for 'pipe':" then echo "stat record and report test [Failed]" @@ -30,7 +30,7 @@ test_stat_record_report() { test_stat_record_script() { echo "stat record and script test" - if ! perf stat record -o - true | perf script -i - 2>&1 | \ + if ! perf stat record -e task-clock -o - true | perf script -i - 2>&1 | \ grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:space:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT" then echo "stat record and script test [Failed]" @@ -196,7 +196,7 @@ test_hybrid() { fi # Run default Perf stat - cycles_events=$(perf stat -- true 2>&1 | grep -E "/cycles/[uH]*| cycles[:uH]* " -c) + cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " -c) # The expectation is that default output will have a cycles events on each # hybrid PMU. In situations with no cycles PMU events, like virtualized, this From 02432d920e3b174ff44a9fabb82fc8316f236a65 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:05 -0800 Subject: [PATCH 284/684] perf test stat csv: Update test expectations and events Explicitly use a metric rather than implicitly expecting '-e instructions,cycles' to produce a metric. Use a metric with software events to make it more compatible. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/lib/stat_output.sh | 2 +- tools/perf/tests/shell/stat+csv_output.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/shell/lib/stat_output.sh b/tools/perf/tests/shell/lib/stat_output.sh index c2ec7881ec1de4..3c36e80fe42287 100644 --- a/tools/perf/tests/shell/lib/stat_output.sh +++ b/tools/perf/tests/shell/lib/stat_output.sh @@ -156,7 +156,7 @@ check_metric_only() echo "[Skip] CPU-measurement counter facility not installed" return fi - perf stat --metric-only $2 -e instructions,cycles true + perf stat --metric-only $2 -M page_faults_per_second true commachecker --metric-only echo "[Success]" } diff --git a/tools/perf/tests/shell/stat+csv_output.sh b/tools/perf/tests/shell/stat+csv_output.sh index 7a6f6e17740283..cd6fff59709116 100755 --- a/tools/perf/tests/shell/stat+csv_output.sh +++ b/tools/perf/tests/shell/stat+csv_output.sh @@ -44,7 +44,7 @@ function commachecker() ;; "--per-die") exp=8 ;; "--per-cluster") exp=8 ;; "--per-cache") exp=8 - ;; "--metric-only") exp=2 + ;; "--metric-only") exp=1 esac while read line From 68cc6ec3ac2960f0871421c16e49cba826fdff52 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 11 Nov 2025 13:22:06 -0800 Subject: [PATCH 285/684] perf tool_pmu: Make core_wide and target_cpu json events For the sake of better documentation, add core_wide and target_cpu to the tool.json. When the values of system_wide and user_requested_cpu_list are unknown, use the values from the global stat_config. Example output showing how '-a' modifies the values in `perf stat`: ``` $ perf stat -e core_wide,target_cpu true Performance counter stats for 'true': 0 core_wide 0 target_cpu 0.000993787 seconds time elapsed 0.001128000 seconds user 0.000000000 seconds sys $ perf stat -e core_wide,target_cpu -a true Performance counter stats for 'system wide': 1 core_wide 1 target_cpu 0.002271723 seconds time elapsed $ perf list ... tool: core_wide [1 if not SMT,if SMT are events being gathered on all SMT threads 1 otherwise 0. Unit: tool] ... target_cpu [1 if CPUs being analyzed,0 if threads/processes. Unit: tool] ... ``` Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- .../pmu-events/arch/common/common/tool.json | 12 + tools/perf/pmu-events/empty-pmu-events.c | 228 +++++++++--------- tools/perf/util/expr.c | 11 +- tools/perf/util/stat-shadow.c | 2 + tools/perf/util/tool_pmu.c | 24 +- tools/perf/util/tool_pmu.h | 9 +- 6 files changed, 163 insertions(+), 123 deletions(-) diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json index 12f2ef1813a63e..14d0d60a19764b 100644 --- a/tools/perf/pmu-events/arch/common/common/tool.json +++ b/tools/perf/pmu-events/arch/common/common/tool.json @@ -70,5 +70,17 @@ "EventName": "system_tsc_freq", "BriefDescription": "The amount a Time Stamp Counter (TSC) increases per second", "ConfigCode": "12" + }, + { + "Unit": "tool", + "EventName": "core_wide", + "BriefDescription": "1 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0", + "ConfigCode": "13" + }, + { + "Unit": "tool", + "EventName": "target_cpu", + "BriefDescription": "1 if CPUs being analyzed, 0 if threads/processes", + "ConfigCode": "14" } ] diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 7fa42f13300f9a..76c395cf513cb4 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1279,62 +1279,64 @@ static const char *const big_c_string = /* offset=125889 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" /* offset=125999 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" /* offset=126106 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" -/* offset=126205 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" -/* offset=126267 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" -/* offset=126329 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" -/* offset=126427 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" -/* offset=126529 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" -/* offset=126662 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" -/* offset=126780 */ "hisi_sccl,ddrc\000" -/* offset=126795 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" -/* offset=126865 */ "uncore_cbox\000" -/* offset=126877 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" -/* offset=127031 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" -/* offset=127085 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" -/* offset=127143 */ "hisi_sccl,l3c\000" -/* offset=127157 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" -/* offset=127225 */ "uncore_imc_free_running\000" -/* offset=127249 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" -/* offset=127329 */ "uncore_imc\000" -/* offset=127340 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" -/* offset=127405 */ "uncore_sys_ddr_pmu\000" -/* offset=127424 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" -/* offset=127500 */ "uncore_sys_ccn_pmu\000" -/* offset=127519 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" -/* offset=127596 */ "uncore_sys_cmn_pmu\000" -/* offset=127615 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=127758 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011" -/* offset=127944 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011" -/* offset=128177 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011" -/* offset=128437 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011" -/* offset=128668 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001" -/* offset=128781 */ "stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001" -/* offset=128945 */ "frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001" -/* offset=129075 */ "backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001" -/* offset=129201 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" -/* offset=129377 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" -/* offset=129557 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" -/* offset=129661 */ "l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001" -/* offset=129777 */ "llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001" -/* offset=129878 */ "l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001" -/* offset=129993 */ "dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001" -/* offset=130099 */ "itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001" -/* offset=130205 */ "l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001" -/* offset=130353 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" -/* offset=130376 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" -/* offset=130440 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" -/* offset=130607 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=130672 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=130740 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" -/* offset=130812 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" -/* offset=130907 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" -/* offset=131042 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" -/* offset=131107 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=131176 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=131247 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" -/* offset=131270 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" -/* offset=131293 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" -/* offset=131314 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" +/* offset=126205 */ "core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0\000config=0xd\000\00000\000\000\000\000\000" +/* offset=126319 */ "target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000" +/* offset=126403 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" +/* offset=126465 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" +/* offset=126527 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" +/* offset=126625 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" +/* offset=126727 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" +/* offset=126860 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" +/* offset=126978 */ "hisi_sccl,ddrc\000" +/* offset=126993 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" +/* offset=127063 */ "uncore_cbox\000" +/* offset=127075 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" +/* offset=127229 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" +/* offset=127283 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" +/* offset=127341 */ "hisi_sccl,l3c\000" +/* offset=127355 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" +/* offset=127423 */ "uncore_imc_free_running\000" +/* offset=127447 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" +/* offset=127527 */ "uncore_imc\000" +/* offset=127538 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" +/* offset=127603 */ "uncore_sys_ddr_pmu\000" +/* offset=127622 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" +/* offset=127698 */ "uncore_sys_ccn_pmu\000" +/* offset=127717 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" +/* offset=127794 */ "uncore_sys_cmn_pmu\000" +/* offset=127813 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" +/* offset=127956 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011" +/* offset=128142 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011" +/* offset=128375 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011" +/* offset=128635 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011" +/* offset=128866 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001" +/* offset=128979 */ "stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001" +/* offset=129143 */ "frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001" +/* offset=129273 */ "backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001" +/* offset=129399 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" +/* offset=129575 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" +/* offset=129755 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" +/* offset=129859 */ "l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001" +/* offset=129975 */ "llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001" +/* offset=130076 */ "l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001" +/* offset=130191 */ "dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130297 */ "itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130403 */ "l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001" +/* offset=130551 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" +/* offset=130574 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" +/* offset=130638 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" +/* offset=130805 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=130870 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=130938 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" +/* offset=131010 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" +/* offset=131105 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" +/* offset=131240 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" +/* offset=131305 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131374 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131445 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" +/* offset=131468 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" +/* offset=131491 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" +/* offset=131512 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { @@ -2587,6 +2589,7 @@ static const struct compact_pmu_event pmu_events__common_software[] = { { 123607 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__common_tool[] = { +{ 126205 }, /* core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0\000config=0xd\000\00000\000\000\000\000\000 */ { 125072 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ { 125286 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ { 125362 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ @@ -2598,6 +2601,7 @@ static const struct compact_pmu_event pmu_events__common_tool[] = { { 125999 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ { 125218 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ { 126106 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ +{ 126319 }, /* target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000 */ { 125148 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ }; @@ -2621,23 +2625,23 @@ static const struct pmu_table_entry pmu_events__common[] = { }; static const struct compact_pmu_event pmu_metrics__common_default_core[] = { -{ 127758 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011 */ -{ 129075 }, /* backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001 */ -{ 129377 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011 */ -{ 129557 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001 */ -{ 127944 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011 */ -{ 129201 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011 */ -{ 129993 }, /* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001 */ -{ 128945 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001 */ -{ 128668 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001 */ -{ 130099 }, /* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001 */ -{ 130205 }, /* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001 */ -{ 129661 }, /* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001 */ -{ 129878 }, /* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001 */ -{ 129777 }, /* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001 */ -{ 128177 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011 */ -{ 128437 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011 */ -{ 128781 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001 */ +{ 127956 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011 */ +{ 129273 }, /* backend_cycles_idle\000Default\000stalled\\-cycles\\-backend / cpu\\-cycles\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001 */ +{ 129575 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011 */ +{ 129755 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001 */ +{ 128142 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011 */ +{ 129399 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011 */ +{ 130191 }, /* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001 */ +{ 129143 }, /* frontend_cycles_idle\000Default\000stalled\\-cycles\\-frontend / cpu\\-cycles\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001 */ +{ 128866 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001 */ +{ 130297 }, /* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001 */ +{ 130403 }, /* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001 */ +{ 129859 }, /* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001 */ +{ 130076 }, /* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001 */ +{ 129975 }, /* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001 */ +{ 128375 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011 */ +{ 128635 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011 */ +{ 128979 }, /* stalled_cycles_per_instruction\000Default\000max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001 */ }; @@ -2650,29 +2654,29 @@ static const struct pmu_table_entry pmu_metrics__common[] = { }; static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { -{ 126205 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ -{ 126267 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ -{ 126529 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ -{ 126662 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ -{ 126329 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ -{ 126427 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ +{ 126403 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ +{ 126465 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ +{ 126727 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ +{ 126860 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ +{ 126527 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ +{ 126625 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { -{ 126795 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ +{ 126993 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { -{ 127157 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ +{ 127355 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { -{ 127031 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ -{ 127085 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ -{ 126877 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ +{ 127229 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ +{ 127283 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ +{ 127075 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { -{ 127340 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ +{ 127538 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { -{ 127249 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ +{ 127447 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ }; @@ -2685,46 +2689,46 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { { .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), - .pmu_name = { 126780 /* hisi_sccl,ddrc\000 */ }, + .pmu_name = { 126978 /* hisi_sccl,ddrc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), - .pmu_name = { 127143 /* hisi_sccl,l3c\000 */ }, + .pmu_name = { 127341 /* hisi_sccl,l3c\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_cbox, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), - .pmu_name = { 126865 /* uncore_cbox\000 */ }, + .pmu_name = { 127063 /* uncore_cbox\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), - .pmu_name = { 127329 /* uncore_imc\000 */ }, + .pmu_name = { 127527 /* uncore_imc\000 */ }, }, { .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), - .pmu_name = { 127225 /* uncore_imc_free_running\000 */ }, + .pmu_name = { 127423 /* uncore_imc_free_running\000 */ }, }, }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 130353 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ -{ 131042 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ -{ 130812 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ -{ 130907 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ -{ 131107 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 131176 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 130440 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ -{ 130376 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ -{ 131314 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ -{ 131247 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ -{ 131270 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ -{ 131293 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ -{ 130740 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ -{ 130607 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ -{ 130672 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ +{ 130551 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ +{ 131240 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ +{ 131010 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ +{ 131105 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ +{ 131305 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 131374 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ +{ 130638 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ +{ 130574 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ +{ 131512 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ +{ 131445 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ +{ 131468 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ +{ 131491 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ +{ 130938 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ +{ 130805 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ +{ 130870 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ }; @@ -2737,13 +2741,13 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { -{ 127519 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ +{ 127717 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { -{ 127615 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ +{ 127813 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { -{ 127424 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ +{ 127622 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ }; @@ -2751,17 +2755,17 @@ static const struct pmu_table_entry pmu_events__test_soc_sys[] = { { .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), - .pmu_name = { 127500 /* uncore_sys_ccn_pmu\000 */ }, + .pmu_name = { 127698 /* uncore_sys_ccn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), - .pmu_name = { 127596 /* uncore_sys_cmn_pmu\000 */ }, + .pmu_name = { 127794 /* uncore_sys_cmn_pmu\000 */ }, }, { .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), - .pmu_name = { 127405 /* uncore_sys_ddr_pmu\000 */ }, + .pmu_name = { 127603 /* uncore_sys_ddr_pmu\000 */ }, }, }; diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 4df56f2b283d6f..465fe2e9bbbeff 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -401,17 +401,12 @@ double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx if (ev != TOOL_PMU__EVENT_NONE) { u64 count; - if (tool_pmu__read_event(ev, /*evsel=*/NULL, &count)) + if (tool_pmu__read_event(ev, /*evsel=*/NULL, + ctx->system_wide, ctx->user_requested_cpu_list, + &count)) result = count; else pr_err("Failure to read '%s'", literal); - - } else if (!strcmp("#core_wide", literal)) { - result = core_wide(ctx->system_wide, ctx->user_requested_cpu_list) - ? 1.0 : 0.0; - } else if (!strcmp("#target_cpu", literal)) { - result = (ctx->system_wide || ctx->user_requested_cpu_list) - ? 1.0 : 0.0; } else { pr_err("Unrecognized literal '%s'", literal); } diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index c1547128c39623..b3b482e1808f1b 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -72,6 +72,8 @@ static int prepare_metric(const struct metric_expr *mexp, case TOOL_PMU__EVENT_SLOTS: case TOOL_PMU__EVENT_SMT_ON: case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: + case TOOL_PMU__EVENT_CORE_WIDE: + case TOOL_PMU__EVENT_TARGET_CPU: default: pr_err("Unexpected tool event '%s'", evsel__name(metric_events[i])); abort(); diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c index f075098488badd..a72c665ee6440d 100644 --- a/tools/perf/util/tool_pmu.c +++ b/tools/perf/util/tool_pmu.c @@ -6,6 +6,7 @@ #include "pmu.h" #include "print-events.h" #include "smt.h" +#include "stat.h" #include "time-utils.h" #include "tool_pmu.h" #include "tsc.h" @@ -30,6 +31,8 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = { "slots", "smt_on", "system_tsc_freq", + "core_wide", + "target_cpu", }; bool tool_pmu__skip_event(const char *name __maybe_unused) @@ -329,7 +332,11 @@ static bool has_pmem(void) return has_pmem; } -bool tool_pmu__read_event(enum tool_pmu_event ev, struct evsel *evsel, u64 *result) +bool tool_pmu__read_event(enum tool_pmu_event ev, + struct evsel *evsel, + bool system_wide, + const char *user_requested_cpu_list, + u64 *result) { const struct cpu_topology *topology; @@ -421,6 +428,14 @@ bool tool_pmu__read_event(enum tool_pmu_event ev, struct evsel *evsel, u64 *resu *result = arch_get_tsc_freq(); return true; + case TOOL_PMU__EVENT_CORE_WIDE: + *result = core_wide(system_wide, user_requested_cpu_list) ? 1 : 0; + return true; + + case TOOL_PMU__EVENT_TARGET_CPU: + *result = system_wide || (user_requested_cpu_list != NULL) ? 1 : 0; + return true; + case TOOL_PMU__EVENT_NONE: case TOOL_PMU__EVENT_DURATION_TIME: case TOOL_PMU__EVENT_USER_TIME: @@ -452,11 +467,16 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) case TOOL_PMU__EVENT_SLOTS: case TOOL_PMU__EVENT_SMT_ON: case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: + case TOOL_PMU__EVENT_CORE_WIDE: + case TOOL_PMU__EVENT_TARGET_CPU: if (evsel->prev_raw_counts) old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread); val = 0; if (cpu_map_idx == 0 && thread == 0) { - if (!tool_pmu__read_event(ev, evsel, &val)) { + if (!tool_pmu__read_event(ev, evsel, + stat_config.system_wide, + stat_config.user_requested_cpu_list, + &val)) { count->lost++; val = 0; } diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h index d642e7d73910ec..f1714001bc1d92 100644 --- a/tools/perf/util/tool_pmu.h +++ b/tools/perf/util/tool_pmu.h @@ -22,6 +22,8 @@ enum tool_pmu_event { TOOL_PMU__EVENT_SLOTS, TOOL_PMU__EVENT_SMT_ON, TOOL_PMU__EVENT_SYSTEM_TSC_FREQ, + TOOL_PMU__EVENT_CORE_WIDE, + TOOL_PMU__EVENT_TARGET_CPU, TOOL_PMU__EVENT_MAX, }; @@ -34,7 +36,12 @@ enum tool_pmu_event tool_pmu__str_to_event(const char *str); bool tool_pmu__skip_event(const char *name); int tool_pmu__num_skip_events(void); -bool tool_pmu__read_event(enum tool_pmu_event ev, struct evsel *evsel, u64 *result); +bool tool_pmu__read_event(enum tool_pmu_event ev, + struct evsel *evsel, + bool system_wide, + const char *user_requested_cpu_list, + u64 *result); + u64 tool_pmu__cpu_slots_per_cycle(void); From da8fcfba0854dbe0b0eca465d35620c9cf4c89c1 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 5 Nov 2025 23:28:34 -0800 Subject: [PATCH 286/684] perf stat: Align metric output without events One of my concern in the perf stat output was the alignment in the metrics and shadow stats. I think it missed to calculate the basic output length using COUNTS_LEN and EVNAME_LEN but missed to add the unit length like "msec" and surround 2 spaces. I'm not sure why it's not printed below though. But anyway, now it shows correctly aligned metric output. $ perf stat true Performance counter stats for 'true': 859,772 task-clock # 0.395 CPUs utilized 0 context-switches # 0.000 /sec 0 cpu-migrations # 0.000 /sec 56 page-faults # 65.134 K/sec 1,075,022 instructions # 0.86 insn per cycle 1,255,911 cycles # 1.461 GHz 220,573 branches # 256.548 M/sec 7,381 branch-misses # 3.35% of all branches TopdownL1 # 19.2 % tma_retiring # 28.6 % tma_backend_bound # 9.5 % tma_bad_speculation # 42.6 % tma_frontend_bound 0.002174871 seconds time elapsed ^ | 0.002154000 seconds user | 0.000000000 seconds sys here Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/stat-display.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index b3596f9f5cdd81..5ac9854f8c5855 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -439,9 +439,9 @@ static inline void __new_line_std_csv(struct perf_stat_config *config, aggr_printout(config, os, os->evsel, os->id, os->aggr_nr); } -static inline void __new_line_std(struct outstate *os) +static inline void __new_line_std(struct perf_stat_config *config, struct outstate *os) { - fprintf(os->fh, " "); + fprintf(os->fh, "%*s", COUNTS_LEN + EVNAME_LEN + config->unit_width + 2, ""); } static void do_new_line_std(struct perf_stat_config *config, @@ -450,7 +450,7 @@ static void do_new_line_std(struct perf_stat_config *config, __new_line_std_csv(config, os); if (config->aggr_mode == AGGR_NONE) fprintf(os->fh, " "); - __new_line_std(os); + __new_line_std(config, os); } static void print_metric_std(struct perf_stat_config *config, @@ -583,13 +583,13 @@ static void print_metricgroup_header_std(struct perf_stat_config *config, int n; if (!metricgroup_name) { - __new_line_std(os); + __new_line_std(config, os); return; } n = fprintf(config->output, " %*s", EVNAME_LEN, metricgroup_name); - fprintf(config->output, "%*s", MGROUP_LEN - n - 1, ""); + fprintf(config->output, "%*s", MGROUP_LEN + config->unit_width + 2 - n, ""); } static void print_metric_only(struct perf_stat_config *config, From ce884de219de43deac6c482590d677872bf358ff Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 20:10:25 +0100 Subject: [PATCH 287/684] pinctrl: cedarfork: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-cedarfork.c | 37 +++++++++-------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cedarfork.c b/drivers/pinctrl/intel/pinctrl-cedarfork.c index 2ce97abeb0e411..2916f7d900903e 100644 --- a/drivers/pinctrl/intel/pinctrl-cedarfork.c +++ b/drivers/pinctrl/intel/pinctrl-cedarfork.c @@ -21,13 +21,6 @@ #define CDF_GPI_IS 0x200 #define CDF_GPI_IE 0x230 -#define CDF_GPP(r, s, e) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - } - #define CDF_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, CDF) @@ -288,24 +281,24 @@ static const struct pinctrl_pin_desc cdf_pins[] = { }; static const struct intel_padgroup cdf_community0_gpps[] = { - CDF_GPP(0, 0, 23), /* WEST2 */ - CDF_GPP(1, 24, 47), /* WEST3 */ - CDF_GPP(2, 48, 70), /* WEST01 */ - CDF_GPP(3, 71, 90), /* WEST5 */ - CDF_GPP(4, 91, 96), /* WESTC */ - CDF_GPP(5, 97, 101), /* WESTC_DFX */ - CDF_GPP(6, 102, 111), /* WESTA */ - CDF_GPP(7, 112, 123), /* WESTB */ - CDF_GPP(8, 124, 143), /* WESTD */ - CDF_GPP(9, 144, 144), /* WESTD_PECI */ - CDF_GPP(10, 145, 167), /* WESTF */ + INTEL_GPP(0, 0, 23, 0), /* WEST2 */ + INTEL_GPP(1, 24, 47, 24), /* WEST3 */ + INTEL_GPP(2, 48, 70, 48), /* WEST01 */ + INTEL_GPP(3, 71, 90, 71), /* WEST5 */ + INTEL_GPP(4, 91, 96, 91), /* WESTC */ + INTEL_GPP(5, 97, 101, 97), /* WESTC_DFX */ + INTEL_GPP(6, 102, 111, 102), /* WESTA */ + INTEL_GPP(7, 112, 123, 112), /* WESTB */ + INTEL_GPP(8, 124, 143, 124), /* WESTD */ + INTEL_GPP(9, 144, 144, 144), /* WESTD_PECI */ + INTEL_GPP(10, 145, 167, 145), /* WESTF */ }; static const struct intel_padgroup cdf_community1_gpps[] = { - CDF_GPP(0, 168, 191), /* EAST2 */ - CDF_GPP(1, 192, 202), /* EAST3 */ - CDF_GPP(2, 203, 225), /* EAST0 */ - CDF_GPP(3, 226, 236), /* EMMC */ + INTEL_GPP(0, 168, 191, 168), /* EAST2 */ + INTEL_GPP(1, 192, 202, 192), /* EAST3 */ + INTEL_GPP(2, 203, 225, 203), /* EAST0 */ + INTEL_GPP(3, 226, 236, 226), /* EMMC */ }; static const struct intel_community cdf_communities[] = { From d772897c7cfd8b158c3997b00ddbd9b5671b4fa4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 20:10:26 +0100 Subject: [PATCH 288/684] pinctrl: denverton: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-denverton.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-denverton.c b/drivers/pinctrl/intel/pinctrl-denverton.c index fef44c663be602..f492f73ba246a7 100644 --- a/drivers/pinctrl/intel/pinctrl-denverton.c +++ b/drivers/pinctrl/intel/pinctrl-denverton.c @@ -21,13 +21,6 @@ #define DNV_GPI_IS 0x100 #define DNV_GPI_IE 0x120 -#define DNV_GPP(n, s, e) \ - { \ - .reg_num = (n), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - } - #define DNV_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, DNV) @@ -222,16 +215,16 @@ static const struct intel_function dnv_functions[] = { }; static const struct intel_padgroup dnv_north_gpps[] = { - DNV_GPP(0, 0, 31), /* North ALL_0 */ - DNV_GPP(1, 32, 40), /* North ALL_1 */ + INTEL_GPP(0, 0, 31, 0), /* North ALL_0 */ + INTEL_GPP(1, 32, 40, 32), /* North ALL_1 */ }; static const struct intel_padgroup dnv_south_gpps[] = { - DNV_GPP(0, 41, 58), /* South DFX */ - DNV_GPP(1, 59, 90), /* South GPP0_0 */ - DNV_GPP(2, 91, 111), /* South GPP0_1 */ - DNV_GPP(3, 112, 143), /* South GPP1_0 */ - DNV_GPP(4, 144, 153), /* South GPP1_1 */ + INTEL_GPP(0, 41, 58, 41), /* South DFX */ + INTEL_GPP(1, 59, 90, 59), /* South GPP0_0 */ + INTEL_GPP(2, 91, 111, 91), /* South GPP0_1 */ + INTEL_GPP(3, 112, 143, 112), /* South GPP1_0 */ + INTEL_GPP(4, 144, 153, 144), /* South GPP1_1 */ }; static const struct intel_community dnv_communities[] = { From 6c7a9976998d97f9ec9eb84e490f5a65fa2bd479 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 20:10:27 +0100 Subject: [PATCH 289/684] pinctrl: emmitsburg: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-emmitsburg.c | 33 +++++++++------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-emmitsburg.c b/drivers/pinctrl/intel/pinctrl-emmitsburg.c index 9d8a32aca177e3..ba06a9ec239aa9 100644 --- a/drivers/pinctrl/intel/pinctrl-emmitsburg.c +++ b/drivers/pinctrl/intel/pinctrl-emmitsburg.c @@ -21,13 +21,6 @@ #define EBG_GPI_IS 0x200 #define EBG_GPI_IE 0x210 -#define EBG_GPP(r, s, e) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - } - #define EBG_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, EBG) @@ -311,31 +304,31 @@ static const struct pinctrl_pin_desc ebg_pins[] = { }; static const struct intel_padgroup ebg_community0_gpps[] = { - EBG_GPP(0, 0, 20), /* GPP_A */ - EBG_GPP(1, 21, 44), /* GPP_B */ - EBG_GPP(2, 45, 65), /* SPI */ + INTEL_GPP(0, 0, 20, 0), /* GPP_A */ + INTEL_GPP(1, 21, 44, 21), /* GPP_B */ + INTEL_GPP(2, 45, 65, 45), /* SPI */ }; static const struct intel_padgroup ebg_community1_gpps[] = { - EBG_GPP(0, 66, 87), /* GPP_C */ - EBG_GPP(1, 88, 111), /* GPP_D */ + INTEL_GPP(0, 66, 87, 66), /* GPP_C */ + INTEL_GPP(1, 88, 111, 88), /* GPP_D */ }; static const struct intel_padgroup ebg_community3_gpps[] = { - EBG_GPP(0, 112, 135), /* GPP_E */ - EBG_GPP(1, 136, 145), /* JTAG */ + INTEL_GPP(0, 112, 135, 112), /* GPP_E */ + INTEL_GPP(1, 136, 145, 136), /* JTAG */ }; static const struct intel_padgroup ebg_community4_gpps[] = { - EBG_GPP(0, 146, 165), /* GPP_H */ - EBG_GPP(1, 166, 183), /* GPP_J */ + INTEL_GPP(0, 146, 165, 146), /* GPP_H */ + INTEL_GPP(1, 166, 183, 166), /* GPP_J */ }; static const struct intel_padgroup ebg_community5_gpps[] = { - EBG_GPP(0, 184, 207), /* GPP_I */ - EBG_GPP(1, 208, 225), /* GPP_L */ - EBG_GPP(2, 226, 243), /* GPP_M */ - EBG_GPP(3, 244, 261), /* GPP_N */ + INTEL_GPP(0, 184, 207, 184), /* GPP_I */ + INTEL_GPP(1, 208, 225, 208), /* GPP_L */ + INTEL_GPP(2, 226, 243, 226), /* GPP_M */ + INTEL_GPP(3, 244, 261, 244), /* GPP_N */ }; static const struct intel_community ebg_communities[] = { From dd0c7bffe3d1c03b5e191d648f0ccc17bffe37e3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 20:10:28 +0100 Subject: [PATCH 290/684] pinctrl: cherryview: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-cherryview.c | 46 ++++++++++------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 077fa1318aaff3..f6c29bdc310350 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -92,12 +92,6 @@ struct intel_community_context { #define PINMODE(m, i) ((m) | ((i) * PINMODE_INVERT_OE)) -#define CHV_GPP(start, end) \ - { \ - .base = (start), \ - .size = (end) - (start) + 1, \ - } - #define CHV_COMMUNITY(g, i, a) \ { \ .gpps = (g), \ @@ -258,13 +252,13 @@ static const struct intel_function southwest_functions[] = { }; static const struct intel_padgroup southwest_gpps[] = { - CHV_GPP(0, 7), - CHV_GPP(15, 22), - CHV_GPP(30, 37), - CHV_GPP(45, 52), - CHV_GPP(60, 67), - CHV_GPP(75, 82), - CHV_GPP(90, 97), + INTEL_GPP(0, 0, 7, 0), + INTEL_GPP(1, 15, 22, 15), + INTEL_GPP(2, 30, 37, 30), + INTEL_GPP(3, 45, 52, 45), + INTEL_GPP(4, 60, 67, 60), + INTEL_GPP(5, 75, 82, 75), + INTEL_GPP(6, 90, 97, 90), }; /* @@ -354,11 +348,11 @@ static const struct pinctrl_pin_desc north_pins[] = { }; static const struct intel_padgroup north_gpps[] = { - CHV_GPP(0, 8), - CHV_GPP(15, 27), - CHV_GPP(30, 41), - CHV_GPP(45, 56), - CHV_GPP(60, 72), + INTEL_GPP(0, 0, 8, 0), + INTEL_GPP(1, 15, 27, 15), + INTEL_GPP(2, 30, 41, 30), + INTEL_GPP(3, 45, 56, 45), + INTEL_GPP(4, 60, 72, 60), }; /* @@ -406,8 +400,8 @@ static const struct pinctrl_pin_desc east_pins[] = { }; static const struct intel_padgroup east_gpps[] = { - CHV_GPP(0, 11), - CHV_GPP(15, 26), + INTEL_GPP(0, 0, 11, 0), + INTEL_GPP(1, 15, 26, 15), }; static const struct intel_community east_communities[] = { @@ -526,12 +520,12 @@ static const struct intel_function southeast_functions[] = { }; static const struct intel_padgroup southeast_gpps[] = { - CHV_GPP(0, 7), - CHV_GPP(15, 26), - CHV_GPP(30, 35), - CHV_GPP(45, 52), - CHV_GPP(60, 69), - CHV_GPP(75, 85), + INTEL_GPP(0, 0, 7, 0), + INTEL_GPP(1, 15, 26, 15), + INTEL_GPP(2, 30, 35, 30), + INTEL_GPP(3, 45, 52, 45), + INTEL_GPP(4, 60, 69, 60), + INTEL_GPP(5, 75, 85, 75), }; static const struct intel_community southeast_communities[] = { From cc4e46fa76afcb4fc56b801c9577dc60a64a00d6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 20:10:29 +0100 Subject: [PATCH 291/684] pinctrl: elkhartlake: Switch to INTEL_GPP() macro Replace custom macro with the recently defined INTEL_GPP(). Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-elkhartlake.c | 43 +++++++++------------ 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-elkhartlake.c b/drivers/pinctrl/intel/pinctrl-elkhartlake.c index ab414e07555a8f..0e8742f31cd43c 100644 --- a/drivers/pinctrl/intel/pinctrl-elkhartlake.c +++ b/drivers/pinctrl/intel/pinctrl-elkhartlake.c @@ -21,13 +21,6 @@ #define EHL_GPI_IS 0x100 #define EHL_GPI_IE 0x120 -#define EHL_GPP(r, s, e) \ - { \ - .reg_num = (r), \ - .base = (s), \ - .size = ((e) - (s) + 1), \ - } - #define EHL_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, EHL) @@ -106,9 +99,9 @@ static const struct pinctrl_pin_desc ehl_community0_pins[] = { }; static const struct intel_padgroup ehl_community0_gpps[] = { - EHL_GPP(0, 0, 25), /* GPP_B */ - EHL_GPP(1, 26, 41), /* GPP_T */ - EHL_GPP(2, 42, 66), /* GPP_G */ + INTEL_GPP(0, 0, 25, 0), /* GPP_B */ + INTEL_GPP(1, 26, 41, 26), /* GPP_T */ + INTEL_GPP(2, 42, 66, 42), /* GPP_G */ }; static const struct intel_community ehl_community0[] = { @@ -245,11 +238,11 @@ static const struct pinctrl_pin_desc ehl_community1_pins[] = { }; static const struct intel_padgroup ehl_community1_gpps[] = { - EHL_GPP(0, 0, 15), /* GPP_V */ - EHL_GPP(1, 16, 39), /* GPP_H */ - EHL_GPP(2, 40, 60), /* GPP_D */ - EHL_GPP(3, 61, 84), /* GPP_U */ - EHL_GPP(4, 85, 112), /* vGPIO */ + INTEL_GPP(0, 0, 15, 0), /* GPP_V */ + INTEL_GPP(1, 16, 39, 16), /* GPP_H */ + INTEL_GPP(2, 40, 60, 40), /* GPP_D */ + INTEL_GPP(3, 61, 84, 61), /* GPP_U */ + INTEL_GPP(4, 85, 112, 85), /* vGPIO */ }; static const struct intel_community ehl_community1[] = { @@ -286,7 +279,7 @@ static const struct pinctrl_pin_desc ehl_community2_pins[] = { }; static const struct intel_padgroup ehl_community2_gpps[] = { - EHL_GPP(0, 0, 16), /* DSW */ + INTEL_GPP(0, 0, 16, 0), /* DSW */ }; static const struct intel_community ehl_community2[] = { @@ -356,10 +349,10 @@ static const struct pinctrl_pin_desc ehl_community3_pins[] = { }; static const struct intel_padgroup ehl_community3_gpps[] = { - EHL_GPP(0, 0, 16), /* CPU */ - EHL_GPP(1, 17, 18), /* GPP_S */ - EHL_GPP(2, 19, 42), /* GPP_A */ - EHL_GPP(3, 43, 46), /* vGPIO_3 */ + INTEL_GPP(0, 0, 16, 0), /* CPU */ + INTEL_GPP(1, 17, 18, 17), /* GPP_S */ + INTEL_GPP(2, 19, 42, 19), /* GPP_A */ + INTEL_GPP(3, 43, 46, 43), /* vGPIO_3 */ }; static const struct intel_community ehl_community3[] = { @@ -462,10 +455,10 @@ static const struct pinctrl_pin_desc ehl_community4_pins[] = { }; static const struct intel_padgroup ehl_community4_gpps[] = { - EHL_GPP(0, 0, 23), /* GPP_C */ - EHL_GPP(1, 24, 48), /* GPP_F */ - EHL_GPP(2, 49, 54), /* HVCMOS */ - EHL_GPP(3, 55, 79), /* GPP_E */ + INTEL_GPP(0, 0, 23, 0), /* GPP_C */ + INTEL_GPP(1, 24, 48, 24), /* GPP_F */ + INTEL_GPP(2, 49, 54, 49), /* HVCMOS */ + INTEL_GPP(3, 55, 79, 55), /* GPP_E */ }; static const struct intel_community ehl_community4[] = { @@ -493,7 +486,7 @@ static const struct pinctrl_pin_desc ehl_community5_pins[] = { }; static const struct intel_padgroup ehl_community5_gpps[] = { - EHL_GPP(0, 0, 7), /* GPP_R */ + INTEL_GPP(0, 0, 7, 0), /* GPP_R */ }; static const struct intel_community ehl_community5[] = { From a40efd0741f228023a87bf65b1cebe683e92172b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 6 Nov 2025 22:16:04 +0100 Subject: [PATCH 292/684] clk: renesas: r8a779a0: Add 3DGE module clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Describe the 3DGE module clock needed to operate the PowerVR GPU. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251106211604.2766465-5-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 449611432059bb..d67dff05d9f4a9 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -142,6 +142,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("3dge", 0, R8A779A0_CLK_ZG), DEF_MOD("isp0", 16, R8A779A0_CLK_S1D1), DEF_MOD("isp1", 17, R8A779A0_CLK_S1D1), DEF_MOD("isp2", 18, R8A779A0_CLK_S1D1), From 145dfd70b9c70e5bc03494a7ce8fa3748ac01af3 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 28 Oct 2025 16:51:23 +0000 Subject: [PATCH 293/684] clk: renesas: r9a09g077: Propagate rate changes to parent clocks Add the CLK_SET_RATE_PARENT flag to divider clock registration so that rate changes can propagate to parent clocks when needed. This allows the CPG divider clocks to request rate adjustments from their parent, ensuring correct frequency scaling and improved flexibility in clock rate selection. Fixes: 065fe720eec6e ("clk: renesas: Add support for R9A09G077 SoC") Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251028165127.991351-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index 8b7e84a4c307f7..1cb33c12234e46 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -221,7 +221,7 @@ r9a09g077_cpg_div_clk_register(struct device *dev, if (core->dtable) clk_hw = clk_hw_register_divider_table(dev, core->name, - parent_name, 0, + parent_name, CLK_SET_RATE_PARENT, addr, GET_SHIFT(core->conf), GET_WIDTH(core->conf), @@ -230,7 +230,7 @@ r9a09g077_cpg_div_clk_register(struct device *dev, &pub->rmw_lock); else clk_hw = clk_hw_register_divider(dev, core->name, - parent_name, 0, + parent_name, CLK_SET_RATE_PARENT, addr, GET_SHIFT(core->conf), GET_WIDTH(core->conf), From 3b32a07584a8fc940129cfd384e180bdd758b8ed Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 28 Oct 2025 16:51:24 +0000 Subject: [PATCH 294/684] clk: renesas: r9a09g077: Remove stray blank line Remove an unnecessary blank line at the end of r9a09g077_cpg_div_clk_register() to tidy up the code. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251028165127.991351-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index 1cb33c12234e46..666fc16b9a81f2 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -240,7 +240,6 @@ r9a09g077_cpg_div_clk_register(struct device *dev, return ERR_CAST(clk_hw); return clk_hw->clk; - } static struct clk * __init From 7a9d0318da5d1d148021d9c9762cefecb552c54f Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 28 Oct 2025 16:51:25 +0000 Subject: [PATCH 295/684] clk: renesas: r9a09g077: Use devm_ helpers for divider clock registration Convert the divider clock registration in the R9A09G077 CPG driver to use device-managed (devm_) helper functions. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251028165127.991351-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index 666fc16b9a81f2..b46167d42084d3 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -220,21 +220,23 @@ r9a09g077_cpg_div_clk_register(struct device *dev, parent_name = __clk_get_name(parent); if (core->dtable) - clk_hw = clk_hw_register_divider_table(dev, core->name, - parent_name, CLK_SET_RATE_PARENT, - addr, - GET_SHIFT(core->conf), - GET_WIDTH(core->conf), - core->flag, - core->dtable, - &pub->rmw_lock); + clk_hw = devm_clk_hw_register_divider_table(dev, core->name, + parent_name, + CLK_SET_RATE_PARENT, + addr, + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, + core->dtable, + &pub->rmw_lock); else - clk_hw = clk_hw_register_divider(dev, core->name, - parent_name, CLK_SET_RATE_PARENT, - addr, - GET_SHIFT(core->conf), - GET_WIDTH(core->conf), - core->flag, &pub->rmw_lock); + clk_hw = devm_clk_hw_register_divider(dev, core->name, + parent_name, + CLK_SET_RATE_PARENT, + addr, + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, &pub->rmw_lock); if (IS_ERR(clk_hw)) return ERR_CAST(clk_hw); From f8def051bbcf8677f64701e9699bf6d11e2780cd Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Thu, 30 Oct 2025 14:16:03 +0800 Subject: [PATCH 296/684] clk: renesas: r9a06g032: Fix memory leak in error path The current code uses of_iomap() to map registers but never calls iounmap() on any error path after the mapping. This causes a memory leak when probe fails after successful ioremap, for example when of_clk_add_provider() or r9a06g032_add_clk_domain() fails. Replace of_iomap() with devm_of_iomap() to automatically unmap the region on probe failure. Update the error check accordingly to use IS_ERR() and PTR_ERR() since devm_of_iomap() returns ERR_PTR on error. Fixes: 4c3d88526eba ("clk: renesas: Renesas R9A06G032 clock driver") Signed-off-by: Haotian Zhang Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251030061603.1954-1-vulab@iscas.ac.cn Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a06g032-clocks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index dcda19318b2a9a..0f5c91b5dfa995 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -1333,9 +1333,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev) if (IS_ERR(mclk)) return PTR_ERR(mclk); - clocks->reg = of_iomap(np, 0); - if (WARN_ON(!clocks->reg)) - return -ENOMEM; + clocks->reg = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(clocks->reg)) + return PTR_ERR(clocks->reg); r9a06g032_init_h2mode(clocks); From f2596d9fa19c0910319fe8eb1ccdf6348f0e02db Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 11 Nov 2025 14:29:44 +0800 Subject: [PATCH 297/684] pinctrl: airoha: convert comma to semicolon Replace comma between expressions with semicolons. Using a ',' in place of a ';' can have unintended side effects. Although that is not the case here, it is seems best to use ';' unless ',' is intended. Found by inspection. No functional change intended. Compile tested only. Signed-off-by: Chen Ni Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index bfcedc7f920b1e..983d96fd399a2d 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -2892,12 +2892,12 @@ static int airoha_pinctrl_probe(struct platform_device *pdev) /* Init pinctrl desc struct */ pinctrl->desc.name = KBUILD_MODNAME; - pinctrl->desc.owner = THIS_MODULE, - pinctrl->desc.pctlops = &airoha_pctlops, - pinctrl->desc.pmxops = &airoha_pmxops, - pinctrl->desc.confops = &airoha_confops, - pinctrl->desc.pins = data->pins, - pinctrl->desc.npins = data->num_pins, + pinctrl->desc.owner = THIS_MODULE; + pinctrl->desc.pctlops = &airoha_pctlops; + pinctrl->desc.pmxops = &airoha_pmxops; + pinctrl->desc.confops = &airoha_confops; + pinctrl->desc.pins = data->pins; + pinctrl->desc.npins = data->num_pins; err = devm_pinctrl_register_and_init(dev, &pinctrl->desc, pinctrl, &pinctrl->ctrl); From 05ace63d0bcfe131e741923394c7ce03322a141e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 1 Oct 2025 21:22:32 +0800 Subject: [PATCH 298/684] dt-bindings: phy: ti,tcan104x-can: Document NXP TJA105X/1048 The TJA1048 is a dual high-speed CAN transceiver with sleep mode supported and no EN pin. The TJA1051 is a high-speed CAN transceiver with slient mode supported, but only TJA1051T/E has EN pin. To make it simple, make enable-gpios as optional for TJA1051. The TJA1057 is a high-speed CAN transceiver with slient mode supported and no EN pin. Reviewed-by: Frank Li Reviewed-by: Rob Herring (Arm) Signed-off-by: Peng Fan Acked-by: Marc Kleine-Budde Link: https://patch.msgid.link/20251001-can-v7-1-fad29efc3884@nxp.com Signed-off-by: Vinod Koul --- .../bindings/phy/ti,tcan104x-can.yaml | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml b/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml index 4a8c3829d85d3c..14d83321317592 100644 --- a/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml +++ b/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml @@ -22,16 +22,26 @@ properties: - enum: - ti,tcan1042 - ti,tcan1043 + - nxp,tja1048 + - nxp,tja1051 + - nxp,tja1057 - nxp,tjr1443 '#phy-cells': - const: 0 + enum: [0, 1] - standby-gpios: + silent-gpios: description: - gpio node to toggle standby signal on transceiver + gpio node to toggle silent signal on transceiver maxItems: 1 + standby-gpios: + description: + gpio node to toggle standby signal on transceiver. For two Items, item 1 + is for stbn1, item 2 is for stbn2. + minItems: 1 + maxItems: 2 + enable-gpios: description: gpio node to toggle enable signal on transceiver @@ -53,6 +63,59 @@ required: - compatible - '#phy-cells' +allOf: + - if: + properties: + compatible: + enum: + - nxp,tjr1443 + - ti,tcan1042 + - ti,tcan1043 + then: + properties: + '#phy-cells': + const: 0 + silent-gpios: false + standby-gpios: + maxItems: 1 + + - if: + properties: + compatible: + contains: + const: nxp,tja1048 + then: + properties: + '#phy-cells': + const: 1 + enable-gpios: false + silent-gpios: false + standby-gpios: + minItems: 2 + + - if: + properties: + compatible: + contains: + const: nxp,tja1051 + then: + properties: + '#phy-cells': + const: 0 + standby-gpios: false + + - if: + properties: + compatible: + contains: + const: nxp,tja1057 + then: + properties: + '#phy-cells': + const: 0 + enable-gpios: false + standby-gpios: false + additionalProperties: false examples: From c77464bd9b4155891a135e51f8e916e1ab94fc14 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 1 Oct 2025 21:22:33 +0800 Subject: [PATCH 299/684] phy: phy-can-transceiver: Introduce can_transceiver_priv To prepare for dual-channel phy support, introduce can_transceiver_priv as a higher level encapsulation for phy. No functional changes. Reviewed-by: Frank Li Signed-off-by: Peng Fan Acked-by: Marc Kleine-Budde Link: https://patch.msgid.link/20251001-can-v7-2-fad29efc3884@nxp.com Signed-off-by: Vinod Koul --- drivers/phy/phy-can-transceiver.c | 34 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index f59caff4b3d4c2..b06ba42854c194 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -23,17 +23,24 @@ struct can_transceiver_phy { struct phy *generic_phy; struct gpio_desc *standby_gpio; struct gpio_desc *enable_gpio; + struct can_transceiver_priv *priv; +}; + +struct can_transceiver_priv { struct mux_state *mux_state; + int num_ch; + struct can_transceiver_phy can_transceiver_phy[] __counted_by(num_ch); }; /* Power on function */ static int can_transceiver_phy_power_on(struct phy *phy) { struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); + struct can_transceiver_priv *priv = can_transceiver_phy->priv; int ret; - if (can_transceiver_phy->mux_state) { - ret = mux_state_select(can_transceiver_phy->mux_state); + if (priv->mux_state) { + ret = mux_state_select(priv->mux_state); if (ret) { dev_err(&phy->dev, "Failed to select CAN mux: %d\n", ret); return ret; @@ -51,13 +58,14 @@ static int can_transceiver_phy_power_on(struct phy *phy) static int can_transceiver_phy_power_off(struct phy *phy) { struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); + struct can_transceiver_priv *priv = can_transceiver_phy->priv; if (can_transceiver_phy->standby_gpio) gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); if (can_transceiver_phy->enable_gpio) gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); - if (can_transceiver_phy->mux_state) - mux_state_deselect(can_transceiver_phy->mux_state); + if (priv->mux_state) + mux_state_deselect(priv->mux_state); return 0; } @@ -108,6 +116,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct device *dev = &pdev->dev; struct can_transceiver_phy *can_transceiver_phy; + struct can_transceiver_priv *priv; const struct can_transceiver_data *drvdata; const struct of_device_id *match; struct phy *phy; @@ -115,20 +124,25 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) struct gpio_desc *enable_gpio; struct mux_state *mux_state; u32 max_bitrate = 0; - int err; - - can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL); - if (!can_transceiver_phy) - return -ENOMEM; + int err, num_ch = 1; match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); drvdata = match->data; + priv = devm_kzalloc(dev, struct_size(priv, can_transceiver_phy, num_ch), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->num_ch = num_ch; + platform_set_drvdata(pdev, priv); + can_transceiver_phy = &priv->can_transceiver_phy[0]; + can_transceiver_phy->priv = priv; + mux_state = devm_mux_state_get_optional(dev, NULL); if (IS_ERR(mux_state)) return PTR_ERR(mux_state); - can_transceiver_phy->mux_state = mux_state; + priv->mux_state = mux_state; phy = devm_phy_create(dev, dev->of_node, &can_transceiver_phy_ops); From 6e9fe9409e10ed25b43928062832037752630979 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 1 Oct 2025 21:22:34 +0800 Subject: [PATCH 300/684] phy: phy-can-transceiver: Add dual channel support for TJA1048 - Introduce new flag CAN_TRANSCEIVER_DUAL_CH to indicate the phy has two channels. - Alloc a phy for each channel - Support TJA1048 which is a dual high-speed CAN transceiver with sleep mode supported. - Add can_transceiver_phy_xlate for parsing phy Reviewed-by: Frank Li Signed-off-by: Peng Fan Acked-by: Marc Kleine-Budde Link: https://patch.msgid.link/20251001-can-v7-3-fad29efc3884@nxp.com Signed-off-by: Vinod Koul --- drivers/phy/phy-can-transceiver.c | 88 ++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index b06ba42854c194..09d1684895568b 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -17,6 +17,7 @@ struct can_transceiver_data { u32 flags; #define CAN_TRANSCEIVER_STB_PRESENT BIT(0) #define CAN_TRANSCEIVER_EN_PRESENT BIT(1) +#define CAN_TRANSCEIVER_DUAL_CH BIT(2) }; struct can_transceiver_phy { @@ -84,6 +85,10 @@ static const struct can_transceiver_data tcan1043_drvdata = { .flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_EN_PRESENT, }; +static const struct can_transceiver_data tja1048_drvdata = { + .flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_DUAL_CH, +}; + static const struct of_device_id can_transceiver_phy_ids[] = { { .compatible = "ti,tcan1042", @@ -93,6 +98,10 @@ static const struct of_device_id can_transceiver_phy_ids[] = { .compatible = "ti,tcan1043", .data = &tcan1043_drvdata }, + { + .compatible = "nxp,tja1048", + .data = &tja1048_drvdata + }, { .compatible = "nxp,tjr1443", .data = &tcan1043_drvdata @@ -111,6 +120,25 @@ devm_mux_state_get_optional(struct device *dev, const char *mux_name) return devm_mux_state_get(dev, mux_name); } +static struct phy *can_transceiver_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct can_transceiver_priv *priv = dev_get_drvdata(dev); + u32 idx; + + if (priv->num_ch == 1) + return priv->can_transceiver_phy[0].generic_phy; + + if (args->args_count != 1) + return ERR_PTR(-EINVAL); + + idx = args->args[0]; + if (idx >= priv->num_ch) + return ERR_PTR(-EINVAL); + + return priv->can_transceiver_phy[idx].generic_phy; +} + static int can_transceiver_phy_probe(struct platform_device *pdev) { struct phy_provider *phy_provider; @@ -124,10 +152,12 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) struct gpio_desc *enable_gpio; struct mux_state *mux_state; u32 max_bitrate = 0; - int err, num_ch = 1; + int err, i, num_ch = 1; match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); drvdata = match->data; + if (drvdata->flags & CAN_TRANSCEIVER_DUAL_CH) + num_ch = 2; priv = devm_kzalloc(dev, struct_size(priv, can_transceiver_phy, num_ch), GFP_KERNEL); if (!priv) @@ -135,8 +165,6 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) priv->num_ch = num_ch; platform_set_drvdata(pdev, priv); - can_transceiver_phy = &priv->can_transceiver_phy[0]; - can_transceiver_phy->priv = priv; mux_state = devm_mux_state_get_optional(dev, NULL); if (IS_ERR(mux_state)) @@ -144,37 +172,45 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) priv->mux_state = mux_state; - phy = devm_phy_create(dev, dev->of_node, - &can_transceiver_phy_ops); - if (IS_ERR(phy)) { - dev_err(dev, "failed to create can transceiver phy\n"); - return PTR_ERR(phy); - } - err = device_property_read_u32(dev, "max-bitrate", &max_bitrate); if ((err != -EINVAL) && !max_bitrate) dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n"); - phy->attrs.max_link_rate = max_bitrate; - can_transceiver_phy->generic_phy = phy; + for (i = 0; i < num_ch; i++) { + can_transceiver_phy = &priv->can_transceiver_phy[i]; + can_transceiver_phy->priv = priv; - if (drvdata->flags & CAN_TRANSCEIVER_STB_PRESENT) { - standby_gpio = devm_gpiod_get_optional(dev, "standby", GPIOD_OUT_HIGH); - if (IS_ERR(standby_gpio)) - return PTR_ERR(standby_gpio); - can_transceiver_phy->standby_gpio = standby_gpio; - } + phy = devm_phy_create(dev, dev->of_node, &can_transceiver_phy_ops); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create can transceiver phy\n"); + return PTR_ERR(phy); + } - if (drvdata->flags & CAN_TRANSCEIVER_EN_PRESENT) { - enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(enable_gpio)) - return PTR_ERR(enable_gpio); - can_transceiver_phy->enable_gpio = enable_gpio; - } + phy->attrs.max_link_rate = max_bitrate; + + can_transceiver_phy->generic_phy = phy; + can_transceiver_phy->priv = priv; - phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy); + if (drvdata->flags & CAN_TRANSCEIVER_STB_PRESENT) { + standby_gpio = devm_gpiod_get_index_optional(dev, "standby", i, + GPIOD_OUT_HIGH); + if (IS_ERR(standby_gpio)) + return PTR_ERR(standby_gpio); + can_transceiver_phy->standby_gpio = standby_gpio; + } + + if (drvdata->flags & CAN_TRANSCEIVER_EN_PRESENT) { + enable_gpio = devm_gpiod_get_index_optional(dev, "enable", i, + GPIOD_OUT_LOW); + if (IS_ERR(enable_gpio)) + return PTR_ERR(enable_gpio); + can_transceiver_phy->enable_gpio = enable_gpio; + } + + phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy); + } - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + phy_provider = devm_of_phy_provider_register(dev, can_transceiver_phy_xlate); return PTR_ERR_OR_ZERO(phy_provider); } From d02a7eb12924b7473a62d5a6c9e670fe5bf6e4b7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 1 Oct 2025 21:22:35 +0800 Subject: [PATCH 301/684] phy: phy-can-transceiver: Drop the gpio desc check gpiod_set_value_cansleep has an internal check on gpio_desc using 'VALIDATE_DESC(desc)', the check before invoking gpiod_set_value_cansleep could be removed. Reviewed-by: Frank Li Signed-off-by: Peng Fan Acked-by: Marc Kleine-Budde Link: https://patch.msgid.link/20251001-can-v7-4-fad29efc3884@nxp.com Signed-off-by: Vinod Koul --- drivers/phy/phy-can-transceiver.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index 09d1684895568b..89189be9b795a6 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -47,10 +47,8 @@ static int can_transceiver_phy_power_on(struct phy *phy) return ret; } } - if (can_transceiver_phy->standby_gpio) - gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0); - if (can_transceiver_phy->enable_gpio) - gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1); + gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0); + gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1); return 0; } @@ -61,10 +59,8 @@ static int can_transceiver_phy_power_off(struct phy *phy) struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); struct can_transceiver_priv *priv = can_transceiver_phy->priv; - if (can_transceiver_phy->standby_gpio) - gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); - if (can_transceiver_phy->enable_gpio) - gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); + gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); + gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); if (priv->mux_state) mux_state_deselect(priv->mux_state); From b817f505926b8ffbdea8aa87b66a622acb9b96e9 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 1 Oct 2025 21:22:36 +0800 Subject: [PATCH 302/684] phy: phy-can-transceiver: Add support for TJA105{1,7} Support TJA105{1,7} which are a single channel high-speed CAN transceiver with silent mode supported. phy mode is not implemented as of now. silent settings are kept in phy_power_on and phy_power_off. After phy mode is supported, the silent settings could be moved to phy_set_mode. Reviewed-by: Frank Li Signed-off-by: Peng Fan Acked-by: Marc Kleine-Budde Link: https://patch.msgid.link/20251001-can-v7-5-fad29efc3884@nxp.com Signed-off-by: Vinod Koul --- drivers/phy/phy-can-transceiver.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index 89189be9b795a6..330356706ad7bd 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -18,10 +18,12 @@ struct can_transceiver_data { #define CAN_TRANSCEIVER_STB_PRESENT BIT(0) #define CAN_TRANSCEIVER_EN_PRESENT BIT(1) #define CAN_TRANSCEIVER_DUAL_CH BIT(2) +#define CAN_TRANSCEIVER_SILENT_PRESENT BIT(3) }; struct can_transceiver_phy { struct phy *generic_phy; + struct gpio_desc *silent_gpio; struct gpio_desc *standby_gpio; struct gpio_desc *enable_gpio; struct can_transceiver_priv *priv; @@ -47,6 +49,7 @@ static int can_transceiver_phy_power_on(struct phy *phy) return ret; } } + gpiod_set_value_cansleep(can_transceiver_phy->silent_gpio, 0); gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0); gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1); @@ -59,6 +62,7 @@ static int can_transceiver_phy_power_off(struct phy *phy) struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); struct can_transceiver_priv *priv = can_transceiver_phy->priv; + gpiod_set_value_cansleep(can_transceiver_phy->silent_gpio, 1); gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); if (priv->mux_state) @@ -85,6 +89,14 @@ static const struct can_transceiver_data tja1048_drvdata = { .flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_DUAL_CH, }; +static const struct can_transceiver_data tja1051_drvdata = { + .flags = CAN_TRANSCEIVER_SILENT_PRESENT | CAN_TRANSCEIVER_EN_PRESENT, +}; + +static const struct can_transceiver_data tja1057_drvdata = { + .flags = CAN_TRANSCEIVER_SILENT_PRESENT, +}; + static const struct of_device_id can_transceiver_phy_ids[] = { { .compatible = "ti,tcan1042", @@ -98,6 +110,14 @@ static const struct of_device_id can_transceiver_phy_ids[] = { .compatible = "nxp,tja1048", .data = &tja1048_drvdata }, + { + .compatible = "nxp,tja1051", + .data = &tja1051_drvdata + }, + { + .compatible = "nxp,tja1057", + .data = &tja1057_drvdata + }, { .compatible = "nxp,tjr1443", .data = &tcan1043_drvdata @@ -144,6 +164,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) const struct can_transceiver_data *drvdata; const struct of_device_id *match; struct phy *phy; + struct gpio_desc *silent_gpio; struct gpio_desc *standby_gpio; struct gpio_desc *enable_gpio; struct mux_state *mux_state; @@ -203,7 +224,16 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) can_transceiver_phy->enable_gpio = enable_gpio; } + if (drvdata->flags & CAN_TRANSCEIVER_SILENT_PRESENT) { + silent_gpio = devm_gpiod_get_index_optional(dev, "silent", i, + GPIOD_OUT_LOW); + if (IS_ERR(silent_gpio)) + return PTR_ERR(silent_gpio); + can_transceiver_phy->silent_gpio = silent_gpio; + } + phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy); + } phy_provider = devm_of_phy_provider_register(dev, can_transceiver_phy_xlate); From 42690b8ec861b502538e425c5a7feb7a38764f04 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Nov 2025 09:52:20 +0100 Subject: [PATCH 303/684] phy: sophgo: Remove unused of_gpio.h of_gpio.h is deprecated and subject to remove. The driver doesn't use it, simply remove the unused header. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/phy/sophgo/phy-cv1800-usb2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/phy/sophgo/phy-cv1800-usb2.c b/drivers/phy/sophgo/phy-cv1800-usb2.c index 64f8e37b4b5273..6fe846534e9cbd 100644 --- a/drivers/phy/sophgo/phy-cv1800-usb2.c +++ b/drivers/phy/sophgo/phy-cv1800-usb2.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include From fc9c17b2235256445b28b06b6dba1709f870b3c4 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 12 Nov 2025 08:48:23 -0800 Subject: [PATCH 304/684] perf test: Add a perf event fallback test This adds test cases to verify the precise ip fallback logic: - If the system supports precise ip, for an event given with the maximum precision level, it should be able to decrease precise_ip to find a supported level. - The same fallback behavior should also work in more complex scenarios, such as event groups or when PEBS is involved Additional fallback tests, such as those covering missing feature cases, can be added in the future. Suggested-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Zide Chen Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- .../tests/shell/test_event_open_fallback.sh | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 tools/perf/tests/shell/test_event_open_fallback.sh diff --git a/tools/perf/tests/shell/test_event_open_fallback.sh b/tools/perf/tests/shell/test_event_open_fallback.sh new file mode 100755 index 00000000000000..9c411153c01b68 --- /dev/null +++ b/tools/perf/tests/shell/test_event_open_fallback.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Perf event open fallback test +# SPDX-License-Identifier: GPL-2.0 + +skip_cnt=0 +ok_cnt=0 +err_cnt=0 + +cleanup() +{ + rm -f perf.data + rm -f perf.data.old + trap - EXIT TERM INT +} + +trap_cleanup() +{ + cleanup + exit 1 +} + +trap trap_cleanup EXIT TERM INT + +perf_record() +{ + perf record "$@" -- true 1>/dev/null 2>&1 +} + +test_decrease_precise_ip() +{ + echo "Decrease precise ip test" + + perf list pmu | grep -q 'cycles' || return 2 + + if ! perf_record -e cycles; then + return 2 + fi + + # It should reduce precision level down to 0 if needed. + if ! perf_record -e cycles:P; then + return 1 + fi + return 0 +} + +test_decrease_precise_ip_complicated() +{ + echo "Decrease precise ip test (complicated case)" + + perf list pmu | grep -q 'mem-loads-aux' || return 2 + + if ! perf_record -e '{cpu/mem-loads-aux/S,cpu/mem-loads/PS}'; then + return 1 + fi + return 0 +} + +count_result() +{ + if [ "$1" -eq 2 ] ; then + skip_cnt=$((skip_cnt + 1)) + return + fi + if [ "$1" -eq 0 ] ; then + ok_cnt=$((ok_cnt + 1)) + return + fi + err_cnt=$((err_cnt + 1)) +} + +ret=0 +test_decrease_precise_ip || ret=$? ; count_result $ret ; ret=0 +test_decrease_precise_ip_complicated || ret=$? ; count_result $ret ; ret=0 + +cleanup + +if [ ${err_cnt} -gt 0 ] ; then + exit 1 +fi + +if [ ${ok_cnt} -gt 0 ] ; then + exit 0 +fi + +# Skip +exit 2 From dc937f12e6c3488713de1262e37a30307ee9feac Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 13 Nov 2025 17:15:25 +0100 Subject: [PATCH 305/684] clk: qcom: apss-ipq5424: remove unused 'apss_clk' structure The locally defined 'apss_clk' structure is not used in the code, so remove that. Compile tested only. Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20251113-ipq5424-remove-apss_clk-v1-1-e942e720cf99@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq5424.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq5424.c b/drivers/clk/qcom/apss-ipq5424.c index 4c67f722e009af..2d622c1fe5d052 100644 --- a/drivers/clk/qcom/apss-ipq5424.c +++ b/drivers/clk/qcom/apss-ipq5424.c @@ -35,13 +35,6 @@ enum { P_L3_PLL, }; -struct apss_clk { - struct notifier_block cpu_clk_notifier; - struct clk_hw *hw; - struct device *dev; - struct clk *l3_clk; -}; - static const struct alpha_pll_config apss_pll_config = { .l = 0x3b, .config_ctl_val = 0x08200920, From 4145fc363eb23a1caf14f7ebf6830ab32bcaa50e Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 13 Nov 2025 17:42:52 +0100 Subject: [PATCH 306/684] clk: qcom: use different Kconfig prompts for APSS IPQ5424/6018 drivers Both the IPQ_APSS_5424 and IPQ_APSS_6018 symbols are using the same prompt which complicates to see that which option corresponds to which driver. Add a prefix to both prompts to make it easier to differentiate the two options. While at it, also fix a typo in the help text of the IPQ_APSS_5424 symbol. Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20251113-clk-qcom-apss-ipq-prompt-v1-1-b62cf2142609@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 4a78099e706c2c..550a9d82a6b386 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -215,16 +215,16 @@ config IPQ_APSS_PLL devices. config IPQ_APSS_5424 - tristate "IPQ APSS Clock Controller" + tristate "IPQ5424 APSS Clock Controller" select IPQ_APSS_PLL default y if IPQ_GCC_5424 help - Support for APSS Clock controller on Qualcom IPQ5424 platform. + Support for APSS Clock controller on Qualcomm IPQ5424 platform. Say Y if you want to support CPU frequency scaling on ipq based devices. config IPQ_APSS_6018 - tristate "IPQ APSS Clock Controller" + tristate "IPQ6018 APSS Clock Controller" select IPQ_APSS_PLL depends on QCOM_APCS_IPC || COMPILE_TEST depends on QCOM_SMEM From 280b7cdddc3d96c4887fdb31b6766e4db1b2f2a3 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Sat, 1 Nov 2025 05:00:31 +0000 Subject: [PATCH 307/684] dt-bindings: clock: renesas,r9a09g057-cpg: Add USB3.0 core clocks Add definitions for USB3.0 core clocks in the R9A09G057 CPG DT bindings header file. Signed-off-by: Lad Prabhakar Acked-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251101050034.738807-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/renesas,r9a09g057-cpg.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/dt-bindings/clock/renesas,r9a09g057-cpg.h b/include/dt-bindings/clock/renesas,r9a09g057-cpg.h index 5346a898ab60a2..f91d7f72922af3 100644 --- a/include/dt-bindings/clock/renesas,r9a09g057-cpg.h +++ b/include/dt-bindings/clock/renesas,r9a09g057-cpg.h @@ -22,5 +22,9 @@ #define R9A09G057_GBETH_0_CLK_PTP_REF_I 11 #define R9A09G057_GBETH_1_CLK_PTP_REF_I 12 #define R9A09G057_SPI_CLK_SPI 13 +#define R9A09G057_USB3_0_REF_ALT_CLK_P 14 +#define R9A09G057_USB3_0_CLKCORE 15 +#define R9A09G057_USB3_1_REF_ALT_CLK_P 16 +#define R9A09G057_USB3_1_CLKCORE 17 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G057_CPG_H__ */ From a95ce05cd0cc8b53f1559390c4e690bb8f79562f Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Sat, 1 Nov 2025 05:00:32 +0000 Subject: [PATCH 308/684] dt-bindings: clock: renesas,r9a09g056-cpg: Add USB3.0 core clocks Add definitions for USB3.0 core clocks in the R9A09G056 CPG DT bindings header file. Signed-off-by: Lad Prabhakar Acked-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251101050034.738807-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/renesas,r9a09g056-cpg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/renesas,r9a09g056-cpg.h b/include/dt-bindings/clock/renesas,r9a09g056-cpg.h index a9af5af9e3a111..234dcf4f0f914f 100644 --- a/include/dt-bindings/clock/renesas,r9a09g056-cpg.h +++ b/include/dt-bindings/clock/renesas,r9a09g056-cpg.h @@ -21,5 +21,7 @@ #define R9A09G056_GBETH_0_CLK_PTP_REF_I 10 #define R9A09G056_GBETH_1_CLK_PTP_REF_I 11 #define R9A09G056_SPI_CLK_SPI 12 +#define R9A09G056_USB3_0_REF_ALT_CLK_P 13 +#define R9A09G056_USB3_0_CLKCORE 14 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__ */ From c6b63d54c6f8d81e72c8b9b8e8d1cb5ada03c5dd Mon Sep 17 00:00:00 2001 From: Biju Das Date: Mon, 27 Oct 2025 15:45:48 +0000 Subject: [PATCH 309/684] clk: renesas: r9a09g047: Add RSCI clocks/resets Add RSCI clock and reset entries. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251027154615.115759-2-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g047-cpg.c | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/clk/renesas/r9a09g047-cpg.c b/drivers/clk/renesas/r9a09g047-cpg.c index 68f8b08bd16f3f..1e9896742a062e 100644 --- a/drivers/clk/renesas/r9a09g047-cpg.c +++ b/drivers/clk/renesas/r9a09g047-cpg.c @@ -44,6 +44,9 @@ enum clk_ids { CLK_PLLCLN_DIV8, CLK_PLLCLN_DIV16, CLK_PLLCLN_DIV20, + CLK_PLLCLN_DIV64, + CLK_PLLCLN_DIV256, + CLK_PLLCLN_DIV1024, CLK_PLLDTY_ACPU, CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU_DIV4, @@ -142,6 +145,9 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8), DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16), DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20), + DEF_FIXED(".pllcln_div64", CLK_PLLCLN_DIV64, CLK_PLLCLN, 1, 64), + DEF_FIXED(".pllcln_div256", CLK_PLLCLN_DIV256, CLK_PLLCLN, 1, 256), + DEF_FIXED(".pllcln_div1024", CLK_PLLCLN_DIV1024, CLK_PLLCLN, 1, 1024), DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64), DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2), @@ -218,6 +224,106 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = { BUS_MSTOP(5, BIT(13))), DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18, BUS_MSTOP(5, BIT(13))), + DEF_MOD("rsci0_pclk", CLK_PLLCLN_DIV16, 5, 13, 2, 29, + BUS_MSTOP(11, BIT(3))), + DEF_MOD("rsci0_tclk", CLK_PLLCLN_DIV16, 5, 14, 2, 30, + BUS_MSTOP(11, BIT(3))), + DEF_MOD("rsci0_ps_ps3_n", CLK_PLLCLN_DIV1024, 5, 15, 2, 31, + BUS_MSTOP(11, BIT(3))), + DEF_MOD("rsci0_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 0, 3, 0, + BUS_MSTOP(11, BIT(3))), + DEF_MOD("rsci0_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 1, 3, 1, + BUS_MSTOP(11, BIT(3))), + DEF_MOD("rsci1_pclk", CLK_PLLCLN_DIV16, 6, 2, 3, 2, + BUS_MSTOP(11, BIT(4))), + DEF_MOD("rsci1_tclk", CLK_PLLCLN_DIV16, 6, 3, 3, 3, + BUS_MSTOP(11, BIT(4))), + DEF_MOD("rsci1_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 4, 3, 4, + BUS_MSTOP(11, BIT(4))), + DEF_MOD("rsci1_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 5, 3, 5, + BUS_MSTOP(11, BIT(4))), + DEF_MOD("rsci1_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 6, 3, 6, + BUS_MSTOP(11, BIT(4))), + DEF_MOD("rsci2_pclk", CLK_PLLCLN_DIV16, 6, 7, 3, 7, + BUS_MSTOP(11, BIT(5))), + DEF_MOD("rsci2_tclk", CLK_PLLCLN_DIV16, 6, 8, 3, 8, + BUS_MSTOP(11, BIT(5))), + DEF_MOD("rsci2_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 9, 3, 9, + BUS_MSTOP(11, BIT(5))), + DEF_MOD("rsci2_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 10, 3, 10, + BUS_MSTOP(11, BIT(5))), + DEF_MOD("rsci2_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 11, 3, 11, + BUS_MSTOP(11, BIT(5))), + DEF_MOD("rsci3_pclk", CLK_PLLCLN_DIV16, 6, 12, 3, 12, + BUS_MSTOP(11, BIT(6))), + DEF_MOD("rsci3_tclk", CLK_PLLCLN_DIV16, 6, 13, 3, 13, + BUS_MSTOP(11, BIT(6))), + DEF_MOD("rsci3_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 14, 3, 14, + BUS_MSTOP(11, BIT(6))), + DEF_MOD("rsci3_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 15, 3, 15, + BUS_MSTOP(11, BIT(6))), + DEF_MOD("rsci3_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 0, 3, 16, + BUS_MSTOP(11, BIT(6))), + DEF_MOD("rsci4_pclk", CLK_PLLCLN_DIV16, 7, 1, 3, 17, + BUS_MSTOP(11, BIT(7))), + DEF_MOD("rsci4_tclk", CLK_PLLCLN_DIV16, 7, 2, 3, 18, + BUS_MSTOP(11, BIT(7))), + DEF_MOD("rsci4_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 3, 3, 19, + BUS_MSTOP(11, BIT(7))), + DEF_MOD("rsci4_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 4, 3, 20, + BUS_MSTOP(11, BIT(7))), + DEF_MOD("rsci4_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 5, 3, 21, + BUS_MSTOP(11, BIT(7))), + DEF_MOD("rsci5_pclk", CLK_PLLCLN_DIV16, 7, 6, 3, 22, + BUS_MSTOP(11, BIT(8))), + DEF_MOD("rsci5_tclk", CLK_PLLCLN_DIV16, 7, 7, 3, 23, + BUS_MSTOP(11, BIT(8))), + DEF_MOD("rsci5_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 8, 3, 24, + BUS_MSTOP(11, BIT(8))), + DEF_MOD("rsci5_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 9, 3, 25, + BUS_MSTOP(11, BIT(8))), + DEF_MOD("rsci5_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 10, 3, 26, + BUS_MSTOP(11, BIT(8))), + DEF_MOD("rsci6_pclk", CLK_PLLCLN_DIV16, 7, 11, 3, 27, + BUS_MSTOP(11, BIT(9))), + DEF_MOD("rsci6_tclk", CLK_PLLCLN_DIV16, 7, 12, 3, 28, + BUS_MSTOP(11, BIT(9))), + DEF_MOD("rsci6_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 13, 3, 29, + BUS_MSTOP(11, BIT(9))), + DEF_MOD("rsci6_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 14, 3, 30, + BUS_MSTOP(11, BIT(9))), + DEF_MOD("rsci6_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 15, 3, 31, + BUS_MSTOP(11, BIT(9))), + DEF_MOD("rsci7_pclk", CLK_PLLCLN_DIV16, 8, 0, 4, 0, + BUS_MSTOP(11, BIT(10))), + DEF_MOD("rsci7_tclk", CLK_PLLCLN_DIV16, 8, 1, 4, 1, + BUS_MSTOP(11, BIT(10))), + DEF_MOD("rsci7_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 2, 4, 2, + BUS_MSTOP(11, BIT(10))), + DEF_MOD("rsci7_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 3, 4, 3, + BUS_MSTOP(11, BIT(10))), + DEF_MOD("rsci7_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 4, 4, 4, + BUS_MSTOP(11, BIT(10))), + DEF_MOD("rsci8_pclk", CLK_PLLCLN_DIV16, 8, 5, 4, 5, + BUS_MSTOP(11, BIT(11))), + DEF_MOD("rsci8_tclk", CLK_PLLCLN_DIV16, 8, 6, 4, 6, + BUS_MSTOP(11, BIT(11))), + DEF_MOD("rsci8_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 7, 4, 7, + BUS_MSTOP(11, BIT(11))), + DEF_MOD("rsci8_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 8, 4, 8, + BUS_MSTOP(11, BIT(11))), + DEF_MOD("rsci8_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 9, 4, 9, + BUS_MSTOP(11, BIT(11))), + DEF_MOD("rsci9_pclk", CLK_PLLCLN_DIV16, 8, 10, 4, 10, + BUS_MSTOP(11, BIT(12))), + DEF_MOD("rsci9_tclk", CLK_PLLCLN_DIV16, 8, 11, 4, 11, + BUS_MSTOP(11, BIT(12))), + DEF_MOD("rsci9_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 12, 4, 12, + BUS_MSTOP(11, BIT(12))), + DEF_MOD("rsci9_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 13, 4, 13, + BUS_MSTOP(11, BIT(12))), + DEF_MOD("rsci9_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 14, 4, 14, + BUS_MSTOP(11, BIT(12))), DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15, BUS_MSTOP(3, BIT(14))), DEF_MOD("i3c_0_pclkrw", CLK_PLLCLN_DIV16, 9, 0, 4, 16, @@ -351,6 +457,26 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = { DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */ DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */ DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */ + DEF_RST(8, 1, 3, 18), /* RSCI0_PRESETN */ + DEF_RST(8, 2, 3, 19), /* RSCI0_TRESETN */ + DEF_RST(8, 3, 3, 20), /* RSCI1_PRESETN */ + DEF_RST(8, 4, 3, 21), /* RSCI1_TRESETN */ + DEF_RST(8, 5, 3, 22), /* RSCI2_PRESETN */ + DEF_RST(8, 6, 3, 23), /* RSCI2_TRESETN */ + DEF_RST(8, 7, 3, 24), /* RSCI3_PRESETN */ + DEF_RST(8, 8, 3, 25), /* RSCI3_TRESETN */ + DEF_RST(8, 9, 3, 26), /* RSCI4_PRESETN */ + DEF_RST(8, 10, 3, 27), /* RSCI4_TRESETN */ + DEF_RST(8, 11, 3, 28), /* RSCI5_PRESETN */ + DEF_RST(8, 12, 3, 29), /* RSCI5_TRESETN */ + DEF_RST(8, 13, 3, 30), /* RSCI6_PRESETN */ + DEF_RST(8, 14, 3, 31), /* RSCI6_TRESETN */ + DEF_RST(8, 15, 4, 0), /* RSCI7_PRESETN */ + DEF_RST(9, 0, 4, 1), /* RSCI7_TRESETN */ + DEF_RST(9, 1, 4, 2), /* RSCI8_PRESETN */ + DEF_RST(9, 2, 4, 3), /* RSCI8_TRESETN */ + DEF_RST(9, 3, 4, 4), /* RSCI9_PRESETN */ + DEF_RST(9, 4, 4, 5), /* RSCI9_TRESETN */ DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */ DEF_RST(9, 6, 4, 7), /* I3C_0_PRESETN */ DEF_RST(9, 7, 4, 8), /* I3C_0_TRESETN */ From 4ecc8ccde5b488eb7284c1e674f274850eb039a6 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Sat, 1 Nov 2025 05:00:33 +0000 Subject: [PATCH 310/684] clk: renesas: r9a09g057: Add USB3.0 clocks/resets Add USB3.0 clock and reset entries. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251101050034.738807-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g057-cpg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index c9f6d91884c39b..400d9e94f2e9f3 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -17,7 +17,7 @@ enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R9A09G057_SPI_CLK_SPI, + LAST_DT_CORE_CLK = R9A09G057_USB3_1_CLKCORE, /* External Input Clocks */ CLK_AUDIO_EXTAL, @@ -235,6 +235,10 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { CLK_PLLETH_DIV_125_FIX, 1, 1), DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2, FIXED_MOD_CONF_XSPI), + DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G057_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1), + DEF_FIXED("usb3_0_core_clk", R9A09G057_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1), + DEF_FIXED("usb3_1_ref_alt_clk_p", R9A09G057_USB3_1_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1), + DEF_FIXED("usb3_1_core_clk", R9A09G057_USB3_1_CLKCORE, CLK_QEXTAL, 1, 1), }; static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { @@ -360,6 +364,14 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { BUS_MSTOP(8, BIT(4))), DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14, BUS_MSTOP(8, BIT(4))), + DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15, + BUS_MSTOP(7, BIT(12))), + DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16, + BUS_MSTOP(7, BIT(14))), + DEF_MOD("usb3_1_aclk", CLK_PLLDTY_DIV8, 11, 1, 5, 17, + BUS_MSTOP(7, BIT(13))), + DEF_MOD("usb3_1_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 2, 5, 18, + BUS_MSTOP(7, BIT(15))), DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19, BUS_MSTOP(7, BIT(7))), DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20, @@ -501,6 +513,8 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = { DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */ DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */ + DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */ + DEF_RST(10, 11, 4, 28), /* USB3_1_ARESETN */ DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */ DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */ DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */ From 7efa3a6d96348bfbe02e330219b05ec922958fab Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Sat, 1 Nov 2025 05:00:34 +0000 Subject: [PATCH 311/684] clk: renesas: r9a09g056: Add USB3.0 clocks/resets Add USB3.0 clock and reset entries. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251101050034.738807-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g056-cpg.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g056-cpg.c b/drivers/clk/renesas/r9a09g056-cpg.c index e4a6dfd2bec93d..f48a082e65d77c 100644 --- a/drivers/clk/renesas/r9a09g056-cpg.c +++ b/drivers/clk/renesas/r9a09g056-cpg.c @@ -17,7 +17,7 @@ enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R9A09G056_SPI_CLK_SPI, + LAST_DT_CORE_CLK = R9A09G056_USB3_0_CLKCORE, /* External Input Clocks */ CLK_AUDIO_EXTAL, @@ -226,6 +226,8 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = { CLK_PLLETH_DIV_125_FIX, 1, 1), DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G056_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2, FIXED_MOD_CONF_XSPI), + DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G056_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1), + DEF_FIXED("usb3_0_core_clk", R9A09G056_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1), }; static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = { @@ -319,6 +321,10 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = { BUS_MSTOP(8, BIT(4))), DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14, BUS_MSTOP(8, BIT(4))), + DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15, + BUS_MSTOP(7, BIT(12))), + DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16, + BUS_MSTOP(7, BIT(14))), DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19, BUS_MSTOP(7, BIT(7))), DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21, @@ -426,6 +432,7 @@ static const struct rzv2h_reset r9a09g056_resets[] __initconst = { DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */ DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */ + DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */ DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */ DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */ DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */ From 5fb2f67341bd4b7c482f2bbda6b78244a51c3923 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Wed, 5 Nov 2025 12:41:38 +0200 Subject: [PATCH 312/684] clk: renesas: r9a09g077: Add SPI module clocks The Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs have four SPI peripherals, each with their own clock divider, which divides PLL4 by either 24, 25, 30 or 32, similar to the SCI peripheral. The dividers feed into the usual module clocks. Add them all. Signed-off-by: Cosmin Tanislav Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251105104151.1489281-2-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index b46167d42084d3..fb6cc94d08a11f 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -46,8 +46,12 @@ #define DIVCA55C2 CONF_PACK(SCKCR2, 10, 1) #define DIVCA55C3 CONF_PACK(SCKCR2, 11, 1) #define DIVCA55S CONF_PACK(SCKCR2, 12, 1) +#define DIVSPI3ASYNC CONF_PACK(SCKCR2, 16, 2) #define DIVSCI5ASYNC CONF_PACK(SCKCR2, 18, 2) +#define DIVSPI0ASYNC CONF_PACK(SCKCR3, 0, 2) +#define DIVSPI1ASYNC CONF_PACK(SCKCR3, 2, 2) +#define DIVSPI2ASYNC CONF_PACK(SCKCR3, 4, 2) #define DIVSCI0ASYNC CONF_PACK(SCKCR3, 6, 2) #define DIVSCI1ASYNC CONF_PACK(SCKCR3, 8, 2) #define DIVSCI2ASYNC CONF_PACK(SCKCR3, 10, 2) @@ -56,7 +60,6 @@ #define SEL_PLL CONF_PACK(SCKCR, 22, 1) - enum rzt2h_clk_types { CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */ CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */ @@ -94,6 +97,10 @@ enum clk_ids { CLK_SCI3ASYNC, CLK_SCI4ASYNC, CLK_SCI5ASYNC, + CLK_SPI0ASYNC, + CLK_SPI1ASYNC, + CLK_SPI2ASYNC, + CLK_SPI3ASYNC, /* Module Clocks */ MOD_CLK_BASE, @@ -154,6 +161,15 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC, dtable_24_25_30_32), + DEF_DIV(".spi0async", CLK_SPI0ASYNC, CLK_PLL4D1, DIVSPI0ASYNC, + dtable_24_25_30_32), + DEF_DIV(".spi1async", CLK_SPI1ASYNC, CLK_PLL4D1, DIVSPI1ASYNC, + dtable_24_25_30_32), + DEF_DIV(".spi2async", CLK_SPI2ASYNC, CLK_PLL4D1, DIVSPI2ASYNC, + dtable_24_25_30_32), + DEF_DIV(".spi3async", CLK_SPI3ASYNC, CLK_PLL4D1, DIVSPI3ASYNC, + dtable_24_25_30_32), + /* Core output clk */ DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0, dtable_1_2), @@ -188,6 +204,9 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC), DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL), DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL), + DEF_MOD("spi0", 104, CLK_SPI0ASYNC), + DEF_MOD("spi1", 105, CLK_SPI1ASYNC), + DEF_MOD("spi2", 106, CLK_SPI2ASYNC), DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH), DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH), DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM), @@ -200,6 +219,7 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("gmac2", 417, R9A09G077_CLK_PCLKAM), DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC), DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL), + DEF_MOD("spi3", 602, CLK_SPI3ASYNC), DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM), DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM), }; From 3b0cf6ab35909d7ac8d561e18159c62d42d914c2 Mon Sep 17 00:00:00 2001 From: John Madieu Date: Thu, 6 Nov 2025 09:07:58 +0100 Subject: [PATCH 313/684] pinctrl: renesas: rzg2l: Refactor OEN register PWPR handling Extract the OEN register write with PWPR protection logic into a helper function to eliminate code duplication between rzg2l_write_oen() and rzg2l_pinctrl_resume_noirq(). Introduce rzg2l_oen_write_with_pwpr() helper that encapsulates the PWPR unlock, OEN register write, and PWPR lock sequence. This helper must be called with pctrl->lock already held by the caller. Reported-by: Pavel Machek Closes: https://lore.kernel.org/cip-dev/OS9PR01MB16368C765305362F5F4132759FFC4A@OS9PR01MB16368.jpnprd01.prod.outlook.com/T/#u Signed-off-by: John Madieu Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251106080758.36645-1-john.madieu.xa@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 53 +++++++++++++++---------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index f25ecada5c6929..863e779dda0285 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -1112,13 +1112,37 @@ static int rzg2l_read_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin) return !(readb(pctrl->base + pctrl->data->hwcfg->regs.oen) & BIT(bit)); } -static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen) +/** + * rzg2l_oen_write_with_pwpr - Write to OEN register with PWPR protection + * @pctrl: pinctrl driver data + * @val: value to write to OEN register + * + * Writes to the OEN register, handling PWPR write protection if required + * by the hardware configuration. Must be called with pctrl->lock held. + */ +static void rzg2l_oen_write_with_pwpr(struct rzg2l_pinctrl *pctrl, u8 val) { const struct rzg2l_register_offsets *regs = &pctrl->data->hwcfg->regs; + u16 oen_offset = pctrl->data->hwcfg->regs.oen; + u8 pwpr; + + if (pctrl->data->hwcfg->oen_pwpr_lock) { + pwpr = readb(pctrl->base + regs->pwpr); + writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); + } + + writeb(val, pctrl->base + oen_offset); + + if (pctrl->data->hwcfg->oen_pwpr_lock) + writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); +} + +static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen) +{ u16 oen_offset = pctrl->data->hwcfg->regs.oen; unsigned long flags; - u8 val, pwpr; int bit; + u8 val; if (!pctrl->data->pin_to_oen_bit) return -EOPNOTSUPP; @@ -1133,13 +1157,8 @@ static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oe val &= ~BIT(bit); else val |= BIT(bit); - if (pctrl->data->hwcfg->oen_pwpr_lock) { - pwpr = readb(pctrl->base + regs->pwpr); - writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); - } - writeb(val, pctrl->base + oen_offset); - if (pctrl->data->hwcfg->oen_pwpr_lock) - writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); + + rzg2l_oen_write_with_pwpr(pctrl, val); raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; @@ -3200,7 +3219,6 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) const struct rzg2l_register_offsets *regs = &hwcfg->regs; struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; unsigned long flags; - u8 pwpr; int ret; if (!atomic_read(&pctrl->wakeup_path)) { @@ -3210,16 +3228,11 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) } writeb(cache->qspi, pctrl->base + QSPI); - if (pctrl->data->hwcfg->oen_pwpr_lock) { - raw_spin_lock_irqsave(&pctrl->lock, flags); - pwpr = readb(pctrl->base + regs->pwpr); - writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); - } - writeb(cache->oen, pctrl->base + pctrl->data->hwcfg->regs.oen); - if (pctrl->data->hwcfg->oen_pwpr_lock) { - writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - } + + raw_spin_lock_irqsave(&pctrl->lock, flags); + rzg2l_oen_write_with_pwpr(pctrl, cache->oen); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + for (u8 i = 0; i < 2; i++) { if (regs->sd_ch) writeb(cache->sd_ch[i], pctrl->base + SD_CH(regs->sd_ch, i)); From fa3542e822c99196a27f030e87eab5458072613a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Barna=C5=9B?= Date: Tue, 28 Oct 2025 16:16:42 +0000 Subject: [PATCH 314/684] clk: keystone: Fix discarded const qualifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add const qualifiers to the pointers returned from 'container_of' macro to prevent breaking the const promise on const struct pointers from parameters. Once you have a mutable container structure pointer, you can change structure fields through it, which violates the const guarantee. Signed-off-by: Adrian Barnaś Reviewed-by: Nishanth Menon Signed-off-by: Stephen Boyd --- drivers/clk/keystone/sci-clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index a4b42811de55de..9d5071223f4cb3 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -496,8 +496,8 @@ static int ti_sci_scan_clocks_from_fw(struct sci_clk_provider *provider) static int _cmp_sci_clk_list(void *priv, const struct list_head *a, const struct list_head *b) { - struct sci_clk *ca = container_of(a, struct sci_clk, node); - struct sci_clk *cb = container_of(b, struct sci_clk, node); + const struct sci_clk *ca = container_of(a, struct sci_clk, node); + const struct sci_clk *cb = container_of(b, struct sci_clk, node); return _cmp_sci_clk(ca, &cb); } From 2e12d91cbf3d0105fc58d07b8a0548ebd7bb619b Mon Sep 17 00:00:00 2001 From: Encrow Thorne Date: Tue, 11 Nov 2025 23:50:09 +0800 Subject: [PATCH 315/684] clk: spacemit: fix comment typo Fix incorrect comment to match the filename. Reviewd-by: Troy Mitchell Signed-off-by: Encrow Thorne Reviewed-by: Yixun Lan Signed-off-by: Stephen Boyd --- drivers/clk/spacemit/ccu_mix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/spacemit/ccu_mix.h b/drivers/clk/spacemit/ccu_mix.h index 54d40cd39b2752..c406508e3504ef 100644 --- a/drivers/clk/spacemit/ccu_mix.h +++ b/drivers/clk/spacemit/ccu_mix.h @@ -220,4 +220,4 @@ extern const struct clk_ops spacemit_ccu_div_gate_ops; extern const struct clk_ops spacemit_ccu_mux_gate_ops; extern const struct clk_ops spacemit_ccu_mux_div_ops; extern const struct clk_ops spacemit_ccu_mux_div_gate_ops; -#endif /* _CCU_DIV_H_ */ +#endif /* _CCU_MIX_H_ */ From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Mon, 10 Nov 2025 06:56:43 +0300 Subject: [PATCH 316/684] dt-bindings: clock: airoha: Add reset support to EN7523 clock binding Introduce reset capability to EN7523 device-tree clock binding documentation. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: Rob Herring (Arm) Signed-off-by: Stephen Boyd --- .../bindings/clock/airoha,en7523-scu.yaml | 3 +- .../dt-bindings/reset/airoha,en7523-reset.h | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/reset/airoha,en7523-reset.h diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml index fe2c5c1baf4332..a8471367175b14 100644 --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -64,8 +64,6 @@ allOf: reg: minItems: 2 - '#reset-cells': false - - if: properties: compatible: @@ -85,6 +83,7 @@ examples: reg = <0x1fa20000 0x400>, <0x1fb00000 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; }; - | diff --git a/include/dt-bindings/reset/airoha,en7523-reset.h b/include/dt-bindings/reset/airoha,en7523-reset.h new file mode 100644 index 00000000000000..211e8a23a21cd2 --- /dev/null +++ b/include/dt-bindings/reset/airoha,en7523-reset.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 iopsys Software Solutions AB. + * Copyright (C) 2025 Genexis AB. + * + * Author: Mikhail Kshevetskiy + * + * based on + * include/dt-bindings/reset/airoha,en7581-reset.h + * by Lorenzo Bianconi + */ + +#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ +#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ + +/* RST_CTRL2 */ +#define EN7523_XPON_PHY_RST 0 +#define EN7523_XSI_MAC_RST 1 +#define EN7523_XSI_PHY_RST 2 +#define EN7523_NPU_RST 3 +#define EN7523_I2S_RST 4 +#define EN7523_TRNG_RST 5 +#define EN7523_TRNG_MSTART_RST 6 +#define EN7523_DUAL_HSI0_RST 7 +#define EN7523_DUAL_HSI1_RST 8 +#define EN7523_HSI_RST 9 +#define EN7523_DUAL_HSI0_MAC_RST 10 +#define EN7523_DUAL_HSI1_MAC_RST 11 +#define EN7523_HSI_MAC_RST 12 +#define EN7523_WDMA_RST 13 +#define EN7523_WOE0_RST 14 +#define EN7523_WOE1_RST 15 +#define EN7523_HSDMA_RST 16 +#define EN7523_I2C2RBUS_RST 17 +#define EN7523_TDMA_RST 18 +/* RST_CTRL1 */ +#define EN7523_PCM1_ZSI_ISI_RST 19 +#define EN7523_FE_PDMA_RST 20 +#define EN7523_FE_QDMA_RST 21 +#define EN7523_PCM_SPIWP_RST 22 +#define EN7523_CRYPTO_RST 23 +#define EN7523_TIMER_RST 24 +#define EN7523_PCM1_RST 25 +#define EN7523_UART_RST 26 +#define EN7523_GPIO_RST 27 +#define EN7523_GDMA_RST 28 +#define EN7523_I2C_MASTER_RST 29 +#define EN7523_PCM2_ZSI_ISI_RST 30 +#define EN7523_SFC_RST 31 +#define EN7523_UART2_RST 32 +#define EN7523_GDMP_RST 33 +#define EN7523_FE_RST 34 +#define EN7523_USB_HOST_P0_RST 35 +#define EN7523_GSW_RST 36 +#define EN7523_SFC2_PCM_RST 37 +#define EN7523_PCIE0_RST 38 +#define EN7523_PCIE1_RST 39 +#define EN7523_PCIE_HB_RST 40 +#define EN7523_XPON_MAC_RST 41 + +#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */ From 1c0608d860db973ad09b5a9ccb19b76ae07622a3 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Mon, 10 Nov 2025 06:56:44 +0300 Subject: [PATCH 317/684] clk: en7523: Add reset-controller support for EN7523 SoC Introduce reset API support to EN7523 clock driver. EN7523 uses the same reset logic as EN7581, so just reuse existing code. Signed-off-by: Mikhail Kshevetskiy Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/clk-en7523.c | 64 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c index 15bbdeb60b8e66..08cc8e5acf4375 100644 --- a/drivers/clk/clk-en7523.c +++ b/drivers/clk/clk-en7523.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #define RST_NR_PER_BANK 32 @@ -299,6 +300,53 @@ static const u16 en7581_rst_ofs[] = { REG_RST_CTRL1, }; +static const u16 en7523_rst_map[] = { + /* RST_CTRL2 */ + [EN7523_XPON_PHY_RST] = 0, + [EN7523_XSI_MAC_RST] = 7, + [EN7523_XSI_PHY_RST] = 8, + [EN7523_NPU_RST] = 9, + [EN7523_I2S_RST] = 10, + [EN7523_TRNG_RST] = 11, + [EN7523_TRNG_MSTART_RST] = 12, + [EN7523_DUAL_HSI0_RST] = 13, + [EN7523_DUAL_HSI1_RST] = 14, + [EN7523_HSI_RST] = 15, + [EN7523_DUAL_HSI0_MAC_RST] = 16, + [EN7523_DUAL_HSI1_MAC_RST] = 17, + [EN7523_HSI_MAC_RST] = 18, + [EN7523_WDMA_RST] = 19, + [EN7523_WOE0_RST] = 20, + [EN7523_WOE1_RST] = 21, + [EN7523_HSDMA_RST] = 22, + [EN7523_I2C2RBUS_RST] = 23, + [EN7523_TDMA_RST] = 24, + /* RST_CTRL1 */ + [EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, + [EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1, + [EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2, + [EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, + [EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6, + [EN7523_TIMER_RST] = RST_NR_PER_BANK + 8, + [EN7523_PCM1_RST] = RST_NR_PER_BANK + 11, + [EN7523_UART_RST] = RST_NR_PER_BANK + 12, + [EN7523_GPIO_RST] = RST_NR_PER_BANK + 13, + [EN7523_GDMA_RST] = RST_NR_PER_BANK + 14, + [EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, + [EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, + [EN7523_SFC_RST] = RST_NR_PER_BANK + 18, + [EN7523_UART2_RST] = RST_NR_PER_BANK + 19, + [EN7523_GDMP_RST] = RST_NR_PER_BANK + 20, + [EN7523_FE_RST] = RST_NR_PER_BANK + 21, + [EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, + [EN7523_GSW_RST] = RST_NR_PER_BANK + 23, + [EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, + [EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26, + [EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27, + [EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29, + [EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31, +}; + static const u16 en7581_rst_map[] = { /* RST_CTRL2 */ [EN7581_XPON_PHY_RST] = 0, @@ -357,6 +405,9 @@ static const u16 en7581_rst_map[] = { [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, }; +static int en7581_reset_register(struct device *dev, void __iomem *base, + const u16 *rst_map, int nr_resets); + static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) { if (!desc->base_bits) @@ -552,7 +603,8 @@ static int en7523_clk_hw_init(struct platform_device *pdev, en7523_register_clocks(&pdev->dev, clk_data, base, np_base); - return 0; + return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, + ARRAY_SIZE(en7523_rst_map)); } static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, @@ -652,7 +704,8 @@ static const struct reset_control_ops en7581_reset_ops = { .status = en7523_reset_status, }; -static int en7581_reset_register(struct device *dev, void __iomem *base) +static int en7581_reset_register(struct device *dev, void __iomem *base, + const u16 *rst_map, int nr_resets) { struct en_rst_data *rst_data; @@ -661,10 +714,10 @@ static int en7581_reset_register(struct device *dev, void __iomem *base) return -ENOMEM; rst_data->bank_ofs = en7581_rst_ofs; - rst_data->idx_map = en7581_rst_map; + rst_data->idx_map = rst_map; rst_data->base = base; - rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); + rst_data->rcdev.nr_resets = nr_resets; rst_data->rcdev.of_xlate = en7523_reset_xlate; rst_data->rcdev.ops = &en7581_reset_ops; rst_data->rcdev.of_node = dev->of_node; @@ -698,7 +751,8 @@ static int en7581_clk_hw_init(struct platform_device *pdev, val = readl(base + REG_NP_SCU_PCIC); writel(val | 3, base + REG_NP_SCU_PCIC); - return en7581_reset_register(&pdev->dev, base); + return en7581_reset_register(&pdev->dev, base, en7581_rst_map, + ARRAY_SIZE(en7581_rst_map)); } static int en7523_clk_probe(struct platform_device *pdev) From 8933c624d9c793eed8fa778add30fa50fd8ef4d7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 9 Nov 2025 17:31:48 -0800 Subject: [PATCH 318/684] perf intel-pt: Use the perf provided "cpuid.h" Rather than having a feature test and include of for the __get_cpuid function, use the cpuid function provided by tools/perf/arch/x86/util/cpuid.h. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/tests/intel-pt-test.c | 6 +++--- tools/perf/arch/x86/util/intel-pt.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/arch/x86/tests/intel-pt-test.c b/tools/perf/arch/x86/tests/intel-pt-test.c index b217ed67cd4e52..970997759ec2fb 100644 --- a/tools/perf/arch/x86/tests/intel-pt-test.c +++ b/tools/perf/arch/x86/tests/intel-pt-test.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "intel-pt-decoder/intel-pt-pkt-decoder.h" @@ -11,6 +10,7 @@ #include "debug.h" #include "tests/tests.h" #include "arch-tests.h" +#include "../util/cpuid.h" #include "cpumap.h" /** @@ -363,7 +363,7 @@ static int get_pt_caps(int cpu, struct pt_caps *caps) memset(caps, 0, sizeof(*caps)); for (i = 0; i < INTEL_PT_SUBLEAF_CNT; i++) { - __get_cpuid_count(20, i, &r.eax, &r.ebx, &r.ecx, &r.edx); + cpuid(20, i, &r.eax, &r.ebx, &r.ecx, &r.edx); pr_debug("CPU %d CPUID leaf 20 subleaf %d\n", cpu, i); pr_debug("eax = 0x%08x\n", r.eax); pr_debug("ebx = 0x%08x\n", r.ebx); @@ -380,7 +380,7 @@ static bool is_hybrid(void) unsigned int eax, ebx, ecx, edx = 0; bool result; - __get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx); + cpuid(7, 0, &eax, &ebx, &ecx, &edx); result = edx & BIT(15); pr_debug("Is %shybrid : CPUID leaf 7 subleaf 0 edx %#x (bit-15 indicates hybrid)\n", result ? "" : "not ", edx); diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 2d7c0dec86b073..b394ad9cc635b8 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "../../../util/session.h" #include "../../../util/event.h" @@ -34,6 +33,7 @@ #include // page_size #include "../../../util/intel-pt.h" #include +#include "cpuid.h" #define KiB(x) ((x) * 1024) #define MiB(x) ((x) * 1024 * 1024) @@ -311,7 +311,7 @@ static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) { unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; - __get_cpuid(0x15, &eax, &ebx, &ecx, &edx); + cpuid(0x15, 0, &eax, &ebx, &ecx, &edx); *n = ebx; *d = eax; } From 2566bbfc0a042feadeb0bea1f1f4b2b13f91c664 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 9 Nov 2025 17:31:49 -0800 Subject: [PATCH 319/684] perf build: Don't add NO_AUXTRACE if missing feature-get_cpuid The intel-pt code dependent on __get_cpuid is no longer present so remove the feature test in the Makefile.config. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/Makefile.config | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 5700516aa84aec..5decc3d5fef877 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -1114,16 +1114,8 @@ ifndef NO_CAPSTONE endif ifndef NO_AUXTRACE - ifeq ($(SRCARCH),x86) - ifeq ($(feature-get_cpuid), 0) - $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc) - NO_AUXTRACE := 1 - endif - endif - ifndef NO_AUXTRACE - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT - endif + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT endif ifdef EXTRA_TESTS From c819bfdc4a762ba8a3035815c910c2d5443b616b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 9 Nov 2025 17:31:50 -0800 Subject: [PATCH 320/684] tool build: Remove __get_cpuid feature test This feature test is no longer used so remove. The function tested by the feature test is used in: tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c however, the Makefile just assumes the presence of the function and doesn't perform a build feature test for it. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/build/Makefile.feature | 2 -- tools/build/feature/Makefile | 4 ---- tools/build/feature/test-all.c | 5 ----- tools/build/feature/test-get_cpuid.c | 8 -------- 4 files changed, 19 deletions(-) delete mode 100644 tools/build/feature/test-get_cpuid.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 32bbe29fe5f6c5..fc6abe369f7373 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -90,7 +90,6 @@ FEATURE_TESTS_BASIC := \ timerfd \ zlib \ lzma \ - get_cpuid \ bpf \ scandirat \ sched_getcpu \ @@ -146,7 +145,6 @@ FEATURE_DISPLAY ?= \ llvm-perf \ zlib \ lzma \ - get_cpuid \ bpf \ libaio \ libzstd diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 49b0add392b1c1..7c90e0d0157ac9 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -56,7 +56,6 @@ FILES= \ test-lzma.bin \ test-bpf.bin \ test-libbpf.bin \ - test-get_cpuid.bin \ test-sdt.bin \ test-cxx.bin \ test-gettid.bin \ @@ -318,9 +317,6 @@ $(OUTPUT)test-zlib.bin: $(OUTPUT)test-lzma.bin: $(BUILD) -llzma -$(OUTPUT)test-get_cpuid.bin: - $(BUILD) - $(OUTPUT)test-bpf.bin: $(BUILD) diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index 8a354b81417c6f..eb346160d0ba0e 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -114,10 +114,6 @@ # include "test-lzma.c" #undef main -#define main main_test_get_cpuid -# include "test-get_cpuid.c" -#undef main - #define main main_test_bpf # include "test-bpf.c" #undef main @@ -168,7 +164,6 @@ int main(int argc, char *argv[]) main_test_pthread_attr_setaffinity_np(); main_test_pthread_barrier(); main_test_lzma(); - main_test_get_cpuid(); main_test_bpf(); main_test_scandirat(); main_test_sched_getcpu(); diff --git a/tools/build/feature/test-get_cpuid.c b/tools/build/feature/test-get_cpuid.c deleted file mode 100644 index bb4f065f28a6bb..00000000000000 --- a/tools/build/feature/test-get_cpuid.c +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include - -int main(void) -{ - unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; - return __get_cpuid(0x15, &eax, &ebx, &ecx, &edx); -} From 754187ad73b73bcb44f106a8e5fc88789beff1bd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 9 Nov 2025 17:31:51 -0800 Subject: [PATCH 321/684] perf build: Remove NO_AUXTRACE build option The NO_AUXTRACE build option was used when the __get_cpuid feature test failed or if it was provided on the command line. The option no longer avoids a dependency on a library and so having the option is just adding complexity to the code base. Remove the option CONFIG_AUXTRACE from Build files and HAVE_AUXTRACE_SUPPORT by assuming it is always defined. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-check.txt | 1 - tools/perf/Makefile.config | 5 - tools/perf/Makefile.perf | 2 - tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/pmu.c | 2 - tools/perf/arch/arm64/util/Build | 19 +- tools/perf/arch/powerpc/util/Build | 2 +- tools/perf/arch/s390/util/Build | 2 +- tools/perf/arch/x86/tests/Build | 4 +- tools/perf/arch/x86/tests/arch-tests.c | 4 - tools/perf/arch/x86/util/Build | 6 +- tools/perf/arch/x86/util/pmu.c | 2 - tools/perf/builtin-check.c | 1 - tools/perf/builtin-inject.c | 15 -- tools/perf/builtin-record.c | 36 ---- tools/perf/builtin-script.c | 12 -- tools/perf/tests/make | 4 +- tools/perf/util/Build | 24 +-- tools/perf/util/arm-spe-decoder/Build | 2 +- tools/perf/util/auxtrace.h | 220 +----------------------- tools/perf/util/cs-etm-decoder/Build | 2 +- tools/perf/util/hisi-ptt-decoder/Build | 2 +- tools/perf/util/intel-pt-decoder/Build | 8 +- tools/perf/util/synthetic-events.h | 15 -- 24 files changed, 37 insertions(+), 355 deletions(-) diff --git a/tools/perf/Documentation/perf-check.txt b/tools/perf/Documentation/perf-check.txt index 4c9ccda6ce916b..09e1d35677f5b1 100644 --- a/tools/perf/Documentation/perf-check.txt +++ b/tools/perf/Documentation/perf-check.txt @@ -50,7 +50,6 @@ feature:: dwarf / HAVE_LIBDW_SUPPORT dwarf_getlocations / HAVE_LIBDW_SUPPORT dwarf-unwind / HAVE_DWARF_UNWIND_SUPPORT - auxtrace / HAVE_AUXTRACE_SUPPORT libbfd / HAVE_LIBBFD_SUPPORT libbpf-strings / HAVE_LIBBPF_STRINGS_SUPPORT libcapstone / HAVE_LIBCAPSTONE_SUPPORT diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 5decc3d5fef877..6b62fea21a0ad1 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -1113,11 +1113,6 @@ ifndef NO_CAPSTONE endif endif -ifndef NO_AUXTRACE - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT -endif - ifdef EXTRA_TESTS $(call detected,CONFIG_EXTRA_TESTS) CFLAGS += -DHAVE_EXTRA_TESTS diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index afeb4e4a8a318a..80decc7ce13c04 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -84,8 +84,6 @@ include ../scripts/utilities.mak # # Define NO_LZMA if you do not want to support compressed (xz) kernel modules # -# Define NO_AUXTRACE if you do not want AUX area tracing support -# # Define NO_LIBBPF if you do not want BPF support # # Define NO_LIBCAP if you do not want process capabilities considered by perf diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build index f7a8b37d1c6883..fd695e1fdaee2c 100644 --- a/tools/perf/arch/arm/util/Build +++ b/tools/perf/arch/arm/util/Build @@ -3,4 +3,4 @@ perf-util-y += perf_regs.o perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -perf-util-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o +perf-util-y += pmu.o auxtrace.o cs-etm.o diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c index f70075c89aa07a..9be8da5207f553 100644 --- a/tools/perf/arch/arm/util/pmu.c +++ b/tools/perf/arch/arm/util/pmu.c @@ -20,7 +20,6 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) { struct perf_cpu_map *intersect, *online = cpu_map__online(); -#ifdef HAVE_AUXTRACE_SUPPORT if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) { /* add ETM default config here */ pmu->auxtrace = true; @@ -39,7 +38,6 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) pmu->selectable = true; #endif } -#endif /* Workaround some ARM PMU's failing to correctly set CPU maps for online processors. */ intersect = perf_cpu_map__intersect(online, pmu->cpus); perf_cpu_map__put(online); diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build index a74521b79eaaa3..d63881081d2eb1 100644 --- a/tools/perf/arch/arm64/util/Build +++ b/tools/perf/arch/arm64/util/Build @@ -1,13 +1,14 @@ +perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o +perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o +perf-util-y += ../../arm/util/auxtrace.o +perf-util-y += ../../arm/util/cs-etm.o +perf-util-y += ../../arm/util/pmu.o +perf-util-y += arm-spe.o perf-util-y += header.o +perf-util-y += hisi-ptt.o perf-util-y += machine.o +perf-util-y += mem-events.o perf-util-y += perf_regs.o -perf-util-y += tsc.o perf-util-y += pmu.o -perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o -perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o - -perf-util-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ - ../../arm/util/auxtrace.o \ - ../../arm/util/cs-etm.o \ - arm-spe.o mem-events.o hisi-ptt.o +perf-util-y += tsc.o diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index a5b0babd307e9a..3d0d5427aef7f2 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build @@ -10,4 +10,4 @@ perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -perf-util-$(CONFIG_AUXTRACE) += auxtrace.o +perf-util-y += auxtrace.o diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build index 736c0ad0919437..c64eb18dbdae93 100644 --- a/tools/perf/arch/s390/util/Build +++ b/tools/perf/arch/s390/util/Build @@ -7,4 +7,4 @@ perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o perf-util-y += machine.o perf-util-y += pmu.o -perf-util-$(CONFIG_AUXTRACE) += auxtrace.o +perf-util-y += auxtrace.o diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build index 7790b3e20f4e40..b017d1ca6e3c96 100644 --- a/tools/perf/arch/x86/tests/Build +++ b/tools/perf/arch/x86/tests/Build @@ -3,9 +3,9 @@ perf-test-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o perf-test-y += arch-tests.o perf-test-y += hybrid.o -perf-test-$(CONFIG_AUXTRACE) += intel-pt-test.o +perf-test-y += intel-pt-test.o ifeq ($(CONFIG_EXTRA_TESTS),y) -perf-test-$(CONFIG_AUXTRACE) += insn-x86.o +perf-test-y += insn-x86.o endif perf-test-$(CONFIG_X86_64) += bp-modify.o perf-test-y += amd-ibs-via-core-pmu.o diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c index 8f9cfeaa170ff7..c3e1619c5e7944 100644 --- a/tools/perf/arch/x86/tests/arch-tests.c +++ b/tools/perf/arch/x86/tests/arch-tests.c @@ -3,7 +3,6 @@ #include "tests/tests.h" #include "arch-tests.h" -#ifdef HAVE_AUXTRACE_SUPPORT #ifdef HAVE_EXTRA_TESTS DEFINE_SUITE("x86 instruction decoder - new instructions", insn_x86); #endif @@ -19,7 +18,6 @@ struct test_suite suite__intel_pt = { .test_cases = intel_pt_tests, }; -#endif #if defined(__x86_64__) DEFINE_SUITE("x86 bp modify", bp_modify); #endif @@ -39,12 +37,10 @@ struct test_suite *arch_tests[] = { #ifdef HAVE_DWARF_UNWIND_SUPPORT &suite__dwarf_unwind, #endif -#ifdef HAVE_AUXTRACE_SUPPORT #ifdef HAVE_EXTRA_TESTS &suite__insn_x86, #endif &suite__intel_pt, -#endif #if defined(__x86_64__) &suite__bp_modify, #endif diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index 06d7c0205b3d08..c0dc5965f3624a 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -14,7 +14,7 @@ perf-util-y += iostat.o perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -perf-util-$(CONFIG_AUXTRACE) += auxtrace.o +perf-util-y += auxtrace.o perf-util-y += archinsn.o -perf-util-$(CONFIG_AUXTRACE) += intel-pt.o -perf-util-$(CONFIG_AUXTRACE) += intel-bts.o +perf-util-y += intel-pt.o +perf-util-y += intel-bts.o diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c index 58113482654b79..a3f96221758d58 100644 --- a/tools/perf/arch/x86/util/pmu.c +++ b/tools/perf/arch/x86/util/pmu.c @@ -273,7 +273,6 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) { struct perf_pmu_caps *ldlat_cap; -#ifdef HAVE_AUXTRACE_SUPPORT if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) { pmu->auxtrace = true; pmu->selectable = true; @@ -283,7 +282,6 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) pmu->auxtrace = true; pmu->selectable = true; } -#endif if (x86__is_amd_cpu()) { if (strcmp(pmu->name, "ibs_op")) diff --git a/tools/perf/builtin-check.c b/tools/perf/builtin-check.c index 9ce2e71999dfd7..d19769a8f68977 100644 --- a/tools/perf/builtin-check.c +++ b/tools/perf/builtin-check.c @@ -42,7 +42,6 @@ struct feature_status supported_features[] = { FEATURE_STATUS("dwarf", HAVE_LIBDW_SUPPORT), FEATURE_STATUS("dwarf_getlocations", HAVE_LIBDW_SUPPORT), FEATURE_STATUS("dwarf-unwind", HAVE_DWARF_UNWIND_SUPPORT), - FEATURE_STATUS("auxtrace", HAVE_AUXTRACE_SUPPORT), FEATURE_STATUS_TIP("libbfd", HAVE_LIBBFD_SUPPORT, "Deprecated, license incompatibility, use BUILD_NONDISTRO=1 and install binutils-dev[el]"), FEATURE_STATUS("libbpf-strings", HAVE_LIBBPF_STRINGS_SUPPORT), FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT), diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 044074080aa53a..bd9245d2dd41aa 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -239,8 +239,6 @@ static int perf_event__repipe_event_update(const struct perf_tool *tool, return perf_event__repipe_synth(tool, event); } -#ifdef HAVE_AUXTRACE_SUPPORT - static int copy_bytes(struct perf_inject *inject, struct perf_data *data, off_t size) { char buf[4096]; @@ -297,19 +295,6 @@ static s64 perf_event__repipe_auxtrace(const struct perf_tool *tool, return event->auxtrace.size; } -#else - -static s64 -perf_event__repipe_auxtrace(const struct perf_tool *tool __maybe_unused, - struct perf_session *session __maybe_unused, - union perf_event *event __maybe_unused) -{ - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -#endif - static int perf_event__repipe(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fe10bb7f35cbea..2584d0d8bc8206 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -730,8 +730,6 @@ static void record__sig_exit(void) raise(signr); } -#ifdef HAVE_AUXTRACE_SUPPORT - static int record__process_auxtrace(const struct perf_tool *tool, struct mmap *map, union perf_event *event, void *data1, @@ -889,40 +887,6 @@ static int record__auxtrace_init(struct record *rec) return auxtrace_parse_filters(rec->evlist); } -#else - -static inline -int record__auxtrace_mmap_read(struct record *rec __maybe_unused, - struct mmap *map __maybe_unused) -{ - return 0; -} - -static inline -void record__read_auxtrace_snapshot(struct record *rec __maybe_unused, - bool on_exit __maybe_unused) -{ -} - -static inline -int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) -{ - return 0; -} - -static inline -int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused) -{ - return 0; -} - -static int record__auxtrace_init(struct record *rec __maybe_unused) -{ - return 0; -} - -#endif - static int record__config_text_poke(struct evlist *evlist) { struct evsel *evsel; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index cf0040bbaba9cb..3ac6b80c460eb7 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2000,7 +2000,6 @@ static int perf_sample__fprintf_synth_iflag_chg(struct perf_sample *sample, FILE return len + perf_sample__fprintf_pt_spacing(len, fp); } -#ifdef HAVE_AUXTRACE_SUPPORT static int perf_sample__fprintf_synth_vpadtl(struct perf_sample *data, FILE *fp) { struct powerpc_vpadtl_entry *dtl = (struct powerpc_vpadtl_entry *)data->raw_data; @@ -2019,13 +2018,6 @@ static int perf_sample__fprintf_synth_vpadtl(struct perf_sample *data, FILE *fp) return len; } -#else -static int perf_sample__fprintf_synth_vpadtl(struct perf_sample *data __maybe_unused, - FILE *fp __maybe_unused) -{ - return 0; -} -#endif static int perf_sample__fprintf_synth(struct perf_sample *sample, struct evsel *evsel, FILE *fp) @@ -3856,7 +3848,6 @@ static int process_feature_event(const struct perf_tool *tool __maybe_unused, return 0; } -#ifdef HAVE_AUXTRACE_SUPPORT static int perf_script__process_auxtrace_info(const struct perf_tool *tool, struct perf_session *session, union perf_event *event) @@ -3871,9 +3862,6 @@ static int perf_script__process_auxtrace_info(const struct perf_tool *tool, return ret; } -#else -#define perf_script__process_auxtrace_info 0 -#endif static int parse_insn_trace(const struct option *opt __maybe_unused, const char *str, int unset __maybe_unused) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index b650ce8864ed57..6641701e482856 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -88,7 +88,6 @@ make_no_backtrace := NO_BACKTRACE=1 make_no_libcapstone := NO_CAPSTONE=1 make_no_libnuma := NO_LIBNUMA=1 make_no_libbionic := NO_LIBBIONIC=1 -make_no_auxtrace := NO_AUXTRACE=1 make_no_libbpf := NO_LIBBPF=1 make_libbpf_dynamic := LIBBPF_DYNAMIC=1 make_no_libbpf_DEBUG := NO_LIBBPF=1 DEBUG=1 @@ -121,7 +120,7 @@ make_static := LDFLAGS=-static NO_PERF_READ_VDSO32=1 NO_PERF_READ_VDSOX3 make_minimal := NO_LIBPYTHON=1 NO_GTK2=1 make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_BACKTRACE=1 make_minimal += NO_LIBNUMA=1 NO_LIBBIONIC=1 NO_LIBDW=1 -make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 +make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_LIBBPF=1 make_minimal += NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1 make_minimal += NO_LIBCAP=1 NO_CAPSTONE=1 @@ -158,7 +157,6 @@ run += make_no_backtrace run += make_no_libcapstone run += make_no_libnuma run += make_no_libbionic -run += make_no_auxtrace run += make_no_libbpf run += make_no_libbpf_DEBUG run += make_no_libllvm diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4be313cd115aea..1c2a43e1dc68e7 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -129,22 +129,22 @@ perf-util-y += iostat.o perf-util-y += stream.o perf-util-y += kvm-stat.o perf-util-y += lock-contention.o -perf-util-$(CONFIG_AUXTRACE) += auxtrace.o +perf-util-y += auxtrace.o perf-util-y += intel-pt-decoder/ -perf-util-$(CONFIG_AUXTRACE) += intel-pt.o -perf-util-$(CONFIG_AUXTRACE) += intel-bts.o -perf-util-$(CONFIG_AUXTRACE) += arm-spe.o -perf-util-$(CONFIG_AUXTRACE) += arm-spe-decoder/ -perf-util-$(CONFIG_AUXTRACE) += hisi-ptt.o -perf-util-$(CONFIG_AUXTRACE) += hisi-ptt-decoder/ -perf-util-$(CONFIG_AUXTRACE) += s390-cpumsf.o -perf-util-$(CONFIG_AUXTRACE) += powerpc-vpadtl.o +perf-util-y += intel-pt.o +perf-util-y += intel-bts.o +perf-util-y += arm-spe.o +perf-util-y += arm-spe-decoder/ +perf-util-y += hisi-ptt.o +perf-util-y += hisi-ptt-decoder/ +perf-util-y += s390-cpumsf.o +perf-util-y += powerpc-vpadtl.o ifdef CONFIG_LIBOPENCSD -perf-util-$(CONFIG_AUXTRACE) += cs-etm.o -perf-util-$(CONFIG_AUXTRACE) += cs-etm-decoder/ +perf-util-y += cs-etm.o +perf-util-y += cs-etm-decoder/ endif -perf-util-$(CONFIG_AUXTRACE) += cs-etm-base.o +perf-util-y += cs-etm-base.o perf-util-y += parse-branch-options.o perf-util-y += dump-insn.o diff --git a/tools/perf/util/arm-spe-decoder/Build b/tools/perf/util/arm-spe-decoder/Build index 960062b3cb9ea8..ab500e0efe2449 100644 --- a/tools/perf/util/arm-spe-decoder/Build +++ b/tools/perf/util/arm-spe-decoder/Build @@ -1 +1 @@ -perf-util-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o arm-spe-decoder.o +perf-util-y += arm-spe-pkt-decoder.o arm-spe-decoder.o diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index b320a387464d58..59cf72b935ff37 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -7,17 +7,12 @@ #ifndef __PERF_AUXTRACE_H #define __PERF_AUXTRACE_H -#include #include -#include -#include #include // FILE -#include #include #include -#include -#include #include +#include union perf_event; struct perf_session; @@ -459,8 +454,6 @@ struct addr_filters { struct auxtrace_cache; -#ifdef HAVE_AUXTRACE_SUPPORT - u64 compat_auxtrace_mmap__read_head(struct auxtrace_mmap *mm); int compat_auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail); @@ -706,215 +699,4 @@ void itrace_synth_opts__clear_time_range(struct itrace_synth_opts *opts) opts->range_num = 0; } -#else -#include "debug.h" - -static inline struct auxtrace_record * -auxtrace_record__init(struct evlist *evlist __maybe_unused, - int *err) -{ - *err = 0; - return NULL; -} - -static inline -void auxtrace_record__free(struct auxtrace_record *itr __maybe_unused) -{ -} - -static inline -int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused, - struct evlist *evlist __maybe_unused, - struct record_opts *opts __maybe_unused) -{ - return 0; -} - -static inline -int perf_event__process_auxtrace_info(const struct perf_tool *tool __maybe_unused, - struct perf_session *session __maybe_unused, - union perf_event *event __maybe_unused) -{ - return 0; -} - -static inline -s64 perf_event__process_auxtrace(const struct perf_tool *tool __maybe_unused, - struct perf_session *session __maybe_unused, - union perf_event *event __maybe_unused) -{ - return 0; -} - -static inline -int perf_event__process_auxtrace_error(const struct perf_tool *tool __maybe_unused, - struct perf_session *session __maybe_unused, - union perf_event *event __maybe_unused) -{ - return 0; -} - -static inline -void perf_session__auxtrace_error_inc(struct perf_session *session - __maybe_unused, - union perf_event *event - __maybe_unused) -{ -} - -static inline -void events_stats__auxtrace_error_warn(const struct events_stats *stats - __maybe_unused) -{ -} - -static inline -int itrace_do_parse_synth_opts(struct itrace_synth_opts *synth_opts __maybe_unused, - const char *str __maybe_unused, int unset __maybe_unused) -{ - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -static inline -int itrace_parse_synth_opts(const struct option *opt __maybe_unused, - const char *str __maybe_unused, - int unset __maybe_unused) -{ - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -static inline -int auxtrace_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused, - struct record_opts *opts __maybe_unused, - const char *str) -{ - if (!str) - return 0; - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -static inline -int auxtrace_parse_sample_options(struct auxtrace_record *itr __maybe_unused, - struct evlist *evlist __maybe_unused, - struct record_opts *opts __maybe_unused, - const char *str) -{ - if (!str) - return 0; - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -static inline -int auxtrace_parse_aux_action(struct evlist *evlist __maybe_unused) -{ - pr_err("AUX area tracing not supported\n"); - return -EINVAL; -} - -static inline -int auxtrace__process_event(struct perf_session *session __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_sample *sample __maybe_unused, - const struct perf_tool *tool __maybe_unused) -{ - return 0; -} - -static inline -void auxtrace__dump_auxtrace_sample(struct perf_session *session __maybe_unused, - struct perf_sample *sample __maybe_unused) -{ -} - -static inline -int auxtrace__flush_events(struct perf_session *session __maybe_unused, - const struct perf_tool *tool __maybe_unused) -{ - return 0; -} - -static inline -void auxtrace__free_events(struct perf_session *session __maybe_unused) -{ -} - -static inline -void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache __maybe_unused) -{ -} - -static inline -void auxtrace__free(struct perf_session *session __maybe_unused) -{ -} - -static inline -int auxtrace_index__write(int fd __maybe_unused, - struct list_head *head __maybe_unused) -{ - return -EINVAL; -} - -static inline -int auxtrace_index__process(int fd __maybe_unused, - u64 size __maybe_unused, - struct perf_session *session __maybe_unused, - bool needs_swap __maybe_unused) -{ - return -EINVAL; -} - -static inline -void auxtrace_index__free(struct list_head *head __maybe_unused) -{ -} - -static inline -bool auxtrace__evsel_is_auxtrace(struct perf_session *session __maybe_unused, - struct evsel *evsel __maybe_unused) -{ - return false; -} - -static inline -int auxtrace_parse_filters(struct evlist *evlist __maybe_unused) -{ - return 0; -} - -int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, - struct auxtrace_mmap_params *mp, - void *userpg, int fd); -void auxtrace_mmap__munmap(struct auxtrace_mmap *mm); -void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, - off_t auxtrace_offset, - unsigned int auxtrace_pages, - bool auxtrace_overwrite); -void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, - struct evsel *evsel, int idx); - -#define ITRACE_HELP "" - -static inline -void itrace_synth_opts__set_time_range(struct itrace_synth_opts *opts - __maybe_unused, - struct perf_time_interval *ptime_range - __maybe_unused, - int range_num __maybe_unused) -{ -} - -static inline -void itrace_synth_opts__clear_time_range(struct itrace_synth_opts *opts - __maybe_unused) -{ -} - -#endif - #endif diff --git a/tools/perf/util/cs-etm-decoder/Build b/tools/perf/util/cs-etm-decoder/Build index 056d665f7f88ad..27550db2aa4c5f 100644 --- a/tools/perf/util/cs-etm-decoder/Build +++ b/tools/perf/util/cs-etm-decoder/Build @@ -1 +1 @@ -perf-util-$(CONFIG_AUXTRACE) += cs-etm-decoder.o +perf-util-y += cs-etm-decoder.o diff --git a/tools/perf/util/hisi-ptt-decoder/Build b/tools/perf/util/hisi-ptt-decoder/Build index 3298f7b7e308b6..2ee0eb7316565f 100644 --- a/tools/perf/util/hisi-ptt-decoder/Build +++ b/tools/perf/util/hisi-ptt-decoder/Build @@ -1 +1 @@ -perf-util-$(CONFIG_AUXTRACE) += hisi-ptt-pkt-decoder.o +perf-util-y += hisi-ptt-pkt-decoder.o diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build index 5b8f0149167d97..8fd7e4330044e5 100644 --- a/tools/perf/util/intel-pt-decoder/Build +++ b/tools/perf/util/intel-pt-decoder/Build @@ -1,4 +1,4 @@ -perf-util-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o intel-pt-log.o intel-pt-decoder.o +perf-util-y += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o intel-pt-log.o intel-pt-decoder.o inat_tables_script = $(srctree)/tools/arch/x86/tools/gen-insn-attr-x86.awk inat_tables_maps = $(srctree)/tools/arch/x86/lib/x86-opcode-map.txt @@ -7,11 +7,7 @@ $(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_table $(call rule_mkdir) @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ -ifeq ($(SRCARCH),x86) - perf-util-y += inat.o insn.o -else - perf-util-$(CONFIG_AUXTRACE) += inat.o insn.o -endif +perf-util-y += inat.o insn.o $(OUTPUT)util/intel-pt-decoder/inat.o: $(srctree)/tools/arch/x86/lib/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(call rule_mkdir) diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h index ee29615d68e57f..f8588b6cf11a09 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -107,24 +107,9 @@ int machine__synthesize_threads(struct machine *machine, struct target *target, struct perf_thread_map *threads, bool needs_mmap, bool data_mmap, unsigned int nr_threads_synthesize); -#ifdef HAVE_AUXTRACE_SUPPORT int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, const struct perf_tool *tool, struct perf_session *session, perf_event__handler_t process); -#else // HAVE_AUXTRACE_SUPPORT - -#include - -static inline int -perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused, - const struct perf_tool *tool __maybe_unused, - struct perf_session *session __maybe_unused, - perf_event__handler_t process __maybe_unused) -{ - return -EINVAL; -} -#endif // HAVE_AUXTRACE_SUPPORT - #ifdef HAVE_LIBBPF_SUPPORT int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts); From ca016b6527e154013693722a2cdbec7c05fb6df7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 9 Nov 2025 17:31:52 -0800 Subject: [PATCH 322/684] perf auxtrace: Remove errno.h from auxtrace.h and fix transitive dependencies errno.h isn't used in auxtrace.h so remove it and fix build failures caused by transitive dependencies through auxtrace.h on errno.h. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/arch/arm/annotate/instructions.c | 1 + tools/perf/arch/arm/util/auxtrace.c | 1 + tools/perf/arch/arm64/annotate/instructions.c | 1 + tools/perf/arch/arm64/util/arm-spe.c | 1 + tools/perf/arch/arm64/util/hisi-ptt.c | 1 + tools/perf/arch/powerpc/util/auxtrace.c | 2 +- tools/perf/arch/s390/util/auxtrace.c | 1 + tools/perf/arch/x86/tests/topdown.c | 1 + tools/perf/arch/x86/util/topdown.c | 1 + tools/perf/bench/evlist-open-close.c | 1 + tools/perf/bench/futex.c | 1 + tools/perf/bench/pmu-scan.c | 1 + tools/perf/bench/synthesize.c | 1 + tools/perf/builtin-mem.c | 1 + tools/perf/tests/hwmon_pmu.c | 1 + tools/perf/tests/parse-metric.c | 1 + tools/perf/tests/pfm.c | 1 + tools/perf/ui/hist.c | 1 + tools/perf/util/annotate-data.c | 2 +- tools/perf/util/auxtrace.h | 1 - tools/perf/util/bpf-filter.h | 2 ++ tools/perf/util/bpf-trace-summary.c | 1 + tools/perf/util/bpf_counter_cgroup.c | 1 + tools/perf/util/bpf_ftrace.c | 3 ++- tools/perf/util/bpf_map.c | 1 + tools/perf/util/cgroup.c | 1 + tools/perf/util/drm_pmu.c | 1 + tools/perf/util/evswitch.c | 1 + tools/perf/util/intel-tpebs.c | 1 + tools/perf/util/kvm-stat.h | 1 + tools/perf/util/mmap.c | 1 + tools/perf/util/pfm.c | 1 + tools/perf/util/powerpc-vpadtl.c | 1 + tools/perf/util/stat-shadow.c | 1 + 34 files changed, 35 insertions(+), 4 deletions(-) diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c index cf91a43362b0e3..5e667b0f55126b 100644 --- a/tools/perf/arch/arm/annotate/instructions.c +++ b/tools/perf/arch/arm/annotate/instructions.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c index 3b8eca0ffb1712..eb6404267f1715 100644 --- a/tools/perf/arch/arm/util/auxtrace.c +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c index d465d093e7eb57..16cb62d40bd968 100644 --- a/tools/perf/arch/arm64/annotate/instructions.c +++ b/tools/perf/arch/arm64/annotate/instructions.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index cac43cde7dbee9..d5ec1408d0aec7 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "../../../util/cpumap.h" diff --git a/tools/perf/arch/arm64/util/hisi-ptt.c b/tools/perf/arch/arm64/util/hisi-ptt.c index eac9739c87e6c4..fe457fd58c9e80 100644 --- a/tools/perf/arch/arm64/util/hisi-ptt.c +++ b/tools/perf/arch/arm64/util/hisi-ptt.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include // page_size diff --git a/tools/perf/arch/powerpc/util/auxtrace.c b/tools/perf/arch/powerpc/util/auxtrace.c index 62c6f67f1bbe66..292ea335e4fff6 100644 --- a/tools/perf/arch/powerpc/util/auxtrace.c +++ b/tools/perf/arch/powerpc/util/auxtrace.c @@ -2,7 +2,7 @@ /* * VPA support */ - +#include #include #include #include diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c index 5068baa3e092b9..1a36761450661f 100644 --- a/tools/perf/arch/s390/util/auxtrace.c +++ b/tools/perf/arch/s390/util/auxtrace.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/tools/perf/arch/x86/tests/topdown.c b/tools/perf/arch/x86/tests/topdown.c index 1eba3b4594ef2b..3ee4e5e71be3b7 100644 --- a/tools/perf/arch/x86/tests/topdown.c +++ b/tools/perf/arch/x86/tests/topdown.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include "arch-tests.h" #include "../util/topdown.h" #include "debug.h" diff --git a/tools/perf/arch/x86/util/topdown.c b/tools/perf/arch/x86/util/topdown.c index 0d01b662627a3b..bafd285119d7ae 100644 --- a/tools/perf/arch/x86/util/topdown.c +++ b/tools/perf/arch/x86/util/topdown.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include "util/evlist.h" #include "util/pmu.h" #include "util/pmus.h" diff --git a/tools/perf/bench/evlist-open-close.c b/tools/perf/bench/evlist-open-close.c index bfaf50e4e51933..faf9c34b4a5dc0 100644 --- a/tools/perf/bench/evlist-open-close.c +++ b/tools/perf/bench/evlist-open-close.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include diff --git a/tools/perf/bench/futex.c b/tools/perf/bench/futex.c index 1481196a22f0c0..1968c9d00b5bb0 100644 --- a/tools/perf/bench/futex.c +++ b/tools/perf/bench/futex.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include diff --git a/tools/perf/bench/pmu-scan.c b/tools/perf/bench/pmu-scan.c index 9e4d36486f6255..14a464ad8cea8b 100644 --- a/tools/perf/bench/pmu-scan.c +++ b/tools/perf/bench/pmu-scan.c @@ -4,6 +4,7 @@ * * Copyright 2023 Google LLC. */ +#include #include #include "bench.h" #include "util/debug.h" diff --git a/tools/perf/bench/synthesize.c b/tools/perf/bench/synthesize.c index b3d493697675cb..265d49a913d94f 100644 --- a/tools/perf/bench/synthesize.c +++ b/tools/perf/bench/synthesize.c @@ -6,6 +6,7 @@ * * Copyright 2019 Google LLC. */ +#include #include #include "bench.h" #include "../util/debug.h" diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index c6496adff3fea6..d43500b92a7b9f 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c index 151f02701c8cc3..4aa4aac94f09c7 100644 --- a/tools/perf/tests/hwmon_pmu.c +++ b/tools/perf/tests/hwmon_pmu.c @@ -4,6 +4,7 @@ #include "hwmon_pmu.h" #include "parse-events.h" #include "tests.h" +#include #include #include #include diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 66a5275917e229..9b1df1eb455a7d 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include diff --git a/tools/perf/tests/pfm.c b/tools/perf/tests/pfm.c index 2e38dfa34b6ce1..fca4a86452df63 100644 --- a/tools/perf/tests/pfm.c +++ b/tools/perf/tests/pfm.c @@ -4,6 +4,7 @@ * * Copyright 2020 Google LLC. */ +#include #include "tests.h" #include "util/debug.h" #include "util/evlist.h" diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b085eb0de84997..e58327595d37d6 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index e183c6104d5940..07cf9c334be060 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -4,7 +4,7 @@ * * Written by Namhyung Kim */ - +#include #include #include #include diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 59cf72b935ff37..eee2c11f766683 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -7,7 +7,6 @@ #ifndef __PERF_AUXTRACE_H #define __PERF_AUXTRACE_H -#include #include // FILE #include #include diff --git a/tools/perf/util/bpf-filter.h b/tools/perf/util/bpf-filter.h index 122477f2de44bb..818c554b91b289 100644 --- a/tools/perf/util/bpf-filter.h +++ b/tools/perf/util/bpf-filter.h @@ -36,6 +36,8 @@ int perf_bpf_filter__unpin(void); #else /* !HAVE_BPF_SKEL */ +#include + static inline int perf_bpf_filter__parse(struct list_head *expr_head __maybe_unused, const char *str __maybe_unused) { diff --git a/tools/perf/util/bpf-trace-summary.c b/tools/perf/util/bpf-trace-summary.c index 8dfe7e678941d0..cf6e1e4402d524 100644 --- a/tools/perf/util/bpf-trace-summary.c +++ b/tools/perf/util/bpf-trace-summary.c @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include #include #include #include diff --git a/tools/perf/util/bpf_counter_cgroup.c b/tools/perf/util/bpf_counter_cgroup.c index 68bd994c88807b..17d7196c658920 100644 --- a/tools/perf/util/bpf_counter_cgroup.c +++ b/tools/perf/util/bpf_counter_cgroup.c @@ -4,6 +4,7 @@ /* Copyright (c) 2021 Google */ #include +#include #include #include #include diff --git a/tools/perf/util/bpf_ftrace.c b/tools/perf/util/bpf_ftrace.c index e61a3b20be0a0b..c456d24efa308c 100644 --- a/tools/perf/util/bpf_ftrace.c +++ b/tools/perf/util/bpf_ftrace.c @@ -1,6 +1,7 @@ -#include +#include #include #include +#include #include #include diff --git a/tools/perf/util/bpf_map.c b/tools/perf/util/bpf_map.c index 578f27d2d6b461..442f91b4e8e154 100644 --- a/tools/perf/util/bpf_map.c +++ b/tools/perf/util/bpf_map.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 25e2769b5e74fe..040eb75f080486 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/perf/util/drm_pmu.c b/tools/perf/util/drm_pmu.c index 98d4d2b556d4ed..b3052266d59937 100644 --- a/tools/perf/util/drm_pmu.c +++ b/tools/perf/util/drm_pmu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/perf/util/evswitch.c b/tools/perf/util/evswitch.c index 40cb56a9347dad..d4c06a3f825a88 100644 --- a/tools/perf/util/evswitch.c +++ b/tools/perf/util/evswitch.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo +#include #include "evswitch.h" #include "evlist.h" diff --git a/tools/perf/util/intel-tpebs.c b/tools/perf/util/intel-tpebs.c index 21359155f2a0bf..3c958d738ca6ca 100644 --- a/tools/perf/util/intel-tpebs.c +++ b/tools/perf/util/intel-tpebs.c @@ -25,6 +25,7 @@ #include "stat.h" #include #include +#include #include #include diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index 53db3d56108bd6..a356b839c2ee0f 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -10,6 +10,7 @@ #include "symbol.h" #include "record.h" +#include #include #include diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index a34726219af3da..b69f926d314b14 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c index e5b3a2a5ddef5b..d9043f4afbe7b1 100644 --- a/tools/perf/util/pfm.c +++ b/tools/perf/util/pfm.c @@ -15,6 +15,7 @@ #include "util/strbuf.h" #include "util/thread_map.h" +#include #include #include #include diff --git a/tools/perf/util/powerpc-vpadtl.c b/tools/perf/util/powerpc-vpadtl.c index bfa4156d7a9782..d1c3396f182fdd 100644 --- a/tools/perf/util/powerpc-vpadtl.c +++ b/tools/perf/util/powerpc-vpadtl.c @@ -4,6 +4,7 @@ */ #include +#include #include #include "color.h" #include "evlist.h" diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index b3b482e1808f1b..15e83d74eb0e5d 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include "evsel.h" From c1932fb85af8e51ac9f6bd9947145b06c716106e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 12 Nov 2025 08:24:39 -0800 Subject: [PATCH 323/684] perf vendor metrics s390: Avoid has_event(INSTRUCTIONS) The instructions event is now provided in json meaning the has_event test always succeeds. Switch to using non-legacy event names in the affected metrics. Reported-by: Thomas Richter Closes: https://lore.kernel.org/linux-perf-users/3e80f453-f015-4f4f-93d3-8df6bb6b3c95@linux.ibm.com/ Fixes: 0012e0fa221b ("perf jevents: Add legacy-hardware and legacy-cache json") Signed-off-by: Ian Rogers Reviewed-by: Thomas Richter Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/s390/cf_z16/transaction.json | 8 ++++---- tools/perf/pmu-events/arch/s390/cf_z17/transaction.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json index 3ab1d3a6638c46..57b785307a85f3 100644 --- a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json +++ b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json @@ -7,17 +7,17 @@ { "BriefDescription": "Cycles per Instruction", "MetricName": "cpi", - "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(CPU_CYCLES) else 0" }, { "BriefDescription": "Problem State Instruction Ratio", "MetricName": "prbstate", - "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(PROBLEM_STATE_INSTRUCTIONS) else 0" }, { "BriefDescription": "Level One Miss per 100 Instructions", "MetricName": "l1mp", - "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(L1I_DIR_WRITES) else 0" }, { "BriefDescription": "Percentage sourced from Level 2 cache", @@ -52,7 +52,7 @@ { "BriefDescription": "Estimated Instruction Complexity CPI infinite Level 1", "MetricName": "est_cpi", - "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(CPU_CYCLES) else 0" }, { "BriefDescription": "Estimated Sourcing Cycles per Level 1 Miss", diff --git a/tools/perf/pmu-events/arch/s390/cf_z17/transaction.json b/tools/perf/pmu-events/arch/s390/cf_z17/transaction.json index 74df533c8b6fad..7ded6a5a76c0ff 100644 --- a/tools/perf/pmu-events/arch/s390/cf_z17/transaction.json +++ b/tools/perf/pmu-events/arch/s390/cf_z17/transaction.json @@ -7,17 +7,17 @@ { "BriefDescription": "Cycles per Instruction", "MetricName": "cpi", - "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(CPU_CYCLES) else 0" }, { "BriefDescription": "Problem State Instruction Ratio", "MetricName": "prbstate", - "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(PROBLEM_STATE_INSTRUCTIONS) else 0" }, { "BriefDescription": "Level One Miss per 100 Instructions", "MetricName": "l1mp", - "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(L1I_DIR_WRITES) else 0" }, { "BriefDescription": "Percentage sourced from Level 2 cache", @@ -52,7 +52,7 @@ { "BriefDescription": "Estimated Instruction Complexity CPI infinite Level 1", "MetricName": "est_cpi", - "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(INSTRUCTIONS) else 0" + "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(L1C_TLB2_MISSES) else 0" }, { "BriefDescription": "Estimated Sourcing Cycles per Level 1 Miss", From 7563d021e28ec71bc6266e1848b22205ed7863d6 Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Tue, 14 Oct 2025 11:20:17 -0700 Subject: [PATCH 324/684] mshv: Fix VpRootDispatchThreadBlocked value This value in the VP stats page is used to track if the VP can be dispatched for execution when there are no fast interrupts injected. The original value of 201 was used in a version of the hypervisor which did not ship. It was subsequently changed to 202 so that is the correct value. Signed-off-by: Stanislav Kinsburskii Signed-off-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index e3b2bd417c4640..8a42d996146666 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -41,7 +41,7 @@ MODULE_DESCRIPTION("Microsoft Hyper-V root partition VMM interface /dev/mshv"); /* TODO move this to another file when debugfs code is added */ enum hv_stats_vp_counters { /* HV_THREAD_COUNTER */ #if defined(CONFIG_X86) - VpRootDispatchThreadBlocked = 201, + VpRootDispatchThreadBlocked = 202, #elif defined(CONFIG_ARM64) VpRootDispatchThreadBlocked = 94, #endif From 4cc1aa469cd6b714adc958547a4866247bfd60a9 Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Fri, 17 Oct 2025 11:58:17 -0700 Subject: [PATCH 325/684] mshv: Fix deposit memory in MSHV_ROOT_HVCALL When the MSHV_ROOT_HVCALL ioctl is executing a hypercall, and gets HV_STATUS_INSUFFICIENT_MEMORY, it deposits memory and then returns -EAGAIN to userspace. The expectation is that the VMM will retry. However, some VMM code in the wild doesn't do this and simply fails. Rather than force the VMM to retry, change the ioctl to deposit memory on demand and immediately retry the hypercall as is done with all the other hypercall helper functions. In addition to making the ioctl easier to use, removing the need for multiple syscalls improves performance. There is a complication: unlike the other hypercall helper functions, in MSHV_ROOT_HVCALL the input is opaque to the kernel. This is problematic for rep hypercalls, because the next part of the input list can't be copied on each loop after depositing pages (this was the original reason for returning -EAGAIN in this case). Introduce hv_do_rep_hypercall_ex(), which adds a 'rep_start' parameter. This solves the issue, allowing the deposit loop in MSHV_ROOT_HVCALL to restart a rep hypercall after depositing pages partway through. Fixes: 621191d709b1 ("Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs") Signed-off-by: Nuno Das Neves Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 58 ++++++++++++++++++---------------- include/asm-generic/mshyperv.h | 17 ++++++++-- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 8a42d996146666..a599bbf1f9b8f7 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -159,6 +159,7 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, unsigned int pages_order; void *input_pg = NULL; void *output_pg = NULL; + u16 reps_completed; if (copy_from_user(&args, user_args, sizeof(args))) return -EFAULT; @@ -210,41 +211,42 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, */ *(u64 *)input_pg = partition->pt_id; - if (args.reps) - status = hv_do_rep_hypercall(args.code, args.reps, 0, - input_pg, output_pg); - else - status = hv_do_hypercall(args.code, input_pg, output_pg); - - if (hv_result(status) == HV_STATUS_CALL_PENDING) { - if (is_async) { - mshv_async_hvcall_handler(partition, &status); - } else { /* Paranoia check. This shouldn't happen! */ - ret = -EBADFD; - goto free_pages_out; + reps_completed = 0; + do { + if (args.reps) { + status = hv_do_rep_hypercall_ex(args.code, args.reps, + 0, reps_completed, + input_pg, output_pg); + reps_completed = hv_repcomp(status); + } else { + status = hv_do_hypercall(args.code, input_pg, output_pg); } - } - if (hv_result(status) == HV_STATUS_INSUFFICIENT_MEMORY) { - ret = hv_call_deposit_pages(NUMA_NO_NODE, partition->pt_id, 1); - if (!ret) - ret = -EAGAIN; - } else if (!hv_result_success(status)) { - ret = hv_result_to_errno(status); - } + if (hv_result(status) == HV_STATUS_CALL_PENDING) { + if (is_async) { + mshv_async_hvcall_handler(partition, &status); + } else { /* Paranoia check. This shouldn't happen! */ + ret = -EBADFD; + goto free_pages_out; + } + } + + if (hv_result_success(status)) + break; + + if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) + ret = hv_result_to_errno(status); + else + ret = hv_call_deposit_pages(NUMA_NO_NODE, + partition->pt_id, 1); + } while (!ret); - /* - * Always return the status and output data regardless of result. - * The VMM may need it to determine how to proceed. E.g. the status may - * contain the number of reps completed if a rep hypercall partially - * succeeded. - */ args.status = hv_result(status); - args.reps = args.reps ? hv_repcomp(status) : 0; + args.reps = reps_completed; if (copy_to_user(user_args, &args, sizeof(args))) ret = -EFAULT; - if (output_pg && + if (!ret && output_pg && copy_to_user((void __user *)args.out_ptr, output_pg, args.out_sz)) ret = -EFAULT; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 64ba6bc807d982..b89c7e3a20474f 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -124,10 +124,12 @@ static inline unsigned int hv_repcomp(u64 status) /* * Rep hypercalls. Callers of this functions are supposed to ensure that - * rep_count and varhead_size comply with Hyper-V hypercall definition. + * rep_count, varhead_size, and rep_start comply with Hyper-V hypercall + * definition. */ -static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, - void *input, void *output) +static inline u64 hv_do_rep_hypercall_ex(u16 code, u16 rep_count, + u16 varhead_size, u16 rep_start, + void *input, void *output) { u64 control = code; u64 status; @@ -135,6 +137,7 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, control |= (u64)varhead_size << HV_HYPERCALL_VARHEAD_OFFSET; control |= (u64)rep_count << HV_HYPERCALL_REP_COMP_OFFSET; + control |= (u64)rep_start << HV_HYPERCALL_REP_START_OFFSET; do { status = hv_do_hypercall(control, input, output); @@ -152,6 +155,14 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, return status; } +/* For the typical case where rep_start is 0 */ +static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, + void *input, void *output) +{ + return hv_do_rep_hypercall_ex(code, rep_count, varhead_size, 0, + input, output); +} + /* Generate the guest OS identifier as described in the Hyper-V TLFS */ static inline u64 hv_generate_guest_id(u64 kernel_version) { From f34f5e576f5e17de5591c9ae306aeab2911d8533 Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Thu, 18 Sep 2025 11:00:19 -0400 Subject: [PATCH 326/684] x86/hyperv: Don't use hv apic driver when Secure AVIC is available When Secure AVIC is available, the AMD x2apic Secure AVIC driver will be selected. In that case, have hv_apic_init() return immediately without doing anything. Reviewed-by: Michael Kelley Reviewed-by: Neeraj Upadhyay Signed-off-by: Tianyu Lan Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_apic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index bfde0a3498b900..e669053b637d61 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -293,6 +293,9 @@ static void hv_send_ipi_self(int vector) void __init hv_apic_init(void) { + if (cc_platform_has(CC_ATTR_SNP_SECURE_AVIC)) + return; + if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { pr_info("Hyper-V: Using IPI hypercalls\n"); /* From 3e1b611515d286c6725028e17170f7143e5e51fc Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Thu, 18 Sep 2025 11:00:20 -0400 Subject: [PATCH 327/684] drivers: hv: Allow vmbus message synic interrupt injected from Hyper-V When Secure AVIC is enabled, VMBus driver should call x2apic Secure AVIC interface to allow Hyper-V to inject VMBus message interrupt. Reviewed-by: Michael Kelley Reviewed-by: Neeraj Upadhyay Signed-off-by: Tianyu Lan Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_apic.c | 5 +++++ drivers/hv/hv.c | 2 ++ drivers/hv/hv_common.c | 5 +++++ include/asm-generic/mshyperv.h | 1 + 4 files changed, 13 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index e669053b637d61..a8de503def3705 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -53,6 +53,11 @@ static void hv_apic_icr_write(u32 low, u32 id) wrmsrq(HV_X64_MSR_ICR, reg_val); } +void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set) +{ + apic_update_vector(cpu, vector, set); +} + static u32 hv_apic_read(u32 reg) { u32 reg_val, hi; diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index b14c5f9e0ef29c..ec5d10839e0f05 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -307,6 +307,7 @@ void hv_synic_enable_regs(unsigned int cpu) } hv_set_msr(HV_MSR_SIEFP, siefp.as_uint64); + hv_enable_coco_interrupt(cpu, vmbus_interrupt, true); /* Setup the shared SINT. */ if (vmbus_irq != -1) @@ -350,6 +351,7 @@ void hv_synic_disable_regs(unsigned int cpu) /* Need to correctly cleanup in the case of SMP!!! */ /* Disable the interrupt */ hv_set_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); + hv_enable_coco_interrupt(cpu, vmbus_interrupt, false); simp.as_uint64 = hv_get_msr(HV_MSR_SIMP); /* diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index e109a620c83fc8..3e41f686daa5ec 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -716,6 +716,11 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2) } EXPORT_SYMBOL_GPL(hv_tdx_hypercall); +void __weak hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set) +{ +} +EXPORT_SYMBOL_GPL(hv_enable_coco_interrupt); + void hv_identify_partition_type(void) { /* Assume guest role */ diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index b89c7e3a20474f..db84aced165869 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -347,6 +347,7 @@ bool hv_is_isolation_supported(void); bool hv_isolation_type_snp(void); u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); +void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set); void hyperv_cleanup(void); bool hv_query_ext_cap(u64 cap_query); void hv_setup_dma_ops(struct device *dev, bool coherent); From c52c957e41e75d3f74157acffc53cefa3089ffa7 Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Thu, 18 Sep 2025 11:00:21 -0400 Subject: [PATCH 328/684] x86/hyperv: Don't use auto-eoi when Secure AVIC is available Hyper-V doesn't support auto-eoi with Secure AVIC. So set the HV_DEPRECATING_AEOI_RECOMMENDED flag to force writing the EOI register after handling an interrupt. Reviewed-by: Michael Kelley Reviewed-by: Neeraj Upadhyay Signed-off-by: Tianyu Lan Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index c4febdbcfe4d8a..217a41b63df360 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -470,6 +470,9 @@ static void __init ms_hyperv_init_platform(void) hv_identify_partition_type(); + if (cc_platform_has(CC_ATTR_SNP_SECURE_AVIC)) + ms_hyperv.hints |= HV_DEPRECATING_AEOI_RECOMMENDED; + if (ms_hyperv.hints & HV_X64_HYPERV_NESTED) { hv_nested = true; pr_info("Hyper-V: running on a nested hypervisor\n"); From 5e52db91d112bd1da00b520e21f570db14105bde Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Thu, 18 Sep 2025 11:00:22 -0400 Subject: [PATCH 329/684] x86/hyperv: Allow Hyper-V to inject STIMER0 interrupts When Secure AVIC is enabled, call Secure AVIC function to allow Hyper-V to inject STIMER0 interrupt. Reviewed-by: Neeraj Upadhyay Reviewed-by: Michael Kelley Signed-off-by: Tianyu Lan Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_init.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index e890fd37e9c2d2..21ed8963fafd39 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -170,6 +170,10 @@ static int hv_cpu_init(unsigned int cpu) wrmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64); } + /* Allow Hyper-V stimer vector to be injected from Hypervisor. */ + if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) + apic_update_vector(cpu, HYPERV_STIMER0_VECTOR, true); + return hyperv_init_ghcb(); } @@ -277,6 +281,9 @@ static int hv_cpu_die(unsigned int cpu) *ghcb_va = NULL; } + if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) + apic_update_vector(cpu, HYPERV_STIMER0_VECTOR, false); + hv_common_cpu_die(cpu); if (hv_vp_assist_page && hv_vp_assist_page[cpu]) { From 92c7053b44b312e1cda765507f45fc170dee1b41 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:03 -0700 Subject: [PATCH 330/684] Documentation: hyperv: Confidential VMBus Define what the confidential VMBus is and describe what advantages it offers on the capable hardware. Signed-off-by: Roman Kisel Reviewed-by: Alok Tiwari Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- Documentation/virt/hyperv/coco.rst | 139 ++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/hyperv/coco.rst b/Documentation/virt/hyperv/coco.rst index c15d6fe34b4e84..3231e51444dace 100644 --- a/Documentation/virt/hyperv/coco.rst +++ b/Documentation/virt/hyperv/coco.rst @@ -178,7 +178,7 @@ These Hyper-V and VMBus memory pages are marked as decrypted: * VMBus monitor pages -* Synthetic interrupt controller (synic) related pages (unless supplied by +* Synthetic interrupt controller (SynIC) related pages (unless supplied by the paravisor) * Per-cpu hypercall input and output pages (unless running with a paravisor) @@ -232,6 +232,143 @@ with arguments explicitly describing the access. See _hv_pcifront_read_config() and _hv_pcifront_write_config() and the "use_calls" flag indicating to use hypercalls. +Confidential VMBus +------------------ +The confidential VMBus enables the confidential guest not to interact with +the untrusted host partition and the untrusted hypervisor. Instead, the guest +relies on the trusted paravisor to communicate with the devices processing +sensitive data. The hardware (SNP or TDX) encrypts the guest memory and the +register state while measuring the paravisor image using the platform security +processor to ensure trusted and confidential computing. + +Confidential VMBus provides a secure communication channel between the guest +and the paravisor, ensuring that sensitive data is protected from hypervisor- +level access through memory encryption and register state isolation. + +Confidential VMBus is an extension of Confidential Computing (CoCo) VMs +(a.k.a. "Isolated" VMs in Hyper-V terminology). Without Confidential VMBus, +guest VMBus device drivers (the "VSC"s in VMBus terminology) communicate +with VMBus servers (the VSPs) running on the Hyper-V host. The +communication must be through memory that has been decrypted so the +host can access it. With Confidential VMBus, one or more of the VSPs reside +in the trusted paravisor layer in the guest VM. Since the paravisor layer also +operates in encrypted memory, the memory used for communication with +such VSPs does not need to be decrypted and thereby exposed to the +Hyper-V host. The paravisor is responsible for communicating securely +with the Hyper-V host as necessary. + +The data is transferred directly between the VM and a vPCI device (a.k.a. +a PCI pass-thru device, see :doc:`vpci`) that is directly assigned to VTL2 +and that supports encrypted memory. In such a case, neither the host partition +nor the hypervisor has any access to the data. The guest needs to establish +a VMBus connection only with the paravisor for the channels that process +sensitive data, and the paravisor abstracts the details of communicating +with the specific devices away providing the guest with the well-established +VSP (Virtual Service Provider) interface that has had support in the Hyper-V +drivers for a decade. + +In the case the device does not support encrypted memory, the paravisor +provides bounce-buffering, and although the data is not encrypted, the backing +pages aren't mapped into the host partition through SLAT. While not impossible, +it becomes much more difficult for the host partition to exfiltrate the data +than it would be with a conventional VMBus connection where the host partition +has direct access to the memory used for communication. + +Here is the data flow for a conventional VMBus connection (`C` stands for the +client or VSC, `S` for the server or VSP, the `DEVICE` is a physical one, might +be with multiple virtual functions):: + + +---- GUEST ----+ +----- DEVICE ----+ +----- HOST -----+ + | | | | | | + | | | | | | + | | | ========== | + | | | | | | + | | | | | | + | | | | | | + +----- C -------+ +-----------------+ +------- S ------+ + || || + || || + +------||------------------ VMBus --------------------------||------+ + | Interrupts, MMIO | + +-------------------------------------------------------------------+ + +and the Confidential VMBus connection:: + + +---- GUEST --------------- VTL0 ------+ +-- DEVICE --+ + | | | | + | +- PARAVISOR --------- VTL2 -----+ | | | + | | +-- VMBus Relay ------+ ====+================ | + | | | Interrupts, MMIO | | | | | + | | +-------- S ----------+ | | +------------+ + | | || | | + | +---------+ || | | + | | Linux | || OpenHCL | | + | | kernel | || | | + | +---- C --+-----||---------------+ | + | || || | + +-------++------- C -------------------+ +------------+ + || | HOST | + || +---- S -----+ + +-------||----------------- VMBus ---------------------------||-----+ + | Interrupts, MMIO | + +-------------------------------------------------------------------+ + +An implementation of the VMBus relay that offers the Confidential VMBus +channels is available in the OpenVMM project as a part of the OpenHCL +paravisor. Please refer to + + * https://openvmm.dev/, and + * https://github.com/microsoft/openvmm + +for more information about the OpenHCL paravisor. + +A guest that is running with a paravisor must determine at runtime if +Confidential VMBus is supported by the current paravisor. The x86_64-specific +approach relies on the CPUID Virtualization Stack leaf; the ARM64 implementation +is expected to support the Confidential VMBus unconditionally when running +ARM CCA guests. + +Confidential VMBus is a characteristic of the VMBus connection as a whole, +and of each VMBus channel that is created. When a Confidential VMBus +connection is established, the paravisor provides the guest the message-passing +path that is used for VMBus device creation and deletion, and it provides a +per-CPU synthetic interrupt controller (SynIC) just like the SynIC that is +offered by the Hyper-V host. Each VMBus device that is offered to the guest +indicates the degree to which it participates in Confidential VMBus. The offer +indicates if the device uses encrypted ring buffers, and if the device uses +encrypted memory for DMA that is done outside the ring buffer. These settings +may be different for different devices using the same Confidential VMBus +connection. + +Although these settings are separate, in practice it'll always be encrypted +ring buffer only, or both encrypted ring buffer and external data. If a channel +is offered by the paravisor with confidential VMBus, the ring buffer can always +be encrypted since it's strictly for communication between the VTL2 paravisor +and the VTL0 guest. However, other memory regions are often used for e.g. DMA, +so they need to be accessible by the underlying hardware, and must be +unencrypted (unless the device supports encrypted memory). Currently, there are +not any VSPs in OpenHCL that support encrypted external memory, but future +versions are expected to enable this capability. + +Because some devices on a Confidential VMBus may require decrypted ring buffers +and DMA transfers, the guest must interact with two SynICs -- the one provided +by the paravisor and the one provided by the Hyper-V host when Confidential +VMBus is not offered. Interrupts are always signaled by the paravisor SynIC, +but the guest must check for messages and for channel interrupts on both SynICs. + +In the case of a confidential VMBus, regular SynIC access by the guest is +intercepted by the paravisor (this includes various MSRs such as the SIMP and +SIEFP, as well as hypercalls like HvPostMessage and HvSignalEvent). If the +guest actually wants to communicate with the hypervisor, it has to use special +mechanisms (GHCB page on SNP, or tdcall on TDX). Messages can be of either +kind: with confidential VMBus, messages use the paravisor SynIC, and if the +guest chose to communicate directly to the hypervisor, they use the hypervisor +SynIC. For interrupt signaling, some channels may be running on the host +(non-confidential, using the VMBus relay) and use the hypervisor SynIC, and +some on the paravisor and use its SynIC. The RelIDs are coordinated by the +OpenHCL VMBus server and are guaranteed to be unique regardless of whether +the channel originated on the host or the paravisor. + load_unaligned_zeropad() ------------------------ When transitioning memory between encrypted and decrypted, the caller of From 6802d8af47d1dccd9a74a1f708fb9129244ef843 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:04 -0700 Subject: [PATCH 331/684] Drivers: hv: VMBus protocol version 6.0 The confidential VMBus is supported starting from the protocol version 6.0 onwards. Provide the required definitions. No functional changes. Signed-off-by: Roman Kisel Reviewed-by: Alok Tiwari Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hyperv_vmbus.h | 2 ++ drivers/hv/vmbus_drv.c | 12 +++++++ include/hyperv/hvgdk_mini.h | 1 + include/linux/hyperv.h | 69 +++++++++++++++++++++++++++---------- 4 files changed, 65 insertions(+), 19 deletions(-) diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 0b450e53161e51..4a01797d485139 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -333,6 +333,8 @@ extern const struct vmbus_channel_message_table_entry /* General vmbus interface */ +bool vmbus_is_confidential(void); + struct hv_device *vmbus_device_create(const guid_t *type, const guid_t *instance, struct vmbus_channel *channel); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 69591dc7bad269..3c414560fa5f0b 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -56,6 +56,18 @@ static long __percpu *vmbus_evt; int vmbus_irq; int vmbus_interrupt; +/* + * If the Confidential VMBus is used, the data on the "wire" is not + * visible to either the host or the hypervisor. + */ +static bool is_confidential; + +bool vmbus_is_confidential(void) +{ + return is_confidential; +} +EXPORT_SYMBOL_GPL(vmbus_is_confidential); + /* * The panic notifier below is responsible solely for unloading the * vmbus connection, which is necessary in a panic event. diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index 77abddfc750e40..7f730a0e54e611 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -260,6 +260,7 @@ union hv_hypervisor_version_info { #define HYPERV_CPUID_VIRT_STACK_PROPERTIES 0x40000082 /* Support for the extended IOAPIC RTE format */ #define HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE BIT(2) +#define HYPERV_VS_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE BIT(3) #define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000 #define HYPERV_CPUID_MIN 0x40000005 diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 59826c89171c79..dfc516c1c7193f 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -265,16 +265,18 @@ static inline u32 hv_get_avail_to_write_percent( * Linux kernel. */ -#define VERSION_WS2008 ((0 << 16) | (13)) -#define VERSION_WIN7 ((1 << 16) | (1)) -#define VERSION_WIN8 ((2 << 16) | (4)) -#define VERSION_WIN8_1 ((3 << 16) | (0)) -#define VERSION_WIN10 ((4 << 16) | (0)) -#define VERSION_WIN10_V4_1 ((4 << 16) | (1)) -#define VERSION_WIN10_V5 ((5 << 16) | (0)) -#define VERSION_WIN10_V5_1 ((5 << 16) | (1)) -#define VERSION_WIN10_V5_2 ((5 << 16) | (2)) -#define VERSION_WIN10_V5_3 ((5 << 16) | (3)) +#define VMBUS_MAKE_VERSION(MAJ, MIN) ((((u32)MAJ) << 16) | (MIN)) +#define VERSION_WS2008 VMBUS_MAKE_VERSION(0, 13) +#define VERSION_WIN7 VMBUS_MAKE_VERSION(1, 1) +#define VERSION_WIN8 VMBUS_MAKE_VERSION(2, 4) +#define VERSION_WIN8_1 VMBUS_MAKE_VERSION(3, 0) +#define VERSION_WIN10 VMBUS_MAKE_VERSION(4, 0) +#define VERSION_WIN10_V4_1 VMBUS_MAKE_VERSION(4, 1) +#define VERSION_WIN10_V5 VMBUS_MAKE_VERSION(5, 0) +#define VERSION_WIN10_V5_1 VMBUS_MAKE_VERSION(5, 1) +#define VERSION_WIN10_V5_2 VMBUS_MAKE_VERSION(5, 2) +#define VERSION_WIN10_V5_3 VMBUS_MAKE_VERSION(5, 3) +#define VERSION_WIN10_V6_0 VMBUS_MAKE_VERSION(6, 0) /* Make maximum size of pipe payload of 16K */ #define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384) @@ -335,14 +337,22 @@ struct vmbus_channel_offer { } __packed; /* Server Flags */ -#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 1 -#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 2 -#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 4 -#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 -#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 -#define VMBUS_CHANNEL_PARENT_OFFER 0x200 -#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 -#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000 +#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x0001 +/* + * This flag indicates that the channel is offered by the paravisor, and must + * use encrypted memory for the channel ring buffer. + */ +#define VMBUS_CHANNEL_CONFIDENTIAL_RING_BUFFER 0x0002 +/* + * This flag indicates that the channel is offered by the paravisor, and must + * use encrypted memory for GPA direct packets and additional GPADLs. + */ +#define VMBUS_CHANNEL_CONFIDENTIAL_EXTERNAL_MEMORY 0x0004 +#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x0010 +#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x0100 +#define VMBUS_CHANNEL_PARENT_OFFER 0x0200 +#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x0400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000 struct vmpacket_descriptor { u16 type; @@ -621,6 +631,12 @@ struct vmbus_channel_relid_released { u32 child_relid; } __packed; +/* + * Used by the paravisor only, means that the encrypted ring buffers and + * the encrypted external memory are supported + */ +#define VMBUS_FEATURE_FLAG_CONFIDENTIAL_CHANNELS 0x10 + struct vmbus_channel_initiate_contact { struct vmbus_channel_message_header header; u32 vmbus_version_requested; @@ -630,7 +646,8 @@ struct vmbus_channel_initiate_contact { struct { u8 msg_sint; u8 msg_vtl; - u8 reserved[6]; + u8 reserved[2]; + u32 feature_flags; /* VMBus version 6.0 */ }; }; u64 monitor_page1; @@ -1003,6 +1020,10 @@ struct vmbus_channel { /* boolean to control visibility of sysfs for ring buffer */ bool ring_sysfs_visible; + /* The ring buffer is encrypted */ + bool co_ring_buffer; + /* The external memory is encrypted */ + bool co_external_memory; }; #define lock_requestor(channel, flags) \ @@ -1027,6 +1048,16 @@ u64 vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id, u64 rqst_addr); u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id); +static inline bool is_co_ring_buffer(const struct vmbus_channel_offer_channel *o) +{ + return !!(o->offer.chn_flags & VMBUS_CHANNEL_CONFIDENTIAL_RING_BUFFER); +} + +static inline bool is_co_external_memory(const struct vmbus_channel_offer_channel *o) +{ + return !!(o->offer.chn_flags & VMBUS_CHANNEL_CONFIDENTIAL_EXTERNAL_MEMORY); +} + static inline bool is_hvsock_offer(const struct vmbus_channel_offer_channel *o) { return !!(o->offer.chn_flags & VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER); From 7c8b6c326d830ca5c6b95f390c703966e14167e6 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:05 -0700 Subject: [PATCH 332/684] arch/x86: mshyperv: Discover Confidential VMBus availability Confidential VMBus requires enabling paravisor SynIC, and the x86_64 guest has to inspect the Virtualization Stack (VS) CPUID leaf to see if Confidential VMBus is available. If it is, the guest shall enable the paravisor SynIC. Read the relevant data from the VS CPUID leaf. Refactor the code to avoid repeating CPUID and add flags to the struct ms_hyperv_info. For ARM64, the flag for Confidential VMBus is not set which provides the desired behaviour for now as it is not available on ARM64 just yet. Once ARM64 CCA guests are supported, this flag will be set unconditionally when running such a guest. Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 28 +++++++++++++++------------- include/asm-generic/mshyperv.h | 2 ++ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 217a41b63df360..1369fae7d8a939 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -440,7 +440,7 @@ EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); static void __init ms_hyperv_init_platform(void) { - int hv_max_functions_eax; + int hv_max_functions_eax, eax; #ifdef CONFIG_PARAVIRT pv_info.name = "Hyper-V"; @@ -478,6 +478,19 @@ static void __init ms_hyperv_init_platform(void) pr_info("Hyper-V: running on a nested hypervisor\n"); } + /* + * There is no check against the max function for HYPERV_CPUID_VIRT_STACK_* CPUID + * leaves as the hypervisor doesn't handle them. Even a nested root partition (L2 + * root) will not get them because the nested (L1) hypervisor filters them out. + * These are handled through intercept processing by the Windows Hyper-V stack + * or the paravisor. + */ + eax = cpuid_eax(HYPERV_CPUID_VIRT_STACK_PROPERTIES); + ms_hyperv.confidential_vmbus_available = + eax & HYPERV_VS_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE; + ms_hyperv.msi_ext_dest_id = + eax & HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE; + if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { x86_platform.calibrate_tsc = hv_get_tsc_khz; @@ -678,21 +691,10 @@ static bool __init ms_hyperv_x2apic_available(void) * pci-hyperv host bridge. * * Note: for a Hyper-V root partition, this will always return false. - * The hypervisor doesn't expose these HYPERV_CPUID_VIRT_STACK_* cpuids by - * default, they are implemented as intercepts by the Windows Hyper-V stack. - * Even a nested root partition (L2 root) will not get them because the - * nested (L1) hypervisor filters them out. */ static bool __init ms_hyperv_msi_ext_dest_id(void) { - u32 eax; - - eax = cpuid_eax(HYPERV_CPUID_VIRT_STACK_INTERFACE); - if (eax != HYPERV_VS_INTERFACE_EAX_SIGNATURE) - return false; - - eax = cpuid_eax(HYPERV_CPUID_VIRT_STACK_PROPERTIES); - return eax & HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE; + return ms_hyperv.msi_ext_dest_id; } #ifdef CONFIG_AMD_MEM_ENCRYPT diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index db84aced165869..8da1893365f006 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -62,6 +62,8 @@ struct ms_hyperv_info { }; }; u64 shared_gpa_boundary; + bool msi_ext_dest_id; + bool confidential_vmbus_available; }; extern struct ms_hyperv_info ms_hyperv; extern bool hv_nested; From e6eeb3c782739cd1613a8da856b878b99f741943 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:06 -0700 Subject: [PATCH 333/684] arch: hyperv: Get/set SynIC synth.registers via paravisor The existing Hyper-V wrappers for getting and setting MSRs are hv_get/set_msr(). Via hv_get/set_non_nested_msr(), they detect when running in a CoCo VM with a paravisor, and use the TDX or SNP guest-host communication protocol to bypass the paravisor and go directly to the host hypervisor for SynIC MSRs. The "set" function also implements the required special handling for the SINT MSRs. Provide functions that allow manipulating the SynIC registers through the paravisor. Move vmbus_signal_eom() to a more appropriate location (which also avoids breaking KVM). Signed-off-by: Roman Kisel Reviewed-by: Alok Tiwari Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 20 ++++++++++++++++ drivers/hv/hv_common.c | 11 +++++++++ drivers/hv/hyperv_vmbus.h | 44 ++++++++++++++++++++++++++++++++++ include/asm-generic/mshyperv.h | 42 ++------------------------------ 4 files changed, 77 insertions(+), 40 deletions(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 1369fae7d8a939..eb9f1d7eec61b5 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -86,6 +86,26 @@ void hv_set_non_nested_msr(unsigned int reg, u64 value) } EXPORT_SYMBOL_GPL(hv_set_non_nested_msr); +/* + * Get the SynIC register value from the paravisor. + */ +u64 hv_para_get_synic_register(unsigned int reg) +{ + if (WARN_ON(!ms_hyperv.paravisor_present || !hv_is_synic_msr(reg))) + return ~0ULL; + return native_read_msr(reg); +} + +/* + * Set the SynIC register value with the paravisor. + */ +void hv_para_set_synic_register(unsigned int reg, u64 val) +{ + if (WARN_ON(!ms_hyperv.paravisor_present || !hv_is_synic_msr(reg))) + return; + native_write_msr(reg, val); +} + u64 hv_get_msr(unsigned int reg) { if (hv_nested) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 3e41f686daa5ec..c39472ae8345a7 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -721,6 +721,17 @@ void __weak hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool } EXPORT_SYMBOL_GPL(hv_enable_coco_interrupt); +u64 __weak hv_para_get_synic_register(unsigned int reg) +{ + return ~0ULL; +} +EXPORT_SYMBOL_GPL(hv_para_get_synic_register); + +void __weak hv_para_set_synic_register(unsigned int reg, u64 val) +{ +} +EXPORT_SYMBOL_GPL(hv_para_set_synic_register); + void hv_identify_partition_type(void) { /* Assume guest role */ diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 4a01797d485139..9ac6f552028752 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -335,6 +336,49 @@ extern const struct vmbus_channel_message_table_entry bool vmbus_is_confidential(void); +#if IS_ENABLED(CONFIG_HYPERV_VMBUS) +/* Free the message slot and signal end-of-message if required */ +static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) +{ + /* + * On crash we're reading some other CPU's message page and we need + * to be careful: this other CPU may already had cleared the header + * and the host may already had delivered some other message there. + * In case we blindly write msg->header.message_type we're going + * to lose it. We can still lose a message of the same type but + * we count on the fact that there can only be one + * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages + * on crash. + */ + if (cmpxchg(&msg->header.message_type, old_msg_type, + HVMSG_NONE) != old_msg_type) + return; + + /* + * The cmxchg() above does an implicit memory barrier to + * ensure the write to MessageType (ie set to + * HVMSG_NONE) happens before we read the + * MessagePending and EOMing. Otherwise, the EOMing + * will not deliver any more messages since there is + * no empty slot + */ + if (msg->header.message_flags.msg_pending) { + /* + * This will cause message queue rescan to + * possibly deliver another msg from the + * hypervisor + */ + if (vmbus_is_confidential()) + hv_para_set_synic_register(HV_MSR_EOM, 0); + else + hv_set_msr(HV_MSR_EOM, 0); + } +} + +extern int vmbus_interrupt; +extern int vmbus_irq; +#endif /* CONFIG_HYPERV_VMBUS */ + struct hv_device *vmbus_device_create(const guid_t *type, const guid_t *instance, struct vmbus_channel *channel); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8da1893365f006..c328265de62446 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -176,46 +176,6 @@ static inline u64 hv_generate_guest_id(u64 kernel_version) return guest_id; } -#if IS_ENABLED(CONFIG_HYPERV_VMBUS) -/* Free the message slot and signal end-of-message if required */ -static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) -{ - /* - * On crash we're reading some other CPU's message page and we need - * to be careful: this other CPU may already had cleared the header - * and the host may already had delivered some other message there. - * In case we blindly write msg->header.message_type we're going - * to lose it. We can still lose a message of the same type but - * we count on the fact that there can only be one - * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages - * on crash. - */ - if (cmpxchg(&msg->header.message_type, old_msg_type, - HVMSG_NONE) != old_msg_type) - return; - - /* - * The cmxchg() above does an implicit memory barrier to - * ensure the write to MessageType (ie set to - * HVMSG_NONE) happens before we read the - * MessagePending and EOMing. Otherwise, the EOMing - * will not deliver any more messages since there is - * no empty slot - */ - if (msg->header.message_flags.msg_pending) { - /* - * This will cause message queue rescan to - * possibly deliver another msg from the - * hypervisor - */ - hv_set_msr(HV_MSR_EOM, 0); - } -} - -extern int vmbus_interrupt; -extern int vmbus_irq; -#endif /* CONFIG_HYPERV_VMBUS */ - int hv_get_hypervisor_version(union hv_hypervisor_version_info *info); void hv_setup_vmbus_handler(void (*handler)(void)); @@ -350,6 +310,8 @@ bool hv_isolation_type_snp(void); u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set); +u64 hv_para_get_synic_register(unsigned int reg); +void hv_para_set_synic_register(unsigned int reg, u64 val); void hyperv_cleanup(void); bool hv_query_ext_cap(u64 cap_query); void hv_setup_dma_ops(struct device *dev, bool coherent); From a156ad8c508209ce22f3213d25c3c2ae1774a57d Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:07 -0700 Subject: [PATCH 334/684] arch/x86: mshyperv: Trap on access for some synthetic MSRs hv_set_non_nested_msr() has special handling for SINT MSRs when a paravisor is present. In addition to updating the MSR on the host, the mirror MSR in the paravisor is updated, including with the proxy bit. But with Confidential VMBus, the proxy bit must not be used, so add a special case to skip it. Signed-off-by: Roman Kisel Reviewed-by: Alok Tiwari Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 29 +++++++++++++++++++++++++---- drivers/hv/hv_common.c | 5 +++++ include/asm-generic/mshyperv.h | 1 + 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index eb9f1d7eec61b5..80a641a6ac48b5 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,12 @@ bool hv_nested; struct ms_hyperv_info ms_hyperv; #if IS_ENABLED(CONFIG_HYPERV) +/* + * When running with the paravisor, controls proxying the synthetic interrupts + * from the host + */ +static bool hv_para_sint_proxy; + static inline unsigned int hv_get_nested_msr(unsigned int reg) { if (hv_is_sint_msr(reg)) @@ -75,17 +82,31 @@ EXPORT_SYMBOL_GPL(hv_get_non_nested_msr); void hv_set_non_nested_msr(unsigned int reg, u64 value) { if (hv_is_synic_msr(reg) && ms_hyperv.paravisor_present) { + /* The hypervisor will get the intercept. */ hv_ivm_msr_write(reg, value); - /* Write proxy bit via wrmsl instruction */ - if (hv_is_sint_msr(reg)) - wrmsrq(reg, value | 1 << 20); + /* Using wrmsrq so the following goes to the paravisor. */ + if (hv_is_sint_msr(reg)) { + union hv_synic_sint sint = { .as_uint64 = value }; + + sint.proxy = hv_para_sint_proxy; + native_wrmsrq(reg, sint.as_uint64); + } } else { - wrmsrq(reg, value); + native_wrmsrq(reg, value); } } EXPORT_SYMBOL_GPL(hv_set_non_nested_msr); +/* + * Enable or disable proxying synthetic interrupts + * to the paravisor. + */ +void hv_para_set_sint_proxy(bool enable) +{ + hv_para_sint_proxy = enable; +} + /* * Get the SynIC register value from the paravisor. */ diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index c39472ae8345a7..4b44da7f23b27e 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -721,6 +721,11 @@ void __weak hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool } EXPORT_SYMBOL_GPL(hv_enable_coco_interrupt); +void __weak hv_para_set_sint_proxy(bool enable) +{ +} +EXPORT_SYMBOL_GPL(hv_para_set_sint_proxy); + u64 __weak hv_para_get_synic_register(unsigned int reg) { return ~0ULL; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index c328265de62446..ecedab554c80d0 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -310,6 +310,7 @@ bool hv_isolation_type_snp(void); u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set); +void hv_para_set_sint_proxy(bool enable); u64 hv_para_get_synic_register(unsigned int reg); void hv_para_set_synic_register(unsigned int reg, u64 val); void hyperv_cleanup(void); From 163224c189e8b679ce919aa64ccabb7a992ca2d1 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:08 -0700 Subject: [PATCH 335/684] Drivers: hv: Rename fields for SynIC message and event pages Confidential VMBus requires interacting with two SynICs -- one provided by the host hypervisor, and one provided by the paravisor. Each SynIC requires its own message and event pages. Rename the existing host-accessible SynIC message and event pages with the "hyp_" prefix to clearly distinguish them from the paravisor ones. The field name is also changed in mshv_root.* for consistency. No functional changes. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/channel_mgmt.c | 6 ++-- drivers/hv/hv.c | 66 +++++++++++++++++++-------------------- drivers/hv/hyperv_vmbus.h | 4 +-- drivers/hv/mshv_root.h | 2 +- drivers/hv/mshv_synic.c | 6 ++-- drivers/hv/vmbus_drv.c | 6 ++-- 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 65dd299e2944bd..1a33c6944b3c4e 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -844,14 +844,14 @@ static void vmbus_wait_for_unload(void) = per_cpu_ptr(hv_context.cpu_context, cpu); /* - * In a CoCo VM the synic_message_page is not allocated + * In a CoCo VM the hyp_synic_message_page is not allocated * in hv_synic_alloc(). Instead it is set/cleared in * hv_synic_enable_regs() and hv_synic_disable_regs() * such that it is set only when the CPU is online. If * not all present CPUs are online, the message page * might be NULL, so skip such CPUs. */ - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page; if (!page_addr) continue; @@ -892,7 +892,7 @@ static void vmbus_wait_for_unload(void) struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page; if (!page_addr) continue; diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ec5d10839e0f05..6fbb51e5067364 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -147,20 +147,20 @@ int hv_synic_alloc(void) * Skip these pages allocation here. */ if (!ms_hyperv.paravisor_present && !hv_root_partition()) { - hv_cpu->synic_message_page = + hv_cpu->hyp_synic_message_page = (void *)get_zeroed_page(GFP_ATOMIC); - if (!hv_cpu->synic_message_page) { + if (!hv_cpu->hyp_synic_message_page) { pr_err("Unable to allocate SYNIC message page\n"); goto err; } - hv_cpu->synic_event_page = + hv_cpu->hyp_synic_event_page = (void *)get_zeroed_page(GFP_ATOMIC); - if (!hv_cpu->synic_event_page) { + if (!hv_cpu->hyp_synic_event_page) { pr_err("Unable to allocate SYNIC event page\n"); - free_page((unsigned long)hv_cpu->synic_message_page); - hv_cpu->synic_message_page = NULL; + free_page((unsigned long)hv_cpu->hyp_synic_message_page); + hv_cpu->hyp_synic_message_page = NULL; goto err; } } @@ -168,30 +168,30 @@ int hv_synic_alloc(void) if (!ms_hyperv.paravisor_present && (hv_isolation_type_snp() || hv_isolation_type_tdx())) { ret = set_memory_decrypted((unsigned long) - hv_cpu->synic_message_page, 1); + hv_cpu->hyp_synic_message_page, 1); if (ret) { pr_err("Failed to decrypt SYNIC msg page: %d\n", ret); - hv_cpu->synic_message_page = NULL; + hv_cpu->hyp_synic_message_page = NULL; /* * Free the event page here so that hv_synic_free() * won't later try to re-encrypt it. */ - free_page((unsigned long)hv_cpu->synic_event_page); - hv_cpu->synic_event_page = NULL; + free_page((unsigned long)hv_cpu->hyp_synic_event_page); + hv_cpu->hyp_synic_event_page = NULL; goto err; } ret = set_memory_decrypted((unsigned long) - hv_cpu->synic_event_page, 1); + hv_cpu->hyp_synic_event_page, 1); if (ret) { pr_err("Failed to decrypt SYNIC event page: %d\n", ret); - hv_cpu->synic_event_page = NULL; + hv_cpu->hyp_synic_event_page = NULL; goto err; } - memset(hv_cpu->synic_message_page, 0, PAGE_SIZE); - memset(hv_cpu->synic_event_page, 0, PAGE_SIZE); + memset(hv_cpu->hyp_synic_message_page, 0, PAGE_SIZE); + memset(hv_cpu->hyp_synic_event_page, 0, PAGE_SIZE); } } @@ -227,28 +227,28 @@ void hv_synic_free(void) if (!ms_hyperv.paravisor_present && (hv_isolation_type_snp() || hv_isolation_type_tdx())) { - if (hv_cpu->synic_message_page) { + if (hv_cpu->hyp_synic_message_page) { ret = set_memory_encrypted((unsigned long) - hv_cpu->synic_message_page, 1); + hv_cpu->hyp_synic_message_page, 1); if (ret) { pr_err("Failed to encrypt SYNIC msg page: %d\n", ret); - hv_cpu->synic_message_page = NULL; + hv_cpu->hyp_synic_message_page = NULL; } } - if (hv_cpu->synic_event_page) { + if (hv_cpu->hyp_synic_event_page) { ret = set_memory_encrypted((unsigned long) - hv_cpu->synic_event_page, 1); + hv_cpu->hyp_synic_event_page, 1); if (ret) { pr_err("Failed to encrypt SYNIC event page: %d\n", ret); - hv_cpu->synic_event_page = NULL; + hv_cpu->hyp_synic_event_page = NULL; } } } free_page((unsigned long)hv_cpu->post_msg_page); - free_page((unsigned long)hv_cpu->synic_event_page); - free_page((unsigned long)hv_cpu->synic_message_page); + free_page((unsigned long)hv_cpu->hyp_synic_event_page); + free_page((unsigned long)hv_cpu->hyp_synic_message_page); } kfree(hv_context.hv_numa_map); @@ -278,12 +278,12 @@ void hv_synic_enable_regs(unsigned int cpu) /* Mask out vTOM bit. ioremap_cache() maps decrypted */ u64 base = (simp.base_simp_gpa << HV_HYP_PAGE_SHIFT) & ~ms_hyperv.shared_gpa_boundary; - hv_cpu->synic_message_page = + hv_cpu->hyp_synic_message_page = (void *)ioremap_cache(base, HV_HYP_PAGE_SIZE); - if (!hv_cpu->synic_message_page) + if (!hv_cpu->hyp_synic_message_page) pr_err("Fail to map synic message page.\n"); } else { - simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page) + simp.base_simp_gpa = virt_to_phys(hv_cpu->hyp_synic_message_page) >> HV_HYP_PAGE_SHIFT; } @@ -297,12 +297,12 @@ void hv_synic_enable_regs(unsigned int cpu) /* Mask out vTOM bit. ioremap_cache() maps decrypted */ u64 base = (siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT) & ~ms_hyperv.shared_gpa_boundary; - hv_cpu->synic_event_page = + hv_cpu->hyp_synic_event_page = (void *)ioremap_cache(base, HV_HYP_PAGE_SIZE); - if (!hv_cpu->synic_event_page) + if (!hv_cpu->hyp_synic_event_page) pr_err("Fail to map synic event page.\n"); } else { - siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page) + siefp.base_siefp_gpa = virt_to_phys(hv_cpu->hyp_synic_event_page) >> HV_HYP_PAGE_SHIFT; } @@ -362,8 +362,8 @@ void hv_synic_disable_regs(unsigned int cpu) */ simp.simp_enabled = 0; if (ms_hyperv.paravisor_present || hv_root_partition()) { - iounmap(hv_cpu->synic_message_page); - hv_cpu->synic_message_page = NULL; + iounmap(hv_cpu->hyp_synic_message_page); + hv_cpu->hyp_synic_message_page = NULL; } else { simp.base_simp_gpa = 0; } @@ -374,8 +374,8 @@ void hv_synic_disable_regs(unsigned int cpu) siefp.siefp_enabled = 0; if (ms_hyperv.paravisor_present || hv_root_partition()) { - iounmap(hv_cpu->synic_event_page); - hv_cpu->synic_event_page = NULL; + iounmap(hv_cpu->hyp_synic_event_page); + hv_cpu->hyp_synic_event_page = NULL; } else { siefp.base_siefp_gpa = 0; } @@ -405,7 +405,7 @@ static bool hv_synic_event_pending(void) { struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); union hv_synic_event_flags *event = - (union hv_synic_event_flags *)hv_cpu->synic_event_page + VMBUS_MESSAGE_SINT; + (union hv_synic_event_flags *)hv_cpu->hyp_synic_event_page + VMBUS_MESSAGE_SINT; unsigned long *recv_int_page = event->flags; /* assumes VMBus version >= VERSION_WIN8 */ bool pending; u32 relid; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 9ac6f552028752..d593af45a5b2ae 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -121,8 +121,8 @@ enum { * Per cpu state for channel handling */ struct hv_per_cpu_context { - void *synic_message_page; - void *synic_event_page; + void *hyp_synic_message_page; + void *hyp_synic_event_page; /* * The page is only used in hv_post_message() for a TDX VM (with the diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index e3931b0f126932..db6b42db2fdc63 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -169,7 +169,7 @@ struct mshv_girq_routing_table { }; struct hv_synic_pages { - struct hv_message_page *synic_message_page; + struct hv_message_page *hyp_synic_message_page; struct hv_synic_event_flags_page *synic_event_flags_page; struct hv_synic_event_ring_page *synic_event_ring_page; }; diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c index e6b6381b7c369d..f8b0337cdc8214 100644 --- a/drivers/hv/mshv_synic.c +++ b/drivers/hv/mshv_synic.c @@ -394,7 +394,7 @@ mshv_intercept_isr(struct hv_message *msg) void mshv_isr(void) { struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); - struct hv_message_page **msg_page = &spages->synic_message_page; + struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_message *msg; bool handled; @@ -456,7 +456,7 @@ int mshv_synic_init(unsigned int cpu) #endif union hv_synic_scontrol sctrl; struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); - struct hv_message_page **msg_page = &spages->synic_message_page; + struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; struct hv_synic_event_ring_page **event_ring_page = @@ -550,7 +550,7 @@ int mshv_synic_cleanup(unsigned int cpu) union hv_synic_sirbp sirbp; union hv_synic_scontrol sctrl; struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); - struct hv_message_page **msg_page = &spages->synic_message_page; + struct hv_message_page **msg_page = &spages->hyp_synic_message_page; struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; struct hv_synic_event_ring_page **event_ring_page = diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 3c414560fa5f0b..e12f0ba0701ff6 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1060,7 +1060,7 @@ static void vmbus_onmessage_work(struct work_struct *work) void vmbus_on_msg_dpc(unsigned long data) { struct hv_per_cpu_context *hv_cpu = (void *)data; - void *page_addr = hv_cpu->synic_message_page; + void *page_addr = hv_cpu->hyp_synic_message_page; struct hv_message msg_copy, *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct vmbus_channel_message_header *hdr; @@ -1244,7 +1244,7 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) * The event page can be directly checked to get the id of * the channel that has the interrupt pending. */ - void *page_addr = hv_cpu->synic_event_page; + void *page_addr = hv_cpu->hyp_synic_event_page; union hv_synic_event_flags *event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; @@ -1327,7 +1327,7 @@ static void vmbus_isr(void) vmbus_chan_sched(hv_cpu); - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; /* Check if there are actual msgs to be processed */ From 226494e5ee4eb0bae4fc7b525505828271d5047e Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:09 -0700 Subject: [PATCH 336/684] Drivers: hv: Allocate the paravisor SynIC pages when required Confidential VMBus requires interacting with two SynICs -- one provided by the host hypervisor, and one provided by the paravisor. Each SynIC requires its own message and event pages. Refactor and extend the existing code to add allocating and freeing the message and event pages for the paravisor SynIC when it is present. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hv.c | 184 +++++++++++++++++++------------------- drivers/hv/hyperv_vmbus.h | 18 ++++ 2 files changed, 112 insertions(+), 90 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 6fbb51e5067364..d380e0df63f39f 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -96,10 +96,70 @@ int hv_post_message(union hv_connection_id connection_id, return hv_result(status); } +static int hv_alloc_page(void **page, bool decrypt, const char *note) +{ + int ret = 0; + + /* + * After the page changes its encryption status, its contents might + * appear scrambled on some hardware. Thus `get_zeroed_page` would + * zero the page out in vain, so do that explicitly exactly once. + * + * By default, the page is allocated encrypted in a CoCo VM. + */ + *page = (void *)__get_free_page(GFP_KERNEL); + if (!*page) + return -ENOMEM; + + if (decrypt) + ret = set_memory_decrypted((unsigned long)*page, 1); + if (ret) + goto failed; + + memset(*page, 0, PAGE_SIZE); + return 0; + +failed: + /* + * Report the failure but don't put the page back on the free list as + * its encryption status is unknown. + */ + pr_err("allocation failed for %s page, error %d, decrypted %d\n", + note, ret, decrypt); + *page = NULL; + return ret; +} + +static int hv_free_page(void **page, bool encrypt, const char *note) +{ + int ret = 0; + + if (!*page) + return 0; + + if (encrypt) + ret = set_memory_encrypted((unsigned long)*page, 1); + + /* + * In the case of the failure, the page is leaked. Something is wrong, + * prefer to lose the page with the unknown encryption status and stay afloat. + */ + if (ret) + pr_err("deallocation failed for %s page, error %d, encrypt %d\n", + note, ret, encrypt); + else + free_page((unsigned long)*page); + + *page = NULL; + + return ret; +} + int hv_synic_alloc(void) { int cpu, ret = -ENOMEM; struct hv_per_cpu_context *hv_cpu; + const bool decrypt = !vmbus_is_confidential(); /* * First, zero all per-cpu memory areas so hv_synic_free() can @@ -125,73 +185,37 @@ int hv_synic_alloc(void) vmbus_on_msg_dpc, (unsigned long)hv_cpu); if (ms_hyperv.paravisor_present && hv_isolation_type_tdx()) { - hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC); - if (!hv_cpu->post_msg_page) { - pr_err("Unable to allocate post msg page\n"); + ret = hv_alloc_page(&hv_cpu->post_msg_page, + decrypt, "post msg"); + if (ret) goto err; - } - - ret = set_memory_decrypted((unsigned long)hv_cpu->post_msg_page, 1); - if (ret) { - pr_err("Failed to decrypt post msg page: %d\n", ret); - /* Just leak the page, as it's unsafe to free the page. */ - hv_cpu->post_msg_page = NULL; - goto err; - } - - memset(hv_cpu->post_msg_page, 0, PAGE_SIZE); } /* - * Synic message and event pages are allocated by paravisor. - * Skip these pages allocation here. + * If these SynIC pages are not allocated, SIEF and SIM pages + * are configured using what the root partition or the paravisor + * provides upon reading the SIEFP and SIMP registers. */ if (!ms_hyperv.paravisor_present && !hv_root_partition()) { - hv_cpu->hyp_synic_message_page = - (void *)get_zeroed_page(GFP_ATOMIC); - if (!hv_cpu->hyp_synic_message_page) { - pr_err("Unable to allocate SYNIC message page\n"); + ret = hv_alloc_page(&hv_cpu->hyp_synic_message_page, + decrypt, "hypervisor SynIC msg"); + if (ret) goto err; - } - - hv_cpu->hyp_synic_event_page = - (void *)get_zeroed_page(GFP_ATOMIC); - if (!hv_cpu->hyp_synic_event_page) { - pr_err("Unable to allocate SYNIC event page\n"); - - free_page((unsigned long)hv_cpu->hyp_synic_message_page); - hv_cpu->hyp_synic_message_page = NULL; + ret = hv_alloc_page(&hv_cpu->hyp_synic_event_page, + decrypt, "hypervisor SynIC event"); + if (ret) goto err; - } } - if (!ms_hyperv.paravisor_present && - (hv_isolation_type_snp() || hv_isolation_type_tdx())) { - ret = set_memory_decrypted((unsigned long) - hv_cpu->hyp_synic_message_page, 1); - if (ret) { - pr_err("Failed to decrypt SYNIC msg page: %d\n", ret); - hv_cpu->hyp_synic_message_page = NULL; - - /* - * Free the event page here so that hv_synic_free() - * won't later try to re-encrypt it. - */ - free_page((unsigned long)hv_cpu->hyp_synic_event_page); - hv_cpu->hyp_synic_event_page = NULL; + if (vmbus_is_confidential()) { + ret = hv_alloc_page(&hv_cpu->para_synic_message_page, + false, "paravisor SynIC msg"); + if (ret) goto err; - } - - ret = set_memory_decrypted((unsigned long) - hv_cpu->hyp_synic_event_page, 1); - if (ret) { - pr_err("Failed to decrypt SYNIC event page: %d\n", ret); - hv_cpu->hyp_synic_event_page = NULL; + ret = hv_alloc_page(&hv_cpu->para_synic_event_page, + false, "paravisor SynIC event"); + if (ret) goto err; - } - - memset(hv_cpu->hyp_synic_message_page, 0, PAGE_SIZE); - memset(hv_cpu->hyp_synic_event_page, 0, PAGE_SIZE); } } @@ -207,48 +231,28 @@ int hv_synic_alloc(void) void hv_synic_free(void) { - int cpu, ret; + int cpu; + const bool encrypt = !vmbus_is_confidential(); for_each_present_cpu(cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - /* It's better to leak the page if the encryption fails. */ - if (ms_hyperv.paravisor_present && hv_isolation_type_tdx()) { - if (hv_cpu->post_msg_page) { - ret = set_memory_encrypted((unsigned long) - hv_cpu->post_msg_page, 1); - if (ret) { - pr_err("Failed to encrypt post msg page: %d\n", ret); - hv_cpu->post_msg_page = NULL; - } - } + if (ms_hyperv.paravisor_present && hv_isolation_type_tdx()) + hv_free_page(&hv_cpu->post_msg_page, + encrypt, "post msg"); + if (!ms_hyperv.paravisor_present && !hv_root_partition()) { + hv_free_page(&hv_cpu->hyp_synic_event_page, + encrypt, "hypervisor SynIC event"); + hv_free_page(&hv_cpu->hyp_synic_message_page, + encrypt, "hypervisor SynIC msg"); } - - if (!ms_hyperv.paravisor_present && - (hv_isolation_type_snp() || hv_isolation_type_tdx())) { - if (hv_cpu->hyp_synic_message_page) { - ret = set_memory_encrypted((unsigned long) - hv_cpu->hyp_synic_message_page, 1); - if (ret) { - pr_err("Failed to encrypt SYNIC msg page: %d\n", ret); - hv_cpu->hyp_synic_message_page = NULL; - } - } - - if (hv_cpu->hyp_synic_event_page) { - ret = set_memory_encrypted((unsigned long) - hv_cpu->hyp_synic_event_page, 1); - if (ret) { - pr_err("Failed to encrypt SYNIC event page: %d\n", ret); - hv_cpu->hyp_synic_event_page = NULL; - } - } + if (vmbus_is_confidential()) { + hv_free_page(&hv_cpu->para_synic_event_page, + false, "paravisor SynIC event"); + hv_free_page(&hv_cpu->para_synic_message_page, + false, "paravisor SynIC msg"); } - - free_page((unsigned long)hv_cpu->post_msg_page); - free_page((unsigned long)hv_cpu->hyp_synic_event_page); - free_page((unsigned long)hv_cpu->hyp_synic_message_page); } kfree(hv_context.hv_numa_map); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index d593af45a5b2ae..3c70051c043127 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -121,8 +121,26 @@ enum { * Per cpu state for channel handling */ struct hv_per_cpu_context { + /* + * SynIC pages for communicating with the host. + * + * These pages are accessible to the host partition and the hypervisor. + * They may be used for exchanging data with the host partition and the + * hypervisor even when they aren't trusted yet the guest partition + * must be prepared to handle the malicious behavior. + */ void *hyp_synic_message_page; void *hyp_synic_event_page; + /* + * SynIC pages for communicating with the paravisor. + * + * These pages may be accessed from within the guest partition only in + * CoCo VMs. Neither the host partition nor the hypervisor can access + * these pages in that case; they are used for exchanging data with the + * paravisor. + */ + void *para_synic_message_page; + void *para_synic_event_page; /* * The page is only used in hv_post_message() for a TDX VM (with the From 25059d5e4c5af37688797d87b2d2004ac1cddff7 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:10 -0700 Subject: [PATCH 337/684] Drivers: hv: Post messages through the confidential VMBus if available When the confidential VMBus is available, the guest should post messages to the paravisor. Update hv_post_message() to post messages to the paravisor rather than through GHCB or TD calls. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hv.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index d380e0df63f39f..aca3a275bb1f92 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -74,7 +74,11 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - if (ms_hyperv.paravisor_present) { + if (ms_hyperv.paravisor_present && !vmbus_is_confidential()) { + /* + * If the VMBus isn't confidential, use the CoCo-specific + * mechanism to communicate with the hypervisor. + */ if (hv_isolation_type_tdx()) status = hv_tdx_hypercall(HVCALL_POST_MESSAGE, virt_to_phys(aligned_msg), 0); @@ -88,6 +92,11 @@ int hv_post_message(union hv_connection_id connection_id, u64 control = HVCALL_POST_MESSAGE; control |= hv_nested ? HV_HYPERCALL_NESTED : 0; + /* + * If there is no paravisor, this will go to the hypervisor. + * In the Confidential VMBus case, there is the paravisor + * to which this will trap. + */ status = hv_do_hypercall(control, aligned_msg, NULL); } From 1bb15327d529a4e30f69b6c3486dfe8d7a753ff5 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:11 -0700 Subject: [PATCH 338/684] Drivers: hv: remove stale comment The comment about the x2v shim is ancient and long since incorrect. Remove the incorrect comment. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hv.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index aca3a275bb1f92..e9e1edd751079f 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -268,11 +268,7 @@ void hv_synic_free(void) } /* - * hv_synic_init - Initialize the Synthetic Interrupt Controller. - * - * If it is already initialized by another entity (ie x2v shim), we need to - * retrieve the initialized message and event pages. Otherwise, we create and - * initialize the message and event pages. + * hv_synic_enable_regs - Initialize the Synthetic Interrupt Controller. */ void hv_synic_enable_regs(unsigned int cpu) { From 09406f2f8466fe44894f444943134a09c8519e4f Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:12 -0700 Subject: [PATCH 339/684] Drivers: hv: Check message and event pages for non-NULL before iounmap() It might happen that some hyp SynIC pages aren't allocated. Check for that and only then call iounmap(). Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index e9e1edd751079f..77da2d21137899 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -371,8 +371,10 @@ void hv_synic_disable_regs(unsigned int cpu) */ simp.simp_enabled = 0; if (ms_hyperv.paravisor_present || hv_root_partition()) { - iounmap(hv_cpu->hyp_synic_message_page); - hv_cpu->hyp_synic_message_page = NULL; + if (hv_cpu->hyp_synic_message_page) { + iounmap(hv_cpu->hyp_synic_message_page); + hv_cpu->hyp_synic_message_page = NULL; + } } else { simp.base_simp_gpa = 0; } @@ -383,8 +385,10 @@ void hv_synic_disable_regs(unsigned int cpu) siefp.siefp_enabled = 0; if (ms_hyperv.paravisor_present || hv_root_partition()) { - iounmap(hv_cpu->hyp_synic_event_page); - hv_cpu->hyp_synic_event_page = NULL; + if (hv_cpu->hyp_synic_event_page) { + iounmap(hv_cpu->hyp_synic_event_page); + hv_cpu->hyp_synic_event_page = NULL; + } } else { siefp.base_siefp_gpa = 0; } From 74fa5d7e5fbdecdff64f149d9c14c74baa5cb27b Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:13 -0700 Subject: [PATCH 340/684] Drivers: hv: Rename the SynIC enable and disable routines The confidential VMBus requires support for the both hypervisor facing SynIC and the paravisor one. Rename the functions that enable and disable SynIC with the hypervisor. No functional changes. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/channel_mgmt.c | 2 +- drivers/hv/hv.c | 11 ++++++----- drivers/hv/hyperv_vmbus.h | 4 ++-- drivers/hv/vmbus_drv.c | 6 +++--- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 1a33c6944b3c4e..6d66cbc9030b23 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -846,7 +846,7 @@ static void vmbus_wait_for_unload(void) /* * In a CoCo VM the hyp_synic_message_page is not allocated * in hv_synic_alloc(). Instead it is set/cleared in - * hv_synic_enable_regs() and hv_synic_disable_regs() + * hv_hyp_synic_enable_regs() and hv_hyp_synic_disable_regs() * such that it is set only when the CPU is online. If * not all present CPUs are online, the message page * might be NULL, so skip such CPUs. diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 77da2d21137899..81b6c3b0f21a4a 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -268,9 +268,10 @@ void hv_synic_free(void) } /* - * hv_synic_enable_regs - Initialize the Synthetic Interrupt Controller. + * hv_hyp_synic_enable_regs - Initialize the Synthetic Interrupt Controller + * with the hypervisor. */ -void hv_synic_enable_regs(unsigned int cpu) +void hv_hyp_synic_enable_regs(unsigned int cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); @@ -337,14 +338,14 @@ void hv_synic_enable_regs(unsigned int cpu) int hv_synic_init(unsigned int cpu) { - hv_synic_enable_regs(cpu); + hv_hyp_synic_enable_regs(cpu); hv_stimer_legacy_init(cpu, VMBUS_MESSAGE_SINT); return 0; } -void hv_synic_disable_regs(unsigned int cpu) +void hv_hyp_synic_disable_regs(unsigned int cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); @@ -532,7 +533,7 @@ int hv_synic_cleanup(unsigned int cpu) always_cleanup: hv_stimer_legacy_cleanup(cpu); - hv_synic_disable_regs(cpu); + hv_hyp_synic_disable_regs(cpu); return ret; } diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 3c70051c043127..552ed782bcfc8a 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -190,10 +190,10 @@ extern int hv_synic_alloc(void); extern void hv_synic_free(void); -extern void hv_synic_enable_regs(unsigned int cpu); +extern void hv_hyp_synic_enable_regs(unsigned int cpu); extern int hv_synic_init(unsigned int cpu); -extern void hv_synic_disable_regs(unsigned int cpu); +extern void hv_hyp_synic_disable_regs(unsigned int cpu); extern int hv_synic_cleanup(unsigned int cpu); /* Interface */ diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e12f0ba0701ff6..2b5bf672c46718 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2810,7 +2810,7 @@ static void hv_crash_handler(struct pt_regs *regs) */ cpu = smp_processor_id(); hv_stimer_cleanup(cpu); - hv_synic_disable_regs(cpu); + hv_hyp_synic_disable_regs(cpu); }; static int hv_synic_suspend(void) @@ -2835,14 +2835,14 @@ static int hv_synic_suspend(void) * interrupts-disabled context. */ - hv_synic_disable_regs(0); + hv_hyp_synic_disable_regs(0); return 0; } static void hv_synic_resume(void) { - hv_synic_enable_regs(0); + hv_hyp_synic_enable_regs(0); /* * Note: we don't need to call hv_stimer_init(0), because the timer From e096fe2bd623f77d5407f1d9a40f5d8d2a596680 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:14 -0700 Subject: [PATCH 341/684] Drivers: hv: Functions for setting up and tearing down the paravisor SynIC The confidential VMBus runs with the paravisor SynIC and requires configuring it with the paravisor. Add the functions for configuring the paravisor SynIC. Update overall SynIC initialization logic to initialize the SynIC if it is present. Finally, break out SynIC interrupt enable/disable code into separate functions so that SynIC interrupts can be enabled or disabled via the paravisor instead of the hypervisor if the paravisor SynIC is present. Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/hv.c | 138 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 12 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 81b6c3b0f21a4a..936c5f310df6ff 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -278,9 +278,8 @@ void hv_hyp_synic_enable_regs(unsigned int cpu) union hv_synic_simp simp; union hv_synic_siefp siefp; union hv_synic_sint shared_sint; - union hv_synic_scontrol sctrl; - /* Setup the Synic's message page */ + /* Setup the Synic's message page with the hypervisor. */ simp.as_uint64 = hv_get_msr(HV_MSR_SIMP); simp.simp_enabled = 1; @@ -299,7 +298,7 @@ void hv_hyp_synic_enable_regs(unsigned int cpu) hv_set_msr(HV_MSR_SIMP, simp.as_uint64); - /* Setup the Synic's event page */ + /* Setup the Synic's event page with the hypervisor. */ siefp.as_uint64 = hv_get_msr(HV_MSR_SIEFP); siefp.siefp_enabled = 1; @@ -328,6 +327,11 @@ void hv_hyp_synic_enable_regs(unsigned int cpu) shared_sint.masked = false; shared_sint.auto_eoi = hv_recommend_using_aeoi(); hv_set_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); +} + +static void hv_hyp_synic_enable_interrupts(void) +{ + union hv_synic_scontrol sctrl; /* Enable the global synic bit */ sctrl.as_uint64 = hv_get_msr(HV_MSR_SCONTROL); @@ -336,9 +340,59 @@ void hv_hyp_synic_enable_regs(unsigned int cpu) hv_set_msr(HV_MSR_SCONTROL, sctrl.as_uint64); } +static void hv_para_synic_enable_regs(unsigned int cpu) +{ + union hv_synic_simp simp; + union hv_synic_siefp siefp; + struct hv_per_cpu_context *hv_cpu + = per_cpu_ptr(hv_context.cpu_context, cpu); + + /* Setup the Synic's message page with the paravisor. */ + simp.as_uint64 = hv_para_get_synic_register(HV_MSR_SIMP); + simp.simp_enabled = 1; + simp.base_simp_gpa = virt_to_phys(hv_cpu->para_synic_message_page) + >> HV_HYP_PAGE_SHIFT; + hv_para_set_synic_register(HV_MSR_SIMP, simp.as_uint64); + + /* Setup the Synic's event page with the paravisor. */ + siefp.as_uint64 = hv_para_get_synic_register(HV_MSR_SIEFP); + siefp.siefp_enabled = 1; + siefp.base_siefp_gpa = virt_to_phys(hv_cpu->para_synic_event_page) + >> HV_HYP_PAGE_SHIFT; + hv_para_set_synic_register(HV_MSR_SIEFP, siefp.as_uint64); +} + +static void hv_para_synic_enable_interrupts(void) +{ + union hv_synic_scontrol sctrl; + + /* Enable the global synic bit */ + sctrl.as_uint64 = hv_para_get_synic_register(HV_MSR_SCONTROL); + sctrl.enable = 1; + hv_para_set_synic_register(HV_MSR_SCONTROL, sctrl.as_uint64); +} + int hv_synic_init(unsigned int cpu) { + if (vmbus_is_confidential()) + hv_para_synic_enable_regs(cpu); + + /* + * The SINT is set in hv_hyp_synic_enable_regs() by calling + * hv_set_msr(). hv_set_msr() in turn has special case code for the + * SINT MSRs that write to the hypervisor version of the MSR *and* + * the paravisor version of the MSR (but *without* the proxy bit when + * VMBus is confidential). + * + * Then enable interrupts via the paravisor if VMBus is confidential, + * and otherwise via the hypervisor. + */ + hv_hyp_synic_enable_regs(cpu); + if (vmbus_is_confidential()) + hv_para_synic_enable_interrupts(); + else + hv_hyp_synic_enable_interrupts(); hv_stimer_legacy_init(cpu, VMBUS_MESSAGE_SINT); @@ -352,7 +406,6 @@ void hv_hyp_synic_disable_regs(unsigned int cpu) union hv_synic_sint shared_sint; union hv_synic_simp simp; union hv_synic_siefp siefp; - union hv_synic_scontrol sctrl; shared_sint.as_uint64 = hv_get_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT); @@ -365,7 +418,7 @@ void hv_hyp_synic_disable_regs(unsigned int cpu) simp.as_uint64 = hv_get_msr(HV_MSR_SIMP); /* - * In Isolation VM, sim and sief pages are allocated by + * In Isolation VM, simp and sief pages are allocated by * paravisor. These pages also will be used by kdump * kernel. So just reset enable bit here and keep page * addresses. @@ -395,14 +448,42 @@ void hv_hyp_synic_disable_regs(unsigned int cpu) } hv_set_msr(HV_MSR_SIEFP, siefp.as_uint64); +} + +static void hv_hyp_synic_disable_interrupts(void) +{ + union hv_synic_scontrol sctrl; /* Disable the global synic bit */ sctrl.as_uint64 = hv_get_msr(HV_MSR_SCONTROL); sctrl.enable = 0; hv_set_msr(HV_MSR_SCONTROL, sctrl.as_uint64); +} - if (vmbus_irq != -1) - disable_percpu_irq(vmbus_irq); +static void hv_para_synic_disable_regs(unsigned int cpu) +{ + union hv_synic_simp simp; + union hv_synic_siefp siefp; + + /* Disable SynIC's message page in the paravisor. */ + simp.as_uint64 = hv_para_get_synic_register(HV_MSR_SIMP); + simp.simp_enabled = 0; + hv_para_set_synic_register(HV_MSR_SIMP, simp.as_uint64); + + /* Disable SynIC's event page in the paravisor. */ + siefp.as_uint64 = hv_para_get_synic_register(HV_MSR_SIEFP); + siefp.siefp_enabled = 0; + hv_para_set_synic_register(HV_MSR_SIEFP, siefp.as_uint64); +} + +static void hv_para_synic_disable_interrupts(void) +{ + union hv_synic_scontrol sctrl; + + /* Disable the global synic bit */ + sctrl.as_uint64 = hv_para_get_synic_register(HV_MSR_SCONTROL); + sctrl.enable = 0; + hv_para_set_synic_register(HV_MSR_SCONTROL, sctrl.as_uint64); } #define HV_MAX_TRIES 3 @@ -415,16 +496,18 @@ void hv_hyp_synic_disable_regs(unsigned int cpu) * that the normal interrupt handling mechanism will find and process the channel interrupt * "very soon", and in the process clear the bit. */ -static bool hv_synic_event_pending(void) +static bool __hv_synic_event_pending(union hv_synic_event_flags *event, int sint) { - struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); - union hv_synic_event_flags *event = - (union hv_synic_event_flags *)hv_cpu->hyp_synic_event_page + VMBUS_MESSAGE_SINT; - unsigned long *recv_int_page = event->flags; /* assumes VMBus version >= VERSION_WIN8 */ + unsigned long *recv_int_page; bool pending; u32 relid; int tries = 0; + if (!event) + return false; + + event += sint; + recv_int_page = event->flags; /* assumes VMBus version >= VERSION_WIN8 */ retry: pending = false; for_each_set_bit(relid, recv_int_page, HV_EVENT_FLAGS_COUNT) { @@ -441,6 +524,17 @@ static bool hv_synic_event_pending(void) return pending; } +static bool hv_synic_event_pending(void) +{ + struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); + union hv_synic_event_flags *hyp_synic_event_page = hv_cpu->hyp_synic_event_page; + union hv_synic_event_flags *para_synic_event_page = hv_cpu->para_synic_event_page; + + return + __hv_synic_event_pending(hyp_synic_event_page, VMBUS_MESSAGE_SINT) || + __hv_synic_event_pending(para_synic_event_page, VMBUS_MESSAGE_SINT); +} + static int hv_pick_new_cpu(struct vmbus_channel *channel) { int ret = -EBUSY; @@ -533,7 +627,27 @@ int hv_synic_cleanup(unsigned int cpu) always_cleanup: hv_stimer_legacy_cleanup(cpu); + /* + * First, disable the event and message pages + * used for communicating with the host, and then + * disable the host interrupts if VMBus is not + * confidential. + */ hv_hyp_synic_disable_regs(cpu); + if (!vmbus_is_confidential()) + hv_hyp_synic_disable_interrupts(); + + /* + * Perform the same steps for the Confidential VMBus. + * The sequencing provides the guarantee that no data + * may be posted for processing before disabling interrupts. + */ + if (vmbus_is_confidential()) { + hv_para_synic_disable_regs(cpu); + hv_para_synic_disable_interrupts(); + } + if (vmbus_irq != -1) + disable_percpu_irq(vmbus_irq); return ret; } From 0a4534bdf29a5b7f5a355c267d28dad9c40ba252 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:15 -0700 Subject: [PATCH 342/684] Drivers: hv: Allocate encrypted buffers when requested Confidential VMBus is built around using buffers not shared with the host. Support allocating encrypted buffers when requested. Signed-off-by: Roman Kisel Reviewed-by: Tianyu Lan Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/channel.c | 49 +++++++++++++++++++++++---------------- drivers/hv/hyperv_vmbus.h | 3 ++- drivers/hv/ring_buffer.c | 5 ++-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 162d6aeece7b3b..d69713201beffd 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -444,20 +444,23 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, return ret; } - /* - * Set the "decrypted" flag to true for the set_memory_decrypted() - * success case. In the failure case, the encryption state of the - * memory is unknown. Leave "decrypted" as true to ensure the - * memory will be leaked instead of going back on the free list. - */ - gpadl->decrypted = true; - ret = set_memory_decrypted((unsigned long)kbuffer, - PFN_UP(size)); - if (ret) { - dev_warn(&channel->device_obj->device, - "Failed to set host visibility for new GPADL %d.\n", - ret); - return ret; + gpadl->decrypted = !((channel->co_external_memory && type == HV_GPADL_BUFFER) || + (channel->co_ring_buffer && type == HV_GPADL_RING)); + if (gpadl->decrypted) { + /* + * The "decrypted" flag being true assumes that set_memory_decrypted() succeeds. + * But if it fails, the encryption state of the memory is unknown. In that case, + * leave "decrypted" as true to ensure the memory is leaked instead of going back + * on the free list. + */ + ret = set_memory_decrypted((unsigned long)kbuffer, + PFN_UP(size)); + if (ret) { + dev_warn(&channel->device_obj->device, + "Failed to set host visibility for new GPADL %d.\n", + ret); + return ret; + } } init_completion(&msginfo->waitevent); @@ -545,8 +548,10 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, * left as true so the memory is leaked instead of being * put back on the free list. */ - if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size))) - gpadl->decrypted = false; + if (gpadl->decrypted) { + if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size))) + gpadl->decrypted = false; + } } return ret; @@ -677,12 +682,13 @@ static int __vmbus_open(struct vmbus_channel *newchannel, goto error_clean_ring; err = hv_ringbuffer_init(&newchannel->outbound, - page, send_pages, 0); + page, send_pages, 0, newchannel->co_ring_buffer); if (err) goto error_free_gpadl; err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages], - recv_pages, newchannel->max_pkt_size); + recv_pages, newchannel->max_pkt_size, + newchannel->co_ring_buffer); if (err) goto error_free_gpadl; @@ -863,8 +869,11 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad kfree(info); - ret = set_memory_encrypted((unsigned long)gpadl->buffer, - PFN_UP(gpadl->size)); + if (gpadl->decrypted) + ret = set_memory_encrypted((unsigned long)gpadl->buffer, + PFN_UP(gpadl->size)); + else + ret = 0; if (ret) pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 552ed782bcfc8a..f7fc2630c054d0 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -201,7 +201,8 @@ extern int hv_synic_cleanup(unsigned int cpu); void hv_ringbuffer_pre_init(struct vmbus_channel *channel); int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, - struct page *pages, u32 pagecnt, u32 max_pkt_size); + struct page *pages, u32 pagecnt, u32 max_pkt_size, + bool confidential); void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 23ce1fb70de143..3c421a7f78c004 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -184,7 +184,8 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel) /* Initialize the ring buffer. */ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, - struct page *pages, u32 page_cnt, u32 max_pkt_size) + struct page *pages, u32 page_cnt, u32 max_pkt_size, + bool confidential) { struct page **pages_wraparound; int i; @@ -208,7 +209,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, ring_info->ring_buffer = (struct hv_ring_buffer *) vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP, - pgprot_decrypted(PAGE_KERNEL)); + confidential ? PAGE_KERNEL : pgprot_decrypted(PAGE_KERNEL)); kfree(pages_wraparound); if (!ring_info->ring_buffer) From 510164539f16062e842a9de762616b5008616fa1 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:16 -0700 Subject: [PATCH 343/684] Drivers: hv: Free msginfo when the buffer fails to decrypt The early failure path in __vmbus_establish_gpadl() doesn't deallocate msginfo if the buffer fails to decrypt. Fix the leak by breaking out the cleanup code into a separate function and calling it where required. Fixes: d4dccf353db80 ("Drivers: hv: vmbus: Mark vmbus ring buffer visible to host in Isolation VM") Reported-by: Michael Kelley Closes: https://lore.kernel.org/linux-hyperv/SN6PR02MB41573796F9787F67E0E97049D472A@SN6PR02MB4157.namprd02.prod.outlook.com Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/channel.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index d69713201beffd..88485d255a4224 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -410,6 +410,21 @@ static int create_gpadl_header(enum hv_gpadl_type type, void *kbuffer, return 0; } +static void vmbus_free_channel_msginfo(struct vmbus_channel_msginfo *msginfo) +{ + struct vmbus_channel_msginfo *submsginfo, *tmp; + + if (!msginfo) + return; + + list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist, + msglistentry) { + kfree(submsginfo); + } + + kfree(msginfo); +} + /* * __vmbus_establish_gpadl - Establish a GPADL for a buffer or ringbuffer * @@ -429,7 +444,7 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, struct vmbus_channel_gpadl_header *gpadlmsg; struct vmbus_channel_gpadl_body *gpadl_body; struct vmbus_channel_msginfo *msginfo = NULL; - struct vmbus_channel_msginfo *submsginfo, *tmp; + struct vmbus_channel_msginfo *submsginfo; struct list_head *curr; u32 next_gpadl_handle; unsigned long flags; @@ -459,6 +474,7 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, dev_warn(&channel->device_obj->device, "Failed to set host visibility for new GPADL %d.\n", ret); + vmbus_free_channel_msginfo(msginfo); return ret; } } @@ -535,12 +551,8 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&msginfo->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist, - msglistentry) { - kfree(submsginfo); - } - kfree(msginfo); + vmbus_free_channel_msginfo(msginfo); if (ret) { /* From bf35d298bb9ab2ccbcf654c1acb65ddc758ad690 Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:17 -0700 Subject: [PATCH 344/684] Drivers: hv: Support confidential VMBus channels To make use of Confidential VMBus channels, initialize the co_ring_buffers and co_external_memory fields of the channel structure. Advertise support upon negotiating the version and compute values for those fields and initialize them. Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/channel_mgmt.c | 19 +++++++++++++++++++ drivers/hv/connection.c | 3 +++ 2 files changed, 22 insertions(+) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 6d66cbc9030b23..74fed2c073d447 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -1022,6 +1022,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) struct vmbus_channel_offer_channel *offer; struct vmbus_channel *oldchannel, *newchannel; size_t offer_sz; + bool co_ring_buffer, co_external_memory; offer = (struct vmbus_channel_offer_channel *)hdr; @@ -1034,6 +1035,22 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) return; } + co_ring_buffer = is_co_ring_buffer(offer); + co_external_memory = is_co_external_memory(offer); + if (!co_ring_buffer && co_external_memory) { + pr_err("Invalid offer relid=%d: the ring buffer isn't encrypted\n", + offer->child_relid); + return; + } + if (co_ring_buffer || co_external_memory) { + if (vmbus_proto_version < VERSION_WIN10_V6_0 || !vmbus_is_confidential()) { + pr_err("Invalid offer relid=%d: no support for confidential VMBus\n", + offer->child_relid); + atomic_dec(&vmbus_connection.offer_in_progress); + return; + } + } + oldchannel = find_primary_channel_by_offer(offer); if (oldchannel != NULL) { @@ -1112,6 +1129,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) pr_err("Unable to allocate channel object\n"); return; } + newchannel->co_ring_buffer = co_ring_buffer; + newchannel->co_external_memory = co_external_memory; vmbus_setup_channel_state(newchannel, offer); diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 1fe3573ae52a4b..5ac9232396f7cd 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -105,6 +105,9 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID; } + if (vmbus_is_confidential() && version >= VERSION_WIN10_V6_0) + msg->feature_flags = VMBUS_FEATURE_FLAG_CONFIDENTIAL_CHANNELS; + /* * shared_gpa_boundary is zero in non-SNP VMs, so it's safe to always * bitwise OR it From b537794bc28aafd05c317bda9d7a4d8f7d6a528d Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:18 -0700 Subject: [PATCH 345/684] Drivers: hv: Set the default VMBus version to 6.0 The confidential VMBus is supported by the protocol version 6.0 onwards. Attempt to establish the VMBus 6.0 connection thus enabling the confidential VMBus features when available. Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 5ac9232396f7cd..5d9cb5bf2d6232 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -51,6 +51,7 @@ EXPORT_SYMBOL_GPL(vmbus_proto_version); * Linux guests and are not listed. */ static __u32 vmbus_versions[] = { + VERSION_WIN10_V6_0, VERSION_WIN10_V5_3, VERSION_WIN10_V5_2, VERSION_WIN10_V5_1, @@ -65,7 +66,7 @@ static __u32 vmbus_versions[] = { * Maximal VMBus protocol version guests can negotiate. Useful to cap the * VMBus version for testing and debugging purpose. */ -static uint max_version = VERSION_WIN10_V5_3; +static uint max_version = VERSION_WIN10_V6_0; module_param(max_version, uint, S_IRUGO); MODULE_PARM_DESC(max_version, From 2647c96649ba4ba9fb0fa5dfd101a15257145a3d Mon Sep 17 00:00:00 2001 From: Roman Kisel Date: Wed, 8 Oct 2025 16:34:19 -0700 Subject: [PATCH 346/684] Drivers: hv: Support establishing the confidential VMBus connection To establish the confidential VMBus connection the CoCo VM, the guest first checks on the confidential VMBus availability, and then proceeds to initializing the communication stack. Implement that in the VMBus driver initialization. Signed-off-by: Roman Kisel Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/vmbus_drv.c | 168 ++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 62 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 2b5bf672c46718..0dc4692b411ae5 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1057,12 +1057,9 @@ static void vmbus_onmessage_work(struct work_struct *work) kfree(ctx); } -void vmbus_on_msg_dpc(unsigned long data) +static void __vmbus_on_msg_dpc(void *message_page_addr) { - struct hv_per_cpu_context *hv_cpu = (void *)data; - void *page_addr = hv_cpu->hyp_synic_message_page; - struct hv_message msg_copy, *msg = (struct hv_message *)page_addr + - VMBUS_MESSAGE_SINT; + struct hv_message msg_copy, *msg; struct vmbus_channel_message_header *hdr; enum vmbus_channel_message_type msgtype; const struct vmbus_channel_message_table_entry *entry; @@ -1070,6 +1067,10 @@ void vmbus_on_msg_dpc(unsigned long data) __u8 payload_size; u32 message_type; + if (!message_page_addr) + return; + msg = (struct hv_message *)message_page_addr + VMBUS_MESSAGE_SINT; + /* * 'enum vmbus_channel_message_type' is supposed to always be 'u32' as * it is being used in 'struct vmbus_channel_message_header' definition @@ -1195,6 +1196,14 @@ void vmbus_on_msg_dpc(unsigned long data) vmbus_signal_eom(msg, message_type); } +void vmbus_on_msg_dpc(unsigned long data) +{ + struct hv_per_cpu_context *hv_cpu = (void *)data; + + __vmbus_on_msg_dpc(hv_cpu->hyp_synic_message_page); + __vmbus_on_msg_dpc(hv_cpu->para_synic_message_page); +} + #ifdef CONFIG_PM_SLEEP /* * Fake RESCIND_CHANNEL messages to clean up hv_sock channels by force for @@ -1233,21 +1242,19 @@ static void vmbus_force_channel_rescinded(struct vmbus_channel *channel) #endif /* CONFIG_PM_SLEEP */ /* - * Schedule all channels with events pending + * Schedule all channels with events pending. + * The event page can be directly checked to get the id of + * the channel that has the interrupt pending. */ -static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) +static void vmbus_chan_sched(void *event_page_addr) { unsigned long *recv_int_page; u32 maxbits, relid; + union hv_synic_event_flags *event; - /* - * The event page can be directly checked to get the id of - * the channel that has the interrupt pending. - */ - void *page_addr = hv_cpu->hyp_synic_event_page; - union hv_synic_event_flags *event - = (union hv_synic_event_flags *)page_addr + - VMBUS_MESSAGE_SINT; + if (!event_page_addr) + return; + event = (union hv_synic_event_flags *)event_page_addr + VMBUS_MESSAGE_SINT; maxbits = HV_EVENT_FLAGS_COUNT; recv_int_page = event->flags; @@ -1255,6 +1262,11 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) if (unlikely(!recv_int_page)) return; + /* + * Suggested-by: Michael Kelley + * One possible optimization would be to keep track of the largest relID that's in use, + * and only scan up to that relID. + */ for_each_set_bit(relid, recv_int_page, maxbits) { void (*callback_fn)(void *context); struct vmbus_channel *channel; @@ -1318,26 +1330,35 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) } } -static void vmbus_isr(void) +static void vmbus_message_sched(struct hv_per_cpu_context *hv_cpu, void *message_page_addr) { - struct hv_per_cpu_context *hv_cpu - = this_cpu_ptr(hv_context.cpu_context); - void *page_addr; struct hv_message *msg; - vmbus_chan_sched(hv_cpu); - - page_addr = hv_cpu->hyp_synic_message_page; - msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; + if (!message_page_addr) + return; + msg = (struct hv_message *)message_page_addr + VMBUS_MESSAGE_SINT; /* Check if there are actual msgs to be processed */ if (msg->header.message_type != HVMSG_NONE) { if (msg->header.message_type == HVMSG_TIMER_EXPIRED) { hv_stimer0_isr(); vmbus_signal_eom(msg, HVMSG_TIMER_EXPIRED); - } else + } else { tasklet_schedule(&hv_cpu->msg_dpc); + } } +} + +static void vmbus_isr(void) +{ + struct hv_per_cpu_context *hv_cpu + = this_cpu_ptr(hv_context.cpu_context); + + vmbus_chan_sched(hv_cpu->hyp_synic_event_page); + vmbus_chan_sched(hv_cpu->para_synic_event_page); + + vmbus_message_sched(hv_cpu, hv_cpu->hyp_synic_message_page); + vmbus_message_sched(hv_cpu, hv_cpu->para_synic_message_page); add_interrupt_randomness(vmbus_interrupt); } @@ -1355,6 +1376,59 @@ static void vmbus_percpu_work(struct work_struct *work) hv_synic_init(cpu); } +static int vmbus_alloc_synic_and_connect(void) +{ + int ret, cpu; + struct work_struct __percpu *works; + int hyperv_cpuhp_online; + + ret = hv_synic_alloc(); + if (ret < 0) + goto err_alloc; + + works = alloc_percpu(struct work_struct); + if (!works) { + ret = -ENOMEM; + goto err_alloc; + } + + /* + * Initialize the per-cpu interrupt state and stimer state. + * Then connect to the host. + */ + cpus_read_lock(); + for_each_online_cpu(cpu) { + struct work_struct *work = per_cpu_ptr(works, cpu); + + INIT_WORK(work, vmbus_percpu_work); + schedule_work_on(cpu, work); + } + + for_each_online_cpu(cpu) + flush_work(per_cpu_ptr(works, cpu)); + + /* Register the callbacks for possible CPU online/offline'ing */ + ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", + hv_synic_init, hv_synic_cleanup); + cpus_read_unlock(); + free_percpu(works); + if (ret < 0) + goto err_alloc; + hyperv_cpuhp_online = ret; + + ret = vmbus_connect(); + if (ret) + goto err_connect; + return 0; + +err_connect: + cpuhp_remove_state(hyperv_cpuhp_online); + return -ENODEV; +err_alloc: + hv_synic_free(); + return -ENOMEM; +} + /* * vmbus_bus_init -Main vmbus driver initialization routine. * @@ -1365,8 +1439,7 @@ static void vmbus_percpu_work(struct work_struct *work) */ static int vmbus_bus_init(void) { - int ret, cpu; - struct work_struct __percpu *works; + int ret; ret = hv_init(); if (ret != 0) { @@ -1401,41 +1474,15 @@ static int vmbus_bus_init(void) } } - ret = hv_synic_alloc(); - if (ret) - goto err_alloc; - - works = alloc_percpu(struct work_struct); - if (!works) { - ret = -ENOMEM; - goto err_alloc; - } - /* - * Initialize the per-cpu interrupt state and stimer state. - * Then connect to the host. + * Cache the value as getting it involves a VM exit on x86(_64), and + * doing that on each VP while initializing SynIC's wastes time. */ - cpus_read_lock(); - for_each_online_cpu(cpu) { - struct work_struct *work = per_cpu_ptr(works, cpu); - - INIT_WORK(work, vmbus_percpu_work); - schedule_work_on(cpu, work); - } - - for_each_online_cpu(cpu) - flush_work(per_cpu_ptr(works, cpu)); - - /* Register the callbacks for possible CPU online/offline'ing */ - ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", - hv_synic_init, hv_synic_cleanup); - cpus_read_unlock(); - free_percpu(works); - if (ret < 0) - goto err_alloc; - hyperv_cpuhp_online = ret; - - ret = vmbus_connect(); + is_confidential = ms_hyperv.confidential_vmbus_available; + if (is_confidential) + pr_info("Establishing connection to the confidential VMBus\n"); + hv_para_set_sint_proxy(!is_confidential); + ret = vmbus_alloc_synic_and_connect(); if (ret) goto err_connect; @@ -1451,9 +1498,6 @@ static int vmbus_bus_init(void) return 0; err_connect: - cpuhp_remove_state(hyperv_cpuhp_online); -err_alloc: - hv_synic_free(); if (vmbus_irq == -1) { hv_remove_vmbus_handler(); } else { From 9ebc528cfdada055984f919710c31be281cb717c Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Fri, 10 Oct 2025 14:55:47 -0700 Subject: [PATCH 347/684] mshv: Only map vp->vp_stats_pages if on root scheduler This mapping is only used for checking if the dispatch thread is blocked. This is only relevant for the root scheduler, so check the scheduler type to determine whether to map/unmap these pages, instead of the current check, which is incorrect. Signed-off-by: Nuno Das Neves Reviewed-by: Anirudh Rayabharam Reviewed-by: Praveen K Paladugu Reviewed-by: Easwar Hariharan Reviewed-by: Tianyu Lan Acked-by: Stanislav Kinsburskii Reviewed-by: Anirudh Rayabharam (Microsoft) Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index a599bbf1f9b8f7..f1fabf52c8f5e5 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -936,7 +936,11 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, goto unmap_register_page; } - if (hv_parent_partition()) { + /* + * This mapping of the stats page is for detecting if dispatch thread + * is blocked - only relevant for root scheduler + */ + if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) { ret = mshv_vp_stats_map(partition->pt_id, args.vp_index, stats_pages); if (ret) @@ -965,7 +969,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) vp->vp_ghcb_page = page_to_virt(ghcb_page); - if (hv_parent_partition()) + if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) memcpy(vp->vp_stats_pages, stats_pages, sizeof(stats_pages)); /* @@ -988,7 +992,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, free_vp: kfree(vp); unmap_stats_pages: - if (hv_parent_partition()) + if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) mshv_vp_stats_unmap(partition->pt_id, args.vp_index); unmap_ghcb_page: if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) { @@ -1742,7 +1746,7 @@ static void destroy_partition(struct mshv_partition *partition) if (!vp) continue; - if (hv_parent_partition()) + if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) mshv_vp_stats_unmap(partition->pt_id, vp->vp_index); if (vp->vp_register_page) { From 59aeea195948fd507cef2e439a5a964b8432750e Mon Sep 17 00:00:00 2001 From: Purna Pavan Chandra Aekkaladevi Date: Fri, 10 Oct 2025 14:55:48 -0700 Subject: [PATCH 348/684] mshv: Add the HVCALL_GET_PARTITION_PROPERTY_EX hypercall This hypercall can be used to fetch extended properties of a partition. Extended properties are properties with values larger than a u64. Some of these also need additional input arguments. Add helper function for using the hypercall in the mshv_root driver. Signed-off-by: Purna Pavan Chandra Aekkaladevi Signed-off-by: Nuno Das Neves Reviewed-by: Anirudh Rayabharam Reviewed-by: Praveen K Paladugu Reviewed-by: Easwar Hariharan Reviewed-by: Tianyu Lan Signed-off-by: Wei Liu --- drivers/hv/mshv_root.h | 2 ++ drivers/hv/mshv_root_hv_call.c | 31 ++++++++++++++++++++++++++ include/hyperv/hvgdk_mini.h | 1 + include/hyperv/hvhdk.h | 40 ++++++++++++++++++++++++++++++++++ include/hyperv/hvhdk_mini.h | 26 ++++++++++++++++++++++ 5 files changed, 100 insertions(+) diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index db6b42db2fdc63..0e62badfc9f19d 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -303,6 +303,8 @@ int hv_call_unmap_stat_page(enum hv_stats_object_type type, int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages, u64 page_struct_count, u32 host_access, u32 flags, u8 acquire); +int hv_call_get_partition_property_ex(u64 partition_id, u64 property_code, u64 arg, + void *property_value, size_t property_value_sz); extern struct mshv_root mshv_root; extern enum hv_scheduler_type hv_scheduler_type; diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c index c9c274f29c3c61..8049e51c45dcdc 100644 --- a/drivers/hv/mshv_root_hv_call.c +++ b/drivers/hv/mshv_root_hv_call.c @@ -590,6 +590,37 @@ int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, return hv_result_to_errno(status); } +int hv_call_get_partition_property_ex(u64 partition_id, u64 property_code, + u64 arg, void *property_value, + size_t property_value_sz) +{ + u64 status; + unsigned long flags; + struct hv_input_get_partition_property_ex *input; + struct hv_output_get_partition_property_ex *output; + + local_irq_save(flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + output = *this_cpu_ptr(hyperv_pcpu_output_arg); + + memset(input, 0, sizeof(*input)); + input->partition_id = partition_id; + input->property_code = property_code; + input->arg = arg; + status = hv_do_hypercall(HVCALL_GET_PARTITION_PROPERTY_EX, input, output); + + if (!hv_result_success(status)) { + local_irq_restore(flags); + hv_status_debug(status, "\n"); + return hv_result_to_errno(status); + } + memcpy(property_value, &output->property_value, property_value_sz); + + local_irq_restore(flags); + + return 0; +} + int hv_call_clear_virtual_interrupt(u64 partition_id) { diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index 7f730a0e54e611..af85b1c36b6e46 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -491,6 +491,7 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_GET_VP_STATE 0x00e3 #define HVCALL_SET_VP_STATE 0x00e4 #define HVCALL_GET_VP_CPUID_VALUES 0x00f4 +#define HVCALL_GET_PARTITION_PROPERTY_EX 0x0101 #define HVCALL_MMIO_READ 0x0106 #define HVCALL_MMIO_WRITE 0x0107 diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h index b4067ada02cf13..416c0d45b79342 100644 --- a/include/hyperv/hvhdk.h +++ b/include/hyperv/hvhdk.h @@ -376,6 +376,46 @@ struct hv_input_set_partition_property { u64 property_value; } __packed; +union hv_partition_property_arg { + u64 as_uint64; + struct { + union { + u32 arg; + u32 vp_index; + }; + u16 reserved0; + u8 reserved1; + u8 object_type; + } __packed; +}; + +struct hv_input_get_partition_property_ex { + u64 partition_id; + u32 property_code; /* enum hv_partition_property_code */ + u32 padding; + union { + union hv_partition_property_arg arg_data; + u64 arg; + }; +} __packed; + +/* + * NOTE: Should use hv_input_set_partition_property_ex_header to compute this + * size, but hv_input_get_partition_property_ex is identical so it suffices + */ +#define HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE \ + (HV_HYP_PAGE_SIZE - sizeof(struct hv_input_get_partition_property_ex)) + +union hv_partition_property_ex { + u8 buffer[HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE]; + struct hv_partition_property_vmm_capabilities vmm_capabilities; + /* More fields to be filled in when needed */ +}; + +struct hv_output_get_partition_property_ex { + union hv_partition_property_ex property_value; +} __packed; + enum hv_vp_state_page_type { HV_VP_STATE_PAGE_REGISTERS = 0, HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1, diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index 858f6a3925b30f..bf2ce27dfcc5c5 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -96,8 +96,34 @@ enum hv_partition_property_code { HV_PARTITION_PROPERTY_XSAVE_STATES = 0x00060007, HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE = 0x00060008, HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY = 0x00060009, + + /* Extended properties with larger property values */ + HV_PARTITION_PROPERTY_VMM_CAPABILITIES = 0x00090007, }; +#define HV_PARTITION_VMM_CAPABILITIES_BANK_COUNT 1 +#define HV_PARTITION_VMM_CAPABILITIES_RESERVED_BITFIELD_COUNT 59 + +struct hv_partition_property_vmm_capabilities { + u16 bank_count; + u16 reserved[3]; + union { + u64 as_uint64[HV_PARTITION_VMM_CAPABILITIES_BANK_COUNT]; + struct { + u64 map_gpa_preserve_adjustable: 1; + u64 vmm_can_provide_overlay_gpfn: 1; + u64 vp_affinity_property: 1; +#if IS_ENABLED(CONFIG_ARM64) + u64 vmm_can_provide_gic_overlay_locations: 1; +#else + u64 reservedbit3: 1; +#endif + u64 assignable_synthetic_proc_features: 1; + u64 reserved0: HV_PARTITION_VMM_CAPABILITIES_RESERVED_BITFIELD_COUNT; + } __packed; + }; +} __packed; + enum hv_snp_status { HV_SNP_STATUS_NONE = 0, HV_SNP_STATUS_AVAILABLE = 1, From fd612d97a458f0c44d1395e2def4fa719ec2ea48 Mon Sep 17 00:00:00 2001 From: Purna Pavan Chandra Aekkaladevi Date: Fri, 10 Oct 2025 14:55:49 -0700 Subject: [PATCH 349/684] mshv: Get the vmm capabilities offered by the hypervisor Some hypervisor APIs are gated by feature bits in the "vmm capabilities" partition property. Store the capabilities on mshv_root module init, using HVCALL_GET_PARTITION_PROPERTY_EX. This is not supported on all hypervisors. In that case, just set the capabilities to 0 and proceed as normal. Signed-off-by: Purna Pavan Chandra Aekkaladevi Signed-off-by: Nuno Das Neves Reviewed-by: Praveen K Paladugu Reviewed-by: Easwar Hariharan Reviewed-by: Tianyu Lan Signed-off-by: Wei Liu --- drivers/hv/mshv_root.h | 1 + drivers/hv/mshv_root_main.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 0e62badfc9f19d..f47d36d0c9427c 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -178,6 +178,7 @@ struct mshv_root { struct hv_synic_pages __percpu *synic_pages; spinlock_t pt_ht_lock; DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); + struct hv_partition_property_vmm_capabilities vmm_caps; }; /* diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index f1fabf52c8f5e5..33160f6ac02871 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -2203,6 +2203,22 @@ static int __init mshv_root_partition_init(struct device *dev) return err; } +static void mshv_init_vmm_caps(struct device *dev) +{ + /* + * This can only fail here if HVCALL_GET_PARTITION_PROPERTY_EX or + * HV_PARTITION_PROPERTY_VMM_CAPABILITIES are not supported. In that + * case it's valid to proceed as if all vmm_caps are disabled (zero). + */ + if (hv_call_get_partition_property_ex(HV_PARTITION_ID_SELF, + HV_PARTITION_PROPERTY_VMM_CAPABILITIES, + 0, &mshv_root.vmm_caps, + sizeof(mshv_root.vmm_caps))) + dev_warn(dev, "Unable to get VMM capabilities\n"); + + dev_dbg(dev, "vmm_caps = %#llx\n", mshv_root.vmm_caps.as_uint64[0]); +} + static int __init mshv_parent_partition_init(void) { int ret; @@ -2255,6 +2271,8 @@ static int __init mshv_parent_partition_init(void) if (ret) goto remove_cpu_state; + mshv_init_vmm_caps(dev); + ret = mshv_irqfd_wq_init(); if (ret) goto exit_partition; From 19c515c27cee3bbba7e70a4d84f4b7e4d8d1cd7e Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Fri, 10 Oct 2025 14:55:50 -0700 Subject: [PATCH 350/684] mshv: Allocate vp state page for HVCALL_MAP_VP_STATE_PAGE on L1VH Introduce mshv_use_overlay_gpfn() to check if a page needs to be allocated and passed to the hypervisor to map VP state pages. This is only needed on L1VH, and only on some (newer) versions of the hypervisor, hence the need to check vmm_capabilities. Introduce functions hv_map/unmap_vp_state_page() to handle the allocation and freeing. Signed-off-by: Jinank Jain Signed-off-by: Nuno Das Neves Reviewed-by: Praveen K Paladugu Reviewed-by: Easwar Hariharan Reviewed-by: Stanislav Kinsburskii Reviewed-by: Anirudh Rayabharam Reviewed-by: Tianyu Lan Signed-off-by: Wei Liu --- drivers/hv/mshv_root.h | 11 ++--- drivers/hv/mshv_root_hv_call.c | 64 +++++++++++++++++++++++++--- drivers/hv/mshv_root_main.c | 76 +++++++++++++++++----------------- 3 files changed, 101 insertions(+), 50 deletions(-) diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index f47d36d0c9427c..5b57d894358a85 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -279,11 +279,12 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id, /* Choose between pages and bytes */ struct hv_vp_state_data state_data, u64 page_count, struct page **pages, u32 num_bytes, u8 *bytes); -int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, - union hv_input_vtl input_vtl, - struct page **state_page); -int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, - union hv_input_vtl input_vtl); +int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + union hv_input_vtl input_vtl, + struct page **state_page); +int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + struct page *state_page, + union hv_input_vtl input_vtl); int hv_call_create_port(u64 port_partition_id, union hv_port_id port_id, u64 connection_partition_id, struct hv_port_info *port_info, u8 port_vtl, u8 min_connection_vtl, int node); diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c index 8049e51c45dcdc..6dac9fcc092c43 100644 --- a/drivers/hv/mshv_root_hv_call.c +++ b/drivers/hv/mshv_root_hv_call.c @@ -526,9 +526,9 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id, return ret; } -int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, - union hv_input_vtl input_vtl, - struct page **state_page) +static int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + union hv_input_vtl input_vtl, + struct page **state_page) { struct hv_input_map_vp_state_page *input; struct hv_output_map_vp_state_page *output; @@ -542,12 +542,20 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, input = *this_cpu_ptr(hyperv_pcpu_input_arg); output = *this_cpu_ptr(hyperv_pcpu_output_arg); + memset(input, 0, sizeof(*input)); input->partition_id = partition_id; input->vp_index = vp_index; input->type = type; input->input_vtl = input_vtl; - status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input, output); + if (*state_page) { + input->flags.map_location_provided = 1; + input->requested_map_location = + page_to_pfn(*state_page); + } + + status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input, + output); if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { if (hv_result_success(status)) @@ -565,8 +573,41 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, return ret; } -int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, - union hv_input_vtl input_vtl) +static bool mshv_use_overlay_gpfn(void) +{ + return hv_l1vh_partition() && + mshv_root.vmm_caps.vmm_can_provide_overlay_gpfn; +} + +int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + union hv_input_vtl input_vtl, + struct page **state_page) +{ + int ret = 0; + struct page *allocated_page = NULL; + + if (mshv_use_overlay_gpfn()) { + allocated_page = alloc_page(GFP_KERNEL); + if (!allocated_page) + return -ENOMEM; + *state_page = allocated_page; + } else { + *state_page = NULL; + } + + ret = hv_call_map_vp_state_page(partition_id, vp_index, type, input_vtl, + state_page); + + if (ret && allocated_page) { + __free_page(allocated_page); + *state_page = NULL; + } + + return ret; +} + +static int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + union hv_input_vtl input_vtl) { unsigned long flags; u64 status; @@ -590,6 +631,17 @@ int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, return hv_result_to_errno(status); } +int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, + struct page *state_page, union hv_input_vtl input_vtl) +{ + int ret = hv_call_unmap_vp_state_page(partition_id, vp_index, type, input_vtl); + + if (mshv_use_overlay_gpfn() && state_page) + __free_page(state_page); + + return ret; +} + int hv_call_get_partition_property_ex(u64 partition_id, u64 property_code, u64 arg, void *property_value, size_t property_value_sz) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 33160f6ac02871..288695a859f73e 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -892,7 +892,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, { struct mshv_create_vp args; struct mshv_vp *vp; - struct page *intercept_message_page, *register_page, *ghcb_page; + struct page *intercept_msg_page, *register_page, *ghcb_page; void *stats_pages[2]; long ret; @@ -910,28 +910,25 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, if (ret) return ret; - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, - input_vtl_zero, - &intercept_message_page); + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, + input_vtl_zero, &intercept_msg_page); if (ret) goto destroy_vp; if (!mshv_partition_encrypted(partition)) { - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_REGISTERS, - input_vtl_zero, - ®ister_page); + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_REGISTERS, + input_vtl_zero, ®ister_page); if (ret) goto unmap_intercept_message_page; } if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) { - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_GHCB, - input_vtl_normal, - &ghcb_page); + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_GHCB, + input_vtl_normal, &ghcb_page); if (ret) goto unmap_register_page; } @@ -962,7 +959,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, atomic64_set(&vp->run.vp_signaled_count, 0); vp->vp_index = args.vp_index; - vp->vp_intercept_msg_page = page_to_virt(intercept_message_page); + vp->vp_intercept_msg_page = page_to_virt(intercept_msg_page); if (!mshv_partition_encrypted(partition)) vp->vp_register_page = page_to_virt(register_page); @@ -995,21 +992,19 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) mshv_vp_stats_unmap(partition->pt_id, args.vp_index); unmap_ghcb_page: - if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) { - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_GHCB, - input_vtl_normal); - } + if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) + hv_unmap_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_GHCB, ghcb_page, + input_vtl_normal); unmap_register_page: - if (!mshv_partition_encrypted(partition)) { - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_REGISTERS, - input_vtl_zero); - } + if (!mshv_partition_encrypted(partition)) + hv_unmap_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_REGISTERS, + register_page, input_vtl_zero); unmap_intercept_message_page: - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index, - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, - input_vtl_zero); + hv_unmap_vp_state_page(partition->pt_id, args.vp_index, + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, + intercept_msg_page, input_vtl_zero); destroy_vp: hv_call_delete_vp(partition->pt_id, args.vp_index); return ret; @@ -1750,24 +1745,27 @@ static void destroy_partition(struct mshv_partition *partition) mshv_vp_stats_unmap(partition->pt_id, vp->vp_index); if (vp->vp_register_page) { - (void)hv_call_unmap_vp_state_page(partition->pt_id, - vp->vp_index, - HV_VP_STATE_PAGE_REGISTERS, - input_vtl_zero); + (void)hv_unmap_vp_state_page(partition->pt_id, + vp->vp_index, + HV_VP_STATE_PAGE_REGISTERS, + virt_to_page(vp->vp_register_page), + input_vtl_zero); vp->vp_register_page = NULL; } - (void)hv_call_unmap_vp_state_page(partition->pt_id, - vp->vp_index, - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, - input_vtl_zero); + (void)hv_unmap_vp_state_page(partition->pt_id, + vp->vp_index, + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE, + virt_to_page(vp->vp_intercept_msg_page), + input_vtl_zero); vp->vp_intercept_msg_page = NULL; if (vp->vp_ghcb_page) { - (void)hv_call_unmap_vp_state_page(partition->pt_id, - vp->vp_index, - HV_VP_STATE_PAGE_GHCB, - input_vtl_normal); + (void)hv_unmap_vp_state_page(partition->pt_id, + vp->vp_index, + HV_VP_STATE_PAGE_GHCB, + virt_to_page(vp->vp_ghcb_page), + input_vtl_normal); vp->vp_ghcb_page = NULL; } From d62313bdf5961b5f815f0b212f029cf146a8a804 Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Fri, 10 Oct 2025 14:55:51 -0700 Subject: [PATCH 351/684] mshv: Introduce new hypercall to map stats page for L1VH partitions Introduce HVCALL_MAP_STATS_PAGE2 which provides a map location (GPFN) to map the stats to. This hypercall is required for L1VH partitions, depending on the hypervisor version. This uses the same check as the state page map location; mshv_use_overlay_gpfn(). Add mshv_map_vp_state_page() helpers to use this new hypercall or the old one depending on availability. For unmapping, the original HVCALL_UNMAP_STATS_PAGE works for both cases. Signed-off-by: Jinank Jain Signed-off-by: Nuno Das Neves Reviewed-by: Easwar Hariharan Signed-off-by: Wei Liu --- drivers/hv/mshv_root.h | 10 ++-- drivers/hv/mshv_root_hv_call.c | 95 ++++++++++++++++++++++++++++++++-- drivers/hv/mshv_root_main.c | 22 ++++---- include/hyperv/hvgdk_mini.h | 1 + include/hyperv/hvhdk_mini.h | 7 +++ 5 files changed, 115 insertions(+), 20 deletions(-) diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 5b57d894358a85..3eb815011b46b2 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -297,11 +297,11 @@ int hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id, int hv_call_disconnect_port(u64 connection_partition_id, union hv_connection_id connection_id); int hv_call_notify_port_ring_empty(u32 sint_index); -int hv_call_map_stat_page(enum hv_stats_object_type type, - const union hv_stats_object_identity *identity, - void **addr); -int hv_call_unmap_stat_page(enum hv_stats_object_type type, - const union hv_stats_object_identity *identity); +int hv_map_stats_page(enum hv_stats_object_type type, + const union hv_stats_object_identity *identity, + void **addr); +int hv_unmap_stats_page(enum hv_stats_object_type type, void *page_addr, + const union hv_stats_object_identity *identity); int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages, u64 page_struct_count, u32 host_access, u32 flags, u8 acquire); diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c index 6dac9fcc092c43..caf02cfa49c93a 100644 --- a/drivers/hv/mshv_root_hv_call.c +++ b/drivers/hv/mshv_root_hv_call.c @@ -807,9 +807,51 @@ hv_call_notify_port_ring_empty(u32 sint_index) return hv_result_to_errno(status); } -int hv_call_map_stat_page(enum hv_stats_object_type type, - const union hv_stats_object_identity *identity, - void **addr) +static int hv_call_map_stats_page2(enum hv_stats_object_type type, + const union hv_stats_object_identity *identity, + u64 map_location) +{ + unsigned long flags; + struct hv_input_map_stats_page2 *input; + u64 status; + int ret; + + if (!map_location || !mshv_use_overlay_gpfn()) + return -EINVAL; + + do { + local_irq_save(flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + + memset(input, 0, sizeof(*input)); + input->type = type; + input->identity = *identity; + input->map_location = map_location; + + status = hv_do_hypercall(HVCALL_MAP_STATS_PAGE2, input, NULL); + + local_irq_restore(flags); + + ret = hv_result_to_errno(status); + + if (!ret) + break; + + if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { + hv_status_debug(status, "\n"); + break; + } + + ret = hv_call_deposit_pages(NUMA_NO_NODE, + hv_current_partition_id, 1); + } while (!ret); + + return ret; +} + +static int hv_call_map_stats_page(enum hv_stats_object_type type, + const union hv_stats_object_identity *identity, + void **addr) { unsigned long flags; struct hv_input_map_stats_page *input; @@ -848,8 +890,38 @@ int hv_call_map_stat_page(enum hv_stats_object_type type, return ret; } -int hv_call_unmap_stat_page(enum hv_stats_object_type type, - const union hv_stats_object_identity *identity) +int hv_map_stats_page(enum hv_stats_object_type type, + const union hv_stats_object_identity *identity, + void **addr) +{ + int ret; + struct page *allocated_page = NULL; + + if (!addr) + return -EINVAL; + + if (mshv_use_overlay_gpfn()) { + allocated_page = alloc_page(GFP_KERNEL); + if (!allocated_page) + return -ENOMEM; + + ret = hv_call_map_stats_page2(type, identity, + page_to_pfn(allocated_page)); + *addr = page_address(allocated_page); + } else { + ret = hv_call_map_stats_page(type, identity, addr); + } + + if (ret && allocated_page) { + __free_page(allocated_page); + *addr = NULL; + } + + return ret; +} + +static int hv_call_unmap_stats_page(enum hv_stats_object_type type, + const union hv_stats_object_identity *identity) { unsigned long flags; struct hv_input_unmap_stats_page *input; @@ -868,6 +940,19 @@ int hv_call_unmap_stat_page(enum hv_stats_object_type type, return hv_result_to_errno(status); } +int hv_unmap_stats_page(enum hv_stats_object_type type, void *page_addr, + const union hv_stats_object_identity *identity) +{ + int ret; + + ret = hv_call_unmap_stats_page(type, identity); + + if (mshv_use_overlay_gpfn() && page_addr) + __free_page(virt_to_page(page_addr)); + + return ret; +} + int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages, u64 page_struct_count, u32 host_access, u32 flags, u8 acquire) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 288695a859f73e..7684645ef00d27 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -843,7 +843,8 @@ mshv_vp_release(struct inode *inode, struct file *filp) return 0; } -static void mshv_vp_stats_unmap(u64 partition_id, u32 vp_index) +static void mshv_vp_stats_unmap(u64 partition_id, u32 vp_index, + void *stats_pages[]) { union hv_stats_object_identity identity = { .vp.partition_id = partition_id, @@ -851,10 +852,10 @@ static void mshv_vp_stats_unmap(u64 partition_id, u32 vp_index) }; identity.vp.stats_area_type = HV_STATS_AREA_SELF; - hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity); + hv_unmap_stats_page(HV_STATS_OBJECT_VP, NULL, &identity); identity.vp.stats_area_type = HV_STATS_AREA_PARENT; - hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity); + hv_unmap_stats_page(HV_STATS_OBJECT_VP, NULL, &identity); } static int mshv_vp_stats_map(u64 partition_id, u32 vp_index, @@ -867,14 +868,14 @@ static int mshv_vp_stats_map(u64 partition_id, u32 vp_index, int err; identity.vp.stats_area_type = HV_STATS_AREA_SELF; - err = hv_call_map_stat_page(HV_STATS_OBJECT_VP, &identity, - &stats_pages[HV_STATS_AREA_SELF]); + err = hv_map_stats_page(HV_STATS_OBJECT_VP, &identity, + &stats_pages[HV_STATS_AREA_SELF]); if (err) return err; identity.vp.stats_area_type = HV_STATS_AREA_PARENT; - err = hv_call_map_stat_page(HV_STATS_OBJECT_VP, &identity, - &stats_pages[HV_STATS_AREA_PARENT]); + err = hv_map_stats_page(HV_STATS_OBJECT_VP, &identity, + &stats_pages[HV_STATS_AREA_PARENT]); if (err) goto unmap_self; @@ -882,7 +883,7 @@ static int mshv_vp_stats_map(u64 partition_id, u32 vp_index, unmap_self: identity.vp.stats_area_type = HV_STATS_AREA_SELF; - hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity); + hv_unmap_stats_page(HV_STATS_OBJECT_VP, NULL, &identity); return err; } @@ -990,7 +991,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition, kfree(vp); unmap_stats_pages: if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) - mshv_vp_stats_unmap(partition->pt_id, args.vp_index); + mshv_vp_stats_unmap(partition->pt_id, args.vp_index, stats_pages); unmap_ghcb_page: if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) hv_unmap_vp_state_page(partition->pt_id, args.vp_index, @@ -1742,7 +1743,8 @@ static void destroy_partition(struct mshv_partition *partition) continue; if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) - mshv_vp_stats_unmap(partition->pt_id, vp->vp_index); + mshv_vp_stats_unmap(partition->pt_id, vp->vp_index, + (void **)vp->vp_stats_pages); if (vp->vp_register_page) { (void)hv_unmap_vp_state_page(partition->pt_id, diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index af85b1c36b6e46..f6e31d1c3267f4 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -494,6 +494,7 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_GET_PARTITION_PROPERTY_EX 0x0101 #define HVCALL_MMIO_READ 0x0106 #define HVCALL_MMIO_WRITE 0x0107 +#define HVCALL_MAP_STATS_PAGE2 0x0131 /* HV_HYPERCALL_INPUT */ #define HV_HYPERCALL_RESULT_MASK GENMASK_ULL(15, 0) diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index bf2ce27dfcc5c5..064bf735cab6b9 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -177,6 +177,13 @@ struct hv_input_map_stats_page { union hv_stats_object_identity identity; } __packed; +struct hv_input_map_stats_page2 { + u32 type; /* enum hv_stats_object_type */ + u32 padding; + union hv_stats_object_identity identity; + u64 map_location; +} __packed; + struct hv_output_map_stats_page { u64 map_location; } __packed; From 428ca2d4c6aa4124fb91580e5918f012d32ad4c4 Mon Sep 17 00:00:00 2001 From: Long Li Date: Fri, 17 Oct 2025 14:58:14 -0700 Subject: [PATCH 352/684] MAINTAINERS: Add Long Li as a Hyper-V maintainer Also include MANA RDMA driver in the Hyper-V maintained list. Signed-off-by: Long Li Signed-off-by: Wei Liu --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968e4..da844816d2a01f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11590,6 +11590,7 @@ M: "K. Y. Srinivasan" M: Haiyang Zhang M: Wei Liu M: Dexuan Cui +M: Long Li L: linux-hyperv@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git @@ -11607,6 +11608,7 @@ F: arch/x86/kernel/cpu/mshyperv.c F: drivers/clocksource/hyperv_timer.c F: drivers/hid/hid-hyperv.c F: drivers/hv/ +F: drivers/infiniband/hw/mana/ F: drivers/input/serio/hyperv-keyboard.c F: drivers/iommu/hyperv-iommu.c F: drivers/net/ethernet/microsoft/ @@ -11625,6 +11627,7 @@ F: include/hyperv/hvhdk_mini.h F: include/linux/hyperv.h F: include/net/mana F: include/uapi/linux/hyperv.h +F: include/uapi/rdma/mana-abi.h F: net/vmw_vsock/hyperv_transport.c F: tools/hv/ From 77c3a45a0f4866d4c36246abdf9633d3bde13f9e Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 15 Oct 2025 09:50:14 +0800 Subject: [PATCH 353/684] x86: mshyperv: Remove duplicate asm/msr.h header ./arch/x86/kernel/cpu/mshyperv.c: asm/msr.h is included more than once. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=26164 Signed-off-by: Jiapeng Chong Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 80a641a6ac48b5..6802d89ca7909e 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include From 91a076d30450237181e474396e3128082d0ffe6e Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:03 -0700 Subject: [PATCH 354/684] x86/hyperv: Rename guest crash shutdown function Rename hv_machine_crash_shutdown to more appropriate hv_guest_crash_shutdown and make it applicable to guests only. This in preparation for the subsequent hypervisor root crash support patches. Signed-off-by: Mukesh Rathor Signed-off-by: Wei Liu --- arch/x86/kernel/cpu/mshyperv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 6802d89ca7909e..fac9953a72eff6 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -255,7 +255,7 @@ static void hv_machine_shutdown(void) #endif /* CONFIG_KEXEC_CORE */ #ifdef CONFIG_CRASH_DUMP -static void hv_machine_crash_shutdown(struct pt_regs *regs) +static void hv_guest_crash_shutdown(struct pt_regs *regs) { if (hv_crash_handler) hv_crash_handler(regs); @@ -625,7 +625,8 @@ static void __init ms_hyperv_init_platform(void) machine_ops.shutdown = hv_machine_shutdown; #endif #if defined(CONFIG_CRASH_DUMP) - machine_ops.crash_shutdown = hv_machine_crash_shutdown; + if (!hv_root_partition()) + machine_ops.crash_shutdown = hv_guest_crash_shutdown; #endif #endif /* From 56c3feb3cc17b764f51191fd3dc461ab55a7b803 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:04 -0700 Subject: [PATCH 355/684] hyperv: Add two new hypercall numbers to guest ABI public header In preparation for the subsequent crashdump patches, copy two hypercall numbers to the guest ABI header published by Hyper-V. One to notify hypervisor of an event that occurs in the root partition, other to ask hypervisor to disable the hypervisor. Signed-off-by: Mukesh Rathor Signed-off-by: Wei Liu --- include/hyperv/hvgdk_mini.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index f6e31d1c3267f4..7499a679e60ac2 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -470,6 +470,7 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_MAP_DEVICE_INTERRUPT 0x007c #define HVCALL_UNMAP_DEVICE_INTERRUPT 0x007d #define HVCALL_RETARGET_INTERRUPT 0x007e +#define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b #define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 @@ -494,6 +495,7 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_GET_PARTITION_PROPERTY_EX 0x0101 #define HVCALL_MMIO_READ 0x0106 #define HVCALL_MMIO_WRITE 0x0107 +#define HVCALL_DISABLE_HYP_EX 0x010f #define HVCALL_MAP_STATS_PAGE2 0x0131 /* HV_HYPERCALL_INPUT */ From e0a975ecd2e671664d208723476eeabb3baf08be Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:05 -0700 Subject: [PATCH 356/684] hyperv: Add definitions for hypervisor crash dump support Add data structures for hypervisor crash dump support to the hypervisor host ABI header file. Details of their usages are in subsequent commits. Signed-off-by: Mukesh Rathor Signed-off-by: Wei Liu --- include/hyperv/hvhdk_mini.h | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index 064bf735cab6b9..f2d7b50de7a42c 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -142,6 +142,17 @@ enum hv_system_property { /* Add more values when needed */ HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15, HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21, + HV_SYSTEM_PROPERTY_CRASHDUMPAREA = 47, +}; + +#define HV_PFN_RANGE_PGBITS 24 /* HV_SPA_PAGE_RANGE_ADDITIONAL_PAGES_BITS */ +union hv_pfn_range { /* HV_SPA_PAGE_RANGE */ + u64 as_uint64; + struct { + /* 39:0: base pfn. 63:40: additional pages */ + u64 base_pfn : 64 - HV_PFN_RANGE_PGBITS; + u64 add_pfns : HV_PFN_RANGE_PGBITS; + } __packed; }; enum hv_dynamic_processor_feature_property { @@ -168,6 +179,8 @@ struct hv_output_get_system_property { #if IS_ENABLED(CONFIG_X86) u64 hv_processor_feature_value; #endif + union hv_pfn_range hv_cda_info; /* CrashdumpAreaAddress */ + u64 hv_tramp_pa; /* CrashdumpTrampolineAddress */ }; } __packed; @@ -267,6 +280,48 @@ union hv_gpa_page_access_state { u8 as_uint8; } __packed; +enum hv_crashdump_action { + HV_CRASHDUMP_NONE = 0, + HV_CRASHDUMP_SUSPEND_ALL_VPS, + HV_CRASHDUMP_PREPARE_FOR_STATE_SAVE, + HV_CRASHDUMP_STATE_SAVED, + HV_CRASHDUMP_ENTRY, +}; + +struct hv_partition_event_root_crashdump_input { + u32 crashdump_action; /* enum hv_crashdump_action */ +} __packed; + +struct hv_input_disable_hyp_ex { /* HV_X64_INPUT_DISABLE_HYPERVISOR_EX */ + u64 rip; + u64 arg; +} __packed; + +struct hv_crashdump_area { /* HV_CRASHDUMP_AREA */ + u32 version; + union { + u32 flags_as_uint32; + struct { + u32 cda_valid : 1; + u32 cda_unused : 31; + } __packed; + }; + /* more unused fields */ +} __packed; + +union hv_partition_event_input { + struct hv_partition_event_root_crashdump_input crashdump_input; +}; + +enum hv_partition_event { + HV_PARTITION_EVENT_ROOT_CRASHDUMP = 2, +}; + +struct hv_input_notify_partition_event { + u32 event; /* enum hv_partition_event */ + union hv_partition_event_input input; +} __packed; + struct hv_lp_startup_status { u64 hv_status; u64 substatus1; From b0574ba75525c6b7e7448dd755d5cc09391478b1 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:06 -0700 Subject: [PATCH 357/684] x86/hyperv: Add trampoline asm code to transition from hypervisor Introduce a small asm stub to transition from the hypervisor to Linux after devirtualization. Devirtualization means disabling hypervisor on the fly, so after it is done, the code is running on physical processor instead of virtual, and hypervisor is gone. This can be done by a root vm only. At a high level, during panic of either the hypervisor or the root, the NMI handler asks hypervisor to devirtualize. As part of that, the arguments include an entry point to return back to Linux. This asm stub implements that entry point. The stub is entered in protected mode, uses temporary gdt and page table to enable long mode and get to kernel entry point which then restores full kernel context to resume execution to kexec. Signed-off-by: Mukesh Rathor Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_trampoline.S | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 arch/x86/hyperv/hv_trampoline.S diff --git a/arch/x86/hyperv/hv_trampoline.S b/arch/x86/hyperv/hv_trampoline.S new file mode 100644 index 00000000000000..25f02ff1228620 --- /dev/null +++ b/arch/x86/hyperv/hv_trampoline.S @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * X86 specific Hyper-V kdump/crash related code. + * + * Copyright (C) 2025, Microsoft, Inc. + * + */ +#include +#include +#include +#include +#include + +/* + * void noreturn hv_crash_asm32(arg1) + * arg1 == edi == 32bit PA of struct hv_crash_tramp_data + * + * The hypervisor jumps here upon devirtualization in protected mode. This + * code gets copied to a page in the low 4G ie, 32bit space so it can run + * in the protected mode. Hence we cannot use any compile/link time offsets or + * addresses. It restores long mode via temporary gdt and page tables and + * eventually jumps to kernel code entry at HV_CRASHDATA_OFFS_C_entry. + * + * PreCondition (ie, Hypervisor call back ABI): + * o CR0 is set to 0x0021: PE(prot mode) and NE are set, paging is disabled + * o CR4 is set to 0x0 + * o IA32_EFER is set to 0x901 (SCE and NXE are set) + * o EDI is set to the Arg passed to HVCALL_DISABLE_HYP_EX. + * o CS, DS, ES, FS, GS are all initialized with a base of 0 and limit 0xFFFF + * o IDTR, TR and GDTR are initialized with a base of 0 and limit of 0xFFFF + * o LDTR is initialized as invalid (limit of 0) + * o MSR PAT is power on default. + * o Other state/registers are cleared. All TLBs flushed. + */ + +#define HV_CRASHDATA_OFFS_TRAMPCR3 0x0 /* 0 */ +#define HV_CRASHDATA_OFFS_KERNCR3 0x8 /* 8 */ +#define HV_CRASHDATA_OFFS_GDTRLIMIT 0x12 /* 18 */ +#define HV_CRASHDATA_OFFS_CS_JMPTGT 0x28 /* 40 */ +#define HV_CRASHDATA_OFFS_C_entry 0x30 /* 48 */ + + .text + .code32 + +SYM_CODE_START(hv_crash_asm32) + UNWIND_HINT_UNDEFINED + ENDBR + movl $X86_CR4_PAE, %ecx + movl %ecx, %cr4 + + movl %edi, %ebx + add $HV_CRASHDATA_OFFS_TRAMPCR3, %ebx + movl %cs:(%ebx), %eax + movl %eax, %cr3 + + /* Setup EFER for long mode now */ + movl $MSR_EFER, %ecx + rdmsr + btsl $_EFER_LME, %eax + wrmsr + + /* Turn paging on using the temp 32bit trampoline page table */ + movl %cr0, %eax + orl $(X86_CR0_PG), %eax + movl %eax, %cr0 + + /* since kernel cr3 could be above 4G, we need to be in the long mode + * before we can load 64bits of the kernel cr3. We use a temp gdt for + * that with CS.L=1 and CS.D=0 */ + mov %edi, %eax + add $HV_CRASHDATA_OFFS_GDTRLIMIT, %eax + lgdtl %cs:(%eax) + + /* not done yet, restore CS now to switch to CS.L=1 */ + mov %edi, %eax + add $HV_CRASHDATA_OFFS_CS_JMPTGT, %eax + ljmp %cs:*(%eax) +SYM_CODE_END(hv_crash_asm32) + + /* we now run in full 64bit IA32-e long mode, CS.L=1 and CS.D=0 */ + .code64 + .balign 8 +SYM_CODE_START(hv_crash_asm64) + UNWIND_HINT_UNDEFINED + ENDBR + /* restore kernel page tables so we can jump to kernel code */ + mov %edi, %eax + add $HV_CRASHDATA_OFFS_KERNCR3, %eax + movq %cs:(%eax), %rbx + movq %rbx, %cr3 + + mov %edi, %eax + add $HV_CRASHDATA_OFFS_C_entry, %eax + movq %cs:(%eax), %rbx + ANNOTATE_RETPOLINE_SAFE + jmp *%rbx + + int $3 + +SYM_INNER_LABEL(hv_crash_asm_end, SYM_L_GLOBAL) +SYM_CODE_END(hv_crash_asm64) From 94212d34618c2608758128da32ddac2ad834cb9f Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:07 -0700 Subject: [PATCH 358/684] x86/hyperv: Implement hypervisor RAM collection into vmcore Introduce a new file to implement collection of hypervisor RAM into the vmcore collected by linux. By default, the hypervisor RAM is locked, ie, protected via hw page table. Hyper-V implements a disable hypercall which essentially devirtualizes the system on the fly. This mechanism makes the hypervisor RAM accessible to linux. Because the hypervisor RAM is already mapped into linux address space (as reserved RAM), it is automatically collected into the vmcore without extra work. More details of the implementation are available in the file prologue. Signed-off-by: Mukesh Rathor Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_crash.c | 642 +++++++++++++++++++++++++++++++++++++ 1 file changed, 642 insertions(+) create mode 100644 arch/x86/hyperv/hv_crash.c diff --git a/arch/x86/hyperv/hv_crash.c b/arch/x86/hyperv/hv_crash.c new file mode 100644 index 00000000000000..c0e22921ace1a4 --- /dev/null +++ b/arch/x86/hyperv/hv_crash.c @@ -0,0 +1,642 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * X86 specific Hyper-V root partition kdump/crash support module + * + * Copyright (C) 2025, Microsoft, Inc. + * + * This module implements hypervisor RAM collection into vmcore for both + * cases of the hypervisor crash and Linux root crash. Hyper-V implements + * a disable hypercall with a 32bit protected mode ABI callback. This + * mechanism must be used to unlock hypervisor RAM. Since the hypervisor RAM + * is already mapped in Linux, it is automatically collected into Linux vmcore, + * and can be examined by the crash command (raw RAM dump) or windbg. + * + * At a high level: + * + * Hypervisor Crash: + * Upon crash, hypervisor goes into an emergency minimal dispatch loop, a + * restrictive mode with very limited hypercall and MSR support. Each cpu + * then injects NMIs into root vcpus. A shared page is used to check + * by Linux in the NMI handler if the hypervisor has crashed. This shared + * page is setup in hv_root_crash_init during boot. + * + * Linux Crash: + * In case of Linux crash, the callback hv_crash_stop_other_cpus will send + * NMIs to all cpus, then proceed to the crash_nmi_callback where it waits + * for all cpus to be in NMI. + * + * NMI Handler (upon quorum): + * Eventually, in both cases, all cpus will end up in the NMI handler. + * Hyper-V requires the disable hypervisor must be done from the BSP. So + * the BSP NMI handler saves current context, does some fixups and makes + * the hypercall to disable the hypervisor, ie, devirtualize. Hypervisor + * at that point will suspend all vcpus (except the BSP), unlock all its + * RAM, and return to Linux at the 32bit mode entry RIP. + * + * Linux 32bit entry trampoline will then restore long mode and call C + * function here to restore context and continue execution to crash kexec. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool hv_crash_enabled; +EXPORT_SYMBOL_GPL(hv_crash_enabled); + +struct hv_crash_ctxt { + ulong rsp; + ulong cr0; + ulong cr2; + ulong cr4; + ulong cr8; + + u16 cs; + u16 ss; + u16 ds; + u16 es; + u16 fs; + u16 gs; + + u16 gdt_fill; + struct desc_ptr gdtr; + char idt_fill[6]; + struct desc_ptr idtr; + + u64 gsbase; + u64 efer; + u64 pat; +}; +static struct hv_crash_ctxt hv_crash_ctxt; + +/* Shared hypervisor page that contains crash dump area we peek into. + * NB: windbg looks for "hv_cda" symbol so don't change it. + */ +static struct hv_crashdump_area *hv_cda; + +static u32 trampoline_pa, devirt_arg; +static atomic_t crash_cpus_wait; +static void *hv_crash_ptpgs[4]; +static bool hv_has_crashed, lx_has_crashed; + +static void __noreturn hv_panic_timeout_reboot(void) +{ + #define PANIC_TIMER_STEP 100 + + if (panic_timeout > 0) { + int i; + + for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) + mdelay(PANIC_TIMER_STEP); + } + + if (panic_timeout) + native_wrmsrq(HV_X64_MSR_RESET, 1); /* get hyp to reboot */ + + for (;;) + cpu_relax(); +} + +/* This cannot be inlined as it needs stack */ +static noinline __noclone void hv_crash_restore_tss(void) +{ + load_TR_desc(); +} + +/* This cannot be inlined as it needs stack */ +static noinline void hv_crash_clear_kernpt(void) +{ + pgd_t *pgd; + p4d_t *p4d; + + /* Clear entry so it's not confusing to someone looking at the core */ + pgd = pgd_offset_k(trampoline_pa); + p4d = p4d_offset(pgd, trampoline_pa); + native_p4d_clear(p4d); +} + +/* + * This is the C entry point from the asm glue code after the disable hypercall. + * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel + * page tables with our below 4G page identity mapped, but using a temporary + * GDT. ds/fs/gs/es are null. ss is not usable. bp is null. stack is not + * available. We restore kernel GDT, and rest of the context, and continue + * to kexec. + */ +static asmlinkage void __noreturn hv_crash_c_entry(void) +{ + struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; + + /* first thing, restore kernel gdt */ + native_load_gdt(&ctxt->gdtr); + + asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss)); + asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp)); + + asm volatile("movw %%ax, %%ds" : : "a"(ctxt->ds)); + asm volatile("movw %%ax, %%es" : : "a"(ctxt->es)); + asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs)); + asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs)); + + native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat); + asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0)); + + asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8)); + asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4)); + asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4)); + + native_load_idt(&ctxt->idtr); + native_wrmsrq(MSR_GS_BASE, ctxt->gsbase); + native_wrmsrq(MSR_EFER, ctxt->efer); + + /* restore the original kernel CS now via far return */ + asm volatile("movzwq %0, %%rax\n\t" + "pushq %%rax\n\t" + "pushq $1f\n\t" + "lretq\n\t" + "1:nop\n\t" : : "m"(ctxt->cs) : "rax"); + + /* We are in asmlinkage without stack frame, hence make C function + * calls which will buy stack frames. + */ + hv_crash_restore_tss(); + hv_crash_clear_kernpt(); + + /* we are now fully in devirtualized normal kernel mode */ + __crash_kexec(NULL); + + hv_panic_timeout_reboot(); +} +/* Tell gcc we are using lretq long jump in the above function intentionally */ +STACK_FRAME_NON_STANDARD(hv_crash_c_entry); + +static void hv_mark_tss_not_busy(void) +{ + struct desc_struct *desc = get_current_gdt_rw(); + tss_desc tss; + + memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc)); + tss.type = 0x9; /* available 64-bit TSS. 0xB is busy TSS */ + write_gdt_entry(desc, GDT_ENTRY_TSS, &tss, DESC_TSS); +} + +/* Save essential context */ +static void hv_hvcrash_ctxt_save(void) +{ + struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; + + asm volatile("movq %%rsp,%0" : "=m"(ctxt->rsp)); + + ctxt->cr0 = native_read_cr0(); + ctxt->cr4 = native_read_cr4(); + + asm volatile("movq %%cr2, %0" : "=a"(ctxt->cr2)); + asm volatile("movq %%cr8, %0" : "=a"(ctxt->cr8)); + + asm volatile("movl %%cs, %%eax" : "=a"(ctxt->cs)); + asm volatile("movl %%ss, %%eax" : "=a"(ctxt->ss)); + asm volatile("movl %%ds, %%eax" : "=a"(ctxt->ds)); + asm volatile("movl %%es, %%eax" : "=a"(ctxt->es)); + asm volatile("movl %%fs, %%eax" : "=a"(ctxt->fs)); + asm volatile("movl %%gs, %%eax" : "=a"(ctxt->gs)); + + native_store_gdt(&ctxt->gdtr); + store_idt(&ctxt->idtr); + + ctxt->gsbase = __rdmsr(MSR_GS_BASE); + ctxt->efer = __rdmsr(MSR_EFER); + ctxt->pat = __rdmsr(MSR_IA32_CR_PAT); +} + +/* Add trampoline page to the kernel pagetable for transition to kernel PT */ +static void hv_crash_fixup_kernpt(void) +{ + pgd_t *pgd; + p4d_t *p4d; + + pgd = pgd_offset_k(trampoline_pa); + p4d = p4d_offset(pgd, trampoline_pa); + + /* trampoline_pa is below 4G, so no pre-existing entry to clobber */ + p4d_populate(&init_mm, p4d, (pud_t *)hv_crash_ptpgs[1]); + p4d->p4d = p4d->p4d & ~(_PAGE_NX); /* enable execute */ +} + +/* + * Notify the hyp that Linux has crashed. This will cause the hyp to quiesce + * and suspend all guest VPs. + */ +static void hv_notify_prepare_hyp(void) +{ + u64 status; + struct hv_input_notify_partition_event *input; + struct hv_partition_event_root_crashdump_input *cda; + + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + cda = &input->input.crashdump_input; + memset(input, 0, sizeof(*input)); + input->event = HV_PARTITION_EVENT_ROOT_CRASHDUMP; + + cda->crashdump_action = HV_CRASHDUMP_ENTRY; + status = hv_do_hypercall(HVCALL_NOTIFY_PARTITION_EVENT, input, NULL); + if (!hv_result_success(status)) + return; + + cda->crashdump_action = HV_CRASHDUMP_SUSPEND_ALL_VPS; + hv_do_hypercall(HVCALL_NOTIFY_PARTITION_EVENT, input, NULL); +} + +/* + * Common function for all cpus before devirtualization. + * + * Hypervisor crash: all cpus get here in NMI context. + * Linux crash: the panicing cpu gets here at base level, all others in NMI + * context. Note, panicing cpu may not be the BSP. + * + * The function is not inlined so it will show on the stack. It is named so + * because the crash cmd looks for certain well known function names on the + * stack before looking into the cpu saved note in the elf section, and + * that work is currently incomplete. + * + * Notes: + * Hypervisor crash: + * - the hypervisor is in a very restrictive mode at this point and any + * vmexit it cannot handle would result in reboot. So, no mumbo jumbo, + * just get to kexec as quickly as possible. + * + * Devirtualization is supported from the BSP only at present. + */ +static noinline __noclone void crash_nmi_callback(struct pt_regs *regs) +{ + struct hv_input_disable_hyp_ex *input; + u64 status; + int msecs = 1000, ccpu = smp_processor_id(); + + if (ccpu == 0) { + /* crash_save_cpu() will be done in the kexec path */ + cpu_emergency_stop_pt(); /* disable performance trace */ + atomic_inc(&crash_cpus_wait); + } else { + crash_save_cpu(regs, ccpu); + cpu_emergency_stop_pt(); /* disable performance trace */ + atomic_inc(&crash_cpus_wait); + for (;;) + cpu_relax(); + } + + while (atomic_read(&crash_cpus_wait) < num_online_cpus() && msecs--) + mdelay(1); + + stop_nmi(); + if (!hv_has_crashed) + hv_notify_prepare_hyp(); + + if (crashing_cpu == -1) + crashing_cpu = ccpu; /* crash cmd uses this */ + + hv_hvcrash_ctxt_save(); + hv_mark_tss_not_busy(); + hv_crash_fixup_kernpt(); + + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + memset(input, 0, sizeof(*input)); + input->rip = trampoline_pa; + input->arg = devirt_arg; + + status = hv_do_hypercall(HVCALL_DISABLE_HYP_EX, input, NULL); + + hv_panic_timeout_reboot(); +} + + +static DEFINE_SPINLOCK(hv_crash_reboot_lk); + +/* + * Generic NMI callback handler: could be called without any crash also. + * hv crash: hypervisor injects NMI's into all cpus + * lx crash: panicing cpu sends NMI to all but self via crash_stop_other_cpus + */ +static int hv_crash_nmi_local(unsigned int cmd, struct pt_regs *regs) +{ + if (!hv_has_crashed && hv_cda && hv_cda->cda_valid) + hv_has_crashed = true; + + if (!hv_has_crashed && !lx_has_crashed) + return NMI_DONE; /* ignore the NMI */ + + if (hv_has_crashed && !kexec_crash_loaded()) { + if (spin_trylock(&hv_crash_reboot_lk)) + hv_panic_timeout_reboot(); + else + for (;;) + cpu_relax(); + } + + crash_nmi_callback(regs); + + return NMI_DONE; +} + +/* + * hv_crash_stop_other_cpus() == smp_ops.crash_stop_other_cpus + * + * On normal Linux panic, this is called twice: first from panic and then again + * from native_machine_crash_shutdown. + * + * In case of hyperv, 3 ways to get here: + * 1. hv crash (only BSP will get here): + * BSP : NMI callback -> DisableHv -> hv_crash_asm32 -> hv_crash_c_entry + * -> __crash_kexec -> native_machine_crash_shutdown + * -> crash_smp_send_stop -> smp_ops.crash_stop_other_cpus + * Linux panic: + * 2. panic cpu x: panic() -> crash_smp_send_stop + * -> smp_ops.crash_stop_other_cpus + * 3. BSP: native_machine_crash_shutdown -> crash_smp_send_stop + * + * NB: noclone and non standard stack because of call to crash_setup_regs(). + */ +static void __noclone hv_crash_stop_other_cpus(void) +{ + static bool crash_stop_done; + struct pt_regs lregs; + int ccpu = smp_processor_id(); + + if (hv_has_crashed) + return; /* all cpus already in NMI handler path */ + + if (!kexec_crash_loaded()) { + hv_notify_prepare_hyp(); + hv_panic_timeout_reboot(); /* no return */ + } + + /* If the hv crashes also, we could come here again before cpus_stopped + * is set in crash_smp_send_stop(). So use our own check. + */ + if (crash_stop_done) + return; + crash_stop_done = true; + + /* Linux has crashed: hv is healthy, we can IPI safely */ + lx_has_crashed = true; + wmb(); /* NMI handlers look at lx_has_crashed */ + + apic->send_IPI_allbutself(NMI_VECTOR); + + if (crashing_cpu == -1) + crashing_cpu = ccpu; /* crash cmd uses this */ + + /* crash_setup_regs() happens in kexec also, but for the kexec cpu which + * is the BSP. We could be here on non-BSP cpu, collect regs if so. + */ + if (ccpu) + crash_setup_regs(&lregs, NULL); + + crash_nmi_callback(&lregs); +} +STACK_FRAME_NON_STANDARD(hv_crash_stop_other_cpus); + +/* This GDT is accessed in IA32-e compat mode which uses 32bits addresses */ +struct hv_gdtreg_32 { + u16 fill; + u16 limit; + u32 address; +} __packed; + +/* We need a CS with L bit to goto IA32-e long mode from 32bit compat mode */ +struct hv_crash_tramp_gdt { + u64 null; /* index 0, selector 0, null selector */ + u64 cs64; /* index 1, selector 8, cs64 selector */ +} __packed; + +/* No stack, so jump via far ptr in memory to load the 64bit CS */ +struct hv_cs_jmptgt { + u32 address; + u16 csval; + u16 fill; +} __packed; + +/* Linux use only, hypervisor doesn't look at this struct */ +struct hv_crash_tramp_data { + u64 tramp32_cr3; + u64 kernel_cr3; + struct hv_gdtreg_32 gdtr32; + struct hv_crash_tramp_gdt tramp_gdt; + struct hv_cs_jmptgt cs_jmptgt; + u64 c_entry_addr; +} __packed; + +/* + * Setup a temporary gdt to allow the asm code to switch to the long mode. + * Since the asm code is relocated/copied to a below 4G page, it cannot use rip + * relative addressing, hence we must use trampoline_pa here. Also, save other + * info like jmp and C entry targets for same reasons. + * + * Returns: 0 on success, -1 on error + */ +static int hv_crash_setup_trampdata(u64 trampoline_va) +{ + int size, offs; + void *dest; + struct hv_crash_tramp_data *tramp; + + /* These must match exactly the ones in the corresponding asm file */ + BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, tramp32_cr3) != 0); + BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, kernel_cr3) != 8); + BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, gdtr32.limit) != 18); + BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, + cs_jmptgt.address) != 40); + BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, c_entry_addr) != 48); + + /* hv_crash_asm_end is beyond last byte by 1 */ + size = &hv_crash_asm_end - &hv_crash_asm32; + if (size + sizeof(struct hv_crash_tramp_data) > PAGE_SIZE) { + pr_err("%s: trampoline page overflow\n", __func__); + return -1; + } + + dest = (void *)trampoline_va; + memcpy(dest, &hv_crash_asm32, size); + + dest += size; + dest = (void *)round_up((ulong)dest, 16); + tramp = (struct hv_crash_tramp_data *)dest; + + /* see MAX_ASID_AVAILABLE in tlb.c: "PCID 0 is reserved for use by + * non-PCID-aware users". Build cr3 with pcid 0 + */ + tramp->tramp32_cr3 = __sme_pa(hv_crash_ptpgs[0]); + + /* Note, when restoring X86_CR4_PCIDE, cr3[11:0] must be zero */ + tramp->kernel_cr3 = __sme_pa(init_mm.pgd); + + tramp->gdtr32.limit = sizeof(struct hv_crash_tramp_gdt); + tramp->gdtr32.address = trampoline_pa + + (ulong)&tramp->tramp_gdt - trampoline_va; + + /* base:0 limit:0xfffff type:b dpl:0 P:1 L:1 D:0 avl:0 G:1 */ + tramp->tramp_gdt.cs64 = 0x00af9a000000ffff; + + tramp->cs_jmptgt.csval = 0x8; + offs = (ulong)&hv_crash_asm64 - (ulong)&hv_crash_asm32; + tramp->cs_jmptgt.address = trampoline_pa + offs; + + tramp->c_entry_addr = (u64)&hv_crash_c_entry; + + devirt_arg = trampoline_pa + (ulong)dest - trampoline_va; + + return 0; +} + +/* + * Build 32bit trampoline page table for transition from protected mode + * non-paging to long-mode paging. This transition needs pagetables below 4G. + */ +static void hv_crash_build_tramp_pt(void) +{ + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + u64 pa, addr = trampoline_pa; + + p4d = hv_crash_ptpgs[0] + pgd_index(addr) * sizeof(p4d); + pa = virt_to_phys(hv_crash_ptpgs[1]); + set_p4d(p4d, __p4d(_PAGE_TABLE | pa)); + p4d->p4d &= ~(_PAGE_NX); /* enable execute */ + + pud = hv_crash_ptpgs[1] + pud_index(addr) * sizeof(pud); + pa = virt_to_phys(hv_crash_ptpgs[2]); + set_pud(pud, __pud(_PAGE_TABLE | pa)); + + pmd = hv_crash_ptpgs[2] + pmd_index(addr) * sizeof(pmd); + pa = virt_to_phys(hv_crash_ptpgs[3]); + set_pmd(pmd, __pmd(_PAGE_TABLE | pa)); + + pte = hv_crash_ptpgs[3] + pte_index(addr) * sizeof(pte); + set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); +} + +/* + * Setup trampoline for devirtualization: + * - a page below 4G, ie 32bit addr containing asm glue code that hyp jmps to + * in protected mode. + * - 4 pages for a temporary page table that asm code uses to turn paging on + * - a temporary gdt to use in the compat mode. + * + * Returns: 0 on success + */ +static int hv_crash_trampoline_setup(void) +{ + int i, rc, order; + struct page *page; + u64 trampoline_va; + gfp_t flags32 = GFP_KERNEL | GFP_DMA32 | __GFP_ZERO; + + /* page for 32bit trampoline assembly code + hv_crash_tramp_data */ + page = alloc_page(flags32); + if (page == NULL) { + pr_err("%s: failed to alloc asm stub page\n", __func__); + return -1; + } + + trampoline_va = (u64)page_to_virt(page); + trampoline_pa = (u32)page_to_phys(page); + + order = 2; /* alloc 2^2 pages */ + page = alloc_pages(flags32, order); + if (page == NULL) { + pr_err("%s: failed to alloc pt pages\n", __func__); + free_page(trampoline_va); + return -1; + } + + for (i = 0; i < 4; i++, page++) + hv_crash_ptpgs[i] = page_to_virt(page); + + hv_crash_build_tramp_pt(); + + rc = hv_crash_setup_trampdata(trampoline_va); + if (rc) + goto errout; + + return 0; + +errout: + free_page(trampoline_va); + free_pages((ulong)hv_crash_ptpgs[0], order); + + return rc; +} + +/* Setup for kdump kexec to collect hypervisor RAM when running as root */ +void hv_root_crash_init(void) +{ + int rc; + struct hv_input_get_system_property *input; + struct hv_output_get_system_property *output; + unsigned long flags; + u64 status; + union hv_pfn_range cda_info; + + if (pgtable_l5_enabled()) { + pr_err("Hyper-V: crash dump not yet supported on 5level PTs\n"); + return; + } + + rc = register_nmi_handler(NMI_LOCAL, hv_crash_nmi_local, NMI_FLAG_FIRST, + "hv_crash_nmi"); + if (rc) { + pr_err("Hyper-V: failed to register crash nmi handler\n"); + return; + } + + local_irq_save(flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + output = *this_cpu_ptr(hyperv_pcpu_output_arg); + + memset(input, 0, sizeof(*input)); + input->property_id = HV_SYSTEM_PROPERTY_CRASHDUMPAREA; + + status = hv_do_hypercall(HVCALL_GET_SYSTEM_PROPERTY, input, output); + cda_info.as_uint64 = output->hv_cda_info.as_uint64; + local_irq_restore(flags); + + if (!hv_result_success(status)) { + pr_err("Hyper-V: %s: property:%d %s\n", __func__, + input->property_id, hv_result_to_string(status)); + goto err_out; + } + + if (cda_info.base_pfn == 0) { + pr_err("Hyper-V: hypervisor crash dump area pfn is 0\n"); + goto err_out; + } + + hv_cda = phys_to_virt(cda_info.base_pfn << HV_HYP_PAGE_SHIFT); + + rc = hv_crash_trampoline_setup(); + if (rc) + goto err_out; + + smp_ops.crash_stop_other_cpus = hv_crash_stop_other_cpus; + + crash_kexec_post_notifiers = true; + hv_crash_enabled = true; + pr_info("Hyper-V: both linux and hypervisor kdump support enabled\n"); + + return; + +err_out: + unregister_nmi_handler(NMI_LOCAL, "hv_crash_nmi"); + pr_err("Hyper-V: only linux root kdump support enabled\n"); +} From 77c860d2dbb72d1f3c6a2e882a07d19eca399db5 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 6 Oct 2025 15:42:08 -0700 Subject: [PATCH 359/684] x86/hyperv: Enable build of hypervisor crashdump collection files Enable build of the new files introduced in the earlier commits and add call to do the setup during boot. Signed-off-by: Mukesh Rathor [ wei: fix build ] Signed-off-by: Wei Liu --- arch/x86/hyperv/Makefile | 6 ++++++ arch/x86/hyperv/hv_init.c | 1 + arch/x86/include/asm/mshyperv.h | 9 +++++++++ 3 files changed, 16 insertions(+) diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index d55f494f471d48..6f5d97cddd8056 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -5,4 +5,10 @@ obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o ifdef CONFIG_X86_64 obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o + + ifdef CONFIG_MSHV_ROOT + CFLAGS_REMOVE_hv_trampoline.o += -pg + CFLAGS_hv_trampoline.o += -fno-stack-protector + obj-$(CONFIG_CRASH_DUMP) += hv_crash.o hv_trampoline.o + endif endif diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 21ed8963fafd39..e28737ec7054fe 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -554,6 +554,7 @@ void __init hyperv_init(void) memunmap(src); hv_remap_tsc_clocksource(); + hv_root_crash_init(); } else { hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 605abd02158dd6..1342d55c2545ce 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -237,6 +237,15 @@ static __always_inline u64 hv_raw_get_msr(unsigned int reg) } int hv_apicid_to_vp_index(u32 apic_id); +#if IS_ENABLED(CONFIG_MSHV_ROOT) && IS_ENABLED(CONFIG_CRASH_DUMP) +void hv_root_crash_init(void); +void hv_crash_asm32(void); +void hv_crash_asm64(void); +void hv_crash_asm_end(void); +#else /* CONFIG_MSHV_ROOT && CONFIG_CRASH_DUMP */ +static inline void hv_root_crash_init(void) {} +#endif /* CONFIG_MSHV_ROOT && CONFIG_CRASH_DUMP */ + #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline void hyperv_setup_mmu_ops(void) {} From 6626f815a1716259f161a4df8d105c9f0c8cbae9 Mon Sep 17 00:00:00 2001 From: Kriish Sharma Date: Sat, 25 Oct 2025 12:07:07 +0000 Subject: [PATCH 360/684] Drivers: hv: fix missing kernel-doc description for 'size' in request_arr_init() Add missing kernel-doc entry for the @size parameter in request_arr_init(), fixing the following documentation warning reported by the kernel test robot and detected via kernel-doc: Warning: drivers/hv/channel.c:595 function parameter 'size' not described in 'request_arr_init' Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202503021934.wH1BERla-lkp@intel.com Signed-off-by: Kriish Sharma Reviewed-by: Easwar Hariharan Signed-off-by: Wei Liu --- drivers/hv/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 88485d255a4224..6821f225248b19 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(vmbus_establish_gpadl); * keeps track of the next available slot in the array. Initially, each * slot points to the next one (as in a Linked List). The last slot * does not point to anything, so its value is U64_MAX by default. - * @size The size of the array + * @size: The size of the array */ static u64 *request_arr_init(u32 size) { From 5f4b5edcb1a389b16b852fb30dcd435bfb1f8d23 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 8 Oct 2025 22:43:29 +0000 Subject: [PATCH 361/684] Drivers: hv: Resolve ambiguity in hypervisor version log Update the log message in hv_common_init to explicitly state that the reported version is for the Microsoft Hypervisor, not the host OS. Previously, this message was accurate for guests running on Windows hosts, where the host and hypervisor versions matched. With support for Linux hosts running the Hyper-V hypervisor, the host OS and hypervisor versions may differ. This change avoids confusion by making it clear that the version refers to the Microsoft Hypervisor regardless of the host operating system. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/hv_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 4b44da7f23b27e..5f5047f122a9f9 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -315,9 +315,9 @@ int __init hv_common_init(void) int i; union hv_hypervisor_version_info version; - /* Get information about the Hyper-V host version */ + /* Get information about the Microsoft Hypervisor version */ if (!hv_get_hypervisor_version(&version)) - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", + pr_info("Hyper-V: Hypervisor Build %d.%d.%d.%d-%d-%d\n", version.major_version, version.minor_version, version.build_number, version.service_number, version.service_pack, version.service_branch); From 22cb2f06fac9a05455eafa3ef3dc49ed7dedb240 Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Tue, 4 Nov 2025 17:46:18 +0530 Subject: [PATCH 362/684] Drivers: hv: Use kmalloc_array() instead of kmalloc() Documentation/process/deprecated.rst recommends against the use of kmalloc with dynamic size calculations due to the risk of overflow and smaller allocation being made than the caller was expecting. Replace kmalloc() with kmalloc_array() in hv_common.c to make the intended allocation size clearer and avoid potential overflow issues. The number of pages (pgcount) is bounded, so overflow is not a practical concern here. However, using kmalloc_array() better reflects the intent to allocate an array and improves consistency with other allocations. No functional change intended. Signed-off-by: Rahul Kumar Signed-off-by: Wei Liu --- drivers/hv/hv_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 5f5047f122a9f9..0a3ab7efed4681 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -487,7 +487,7 @@ int hv_common_cpu_init(unsigned int cpu) * online and then taken offline */ if (!*inputarg) { - mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); + mem = kmalloc_array(pgcount, HV_HYP_PAGE_SIZE, flags); if (!mem) return -ENOMEM; From 8ec6070fc8aca0fce6327d8b2cb8bd77adb155c9 Mon Sep 17 00:00:00 2001 From: Marco Crivellari Date: Fri, 7 Nov 2025 14:27:12 +0100 Subject: [PATCH 363/684] mshv: add WQ_PERCPU to alloc_workqueue users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently if a user enqueues a work item using schedule_delayed_work() the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to schedule_work() that is using system_wq and queue_work(), that makes use again of WORK_CPU_UNBOUND. This lack of consistency cannot be addressed without refactoring the API. alloc_workqueue() treats all queues as per-CPU by default, while unbound workqueues must opt-in via WQ_UNBOUND. This default is suboptimal: most workloads benefit from unbound queues, allowing the scheduler to place worker threads where they’re needed and reducing noise when CPUs are isolated. This continues the effort to refactor workqueue APIs, which began with the introduction of new workqueues and a new alloc_workqueue flag in: commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") This change adds a new WQ_PERCPU flag to explicitly request alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified. With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND), any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND must now use WQ_PERCPU. Once migration is complete, WQ_UNBOUND can be removed and unbound will become the implicit default. Suggested-by: Tejun Heo Signed-off-by: Marco Crivellari Signed-off-by: Wei Liu --- drivers/hv/mshv_eventfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c index 806674722868b6..2a80af1d610ad8 100644 --- a/drivers/hv/mshv_eventfd.c +++ b/drivers/hv/mshv_eventfd.c @@ -592,7 +592,7 @@ static void mshv_irqfd_release(struct mshv_partition *pt) int mshv_irqfd_wq_init(void) { - irqfd_cleanup_wq = alloc_workqueue("mshv-irqfd-cleanup", 0, 0); + irqfd_cleanup_wq = alloc_workqueue("mshv-irqfd-cleanup", WQ_PERCPU, 0); if (!irqfd_cleanup_wq) return -ENOMEM; From ba9eb9b86d232854e983203dc2fb1ba18e316681 Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Thu, 6 Nov 2025 14:13:30 -0800 Subject: [PATCH 364/684] mshv: Fix create memory region overlap check The current check is incorrect; it only checks if the beginning or end of a region is within an existing region. This doesn't account for userspace specifying a region that begins before and ends after an existing region. Change the logic to a range intersection check against gfns and uaddrs for each region. Remove mshv_partition_region_by_uaddr() as it is no longer used. Fixes: 621191d709b1 ("Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs") Reported-by: Michael Kelley Closes: https://lore.kernel.org/linux-hyperv/SN6PR02MB41575BE0406D3AB22E1D7DB5D4C2A@SN6PR02MB4157.namprd02.prod.outlook.com/ Signed-off-by: Nuno Das Neves Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 7684645ef00d27..a8f3c5f3ce3471 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1174,21 +1174,6 @@ mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn) return NULL; } -static struct mshv_mem_region * -mshv_partition_region_by_uaddr(struct mshv_partition *partition, u64 uaddr) -{ - struct mshv_mem_region *region; - - hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) { - if (uaddr >= region->start_uaddr && - uaddr < region->start_uaddr + - (region->nr_pages << HV_HYP_PAGE_SHIFT)) - return region; - } - - return NULL; -} - /* * NB: caller checks and makes sure mem->size is page aligned * Returns: 0 with regionpp updated on success, or -errno @@ -1198,15 +1183,21 @@ static int mshv_partition_create_region(struct mshv_partition *partition, struct mshv_mem_region **regionpp, bool is_mmio) { - struct mshv_mem_region *region; + struct mshv_mem_region *region, *rg; u64 nr_pages = HVPFN_DOWN(mem->size); /* Reject overlapping regions */ - if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) || - mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) || - mshv_partition_region_by_uaddr(partition, mem->userspace_addr) || - mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1)) + hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) { + u64 rg_size = rg->nr_pages << HV_HYP_PAGE_SHIFT; + + if ((mem->guest_pfn + nr_pages <= rg->start_gfn || + rg->start_gfn + rg->nr_pages <= mem->guest_pfn) && + (mem->userspace_addr + mem->size <= rg->start_uaddr || + rg->start_uaddr + rg_size <= mem->userspace_addr)) + continue; + return -EEXIST; + } region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages); if (!region) From f91bc8f61abf0e1d23108ae9871c60d7612a09b2 Mon Sep 17 00:00:00 2001 From: Magnus Kulke Date: Thu, 6 Nov 2025 14:13:31 -0800 Subject: [PATCH 365/684] mshv: Allow mappings that overlap in uaddr Currently the MSHV driver rejects mappings that would overlap in userspace. Some VMMs require the same memory to be mapped to different parts of the guest's address space, and so working around this restriction is difficult. The hypervisor itself doesn't prohibit mappings that overlap in uaddr, (really in SPA; system physical addresses), so supporting this in the driver doesn't require any extra work: only the checks need to be removed. Since no userspace code until now has been able to overlap regions in userspace, relaxing this constraint can't break any existing code. Signed-off-by: Magnus Kulke Signed-off-by: Nuno Das Neves Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 8 ++------ include/uapi/linux/mshv.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index a8f3c5f3ce3471..3f73c468e9759b 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1188,12 +1188,8 @@ static int mshv_partition_create_region(struct mshv_partition *partition, /* Reject overlapping regions */ hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) { - u64 rg_size = rg->nr_pages << HV_HYP_PAGE_SHIFT; - - if ((mem->guest_pfn + nr_pages <= rg->start_gfn || - rg->start_gfn + rg->nr_pages <= mem->guest_pfn) && - (mem->userspace_addr + mem->size <= rg->start_uaddr || - rg->start_uaddr + rg_size <= mem->userspace_addr)) + if (mem->guest_pfn + nr_pages <= rg->start_gfn || + rg->start_gfn + rg->nr_pages <= mem->guest_pfn) continue; return -EEXIST; diff --git a/include/uapi/linux/mshv.h b/include/uapi/linux/mshv.h index 876bfe4e42276e..374f75e198bc1e 100644 --- a/include/uapi/linux/mshv.h +++ b/include/uapi/linux/mshv.h @@ -89,7 +89,7 @@ enum { * @rsvd: MBZ * * Map or unmap a region of userspace memory to Guest Physical Addresses (GPA). - * Mappings can't overlap in GPA space or userspace. + * Mappings can't overlap in GPA space. * To unmap, these fields must match an existing mapping. */ struct mshv_user_mem_region { From c91fe5f162f278d4aa960d06d2dbc42f9857593a Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Thu, 13 Nov 2025 11:45:33 -0800 Subject: [PATCH 366/684] mshv: Extend create partition ioctl to support cpu features The existing mshv create partition ioctl does not provide a way to specify which cpu features are enabled in the guest. Instead, it attempts to enable all features and those that are not supported are silently disabled by the hypervisor. This was done to reduce unnecessary complexity and is sufficient for many cases. However, new scenarios require fine-grained control over these features. Define a new mshv_create_partition_v2 structure which supports passing the disabled processor and xsave feature bits through to the create partition hypercall directly. Introduce a new flag MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES which enables the new structure. If unset, the original mshv_create_partition struct is used, with the old behavior of enabling all features. Co-developed-by: Jinank Jain Signed-off-by: Jinank Jain Signed-off-by: Muminul Islam Signed-off-by: Nuno Das Neves Reviewed-by: Michael Kelley Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 118 +++++++++++++++++++++++++++++------- include/uapi/linux/mshv.h | 34 +++++++++++ 2 files changed, 131 insertions(+), 21 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 3f73c468e9759b..45c7a5fea1cf5b 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1855,43 +1855,119 @@ add_partition(struct mshv_partition *partition) return 0; } -static long -mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev) +static_assert(MSHV_NUM_CPU_FEATURES_BANKS == + HV_PARTITION_PROCESSOR_FEATURES_BANKS); + +static long mshv_ioctl_process_pt_flags(void __user *user_arg, u64 *pt_flags, + struct hv_partition_creation_properties *cr_props, + union hv_partition_isolation_properties *isol_props) { - struct mshv_create_partition args; - u64 creation_flags; - struct hv_partition_creation_properties creation_properties = {}; - union hv_partition_isolation_properties isolation_properties = {}; - struct mshv_partition *partition; - struct file *file; - int fd; - long ret; + int i; + struct mshv_create_partition_v2 args; + union hv_partition_processor_features *disabled_procs; + union hv_partition_processor_xsave_features *disabled_xsave; - if (copy_from_user(&args, user_arg, sizeof(args))) + /* First, copy v1 struct in case user is on previous versions */ + if (copy_from_user(&args, user_arg, + sizeof(struct mshv_create_partition))) return -EFAULT; if ((args.pt_flags & ~MSHV_PT_FLAGS_MASK) || args.pt_isolation >= MSHV_PT_ISOLATION_COUNT) return -EINVAL; + disabled_procs = &cr_props->disabled_processor_features; + disabled_xsave = &cr_props->disabled_processor_xsave_features; + + /* Check if user provided newer struct with feature fields */ + if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES)) { + if (copy_from_user(&args, user_arg, sizeof(args))) + return -EFAULT; + + /* Re-validate v1 fields after second copy_from_user() */ + if ((args.pt_flags & ~MSHV_PT_FLAGS_MASK) || + args.pt_isolation >= MSHV_PT_ISOLATION_COUNT) + return -EINVAL; + + if (args.pt_num_cpu_fbanks != MSHV_NUM_CPU_FEATURES_BANKS || + mshv_field_nonzero(args, pt_rsvd) || + mshv_field_nonzero(args, pt_rsvd1)) + return -EINVAL; + + /* + * Note this assumes MSHV_NUM_CPU_FEATURES_BANKS will never + * change and equals HV_PARTITION_PROCESSOR_FEATURES_BANKS + * (i.e. 2). + * + * Further banks (index >= 2) will be modifiable as 'early' + * properties via the set partition property hypercall. + */ + for (i = 0; i < HV_PARTITION_PROCESSOR_FEATURES_BANKS; i++) + disabled_procs->as_uint64[i] = args.pt_cpu_fbanks[i]; + +#if IS_ENABLED(CONFIG_X86_64) + disabled_xsave->as_uint64 = args.pt_disabled_xsave; +#else + /* + * In practice this field is ignored on arm64, but safer to + * zero it in case it is ever used. + */ + disabled_xsave->as_uint64 = 0; + + if (mshv_field_nonzero(args, pt_rsvd2)) + return -EINVAL; +#endif + } else { + /* + * v1 behavior: try to enable everything. The hypervisor will + * disable features that are not supported. The banks can be + * queried via the get partition property hypercall. + */ + for (i = 0; i < HV_PARTITION_PROCESSOR_FEATURES_BANKS; i++) + disabled_procs->as_uint64[i] = 0; + + disabled_xsave->as_uint64 = 0; + } + /* Only support EXO partitions */ - creation_flags = HV_PARTITION_CREATION_FLAG_EXO_PARTITION | - HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED; + *pt_flags = HV_PARTITION_CREATION_FLAG_EXO_PARTITION | + HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED; + + if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_LAPIC)) + *pt_flags |= HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED; + if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_X2APIC)) + *pt_flags |= HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE; + if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_GPA_SUPER_PAGES)) + *pt_flags |= HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED; - if (args.pt_flags & BIT(MSHV_PT_BIT_LAPIC)) - creation_flags |= HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED; - if (args.pt_flags & BIT(MSHV_PT_BIT_X2APIC)) - creation_flags |= HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE; - if (args.pt_flags & BIT(MSHV_PT_BIT_GPA_SUPER_PAGES)) - creation_flags |= HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED; + isol_props->as_uint64 = 0; switch (args.pt_isolation) { case MSHV_PT_ISOLATION_NONE: - isolation_properties.isolation_type = - HV_PARTITION_ISOLATION_TYPE_NONE; + isol_props->isolation_type = HV_PARTITION_ISOLATION_TYPE_NONE; break; } + return 0; +} + +static long +mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev) +{ + u64 creation_flags; + struct hv_partition_creation_properties creation_properties; + union hv_partition_isolation_properties isolation_properties; + struct mshv_partition *partition; + struct file *file; + int fd; + long ret; + + ret = mshv_ioctl_process_pt_flags(user_arg, &creation_flags, + &creation_properties, + &isolation_properties); + if (ret) + return ret; + partition = kzalloc(sizeof(*partition), GFP_KERNEL); if (!partition) return -ENOMEM; diff --git a/include/uapi/linux/mshv.h b/include/uapi/linux/mshv.h index 374f75e198bc1e..b645d17cc5314e 100644 --- a/include/uapi/linux/mshv.h +++ b/include/uapi/linux/mshv.h @@ -26,6 +26,7 @@ enum { MSHV_PT_BIT_LAPIC, MSHV_PT_BIT_X2APIC, MSHV_PT_BIT_GPA_SUPER_PAGES, + MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES, MSHV_PT_BIT_COUNT, }; @@ -41,6 +42,8 @@ enum { * @pt_flags: Bitmask of 1 << MSHV_PT_BIT_* * @pt_isolation: MSHV_PT_ISOLATION_* * + * This is the initial/v1 version for backward compatibility. + * * Returns a file descriptor to act as a handle to a guest partition. * At this point the partition is not yet initialized in the hypervisor. * Some operations must be done with the partition in this state, e.g. setting @@ -52,6 +55,37 @@ struct mshv_create_partition { __u64 pt_isolation; }; +#define MSHV_NUM_CPU_FEATURES_BANKS 2 + +/** + * struct mshv_create_partition_v2 + * + * This is extended version of the above initial MSHV_CREATE_PARTITION + * ioctl and allows for following additional parameters: + * + * @pt_num_cpu_fbanks: Must be set to MSHV_NUM_CPU_FEATURES_BANKS. + * @pt_cpu_fbanks: Disabled processor feature banks array. + * @pt_disabled_xsave: Disabled xsave feature bits. + * + * pt_cpu_fbanks and pt_disabled_xsave are passed through as-is to the create + * partition hypercall. + * + * Returns : same as above original mshv_create_partition + */ +struct mshv_create_partition_v2 { + __u64 pt_flags; + __u64 pt_isolation; + __u16 pt_num_cpu_fbanks; + __u8 pt_rsvd[6]; /* MBZ */ + __u64 pt_cpu_fbanks[MSHV_NUM_CPU_FEATURES_BANKS]; + __u64 pt_rsvd1[2]; /* MBZ */ +#if defined(__x86_64__) + __u64 pt_disabled_xsave; +#else + __u64 pt_rsvd2; /* MBZ */ +#endif +} __packed; + /* /dev/mshv */ #define MSHV_CREATE_PARTITION _IOW(MSHV_IOCTL, 0x00, struct mshv_create_partition) From 796ef5a7fe86a8605f2844471ed7baa8e80bace8 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Thu, 13 Nov 2025 04:41:47 +0000 Subject: [PATCH 367/684] static_call: allow using STATIC_CALL_TRAMP_STR() from assembly STATIC_CALL_TRAMP_STR() could not be used from .S files because static_call_types.h was not safe to include in assembly as it pulled in C types/constructs that are unavailable under __ASSEMBLY__. Make the header assembly-friendly by adding __ASSEMBLY__ checks and providing only the minimal definitions needed for assembly, so that it can be safely included by .S code. This enables emitting the static call trampoline symbol name via STATIC_CALL_TRAMP_STR() directly in assembly sources, to be used with 'call' instruction. Also, move a certain definitions out of __ASSEMBLY__ checks in compiler_types.h to meet the dependencies. No functional change for C compilation. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Naman Jain Signed-off-by: Wei Liu --- include/linux/compiler_types.h | 8 ++++---- include/linux/static_call_types.h | 4 ++++ tools/include/linux/static_call_types.h | 4 ++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 59288a2c1ad277..6897d4d5cb28a2 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -11,6 +11,10 @@ #define __has_builtin(x) (0) #endif +/* Indirect macros required for expanded argument pasting, eg. __LINE__. */ +#define ___PASTE(a, b) a##b +#define __PASTE(a, b) ___PASTE(a, b) + #ifndef __ASSEMBLY__ /* @@ -79,10 +83,6 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { } # define __builtin_warning(x, y...) (1) #endif /* __CHECKER__ */ -/* Indirect macros required for expanded argument pasting, eg. __LINE__. */ -#define ___PASTE(a,b) a##b -#define __PASTE(a,b) ___PASTE(a,b) - #ifdef __KERNEL__ /* Attributes */ diff --git a/include/linux/static_call_types.h b/include/linux/static_call_types.h index 5a00b8b2cf9fcc..cfb6ddeb292b6c 100644 --- a/include/linux/static_call_types.h +++ b/include/linux/static_call_types.h @@ -25,6 +25,8 @@ #define STATIC_CALL_SITE_INIT 2UL /* init section */ #define STATIC_CALL_SITE_FLAGS 3UL +#ifndef __ASSEMBLY__ + /* * The static call site table needs to be created by external tooling (objtool * or a compiler plugin). @@ -100,4 +102,6 @@ struct static_call_key { #endif /* CONFIG_HAVE_STATIC_CALL */ +#endif /* __ASSEMBLY__ */ + #endif /* _STATIC_CALL_TYPES_H */ diff --git a/tools/include/linux/static_call_types.h b/tools/include/linux/static_call_types.h index 5a00b8b2cf9fcc..cfb6ddeb292b6c 100644 --- a/tools/include/linux/static_call_types.h +++ b/tools/include/linux/static_call_types.h @@ -25,6 +25,8 @@ #define STATIC_CALL_SITE_INIT 2UL /* init section */ #define STATIC_CALL_SITE_FLAGS 3UL +#ifndef __ASSEMBLY__ + /* * The static call site table needs to be created by external tooling (objtool * or a compiler plugin). @@ -100,4 +102,6 @@ struct static_call_key { #endif /* CONFIG_HAVE_STATIC_CALL */ +#endif /* __ASSEMBLY__ */ + #endif /* _STATIC_CALL_TYPES_H */ From cffe9f58de1eb1a2cefce10c9512162fca3f7c89 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Thu, 13 Nov 2025 04:41:48 +0000 Subject: [PATCH 368/684] Drivers: hv: Export some symbols for mshv_vtl MSHV_VTL driver is going to be introduced, which is supposed to provide interface for Virtual Machine Monitors (VMMs) to control Virtual Trust Level (VTL). Export the symbols needed to make it work (vmbus_isr, hv_context and hv_post_message). Co-developed-by: Roman Kisel Signed-off-by: Roman Kisel Co-developed-by: Saurabh Sengar Signed-off-by: Saurabh Sengar Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202506110544.q0NDMQVc-lkp@intel.com/ Reviewed-by: Michael Kelley Signed-off-by: Naman Jain Signed-off-by: Wei Liu --- drivers/hv/hv.c | 3 +++ drivers/hv/hyperv_vmbus.h | 1 + drivers/hv/vmbus_drv.c | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 936c5f310df6ff..c100f04b35813b 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ /* The one and only */ struct hv_context hv_context; +EXPORT_SYMBOL_FOR_MODULES(hv_context, "mshv_vtl"); /* * hv_init - Main initialization routine. @@ -104,6 +106,7 @@ int hv_post_message(union hv_connection_id connection_id, return hv_result(status); } +EXPORT_SYMBOL_FOR_MODULES(hv_post_message, "mshv_vtl"); static int hv_alloc_page(void **page, bool decrypt, const char *note) { diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index f7fc2630c054d0..b2862e0a317a12 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -33,6 +33,7 @@ */ #define HV_UTIL_NEGO_TIMEOUT 55 +void vmbus_isr(void); /* Definitions for the monitored notification facility */ union hv_monitor_trigger_group { diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0dc4692b411ae5..47fcab38398a4a 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include "hyperv_vmbus.h" @@ -1349,7 +1350,7 @@ static void vmbus_message_sched(struct hv_per_cpu_context *hv_cpu, void *message } } -static void vmbus_isr(void) +void vmbus_isr(void) { struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); @@ -1362,6 +1363,7 @@ static void vmbus_isr(void) add_interrupt_randomness(vmbus_interrupt); } +EXPORT_SYMBOL_FOR_MODULES(vmbus_isr, "mshv_vtl"); static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id) { From 86ce2a29dd9a3564fd7be584c8bb7ced28f7ca02 Mon Sep 17 00:00:00 2001 From: James Clark Date: Fri, 14 Nov 2025 14:06:18 +0000 Subject: [PATCH 369/684] perf script: Fix build by removing unused evsel_script() The evsel_script() function is unused since the linked commit. Fix the build by removing it. Fixes the following compilation error: static inline struct evsel_script *evsel_script(struct evsel *evsel) ^ builtin-script.c:347:36: error: unused function 'evsel_script' [-Werror,-Wunused-function] Fixes: 3622990efaab ("perf script: Change metric format to use json metrics") Signed-off-by: James Clark Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-script.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3ac6b80c460eb7..011962e1ee0f68 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -344,11 +344,6 @@ struct evsel_script { u64 samples; }; -static inline struct evsel_script *evsel_script(struct evsel *evsel) -{ - return (struct evsel_script *)evsel->priv; -} - static struct evsel_script *evsel_script__new(struct evsel *evsel, struct perf_data *data) { struct evsel_script *es = zalloc(sizeof(*es)); From 38367a22abba12b9ecd66536ff62274f0afbcf6f Mon Sep 17 00:00:00 2001 From: liujing Date: Mon, 22 Sep 2025 17:50:57 +0800 Subject: [PATCH 370/684] perf sample: Fix the wrong format specifier In the file tools/perf/util/cs-etm.c, queue_nr is of type unsigned int and should be printed with %u. Signed-off-by: liujing Reviewed-by: Mike Leach Signed-off-by: Namhyung Kim --- tools/perf/util/cs-etm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 62812bef1edfee..25d56e0f1c078f 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -777,7 +777,7 @@ static void cs_etm__packet_dump(const char *pkt_string, void *data) char queue_nr[64]; if (verbose) - snprintf(queue_nr, sizeof(queue_nr), "Qnr:%d; ", etmq->queue_nr); + snprintf(queue_nr, sizeof(queue_nr), "Qnr:%u; ", etmq->queue_nr); else queue_nr[0] = '\0'; From c335b7a960291d5b35221304a0b5bf8ebafced15 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 12 Nov 2025 11:53:08 -0800 Subject: [PATCH 371/684] perf test: Be tolerant of missing json metric none value print_metric_only_json and print_metric_end in stat-display.c may create a metric value of "none" which fails validation as isfloat. Add a helper to properly validate metric numeric values. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/lib/perf_json_output_lint.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/lib/perf_json_output_lint.py b/tools/perf/tests/shell/lib/perf_json_output_lint.py index 1369baaa0361bd..dafbde56cc76fe 100644 --- a/tools/perf/tests/shell/lib/perf_json_output_lint.py +++ b/tools/perf/tests/shell/lib/perf_json_output_lint.py @@ -43,6 +43,9 @@ def isint(num): def is_counter_value(num): return isfloat(num) or num == '' or num == '' +def is_metric_value(num): + return isfloat(num) or num == 'none' + def check_json_output(expected_items): checks = { 'counters': lambda x: isfloat(x), @@ -57,7 +60,7 @@ def check_json_output(expected_items): 'event-runtime': lambda x: isfloat(x), 'interval': lambda x: isfloat(x), 'metric-unit': lambda x: True, - 'metric-value': lambda x: isfloat(x), + 'metric-value': lambda x: is_metric_value(x), 'metric-threshold': lambda x: x in ['unknown', 'good', 'less good', 'nearly bad', 'bad'], 'metricgroup': lambda x: True, 'node': lambda x: True, From d3726d4e5bd70e2c159ecb9feb43d3eaa6d76020 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 12 Nov 2025 11:53:09 -0800 Subject: [PATCH 372/684] perf parse-events: Add debug logging to perf_event If verbose is enabled and parse_event is called, typically by tests, log failures. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 0c0dc20b1c1375..e522082c5a2140 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2236,6 +2236,8 @@ int parse_event(struct evlist *evlist, const char *str) parse_events_error__init(&err); ret = parse_events(evlist, str, &err); + if (ret && verbose > 0) + parse_events_error__print(&err, str); parse_events_error__exit(&err); return ret; } From efee18981aeebc14d6fa06f7556a6df1bd1acf92 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 12 Nov 2025 11:53:10 -0800 Subject: [PATCH 373/684] perf test: Don't fail if user rdpmc returns 0 when disabled In certain hypervisor set ups the value 0 may be returned but this is only erroneous if the user rdpmc isn't disabled. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/mmap-basic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 3c89d300188747..3313c236104ee7 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -322,7 +322,7 @@ static int test_stat_user_read(u64 event, enum user_read_state enabled) } perf_evsel__read(evsel, 0, 0, &counts); - if (counts.val == 0) { + if (rdpmc_supported && counts.val == 0) { pr_err("User space counter reading for PMU %s [Failed read]\n", pmu->name); ret = TEST_FAIL; goto cleanup; From 289815011c91dc6532d3fff7ca1c5f0bea08b474 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 12 Nov 2025 11:53:11 -0800 Subject: [PATCH 374/684] perf stat: Display metric-only for 0 counters 0 counters may occur in hypervisor settings but metric-only output is always expected. This resolves an issue in the "perf stat STD output linter" test. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/util/stat-display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 5ac9854f8c5855..6d02f84c5691a4 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -913,6 +913,9 @@ static bool should_skip_zero_counter(struct perf_stat_config *config, if (verbose == 0 && counter->skippable && !counter->supported) return true; + /* Metric only counts won't be displayed but the metric wants to be computed. */ + if (config->metric_only) + return false; /* * Skip value 0 when enabling --per-thread globally, * otherwise it will have too many 0 output. From af9e8d12b139c92e748eb2956bbef03315ea7516 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:07 -0800 Subject: [PATCH 375/684] libperf cpumap: Reduce allocations and sorting in intersect On hybrid platforms the CPU maps are often disjoint. Rather than copy CPUs and trim, compute the number of common CPUs, if none early exit, otherwise copy in an sorted order. This avoids memory allocation in the disjoint case and avoids a second malloc and useless sort in the previous trim cases. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/lib/perf/cpumap.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c index b20a5280f2b333..7e88417ba84d12 100644 --- a/tools/lib/perf/cpumap.c +++ b/tools/lib/perf/cpumap.c @@ -453,21 +453,33 @@ int perf_cpu_map__merge(struct perf_cpu_map **orig, struct perf_cpu_map *other) struct perf_cpu_map *perf_cpu_map__intersect(struct perf_cpu_map *orig, struct perf_cpu_map *other) { - struct perf_cpu *tmp_cpus; - int tmp_len; int i, j, k; - struct perf_cpu_map *merged = NULL; + struct perf_cpu_map *merged; if (perf_cpu_map__is_subset(other, orig)) return perf_cpu_map__get(orig); if (perf_cpu_map__is_subset(orig, other)) return perf_cpu_map__get(other); - tmp_len = max(__perf_cpu_map__nr(orig), __perf_cpu_map__nr(other)); - tmp_cpus = malloc(tmp_len * sizeof(struct perf_cpu)); - if (!tmp_cpus) + i = j = k = 0; + while (i < __perf_cpu_map__nr(orig) && j < __perf_cpu_map__nr(other)) { + if (__perf_cpu_map__cpu(orig, i).cpu < __perf_cpu_map__cpu(other, j).cpu) + i++; + else if (__perf_cpu_map__cpu(orig, i).cpu > __perf_cpu_map__cpu(other, j).cpu) + j++; + else { /* CPUs match. */ + i++; + j++; + k++; + } + } + if (k == 0) /* Maps are completely disjoint. */ return NULL; + merged = perf_cpu_map__alloc(k); + if (!merged) + return NULL; + /* Entries are added to merged in sorted order, so no need to sort again. */ i = j = k = 0; while (i < __perf_cpu_map__nr(orig) && j < __perf_cpu_map__nr(other)) { if (__perf_cpu_map__cpu(orig, i).cpu < __perf_cpu_map__cpu(other, j).cpu) @@ -476,11 +488,8 @@ struct perf_cpu_map *perf_cpu_map__intersect(struct perf_cpu_map *orig, j++; else { j++; - tmp_cpus[k++] = __perf_cpu_map__cpu(orig, i++); + RC_CHK_ACCESS(merged)->map[k++] = __perf_cpu_map__cpu(orig, i++); } } - if (k) - merged = cpu_map__trim_new(k, tmp_cpus); - free(tmp_cpus); return merged; } From f69d34e8f23db8bca38c82a04ee9cd990777aaa2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:08 -0800 Subject: [PATCH 376/684] perf pmu: perf_cpu_map__new_int to avoid parsing a string Prefer perf_cpu_map__new_int(0) to perf_cpu_map__new("0") as it avoids strings parsing. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/drm_pmu.c | 2 +- tools/perf/util/hwmon_pmu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/drm_pmu.c b/tools/perf/util/drm_pmu.c index b3052266d59937..b48a375e45843d 100644 --- a/tools/perf/util/drm_pmu.c +++ b/tools/perf/util/drm_pmu.c @@ -120,7 +120,7 @@ static struct drm_pmu *add_drm_pmu(struct list_head *pmus, char *line, size_t li return NULL; } - drm->pmu.cpus = perf_cpu_map__new("0"); + drm->pmu.cpus = perf_cpu_map__new_int(0); if (!drm->pmu.cpus) { perf_pmu__delete(&drm->pmu); return NULL; diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index 5c27256a220a51..279d6b1a47f03c 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -376,7 +376,7 @@ struct perf_pmu *hwmon_pmu__new(struct list_head *pmus, const char *hwmon_dir, perf_pmu__delete(&hwm->pmu); return NULL; } - hwm->pmu.cpus = perf_cpu_map__new("0"); + hwm->pmu.cpus = perf_cpu_map__new_int(0); if (!hwm->pmu.cpus) { perf_pmu__delete(&hwm->pmu); return NULL; From bdf96c4ecd69523d97c98e47284caddde20b1df7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:09 -0800 Subject: [PATCH 377/684] perf tool_pmu: Use old_count when computing count values for time events When running in interval mode every third count of a time event isn't showing properly: ``` $ perf stat -e duration_time -a -I 1000 1.001082862 1,002,290,425 duration_time 2.004264262 1,003,183,516 duration_time 3.007381401 duration_time 4.011160141 1,003,705,631 duration_time 5.014515385 1,003,290,110 duration_time 6.018539680 duration_time 7.022065321 1,003,591,720 duration_time ``` The regression came in with a different fix, found through bisection, commit 68cb1567439f ("perf tool_pmu: Fix aggregation on duration_time"). The issue is caused by the enabled and running time of the event matching the old_count's and creating a delta of 0, which is indicative of an error. Fixes: 68cb1567439f ("perf tool_pmu: Fix aggregation on duration_time") Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 16 +++++++++-- tools/perf/util/tool_pmu.c | 59 +++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 095016b2209e92..654f840f7a2f10 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -283,17 +283,27 @@ static int read_single_counter(struct evsel *counter, int cpu_map_idx, int threa if (err && cpu_map_idx == 0 && (evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME || evsel__tool_event(counter) == TOOL_PMU__EVENT_SYSTEM_TIME)) { - u64 val, *start_time; struct perf_counts_values *count = perf_counts(counter->counts, cpu_map_idx, thread); + struct perf_counts_values *old_count = NULL; + u64 val; + + if (counter->prev_raw_counts) + old_count = perf_counts(counter->prev_raw_counts, cpu_map_idx, thread); - start_time = xyarray__entry(counter->start_times, cpu_map_idx, thread); if (evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME) val = ru_stats.ru_utime_usec_stat.mean; else val = ru_stats.ru_stime_usec_stat.mean; - count->ena = count->run = *start_time + val; + count->val = val; + if (old_count) { + count->run = old_count->run + 1; + count->ena = old_count->ena + 1; + } else { + count->run++; + count->ena++; + } return 0; } return err; diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c index a72c665ee6440d..6a9df3dc0e076e 100644 --- a/tools/perf/util/tool_pmu.c +++ b/tools/perf/util/tool_pmu.c @@ -446,16 +446,39 @@ bool tool_pmu__read_event(enum tool_pmu_event ev, } } +static void perf_counts__update(struct perf_counts_values *count, + const struct perf_counts_values *old_count, + bool raw, u64 val) +{ + /* + * The values of enabled and running must make a ratio of 100%. The + * exact values don't matter as long as they are non-zero to avoid + * issues with evsel__count_has_error. + */ + if (old_count) { + count->val = raw ? val : old_count->val + val; + count->run = old_count->run + 1; + count->ena = old_count->ena + 1; + count->lost = old_count->lost; + } else { + count->val = val; + count->run++; + count->ena++; + count->lost = 0; + } +} + int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) { __u64 *start_time, cur_time, delta_start; - u64 val; - int fd, err = 0; + int err = 0; struct perf_counts_values *count, *old_count = NULL; bool adjust = false; enum tool_pmu_event ev = evsel__tool_event(evsel); count = perf_counts(evsel->counts, cpu_map_idx, thread); + if (evsel->prev_raw_counts) + old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread); switch (ev) { case TOOL_PMU__EVENT_HAS_PMEM: @@ -466,12 +489,11 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) case TOOL_PMU__EVENT_NUM_PACKAGES: case TOOL_PMU__EVENT_SLOTS: case TOOL_PMU__EVENT_SMT_ON: - case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: case TOOL_PMU__EVENT_CORE_WIDE: case TOOL_PMU__EVENT_TARGET_CPU: - if (evsel->prev_raw_counts) - old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread); - val = 0; + case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: { + u64 val = 0; + if (cpu_map_idx == 0 && thread == 0) { if (!tool_pmu__read_event(ev, evsel, stat_config.system_wide, @@ -481,16 +503,9 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) val = 0; } } - if (old_count) { - count->val = old_count->val + val; - count->run = old_count->run + 1; - count->ena = old_count->ena + 1; - } else { - count->val = val; - count->run++; - count->ena++; - } + perf_counts__update(count, old_count, /*raw=*/false, val); return 0; + } case TOOL_PMU__EVENT_DURATION_TIME: /* * Pretend duration_time is only on the first CPU and thread, or @@ -506,9 +521,9 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) case TOOL_PMU__EVENT_USER_TIME: case TOOL_PMU__EVENT_SYSTEM_TIME: { bool system = evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME; + int fd = FD(evsel, cpu_map_idx, thread); start_time = xyarray__entry(evsel->start_times, cpu_map_idx, thread); - fd = FD(evsel, cpu_map_idx, thread); lseek(fd, SEEK_SET, 0); if (evsel->pid_stat) { /* The event exists solely on 1 CPU. */ @@ -542,17 +557,9 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) if (adjust) { __u64 ticks_per_sec = sysconf(_SC_CLK_TCK); - delta_start *= 1000000000 / ticks_per_sec; + delta_start *= 1e9 / ticks_per_sec; } - count->val = delta_start; - count->lost = 0; - /* - * The values of enabled and running must make a ratio of 100%. The - * exact values don't matter as long as they are non-zero to avoid - * issues with evsel__count_has_error. - */ - count->ena++; - count->run++; + perf_counts__update(count, old_count, /*raw=*/true, delta_start); return 0; } From 3d65f6445fd93e3eb4cb63a828c36625b4929abd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:10 -0800 Subject: [PATCH 378/684] perf stat-shadow: Read tool events directly When reading time values for metrics don't use the globals updated in builtin-stat, just read the events as regular events. The only exception is for time events where nanoseconds need converting to seconds as metrics assume time metrics are in seconds. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/stat-shadow.c | 149 +++++++++++++++------------------- 1 file changed, 66 insertions(+), 83 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 15e83d74eb0e5d..8622ed64c617c1 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -27,7 +27,32 @@ void perf_stat__reset_shadow_stats(void) memset(&ru_stats, 0, sizeof(ru_stats)); } -static int prepare_metric(const struct metric_expr *mexp, +static bool tool_pmu__is_time_event(const struct perf_stat_config *config, + const struct evsel *evsel, int *tool_aggr_idx) +{ + enum tool_pmu_event event = evsel__tool_event(evsel); + int aggr_idx; + + if (event != TOOL_PMU__EVENT_DURATION_TIME && + event != TOOL_PMU__EVENT_USER_TIME && + event != TOOL_PMU__EVENT_SYSTEM_TIME) + return false; + + if (config) { + cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) { + if (config->aggr_map->map[aggr_idx].cpu.cpu == 0) { + *tool_aggr_idx = aggr_idx; + return true; + } + } + pr_debug("Unexpected CPU0 missing in aggregation for tool event.\n"); + } + *tool_aggr_idx = 0; /* Assume the first aggregation index works. */ + return true; +} + +static int prepare_metric(struct perf_stat_config *config, + const struct metric_expr *mexp, const struct evsel *evsel, struct expr_parse_ctx *pctx, int aggr_idx) @@ -37,93 +62,51 @@ static int prepare_metric(const struct metric_expr *mexp, int i; for (i = 0; metric_events[i]; i++) { + int source_count = 0, tool_aggr_idx; + bool is_tool_time = + tool_pmu__is_time_event(config, metric_events[i], &tool_aggr_idx); + struct perf_stat_evsel *ps = metric_events[i]->stats; + struct perf_stat_aggr *aggr; char *n; double val; - int source_count = 0; - if (evsel__is_tool(metric_events[i])) { - struct stats *stats; - double scale; - - switch (evsel__tool_event(metric_events[i])) { - case TOOL_PMU__EVENT_DURATION_TIME: - stats = &walltime_nsecs_stats; - scale = 1e-9; - break; - case TOOL_PMU__EVENT_USER_TIME: - stats = &ru_stats.ru_utime_usec_stat; - scale = 1e-6; + /* + * If there are multiple uncore PMUs and we're not reading the + * leader's stats, determine the stats for the appropriate + * uncore PMU. + */ + if (evsel && evsel->metric_leader && + evsel->pmu != evsel->metric_leader->pmu && + mexp->metric_events[i]->pmu == evsel->metric_leader->pmu) { + struct evsel *pos; + + evlist__for_each_entry(evsel->evlist, pos) { + if (pos->pmu != evsel->pmu) + continue; + if (pos->metric_leader != mexp->metric_events[i]) + continue; + ps = pos->stats; + source_count = 1; break; - case TOOL_PMU__EVENT_SYSTEM_TIME: - stats = &ru_stats.ru_stime_usec_stat; - scale = 1e-6; - break; - case TOOL_PMU__EVENT_NONE: - pr_err("Invalid tool event 'none'"); - abort(); - case TOOL_PMU__EVENT_MAX: - pr_err("Invalid tool event 'max'"); - abort(); - case TOOL_PMU__EVENT_HAS_PMEM: - case TOOL_PMU__EVENT_NUM_CORES: - case TOOL_PMU__EVENT_NUM_CPUS: - case TOOL_PMU__EVENT_NUM_CPUS_ONLINE: - case TOOL_PMU__EVENT_NUM_DIES: - case TOOL_PMU__EVENT_NUM_PACKAGES: - case TOOL_PMU__EVENT_SLOTS: - case TOOL_PMU__EVENT_SMT_ON: - case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: - case TOOL_PMU__EVENT_CORE_WIDE: - case TOOL_PMU__EVENT_TARGET_CPU: - default: - pr_err("Unexpected tool event '%s'", evsel__name(metric_events[i])); - abort(); } - val = avg_stats(stats) * scale; - source_count = 1; - } else { - struct perf_stat_evsel *ps = metric_events[i]->stats; - struct perf_stat_aggr *aggr; - + } + /* Time events are always on CPU0, the first aggregation index. */ + aggr = &ps->aggr[is_tool_time ? tool_aggr_idx : aggr_idx]; + if (!aggr || !metric_events[i]->supported) { /* - * If there are multiple uncore PMUs and we're not - * reading the leader's stats, determine the stats for - * the appropriate uncore PMU. + * Not supported events will have a count of 0, which + * can be confusing in a metric. Explicitly set the + * value to NAN. Not counted events (enable time of 0) + * are read as 0. */ - if (evsel && evsel->metric_leader && - evsel->pmu != evsel->metric_leader->pmu && - mexp->metric_events[i]->pmu == evsel->metric_leader->pmu) { - struct evsel *pos; - - evlist__for_each_entry(evsel->evlist, pos) { - if (pos->pmu != evsel->pmu) - continue; - if (pos->metric_leader != mexp->metric_events[i]) - continue; - ps = pos->stats; - source_count = 1; - break; - } - } - aggr = &ps->aggr[aggr_idx]; - if (!aggr) - break; - - if (!metric_events[i]->supported) { - /* - * Not supported events will have a count of 0, - * which can be confusing in a - * metric. Explicitly set the value to NAN. Not - * counted events (enable time of 0) are read as - * 0. - */ - val = NAN; - source_count = 0; - } else { - val = aggr->counts.val; - if (!source_count) - source_count = evsel__source_count(metric_events[i]); - } + val = NAN; + source_count = 0; + } else { + val = aggr->counts.val; + if (is_tool_time) + val *= 1e-9; /* Convert time event nanoseconds to seconds. */ + if (!source_count) + source_count = evsel__source_count(metric_events[i]); } n = strdup(evsel__metric_id(metric_events[i])); if (!n) @@ -169,7 +152,7 @@ static void generic_metric(struct perf_stat_config *config, pctx->sctx.user_requested_cpu_list = strdup(config->user_requested_cpu_list); pctx->sctx.runtime = runtime; pctx->sctx.system_wide = config->system_wide; - i = prepare_metric(mexp, evsel, pctx, aggr_idx); + i = prepare_metric(config, mexp, evsel, pctx, aggr_idx); if (i < 0) { expr__ctx_free(pctx); return; @@ -230,7 +213,7 @@ double test_generic_metric(struct metric_expr *mexp, int aggr_idx) if (!pctx) return NAN; - if (prepare_metric(mexp, /*evsel=*/NULL, pctx, aggr_idx) < 0) + if (prepare_metric(/*config=*/NULL, mexp, /*evsel=*/NULL, pctx, aggr_idx) < 0) goto out; if (expr__parse(&ratio, pctx, mexp->metric_expr)) From 557c34435b4492860452d6c0e8444320f8614f62 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:11 -0800 Subject: [PATCH 379/684] perf stat: Reduce scope of ru_stats The ru_stats are used to capture user and system time stats when a process exits. These are then applied to user and system time tool events if their reads fail due to the process terminating. Reduce the scope now the metric code no longer reads these values. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 19 ++++++++++++++++++- tools/perf/util/config.c | 1 - tools/perf/util/stat-shadow.c | 2 -- tools/perf/util/stat.h | 21 --------------------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 654f840f7a2f10..d6f4c84f7d7e5c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -104,6 +104,11 @@ #define DEFAULT_SEPARATOR " " #define FREEZE_ON_SMI_PATH "bus/event_source/devices/cpu/freeze_on_smi" +struct rusage_stats { + struct stats ru_utime_usec_stat; + struct stats ru_stime_usec_stat; +}; + static void print_counters(struct timespec *ts, int argc, const char **argv); static struct evlist *evsel_list; @@ -133,6 +138,7 @@ static bool interval_count; static const char *output_name; static int output_fd; static char *metrics; +static struct rusage_stats ru_stats; struct perf_stat { bool record; @@ -730,6 +736,17 @@ static int create_perf_stat_counter(struct evsel *evsel, evsel->core.threads); } +static void update_rusage_stats(const struct rusage *rusage) +{ + const u64 us_to_ns = 1000; + const u64 s_to_ns = 1000000000; + + update_stats(&ru_stats.ru_utime_usec_stat, + (rusage->ru_utime.tv_usec * us_to_ns + rusage->ru_utime.tv_sec * s_to_ns)); + update_stats(&ru_stats.ru_stime_usec_stat, + (rusage->ru_stime.tv_usec * us_to_ns + rusage->ru_stime.tv_sec * s_to_ns)); +} + static int __run_perf_stat(int argc, const char **argv, int run_idx) { int interval = stat_config.interval; @@ -979,7 +996,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) evlist__reset_aggr_stats(evsel_list); } else { update_stats(&walltime_nsecs_stats, t1 - t0); - update_rusage_stats(&ru_stats, &stat_config.ru_data); + update_rusage_stats(&stat_config.ru_data); } /* diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 6f914620c6ff29..cc0746f494f48c 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -45,7 +45,6 @@ struct perf_stat_config stat_config = { .run_count = 1, .metric_only_len = METRIC_ONLY_LEN, .walltime_nsecs_stats = &walltime_nsecs_stats, - .ru_stats = &ru_stats, .big_num = true, .ctl_fd = -1, .ctl_fd_ack = -1, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 8622ed64c617c1..337a8aa547c3d5 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -19,12 +19,10 @@ #include "tool_pmu.h" struct stats walltime_nsecs_stats; -struct rusage_stats ru_stats; void perf_stat__reset_shadow_stats(void) { memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); - memset(&ru_stats, 0, sizeof(ru_stats)); } static bool tool_pmu__is_time_event(const struct perf_stat_config *config, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index b42da4a29c442c..055b95d18106a8 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -56,11 +56,6 @@ enum aggr_mode { AGGR_MAX }; -struct rusage_stats { - struct stats ru_utime_usec_stat; - struct stats ru_stime_usec_stat; -}; - typedef struct aggr_cpu_id (*aggr_get_id_t)(struct perf_stat_config *config, struct perf_cpu cpu); struct perf_stat_config { @@ -102,7 +97,6 @@ struct perf_stat_config { const char *csv_sep; struct stats *walltime_nsecs_stats; struct rusage ru_data; - struct rusage_stats *ru_stats; struct cpu_aggr_map *aggr_map; aggr_get_id_t aggr_get_id; struct cpu_aggr_map *cpus_aggr_map; @@ -132,25 +126,10 @@ static inline void init_stats(struct stats *stats) stats->max = 0; } -static inline void init_rusage_stats(struct rusage_stats *ru_stats) { - init_stats(&ru_stats->ru_utime_usec_stat); - init_stats(&ru_stats->ru_stime_usec_stat); -} - -static inline void update_rusage_stats(struct rusage_stats *ru_stats, struct rusage* rusage) { - const u64 us_to_ns = 1000; - const u64 s_to_ns = 1000000000; - update_stats(&ru_stats->ru_utime_usec_stat, - (rusage->ru_utime.tv_usec * us_to_ns + rusage->ru_utime.tv_sec * s_to_ns)); - update_stats(&ru_stats->ru_stime_usec_stat, - (rusage->ru_stime.tv_usec * us_to_ns + rusage->ru_stime.tv_sec * s_to_ns)); -} - struct evsel; struct evlist; extern struct stats walltime_nsecs_stats; -extern struct rusage_stats ru_stats; enum metric_threshold_classify { METRIC_THRESHOLD_UNKNOWN, From d702c0f4af6e065846e67ff89b34aec2cca7ffa7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:12 -0800 Subject: [PATCH 380/684] perf stat: Reduce scope of walltime_nsecs_stats walltime_nsecs_stats is no longer used for counter values, move into that stat_config where it controls certain things like noise measurement. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 16 ++++++++-------- tools/perf/tests/parse-metric.c | 2 -- tools/perf/tests/pmu-events.c | 2 -- tools/perf/util/config.c | 2 ++ tools/perf/util/stat-shadow.c | 7 ------- tools/perf/util/stat.h | 2 -- 6 files changed, 10 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d6f4c84f7d7e5c..ca1c80c141b658 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -239,7 +239,7 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, static void perf_stat__reset_stats(void) { evlist__reset_stats(evsel_list); - perf_stat__reset_shadow_stats(); + memset(stat_config.walltime_nsecs_stats, 0, sizeof(*stat_config.walltime_nsecs_stats)); } static int process_synthesized_event(const struct perf_tool *tool __maybe_unused, @@ -455,8 +455,8 @@ static void process_interval(void) pr_err("failed to write stat round event\n"); } - init_stats(&walltime_nsecs_stats); - update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000ULL); + init_stats(stat_config.walltime_nsecs_stats); + update_stats(stat_config.walltime_nsecs_stats, stat_config.interval * 1000000ULL); print_counters(&rs, 0, NULL); } @@ -988,14 +988,14 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) if (interval && stat_config.summary) { stat_config.interval = 0; stat_config.stop_read_counter = true; - init_stats(&walltime_nsecs_stats); - update_stats(&walltime_nsecs_stats, t1 - t0); + init_stats(stat_config.walltime_nsecs_stats); + update_stats(stat_config.walltime_nsecs_stats, t1 - t0); evlist__copy_prev_raw_counts(evsel_list); evlist__reset_prev_raw_counts(evsel_list); evlist__reset_aggr_stats(evsel_list); } else { - update_stats(&walltime_nsecs_stats, t1 - t0); + update_stats(stat_config.walltime_nsecs_stats, t1 - t0); update_rusage_stats(&stat_config.ru_data); } @@ -2167,7 +2167,7 @@ static int process_stat_round_event(const struct perf_tool *tool __maybe_unused, process_counters(); if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) - update_stats(&walltime_nsecs_stats, stat_round->time); + update_stats(stat_config.walltime_nsecs_stats, stat_round->time); if (stat_config.interval && stat_round->time) { tsh.tv_sec = stat_round->time / NSEC_PER_SEC; @@ -2975,7 +2975,7 @@ int cmd_stat(int argc, const char **argv) } if (!interval) { - if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL)) + if (WRITE_STAT_ROUND_EVENT(stat_config.walltime_nsecs_stats->max, FINAL)) pr_err("failed to write stat round event\n"); } diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 9b1df1eb455a7d..6bbc209a5c6af8 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -41,8 +41,6 @@ static void load_runtime_stat(struct evlist *evlist, struct value *vals) count = find_value(evsel->name, vals); evsel->supported = true; evsel->stats->aggr->counts.val = count; - if (evsel__name_is(evsel, "duration_time")) - update_stats(&walltime_nsecs_stats, count); } } diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index f40a828c9861af..a9971686216880 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -872,8 +872,6 @@ static int test__parsing_callback(const struct pmu_metric *pm, evlist__alloc_aggr_stats(evlist, 1); evlist__for_each_entry(evlist, evsel) { evsel->stats->aggr->counts.val = k; - if (evsel__name_is(evsel, "duration_time")) - update_stats(&walltime_nsecs_stats, k); k++; } evlist__for_each_entry(evlist, evsel) { diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index cc0746f494f48c..e0219bc6330ae8 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -37,6 +37,8 @@ #define METRIC_ONLY_LEN 20 +static struct stats walltime_nsecs_stats; + struct perf_stat_config stat_config = { .aggr_mode = AGGR_GLOBAL, .aggr_level = MAX_CACHE_LVL + 1, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 337a8aa547c3d5..9c83f7d96caa4e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -18,13 +18,6 @@ #include "util/hashmap.h" #include "tool_pmu.h" -struct stats walltime_nsecs_stats; - -void perf_stat__reset_shadow_stats(void) -{ - memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); -} - static bool tool_pmu__is_time_event(const struct perf_stat_config *config, const struct evsel *evsel, int *tool_aggr_idx) { diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 055b95d18106a8..f986911c9296e7 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -129,8 +129,6 @@ static inline void init_stats(struct stats *stats) struct evsel; struct evlist; -extern struct stats walltime_nsecs_stats; - enum metric_threshold_classify { METRIC_THRESHOLD_UNKNOWN, METRIC_THRESHOLD_BAD, From d8d8a0b3603a9a8fa207cf9e4f292e81dc5d1008 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 13 Nov 2025 10:05:13 -0800 Subject: [PATCH 381/684] perf tool_pmu: More accurately set the cpus for tool events The user and system time events can record on different CPUs, but for all other events a single CPU map of just CPU 0 makes sense. In parse-events detect a tool PMU and then pass the perf_event_attr so that the tool_pmu can return CPUs specific for the event. This avoids a CPU map of all online CPUs being used for events like duration_time. Avoiding this avoids the evlist CPUs containing CPUs for which duration_time just gives 0. Minimizing the evlist CPUs can remove unnecessary sched_setaffinity syscalls that delay metric calculations. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/parse-events.c | 9 +++++++-- tools/perf/util/tool_pmu.c | 19 +++++++++++++++++++ tools/perf/util/tool_pmu.h | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e522082c5a2140..5ffeb7b416d939 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -30,6 +30,7 @@ #include "util/event.h" #include "util/bpf-filter.h" #include "util/stat.h" +#include "util/tool_pmu.h" #include "util/util.h" #include "tracepoint.h" #include @@ -227,8 +228,12 @@ __add_event(struct list_head *list, int *idx, if (pmu) { is_pmu_core = pmu->is_core; pmu_cpus = perf_cpu_map__get(pmu->cpus); - if (perf_cpu_map__is_empty(pmu_cpus)) - pmu_cpus = cpu_map__online(); + if (perf_cpu_map__is_empty(pmu_cpus)) { + if (perf_pmu__is_tool(pmu)) + pmu_cpus = tool_pmu__cpus(attr); + else + pmu_cpus = cpu_map__online(); + } } else { is_pmu_core = (attr->type == PERF_TYPE_HARDWARE || attr->type == PERF_TYPE_HW_CACHE); diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c index 6a9df3dc0e076e..37c4eae0bef1bc 100644 --- a/tools/perf/util/tool_pmu.c +++ b/tools/perf/util/tool_pmu.c @@ -2,6 +2,7 @@ #include "cgroup.h" #include "counts.h" #include "cputopo.h" +#include "debug.h" #include "evsel.h" #include "pmu.h" #include "print-events.h" @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +111,23 @@ const char *evsel__tool_pmu_event_name(const struct evsel *evsel) return tool_pmu__event_to_str(evsel->core.attr.config); } +struct perf_cpu_map *tool_pmu__cpus(struct perf_event_attr *attr) +{ + static struct perf_cpu_map *cpu0_map; + enum tool_pmu_event event = (enum tool_pmu_event)attr->config; + + if (event <= TOOL_PMU__EVENT_NONE || event >= TOOL_PMU__EVENT_MAX) { + pr_err("Invalid tool PMU event config %llx\n", attr->config); + return NULL; + } + if (event == TOOL_PMU__EVENT_USER_TIME || event == TOOL_PMU__EVENT_SYSTEM_TIME) + return cpu_map__online(); + + if (!cpu0_map) + cpu0_map = perf_cpu_map__new_int(0); + return perf_cpu_map__get(cpu0_map); +} + static bool read_until_char(struct io *io, char e) { int c; diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h index f1714001bc1d92..ea343d1983d3a8 100644 --- a/tools/perf/util/tool_pmu.h +++ b/tools/perf/util/tool_pmu.h @@ -46,6 +46,7 @@ bool tool_pmu__read_event(enum tool_pmu_event ev, u64 tool_pmu__cpu_slots_per_cycle(void); bool perf_pmu__is_tool(const struct perf_pmu *pmu); +struct perf_cpu_map *tool_pmu__cpus(struct perf_event_attr *attr); bool evsel__is_tool(const struct evsel *evsel); enum tool_pmu_event evsel__tool_event(const struct evsel *evsel); From 2f61c00972193d014185655e533a809d824cef47 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 18 Nov 2025 13:34:01 +0100 Subject: [PATCH 382/684] pinctrl: intel: Export intel_gpio_add_pin_ranges() Export intel_gpio_add_pin_ranges() for reuse in other drivers. Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 12 +++++++++++- drivers/pinctrl/intel/pinctrl-intel.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 1e2f77d200f9f1..cf9db8ac0f42ea 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1345,7 +1345,16 @@ static int intel_gpio_irq_init_hw(struct gpio_chip *gc) return 0; } -static int intel_gpio_add_pin_ranges(struct gpio_chip *gc) +/** + * intel_gpio_add_pin_ranges - add GPIO pin ranges for all groups in all communities + * @gc: GPIO chip structure + * + * This function iterates over all communities and all groups and adds the respective + * GPIO pin ranges, so the GPIO library will correctly map a GPIO offset to a pin number. + * + * Return: 0, or negative error code if range can't be added. + */ +int intel_gpio_add_pin_ranges(struct gpio_chip *gc) { struct intel_pinctrl *pctrl = gpiochip_get_data(gc); const struct intel_community *community; @@ -1362,6 +1371,7 @@ static int intel_gpio_add_pin_ranges(struct gpio_chip *gc) return 0; } +EXPORT_SYMBOL_NS_GPL(intel_gpio_add_pin_ranges, "PINCTRL_INTEL"); static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl) { diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index 654af5977603d5..c1520797f89597 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -276,6 +276,8 @@ extern const struct dev_pm_ops intel_pinctrl_pm_ops; const struct intel_community *intel_get_community(const struct intel_pinctrl *pctrl, unsigned int pin); +int intel_gpio_add_pin_ranges(struct gpio_chip *gc); + int intel_get_groups_count(struct pinctrl_dev *pctldev); const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group); int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, From 3bcfd55bedfc62e73cc36395e77a67827116cfcd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 18 Nov 2025 13:34:02 +0100 Subject: [PATCH 383/684] pinctrl: cherryview: Convert to use intel_gpio_add_pin_ranges() Driver is ready to use intel_gpio_add_pin_ranges() directly instead of custom approach. Convert it now. Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-cherryview.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index f6c29bdc310350..8bd0c8512f7836 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1511,24 +1511,6 @@ static int chv_gpio_irq_init_hw(struct gpio_chip *chip) return 0; } -static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) -{ - struct intel_pinctrl *pctrl = gpiochip_get_data(chip); - struct device *dev = pctrl->dev; - const struct intel_community *community = &pctrl->communities[0]; - const struct intel_padgroup *gpp; - int ret, i; - - for (i = 0; i < community->ngpps; i++) { - gpp = &community->gpps[i]; - ret = gpiochip_add_pin_range(chip, dev_name(dev), gpp->base, gpp->base, gpp->size); - if (ret) - return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); - } - - return 0; -} - static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) { const struct intel_community *community = &pctrl->communities[0]; @@ -1542,7 +1524,7 @@ static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) chip->ngpio = pctrl->soc->pins[pctrl->soc->npins - 1].number + 1; chip->label = dev_name(dev); - chip->add_pin_ranges = chv_gpio_add_pin_ranges; + chip->add_pin_ranges = intel_gpio_add_pin_ranges; chip->parent = dev; chip->base = -1; From c57210bc15371caa06a5d4040e7d8aaeed4cb661 Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Sun, 16 Nov 2025 04:12:33 +0300 Subject: [PATCH 384/684] dt-bindings: clock: mmcc-sdm660: Add missing MDSS reset Add definition for display subsystem reset control, so display driver can reset display controller properly, clearing any configuration left there by bootloader. Since 6.17 after PM domains rework it became necessary for display to function. Fixes: 0e789b491ba0 ("pmdomain: core: Leave powered-on genpds on until sync_state") Cc: stable@vger.kernel.org # 6.17 Signed-off-by: Alexey Minnekhanov Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20251116-sdm660-mdss-reset-v2-1-6219bec0a97f@postmarketos.org Signed-off-by: Bjorn Andersson --- include/dt-bindings/clock/qcom,mmcc-sdm660.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/qcom,mmcc-sdm660.h b/include/dt-bindings/clock/qcom,mmcc-sdm660.h index f9dbc21cb5c7cf..ee2a89dae72dc5 100644 --- a/include/dt-bindings/clock/qcom,mmcc-sdm660.h +++ b/include/dt-bindings/clock/qcom,mmcc-sdm660.h @@ -157,6 +157,7 @@ #define BIMC_SMMU_GDSC 7 #define CAMSS_MICRO_BCR 0 +#define MDSS_BCR 1 #endif From 0a0ea5541d30c0fbb3dac975bd1983f299cd6948 Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Sun, 16 Nov 2025 04:12:34 +0300 Subject: [PATCH 385/684] clk: qcom: mmcc-sdm660: Add missing MDSS reset Add offset for display subsystem reset in multimedia clock controller block, which is necessary to reset display when there is some configuration in display controller left by previous stock (Android) bootloader to provide continuous splash functionaluty. Before 6.17 power domains were turned off for long enough to clear registers, now this is not the case and a proper reset is needed to have functioning display. Fixes: 0e789b491ba0 ("pmdomain: core: Leave powered-on genpds on until sync_state") Cc: stable@vger.kernel.org # 6.17 Signed-off-by: Alexey Minnekhanov Reviewed-by: Taniya Das Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251116-sdm660-mdss-reset-v2-2-6219bec0a97f@postmarketos.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/mmcc-sdm660.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c index b723c536dfb6ce..dbd3f561dc6d0d 100644 --- a/drivers/clk/qcom/mmcc-sdm660.c +++ b/drivers/clk/qcom/mmcc-sdm660.c @@ -2781,6 +2781,7 @@ static struct gdsc *mmcc_sdm660_gdscs[] = { }; static const struct qcom_reset_map mmcc_660_resets[] = { + [MDSS_BCR] = { 0x2300 }, [CAMSS_MICRO_BCR] = { 0x3490 }, }; From 165d0b6dd248b939fb0d31a00687e6ef672b3b3c Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 18 Nov 2025 12:47:05 +0530 Subject: [PATCH 386/684] clk: qcom: clk_mem_branch: add enable mask and invert flags Introduce mem_enable_mask and mem_enable_invert in clk_mem_branch to describe memory gating implementations that use a separate mask and/or inverted enable logic. This documents hardware behavior in data instead of code and will be used by upcoming platform descriptions. Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20251118-sm8750-videocc-v2-v4-1-049882a70c9f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-branch.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index 292756435f5364..6bc2ba2b535055 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -44,6 +44,8 @@ struct clk_branch { * @mem_enable_reg: branch clock memory gating register * @mem_ack_reg: branch clock memory ack register * @mem_enable_ack_mask: branch clock memory enable and ack field in @mem_ack_reg + * @mem_enable_mask: branch clock memory enable mask + * @mem_enable_invert: branch clock memory enable and disable has invert logic * @branch: branch clock gating handle * * Clock which can gate its memories. @@ -52,6 +54,8 @@ struct clk_mem_branch { u32 mem_enable_reg; u32 mem_ack_reg; u32 mem_enable_ack_mask; + u32 mem_enable_mask; + bool mem_enable_invert; struct clk_branch branch; }; From 53a18958349a627ae5d6b1ea708289b6cf3d8b9d Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 18 Nov 2025 12:47:06 +0530 Subject: [PATCH 387/684] clk: qcom: ecpricc-qdu100: Add mem_enable_mask to the clock memory branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ECPRI clock controller’s mem_ops clocks used the mem_enable_ack_mask directly for both setting and polling. Add the newly introduced 'mem_enable_mask' to the memory control branch clocks of ECPRI clock controller to align to the new mem_ops handling. Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20251118-sm8750-videocc-v2-v4-2-049882a70c9f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/ecpricc-qdu1000.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/clk/qcom/ecpricc-qdu1000.c b/drivers/clk/qcom/ecpricc-qdu1000.c index dbc11260479b6d..c2a16616ed6450 100644 --- a/drivers/clk/qcom/ecpricc-qdu1000.c +++ b/drivers/clk/qcom/ecpricc-qdu1000.c @@ -920,6 +920,7 @@ static struct clk_branch ecpri_cc_eth_100g_c2c1_udp_fifo_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_c2c_0_hm_ff_0_clk = { .mem_enable_reg = 0x8410, .mem_ack_reg = 0x8424, + .mem_enable_mask = BIT(0), .mem_enable_ack_mask = BIT(0), .branch = { .halt_reg = 0x80b4, @@ -943,6 +944,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_c2c_0_hm_ff_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_c2c_0_hm_ff_1_clk = { .mem_enable_reg = 0x8410, .mem_ack_reg = 0x8424, + .mem_enable_mask = BIT(1), .mem_enable_ack_mask = BIT(1), .branch = { .halt_reg = 0x80bc, @@ -966,6 +968,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_c2c_0_hm_ff_1_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_c2c_hm_macsec_clk = { .mem_enable_reg = 0x8410, .mem_ack_reg = 0x8424, + .mem_enable_mask = BIT(4), .mem_enable_ack_mask = BIT(4), .branch = { .halt_reg = 0x80ac, @@ -989,6 +992,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_c2c_hm_macsec_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_dbg_c2c_hm_ff_0_clk = { .mem_enable_reg = 0x8414, .mem_ack_reg = 0x8428, + .mem_enable_mask = BIT(0), .mem_enable_ack_mask = BIT(0), .branch = { .halt_reg = 0x80d8, @@ -1012,6 +1016,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_dbg_c2c_hm_ff_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_dbg_c2c_hm_ff_1_clk = { .mem_enable_reg = 0x8414, .mem_ack_reg = 0x8428, + .mem_enable_mask = BIT(1), .mem_enable_ack_mask = BIT(1), .branch = { .halt_reg = 0x80e0, @@ -1053,6 +1058,7 @@ static struct clk_branch ecpri_cc_eth_100g_dbg_c2c_udp_fifo_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_0_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(0), .mem_enable_ack_mask = BIT(0), .branch = { .halt_reg = 0x800c, @@ -1076,6 +1082,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_1_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(1), .mem_enable_ack_mask = BIT(1), .branch = { .halt_reg = 0x8014, @@ -1099,6 +1106,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_1_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_2_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(2), .mem_enable_ack_mask = BIT(2), .branch = { .halt_reg = 0x801c, @@ -1122,6 +1130,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_2_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_0_hm_ff_3_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(3), .mem_enable_ack_mask = BIT(3), .branch = { .halt_reg = 0x8024, @@ -1163,6 +1172,7 @@ static struct clk_branch ecpri_cc_eth_100g_fh_0_udp_fifo_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_0_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(0), .mem_enable_ack_mask = BIT(0), .branch = { .halt_reg = 0x8044, @@ -1186,6 +1196,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_1_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(1), .mem_enable_ack_mask = BIT(1), .branch = { .halt_reg = 0x804c, @@ -1209,6 +1220,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_1_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_2_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(2), .mem_enable_ack_mask = BIT(2), .branch = { .halt_reg = 0x8054, @@ -1232,6 +1244,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_2_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_1_hm_ff_3_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(3), .mem_enable_ack_mask = BIT(3), .branch = { .halt_reg = 0x805c, @@ -1273,6 +1286,7 @@ static struct clk_branch ecpri_cc_eth_100g_fh_1_udp_fifo_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_0_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(0), .mem_enable_ack_mask = BIT(0), .branch = { .halt_reg = 0x807c, @@ -1296,6 +1310,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_1_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(1), .mem_enable_ack_mask = BIT(1), .branch = { .halt_reg = 0x8084, @@ -1319,6 +1334,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_1_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_2_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(2), .mem_enable_ack_mask = BIT(2), .branch = { .halt_reg = 0x808c, @@ -1342,6 +1358,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_2_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_2_hm_ff_3_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(3), .mem_enable_ack_mask = BIT(3), .branch = { .halt_reg = 0x8094, @@ -1383,6 +1400,7 @@ static struct clk_branch ecpri_cc_eth_100g_fh_2_udp_fifo_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_0_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(4), .mem_enable_ack_mask = BIT(4), .branch = { .halt_reg = 0x8004, @@ -1406,6 +1424,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_0_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_1_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(4), .mem_enable_ack_mask = BIT(4), .branch = { .halt_reg = 0x803c, @@ -1429,6 +1448,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_1_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_2_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(4), .mem_enable_ack_mask = BIT(4), .branch = { .halt_reg = 0x8074, @@ -1452,6 +1472,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_fh_macsec_2_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_mac_c2c_hm_ref_clk = { .mem_enable_reg = 0x8410, .mem_ack_reg = 0x8424, + .mem_enable_mask = BIT(5), .mem_enable_ack_mask = BIT(5), .branch = { .halt_reg = 0x80c4, @@ -1475,6 +1496,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_mac_c2c_hm_ref_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_mac_dbg_c2c_hm_ref_clk = { .mem_enable_reg = 0x8414, .mem_ack_reg = 0x8428, + .mem_enable_mask = BIT(5), .mem_enable_ack_mask = BIT(5), .branch = { .halt_reg = 0x80e8, @@ -1498,6 +1520,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_mac_dbg_c2c_hm_ref_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_mac_fh0_hm_ref_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(5), .mem_enable_ack_mask = BIT(5), .branch = { .halt_reg = 0x802c, @@ -1521,6 +1544,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_mac_fh0_hm_ref_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_mac_fh1_hm_ref_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841c, + .mem_enable_mask = BIT(5), .mem_enable_ack_mask = BIT(5), .branch = { .halt_reg = 0x8064, @@ -1544,6 +1568,7 @@ static struct clk_mem_branch ecpri_cc_eth_100g_mac_fh1_hm_ref_clk = { static struct clk_mem_branch ecpri_cc_eth_100g_mac_fh2_hm_ref_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(5), .mem_enable_ack_mask = BIT(5), .branch = { .halt_reg = 0x809c, @@ -1603,6 +1628,7 @@ static struct clk_branch ecpri_cc_eth_dbg_noc_axi_clk = { static struct clk_mem_branch ecpri_cc_eth_phy_0_ock_sram_clk = { .mem_enable_reg = 0x8404, .mem_ack_reg = 0x8418, + .mem_enable_mask = BIT(6), .mem_enable_ack_mask = BIT(6), .branch = { .halt_reg = 0xd140, @@ -1621,6 +1647,7 @@ static struct clk_mem_branch ecpri_cc_eth_phy_0_ock_sram_clk = { static struct clk_mem_branch ecpri_cc_eth_phy_1_ock_sram_clk = { .mem_enable_reg = 0x8408, .mem_ack_reg = 0x841C, + .mem_enable_mask = BIT(6), .mem_enable_ack_mask = BIT(6), .branch = { .halt_reg = 0xd148, @@ -1639,6 +1666,7 @@ static struct clk_mem_branch ecpri_cc_eth_phy_1_ock_sram_clk = { static struct clk_mem_branch ecpri_cc_eth_phy_2_ock_sram_clk = { .mem_enable_reg = 0x840c, .mem_ack_reg = 0x8420, + .mem_enable_mask = BIT(6), .mem_enable_ack_mask = BIT(6), .branch = { .halt_reg = 0xd150, @@ -1657,6 +1685,7 @@ static struct clk_mem_branch ecpri_cc_eth_phy_2_ock_sram_clk = { static struct clk_mem_branch ecpri_cc_eth_phy_3_ock_sram_clk = { .mem_enable_reg = 0x8410, .mem_ack_reg = 0x8424, + .mem_enable_mask = BIT(6), .mem_enable_ack_mask = BIT(6), .branch = { .halt_reg = 0xd158, @@ -1675,6 +1704,7 @@ static struct clk_mem_branch ecpri_cc_eth_phy_3_ock_sram_clk = { static struct clk_mem_branch ecpri_cc_eth_phy_4_ock_sram_clk = { .mem_enable_reg = 0x8414, .mem_ack_reg = 0x8428, + .mem_enable_mask = BIT(6), .mem_enable_ack_mask = BIT(6), .branch = { .halt_reg = 0xd160, From 4edf654be5471659e3260be0a557eaa2ece668ab Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 12 Nov 2025 16:27:06 +0000 Subject: [PATCH 388/684] phy: add new phy_notify_state() api Add a new phy_notify_state() api that notifies and configures a phy for a given state transition. This is intended to be used by phy drivers which need to do some runtime configuration of parameters that can't be handled by phy_calibrate() or phy_power_{on|off}(). The first usage of this API is in the Samsung UFS phy that needs to issue some register writes when entering and exiting the hibernate link state. Signed-off-by: Peter Griffin Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251112-phy-notify-pmstate-v5-1-39df622d8fcb@linaro.org Signed-off-by: Vinod Koul --- drivers/phy/phy-core.c | 25 +++++++++++++++++++++++++ include/linux/phy/phy.h | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 04a5a34e7a950a..60be8af984bf06 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -520,6 +520,31 @@ int phy_notify_disconnect(struct phy *phy, int port) } EXPORT_SYMBOL_GPL(phy_notify_disconnect); +/** + * phy_notify_state() - phy state notification + * @phy: the PHY returned by phy_get() + * @state: the PHY state + * + * Notify the PHY of a state transition. Used to notify and + * configure the PHY accordingly. + * + * Returns: %0 if successful, a negative error code otherwise + */ +int phy_notify_state(struct phy *phy, union phy_notify state) +{ + int ret; + + if (!phy || !phy->ops->notify_phystate) + return 0; + + mutex_lock(&phy->mutex); + ret = phy->ops->notify_phystate(phy, state); + mutex_unlock(&phy->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_notify_state); + /** * phy_configure() - Changes the phy parameters * @phy: the phy returned by phy_get() diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 13add0c2c40721..2af0d01ebb39f2 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -53,6 +53,15 @@ enum phy_media { PHY_MEDIA_DAC, }; +enum phy_ufs_state { + PHY_UFS_HIBERN8_ENTER, + PHY_UFS_HIBERN8_EXIT, +}; + +union phy_notify { + enum phy_ufs_state ufs_state; +}; + /** * union phy_configure_opts - Opaque generic phy configuration * @@ -83,6 +92,7 @@ union phy_configure_opts { * @set_speed: set the speed of the phy (optional) * @reset: resetting the phy * @calibrate: calibrate the phy + * @notify_phystate: notify and configure the phy for a particular state * @release: ops to be performed while the consumer relinquishes the PHY * @owner: the module owner containing the ops */ @@ -132,6 +142,7 @@ struct phy_ops { int (*connect)(struct phy *phy, int port); int (*disconnect)(struct phy *phy, int port); + int (*notify_phystate)(struct phy *phy, union phy_notify state); void (*release)(struct phy *phy); struct module *owner; }; @@ -255,6 +266,7 @@ int phy_reset(struct phy *phy); int phy_calibrate(struct phy *phy); int phy_notify_connect(struct phy *phy, int port); int phy_notify_disconnect(struct phy *phy, int port); +int phy_notify_state(struct phy *phy, union phy_notify state); static inline int phy_get_bus_width(struct phy *phy) { return phy->attrs.bus_width; @@ -412,6 +424,13 @@ static inline int phy_notify_disconnect(struct phy *phy, int index) return -ENOSYS; } +static inline int phy_notify_state(struct phy *phy, union phy_notify state) +{ + if (!phy) + return 0; + return -ENOSYS; +} + static inline int phy_configure(struct phy *phy, union phy_configure_opts *opts) { From a1af5d2be169ecec92cb4d85c811450d68164aec Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 12 Nov 2025 16:27:07 +0000 Subject: [PATCH 389/684] phy: samsung: gs101-ufs: Add .notify_phystate() & hibern8 enter/exit values Implement the .notify_phystate() callback and provide the gs101 specific phy values that need to be programmed when entering and exiting the hibern8 state. Signed-off-by: Peter Griffin Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251112-phy-notify-pmstate-v5-2-39df622d8fcb@linaro.org Signed-off-by: Vinod Koul --- drivers/phy/samsung/phy-gs101-ufs.c | 28 +++++++++++++++++++ drivers/phy/samsung/phy-samsung-ufs.c | 40 +++++++++++++++++++++++++++ drivers/phy/samsung/phy-samsung-ufs.h | 7 +++++ 3 files changed, 75 insertions(+) diff --git a/drivers/phy/samsung/phy-gs101-ufs.c b/drivers/phy/samsung/phy-gs101-ufs.c index 17b798da5b5761..a15e1f453f7f3c 100644 --- a/drivers/phy/samsung/phy-gs101-ufs.c +++ b/drivers/phy/samsung/phy-gs101-ufs.c @@ -108,12 +108,39 @@ static const struct samsung_ufs_phy_cfg tensor_gs101_post_pwr_hs_config[] = { END_UFS_PHY_CFG, }; +static const struct samsung_ufs_phy_cfg tensor_gs101_post_h8_enter[] = { + PHY_TRSV_REG_CFG_GS101(0x262, 0x08, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_GS101(0x265, 0x0A, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x1, 0x8, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x0, 0x86, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x8, 0x60, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG_GS101(0x222, 0x08, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG_GS101(0x246, 0x01, PWR_MODE_HS_ANY), + END_UFS_PHY_CFG, +}; + +static const struct samsung_ufs_phy_cfg tensor_gs101_pre_h8_exit[] = { + PHY_COMN_REG_CFG(0x0, 0xC6, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x1, 0x0C, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_GS101(0x262, 0x00, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_GS101(0x265, 0x00, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x8, 0xE0, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG_GS101(0x246, 0x03, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG_GS101(0x222, 0x18, PWR_MODE_HS_ANY), + END_UFS_PHY_CFG, +}; + static const struct samsung_ufs_phy_cfg *tensor_gs101_ufs_phy_cfgs[CFG_TAG_MAX] = { [CFG_PRE_INIT] = tensor_gs101_pre_init_cfg, [CFG_PRE_PWR_HS] = tensor_gs101_pre_pwr_hs_config, [CFG_POST_PWR_HS] = tensor_gs101_post_pwr_hs_config, }; +static const struct samsung_ufs_phy_cfg *tensor_gs101_hibern8_cfgs[] = { + [CFG_POST_HIBERN8_ENTER] = tensor_gs101_post_h8_enter, + [CFG_PRE_HIBERN8_EXIT] = tensor_gs101_pre_h8_exit, +}; + static const char * const tensor_gs101_ufs_phy_clks[] = { "ref_clk", }; @@ -170,6 +197,7 @@ static int gs101_phy_wait_for_cdr_lock(struct phy *phy, u8 lane) const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy = { .cfgs = tensor_gs101_ufs_phy_cfgs, + .cfgs_hibern8 = tensor_gs101_hibern8_cfgs, .isol = { .offset = TENSOR_GS101_PHY_CTRL, .mask = TENSOR_GS101_PHY_CTRL_MASK, diff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c index f3cbe6b17b235b..ee665f26c2361f 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.c +++ b/drivers/phy/samsung/phy-samsung-ufs.c @@ -217,6 +217,44 @@ static int samsung_ufs_phy_set_mode(struct phy *generic_phy, return 0; } +static int samsung_ufs_phy_notify_state(struct phy *phy, + union phy_notify state) +{ + struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy); + const struct samsung_ufs_phy_cfg *cfg; + int i, err = -EINVAL; + + if (!ufs_phy->cfgs_hibern8) + return 0; + + if (state.ufs_state == PHY_UFS_HIBERN8_ENTER) + cfg = ufs_phy->cfgs_hibern8[CFG_POST_HIBERN8_ENTER]; + else if (state.ufs_state == PHY_UFS_HIBERN8_EXIT) + cfg = ufs_phy->cfgs_hibern8[CFG_PRE_HIBERN8_EXIT]; + else + goto err_out; + + for_each_phy_cfg(cfg) { + for_each_phy_lane(ufs_phy, i) { + samsung_ufs_phy_config(ufs_phy, cfg, i); + } + } + + if (state.ufs_state == PHY_UFS_HIBERN8_EXIT) { + for_each_phy_lane(ufs_phy, i) { + if (ufs_phy->drvdata->wait_for_cdr) { + err = ufs_phy->drvdata->wait_for_cdr(phy, i); + if (err) + goto err_out; + } + } + } + + return 0; +err_out: + return err; +} + static int samsung_ufs_phy_exit(struct phy *phy) { struct samsung_ufs_phy *ss_phy = get_samsung_ufs_phy(phy); @@ -233,6 +271,7 @@ static const struct phy_ops samsung_ufs_phy_ops = { .power_off = samsung_ufs_phy_power_off, .calibrate = samsung_ufs_phy_calibrate, .set_mode = samsung_ufs_phy_set_mode, + .notify_phystate = samsung_ufs_phy_notify_state, .owner = THIS_MODULE, }; @@ -287,6 +326,7 @@ static int samsung_ufs_phy_probe(struct platform_device *pdev) phy->dev = dev; phy->drvdata = drvdata; phy->cfgs = drvdata->cfgs; + phy->cfgs_hibern8 = drvdata->cfgs_hibern8; memcpy(&phy->isol, &drvdata->isol, sizeof(phy->isol)); if (!of_property_read_u32_index(dev->of_node, "samsung,pmu-syscon", 1, diff --git a/drivers/phy/samsung/phy-samsung-ufs.h b/drivers/phy/samsung/phy-samsung-ufs.h index a28f148081d168..f2c2e744e5bae8 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.h +++ b/drivers/phy/samsung/phy-samsung-ufs.h @@ -92,6 +92,11 @@ enum { CFG_TAG_MAX, }; +enum { + CFG_POST_HIBERN8_ENTER, + CFG_PRE_HIBERN8_EXIT, +}; + struct samsung_ufs_phy_cfg { u32 off_0; u32 off_1; @@ -108,6 +113,7 @@ struct samsung_ufs_phy_pmu_isol { struct samsung_ufs_phy_drvdata { const struct samsung_ufs_phy_cfg **cfgs; + const struct samsung_ufs_phy_cfg **cfgs_hibern8; struct samsung_ufs_phy_pmu_isol isol; const char * const *clk_list; int num_clks; @@ -124,6 +130,7 @@ struct samsung_ufs_phy { struct clk_bulk_data *clks; const struct samsung_ufs_phy_drvdata *drvdata; const struct samsung_ufs_phy_cfg * const *cfgs; + const struct samsung_ufs_phy_cfg * const *cfgs_hibern8; struct samsung_ufs_phy_pmu_isol isol; u8 lane_cnt; int ufs_phy_state; From 54760125b026f25d329158ffb5f5569c8efcea93 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 17 Nov 2025 12:34:22 +0200 Subject: [PATCH 390/684] phy: core: Remove extra space after '=' Remove extra space after '=' to comply with coding style. Signed-off-by: Claudiu Beznea Reviewed-by: Neil Armstrong Signed-off-by: Vinod Koul --- drivers/phy/phy-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 60be8af984bf06..8d227890a345fd 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -361,7 +361,7 @@ int phy_power_off(struct phy *phy) mutex_lock(&phy->mutex); if (phy->power_count == 1 && phy->ops->power_off) { - ret = phy->ops->power_off(phy); + ret = phy->ops->power_off(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); mutex_unlock(&phy->mutex); From 4f816512aaa1fa3b74df7473ef771ebef511255e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 29 Oct 2025 08:40:33 +0000 Subject: [PATCH 391/684] dt-bindings: phy: renesas: Document Renesas RZ/G3E USB3.0 PHY Document Renesas RZ/G3E USB3.0 PHY. This IP is connected between USB3HOST and PHY module. The main functions of the module are as follows: - Reset control - Control of PHY input pins - Monitoring of PHY output pins Acked-by: Conor Dooley Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20251029084037.108610-2-biju.das.jz@bp.renesas.com Signed-off-by: Vinod Koul --- .../bindings/phy/renesas,rzg3e-usb3-phy.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/renesas,rzg3e-usb3-phy.yaml diff --git a/Documentation/devicetree/bindings/phy/renesas,rzg3e-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/renesas,rzg3e-usb3-phy.yaml new file mode 100644 index 00000000000000..b86dc7a291a499 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/renesas,rzg3e-usb3-phy.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/renesas,rzg3e-usb3-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/G3E USB 3.0 PHY + +maintainers: + - Biju Das + +properties: + compatible: + const: renesas,r9a09g047-usb3-phy + + reg: + maxItems: 1 + + clocks: + items: + - description: APB bus clock + - description: USB 2.0 PHY reference clock + - description: USB 3.0 PHY reference clock + + clock-names: + items: + - const: pclk + - const: core + - const: ref_alt_clk_p + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + '#phy-cells': + const: 0 + +required: + - compatible + - reg + - clocks + - clock-names + - power-domains + - resets + - '#phy-cells' + +additionalProperties: false + +examples: + - | + #include + + usb-phy@15870000 { + compatible = "renesas,r9a09g047-usb3-phy"; + reg = <0x15870000 0x10000>; + clocks = <&cpg CPG_MOD 0xb0>, <&cpg CPG_CORE 13>, <&cpg CPG_CORE 12>; + clock-names = "pclk", "core", "ref_alt_clk_p"; + power-domains = <&cpg>; + resets = <&cpg 0xaa>; + #phy-cells = <0>; + }; From ee5f1a3f90a4720f89fd1e250fa6754470da1510 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 29 Oct 2025 08:40:34 +0000 Subject: [PATCH 392/684] phy: renesas: Add Renesas RZ/G3E USB3.0 PHY driver Add Renesas RZ/G3E USB3.0 PHY driver. This module is connected between USB3 Host and PHY module. The main functions of this module are: 1) Reset control 2) Control of PHY input pins 3) Monitoring of PHY output pins Signed-off-by: Biju Das Link: https://patch.msgid.link/20251029084037.108610-3-biju.das.jz@bp.renesas.com Signed-off-by: Vinod Koul --- drivers/phy/renesas/Kconfig | 7 + drivers/phy/renesas/Makefile | 1 + drivers/phy/renesas/phy-rzg3e-usb3.c | 259 +++++++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 drivers/phy/renesas/phy-rzg3e-usb3.c diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig index e342eef0640b78..16211072098e5b 100644 --- a/drivers/phy/renesas/Kconfig +++ b/drivers/phy/renesas/Kconfig @@ -40,3 +40,10 @@ config PHY_RCAR_GEN3_USB3 select GENERIC_PHY help Support for USB 3.0 PHY found on Renesas R-Car generation 3 SoCs. + +config PHY_RZ_G3E_USB3 + tristate "Renesas RZ/G3E USB 3.0 PHY driver" + depends on ARCH_RENESAS || COMPILE_TEST + select GENERIC_PHY + help + Support for USB 3.0 PHY found on Renesas RZ/G3E SoCs. diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile index 8896d1919faa6e..0e98083f2f0c81 100644 --- a/drivers/phy/renesas/Makefile +++ b/drivers/phy/renesas/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_PHY_RCAR_GEN3_PCIE) += phy-rcar-gen3-pcie.o obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o obj-$(CONFIG_PHY_RCAR_GEN3_USB3) += phy-rcar-gen3-usb3.o +obj-$(CONFIG_PHY_RZ_G3E_USB3) += phy-rzg3e-usb3.o diff --git a/drivers/phy/renesas/phy-rzg3e-usb3.c b/drivers/phy/renesas/phy-rzg3e-usb3.c new file mode 100644 index 00000000000000..6b3453ea0004cf --- /dev/null +++ b/drivers/phy/renesas/phy-rzg3e-usb3.c @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G3E USB3.0 PHY driver + * + * Copyright (C) 2025 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB3_TEST_RESET 0x0000 +#define USB3_TEST_UTMICTRL2 0x0b04 +#define USB3_TEST_PRMCTRL5_R 0x0c10 +#define USB3_TEST_PRMCTRL6_R 0x0c14 + +#define USB3_TEST_RSTCTRL 0x1000 +#define USB3_TEST_CLKCTRL 0x1004 +#define USB3_TEST_RAMCTRL 0x100c +#define USB3_TEST_CREGCTRL 0x1010 +#define USB3_TEST_LANECONFIG0 0x1030 + +#define USB3_TEST_RESET_PORTRESET0_CTRL BIT(9) +#define USB3_TEST_RESET_SIDDQ BIT(3) +#define USB3_TEST_RESET_PHY_RESET BIT(2) +#define USB3_TEST_RESET_PORTRESET0 BIT(1) +#define USB3_TEST_RESET_RELEASE_OVERRIDE (0) + +#define USB3_TEST_UTMICTRL2_CTRL_MASK GENMASK(9, 8) +#define USB3_TEST_UTMICTRL2_MODE_MASK GENMASK(1, 0) + +#define USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK GENMASK(2, 1) + +#define USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK GENMASK(2, 0) + +#define USB3_TEST_RSTCTRL_HARDRESET_ODEN BIT(9) +#define USB3_TEST_RSTCTRL_PIPERESET_ODEN BIT(8) +#define USB3_TEST_RSTCTRL_HARDRESET BIT(1) +#define USB3_TEST_RSTCTRL_PIPERESET BIT(0) +#define USB3_TEST_RSTCTRL_ASSERT \ + (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN | \ + USB3_TEST_RSTCTRL_HARDRESET | USB3_TEST_RSTCTRL_PIPERESET) +#define USB3_TEST_RSTCTRL_RELEASE_HARDRESET \ + (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN | \ + USB3_TEST_RSTCTRL_PIPERESET) +#define USB3_TEST_RSTCTRL_DEASSERT \ + (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN) +#define USB3_TEST_RSTCTRL_RELEASE_OVERRIDE (0) + +#define USB3_TEST_CLKCTRL_MPLLA_SSC_EN BIT(2) + +#define USB3_TEST_RAMCTRL_SRAM_INIT_DONE BIT(2) +#define USB3_TEST_RAMCTRL_SRAM_EXT_LD_DONE BIT(0) + +#define USB3_TEST_CREGCTRL_PARA_SEL BIT(8) + +#define USB3_TEST_LANECONFIG0_DEFAULT (0xd) + +struct rz_usb3 { + void __iomem *base; + struct reset_control *rstc; + bool skip_reinit; +}; + +static void rzg3e_phy_usb2test_phy_init(void __iomem *base) +{ + u32 val; + + val = readl(base + USB3_TEST_UTMICTRL2); + val |= USB3_TEST_UTMICTRL2_CTRL_MASK | USB3_TEST_UTMICTRL2_MODE_MASK; + writel(val, base + USB3_TEST_UTMICTRL2); + + val = readl(base + USB3_TEST_PRMCTRL5_R); + val &= ~USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK; + val |= FIELD_PREP(USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK, 2); + writel(val, base + USB3_TEST_PRMCTRL5_R); + + val = readl(base + USB3_TEST_PRMCTRL6_R); + val &= ~USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK; + val |= FIELD_PREP(USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK, 7); + writel(val, base + USB3_TEST_PRMCTRL6_R); + + val = readl(base + USB3_TEST_RESET); + val &= ~USB3_TEST_RESET_SIDDQ; + val |= USB3_TEST_RESET_PORTRESET0_CTRL | USB3_TEST_RESET_PHY_RESET | + USB3_TEST_RESET_PORTRESET0; + writel(val, base + USB3_TEST_RESET); + fsleep(10); + + val &= ~(USB3_TEST_RESET_PHY_RESET | USB3_TEST_RESET_PORTRESET0); + writel(val, base + USB3_TEST_RESET); + fsleep(10); + + val = readl(base + USB3_TEST_UTMICTRL2); + val &= ~USB3_TEST_UTMICTRL2_CTRL_MASK; + writel(val, base + USB3_TEST_UTMICTRL2); + + writel(USB3_TEST_RESET_RELEASE_OVERRIDE, base + USB3_TEST_RESET); +} + +static int rzg3e_phy_usb3test_phy_init(void __iomem *base) +{ + int ret; + u32 val; + + writel(USB3_TEST_CREGCTRL_PARA_SEL, base + USB3_TEST_CREGCTRL); + writel(USB3_TEST_RSTCTRL_ASSERT, base + USB3_TEST_RSTCTRL); + fsleep(20); + + writel(USB3_TEST_CLKCTRL_MPLLA_SSC_EN, base + USB3_TEST_CLKCTRL); + writel(USB3_TEST_LANECONFIG0_DEFAULT, base + USB3_TEST_LANECONFIG0); + writel(USB3_TEST_RSTCTRL_RELEASE_HARDRESET, base + USB3_TEST_RSTCTRL); + + ret = readl_poll_timeout_atomic(base + USB3_TEST_RAMCTRL, val, + val & USB3_TEST_RAMCTRL_SRAM_INIT_DONE, 1, 10000); + if (ret) + return ret; + + writel(USB3_TEST_RSTCTRL_DEASSERT, base + USB3_TEST_RSTCTRL); + writel(USB3_TEST_RAMCTRL_SRAM_EXT_LD_DONE, base + USB3_TEST_RAMCTRL); + writel(USB3_TEST_RSTCTRL_RELEASE_OVERRIDE, base + USB3_TEST_RSTCTRL); + + return 0; +} + +static int rzg3e_phy_usb3_init_helper(void __iomem *base) +{ + rzg3e_phy_usb2test_phy_init(base); + + return rzg3e_phy_usb3test_phy_init(base); +} + +static int rzg3e_phy_usb3_init(struct phy *p) +{ + struct rz_usb3 *r = phy_get_drvdata(p); + int ret = 0; + + if (!r->skip_reinit) + ret = rzg3e_phy_usb3_init_helper(r->base); + + return ret; +} + +static const struct phy_ops rzg3e_phy_usb3_ops = { + .init = rzg3e_phy_usb3_init, + .owner = THIS_MODULE, +}; + +static int rzg3e_phy_usb3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy_provider *provider; + struct rz_usb3 *r; + struct phy *phy; + int ret; + + r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL); + if (!r) + return -ENOMEM; + + r->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(r->base)) + return PTR_ERR(r->base); + + r->rstc = devm_reset_control_get_shared_deasserted(dev, NULL); + if (IS_ERR(r->rstc)) + return dev_err_probe(dev, PTR_ERR(r->rstc), "failed to get deasserted reset\n"); + + /* + * devm_phy_create() will call pm_runtime_enable(&phy->dev); + * And then, phy-core will manage runtime pm for this device. + */ + ret = devm_pm_runtime_enable(dev); + if (ret < 0) + return ret; + + phy = devm_phy_create(dev, NULL, &rzg3e_phy_usb3_ops); + if (IS_ERR(phy)) + return dev_err_probe(dev, PTR_ERR(phy), "failed to create USB3 PHY\n"); + + platform_set_drvdata(pdev, r); + phy_set_drvdata(phy, r); + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(provider)) + return dev_err_probe(dev, PTR_ERR(provider), "failed to register PHY provider\n"); + + return 0; +} + +static int rzg3e_phy_usb3_suspend(struct device *dev) +{ + struct rz_usb3 *r = dev_get_drvdata(dev); + + pm_runtime_put(dev); + reset_control_assert(r->rstc); + r->skip_reinit = false; + + return 0; +} + +static int rzg3e_phy_usb3_resume(struct device *dev) +{ + struct rz_usb3 *r = dev_get_drvdata(dev); + int ret; + + ret = reset_control_deassert(r->rstc); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto reset_assert; + + ret = rzg3e_phy_usb3_init_helper(r->base); + if (ret) + goto pm_put; + + r->skip_reinit = true; + + return 0; + +pm_put: + pm_runtime_put(dev); +reset_assert: + reset_control_assert(r->rstc); + return ret; +} + +static const struct dev_pm_ops rzg3e_phy_usb3_pm = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(rzg3e_phy_usb3_suspend, rzg3e_phy_usb3_resume) +}; + +static const struct of_device_id rzg3e_phy_usb3_match_table[] = { + { .compatible = "renesas,r9a09g047-usb3-phy" }, + { /* Sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, rzg3e_phy_usb3_match_table); +static struct platform_driver rzg3e_phy_usb3_driver = { + .driver = { + .name = "phy_rzg3e_usb3", + .of_match_table = rzg3e_phy_usb3_match_table, + .pm = pm_sleep_ptr(&rzg3e_phy_usb3_pm), + }, + .probe = rzg3e_phy_usb3_probe, +}; +module_platform_driver(rzg3e_phy_usb3_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Renesas RZ/G3E USB3.0 PHY Driver"); +MODULE_AUTHOR("biju.das.jz@bp.renesas.com>"); From aa788d3b475652a3ebaca32ca714f02f8ece3393 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 18 Nov 2025 12:47:07 +0530 Subject: [PATCH 393/684] clk: qcom: branch: Extend invert logic for branch2 mem clocks Some clock branches require inverted logic for memory gating, where disabling the memory involves setting a bit and enabling it involves clearing the same bit. This behavior differs from the standard approach memory branch clocks ops where enabling typically sets the bit. The mem_enable_invert to allow conditional handling of these sequences of the inverted control logic for memory operations required on those memory clock branches. Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20251118-sm8750-videocc-v2-v4-3-049882a70c9f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-branch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 0f10090d4ae681..444e7d8648d42c 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -142,8 +142,8 @@ static int clk_branch2_mem_enable(struct clk_hw *hw) u32 val; int ret; - regmap_update_bits(branch.clkr.regmap, mem_br->mem_enable_reg, - mem_br->mem_enable_ack_mask, mem_br->mem_enable_ack_mask); + regmap_assign_bits(branch.clkr.regmap, mem_br->mem_enable_reg, + mem_br->mem_enable_mask, !mem_br->mem_enable_invert); ret = regmap_read_poll_timeout(branch.clkr.regmap, mem_br->mem_ack_reg, val, val & mem_br->mem_enable_ack_mask, 0, 200); @@ -159,8 +159,8 @@ static void clk_branch2_mem_disable(struct clk_hw *hw) { struct clk_mem_branch *mem_br = to_clk_mem_branch(hw); - regmap_update_bits(mem_br->branch.clkr.regmap, mem_br->mem_enable_reg, - mem_br->mem_enable_ack_mask, 0); + regmap_assign_bits(mem_br->branch.clkr.regmap, mem_br->mem_enable_reg, + mem_br->mem_enable_mask, mem_br->mem_enable_invert); return clk_branch2_disable(hw); } From b190eaea57803da00a4318ba12359625337be9e8 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 18 Nov 2025 12:47:08 +0530 Subject: [PATCH 394/684] dt-bindings: clock: qcom: Add SM8750 video clock controller Add compatible string for SM8750 video clock controller and the bindings for SM8750 Qualcomm SoC. Signed-off-by: Taniya Das Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20251118-sm8750-videocc-v2-v4-4-049882a70c9f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/clock/qcom,sm8450-videocc.yaml | 5 ++- .../dt-bindings/clock/qcom,sm8750-videocc.h | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/qcom,sm8750-videocc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml index fcd2727dae4671..b31bd833552937 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Video Clock & Reset Controller on SM8450 maintainers: - - Taniya Das + - Taniya Das - Jagadeesh Kona description: | @@ -17,6 +17,7 @@ description: | See also: include/dt-bindings/clock/qcom,sm8450-videocc.h include/dt-bindings/clock/qcom,sm8650-videocc.h + include/dt-bindings/clock/qcom,sm8750-videocc.h properties: compatible: @@ -25,6 +26,7 @@ properties: - qcom,sm8475-videocc - qcom,sm8550-videocc - qcom,sm8650-videocc + - qcom,sm8750-videocc - qcom,x1e80100-videocc clocks: @@ -61,6 +63,7 @@ allOf: enum: - qcom,sm8450-videocc - qcom,sm8550-videocc + - qcom,sm8750-videocc then: required: - required-opps diff --git a/include/dt-bindings/clock/qcom,sm8750-videocc.h b/include/dt-bindings/clock/qcom,sm8750-videocc.h new file mode 100644 index 00000000000000..f3bfa2ba51607d --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm8750-videocc.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8750_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8750_H + +/* VIDEO_CC clocks */ +#define VIDEO_CC_AHB_CLK 0 +#define VIDEO_CC_AHB_CLK_SRC 1 +#define VIDEO_CC_MVS0_CLK 2 +#define VIDEO_CC_MVS0_CLK_SRC 3 +#define VIDEO_CC_MVS0_DIV_CLK_SRC 4 +#define VIDEO_CC_MVS0_FREERUN_CLK 5 +#define VIDEO_CC_MVS0_SHIFT_CLK 6 +#define VIDEO_CC_MVS0C_CLK 7 +#define VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC 8 +#define VIDEO_CC_MVS0C_FREERUN_CLK 9 +#define VIDEO_CC_MVS0C_SHIFT_CLK 10 +#define VIDEO_CC_PLL0 11 +#define VIDEO_CC_SLEEP_CLK 12 +#define VIDEO_CC_SLEEP_CLK_SRC 13 +#define VIDEO_CC_XO_CLK 14 +#define VIDEO_CC_XO_CLK_SRC 15 + +/* VIDEO_CC power domains */ +#define VIDEO_CC_MVS0_GDSC 0 +#define VIDEO_CC_MVS0C_GDSC 1 + +/* VIDEO_CC resets */ +#define VIDEO_CC_INTERFACE_BCR 0 +#define VIDEO_CC_MVS0_BCR 1 +#define VIDEO_CC_MVS0C_CLK_ARES 2 +#define VIDEO_CC_MVS0C_BCR 3 +#define VIDEO_CC_MVS0_FREERUN_CLK_ARES 4 +#define VIDEO_CC_MVS0C_FREERUN_CLK_ARES 5 +#define VIDEO_CC_XO_CLK_ARES 6 + +#endif From a160860529b55c54dbd54137f86c818a53d07655 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 18 Nov 2025 12:47:09 +0530 Subject: [PATCH 395/684] clk: qcom: videocc-sm8750: Add video clock controller driver for SM8750 Add support for the video clock controller for video clients to be able to request for videocc clocks on SM8750 platform. Reviewed-by: Konrad Dybcio Signed-off-by: Taniya Das Reviewed-by: Dmitry Baryshkov Reviewed-by: Imran Shaik Link: https://lore.kernel.org/r/20251118-sm8750-videocc-v2-v4-5-049882a70c9f@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 11 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/videocc-sm8750.c | 463 ++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 100644 drivers/clk/qcom/videocc-sm8750.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 550a9d82a6b386..a284ba040b78ba 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1531,6 +1531,17 @@ config SM_VIDEOCC_8550 Say Y if you want to support video devices and functionality such as video encode/decode. +config SM_VIDEOCC_8750 + tristate "SM8750 Video Clock Controller" + depends on ARM64 || COMPILE_TEST + select SM_GCC_8750 + select QCOM_GDSC + help + Support for the video clock controller on Qualcomm Technologies, Inc. + SM8750 devices. + Say Y if you want to support video devices and functionality such as + video encode/decode. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 5a0fd1d843c87a..0ac8a9055a4323 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -185,6 +185,7 @@ obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o obj-$(CONFIG_SM_VIDEOCC_8350) += videocc-sm8350.o obj-$(CONFIG_SM_VIDEOCC_8450) += videocc-sm8450.o obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o +obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o diff --git a/drivers/clk/qcom/videocc-sm8750.c b/drivers/clk/qcom/videocc-sm8750.c new file mode 100644 index 00000000000000..0acf3104d702b6 --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8750.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_SLEEP_CLK, + P_VIDEO_CC_PLL0_OUT_MAIN, +}; + +static const struct pll_vco taycan_elu_vco[] = { + { 249600000, 2500000000, 0 }, +}; + +static const struct alpha_pll_config video_cc_pll0_config = { + .l = 0x25, + .alpha = 0x8000, + .config_ctl_val = 0x19660387, + .config_ctl_hi_val = 0x098060a0, + .config_ctl_hi1_val = 0xb416cb20, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll video_cc_pll0 = { + .offset = 0x0, + .config = &video_cc_pll0_config, + .vco_table = taycan_elu_vco, + .num_vco = ARRAY_SIZE(taycan_elu_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_elu_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0_ao[] = { + { .index = DT_BI_TCXO_AO }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_2_ao[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_ahb_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_ahb_clk_src", + .parent_data = video_cc_parent_data_0_ao, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1260000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1710000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1890000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_sleep_clk_src = { + .cmd_rcgr = 0x80e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_sleep_clk_src", + .parent_data = video_cc_parent_data_2_ao, + .num_parents = ARRAY_SIZE(video_cc_parent_data_2_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 video_cc_xo_clk_src = { + .cmd_rcgr = 0x80bc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_xo_clk_src", + .parent_data = video_cc_parent_data_0_ao, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0x809c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0x807c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x807c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x807c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_mem_branch video_cc_mvs0_freerun_clk = { + .mem_enable_reg = 0x8090, + .mem_ack_reg = 0x8090, + .mem_enable_mask = BIT(3), + .mem_enable_ack_mask = GENMASK(11, 10), + .mem_enable_invert = true, + .branch = { + .halt_reg = 0x808c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x808c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_mem_ops, + }, + }, + }, +}; + +static struct clk_branch video_cc_mvs0_shift_clk = { + .halt_reg = 0x80d8, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80d8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0x804c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_freerun_clk = { + .halt_reg = 0x805c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x805c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_shift_clk = { + .halt_reg = 0x80dc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80dc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc video_cc_mvs0c_gdsc = { + .gdscr = 0x8034, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs0_gdsc = { + .gdscr = 0x8068, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs0c_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL_TRIGGER, +}; + +static struct clk_regmap *video_cc_sm8750_clocks[] = { + [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0_FREERUN_CLK] = &video_cc_mvs0_freerun_clk.branch.clkr, + [VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS0C_FREERUN_CLK] = &video_cc_mvs0c_freerun_clk.clkr, + [VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr, + [VIDEO_CC_PLL0] = &video_cc_pll0.clkr, + [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, + [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, +}; + +static struct gdsc *video_cc_sm8750_gdscs[] = { + [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, + [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, +}; + +static const struct qcom_reset_map video_cc_sm8750_resets[] = { + [VIDEO_CC_INTERFACE_BCR] = { 0x80a0 }, + [VIDEO_CC_MVS0_BCR] = { 0x8064 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, + [VIDEO_CC_MVS0C_BCR] = { 0x8030 }, + [VIDEO_CC_MVS0_FREERUN_CLK_ARES] = { 0x808c, 2 }, + [VIDEO_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 }, + [VIDEO_CC_XO_CLK_ARES] = { 0x80d4, 2 }, +}; + +static const struct regmap_config video_cc_sm8750_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f4c, + .fast_io = true, +}; + +static struct clk_alpha_pll *video_cc_sm8750_plls[] = { + &video_cc_pll0, +}; + +static u32 video_cc_sm8750_critical_cbcrs[] = { + 0x80a4, /* VIDEO_CC_AHB_CLK */ + 0x80f8, /* VIDEO_CC_SLEEP_CLK */ + 0x80d4, /* VIDEO_CC_XO_CLK */ +}; + +static void clk_sm8750_regs_configure(struct device *dev, struct regmap *regmap) +{ + /* Update DLY_ACCU_RED_SHIFTER_DONE to 0xF for mvs0, mvs0c */ + regmap_update_bits(regmap, 0x8074, GENMASK(25, 21), GENMASK(25, 21)); + regmap_update_bits(regmap, 0x8040, GENMASK(25, 21), GENMASK(25, 21)); + + regmap_update_bits(regmap, 0x9f24, BIT(0), BIT(0)); +} + +static struct qcom_cc_driver_data video_cc_sm8750_driver_data = { + .alpha_plls = video_cc_sm8750_plls, + .num_alpha_plls = ARRAY_SIZE(video_cc_sm8750_plls), + .clk_cbcrs = video_cc_sm8750_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(video_cc_sm8750_critical_cbcrs), + .clk_regs_configure = clk_sm8750_regs_configure, +}; + +static struct qcom_cc_desc video_cc_sm8750_desc = { + .config = &video_cc_sm8750_regmap_config, + .clks = video_cc_sm8750_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8750_clocks), + .resets = video_cc_sm8750_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8750_resets), + .gdscs = video_cc_sm8750_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8750_gdscs), + .use_rpm = true, + .driver_data = &video_cc_sm8750_driver_data, +}; + +static const struct of_device_id video_cc_sm8750_match_table[] = { + { .compatible = "qcom,sm8750-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8750_match_table); + +static int video_cc_sm8750_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &video_cc_sm8750_desc); +} + +static struct platform_driver video_cc_sm8750_driver = { + .probe = video_cc_sm8750_probe, + .driver = { + .name = "video_cc-sm8750", + .of_match_table = video_cc_sm8750_match_table, + }, +}; + +static int __init video_cc_sm8750_init(void) +{ + return platform_driver_register(&video_cc_sm8750_driver); +} +subsys_initcall(video_cc_sm8750_init); + +static void __exit video_cc_sm8750_exit(void) +{ + platform_driver_unregister(&video_cc_sm8750_driver); +} +module_exit(video_cc_sm8750_exit); + +MODULE_DESCRIPTION("QTI VIDEO_CC SM8750 Driver"); +MODULE_LICENSE("GPL"); From c84b824d3a8f14bedec8108cb8061da761180f49 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 18 Nov 2025 18:33:11 +0100 Subject: [PATCH 396/684] dt-bindings: clock: qcom: x1e80100-dispcc: Add USB4 router link resets The router link clock branches also feature some reset logic, which is required to properly power sequence the hardware for DP tunneling over USB4. Describe these missing resets. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20251118-topic-usb4_x1e_dispcc-v1-1-14c68d842c71@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/clock/qcom,x1e80100-dispcc.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/clock/qcom,x1e80100-dispcc.h b/include/dt-bindings/clock/qcom,x1e80100-dispcc.h index d4a83e4fd0d1ff..49b3a9e5ce4a9e 100644 --- a/include/dt-bindings/clock/qcom,x1e80100-dispcc.h +++ b/include/dt-bindings/clock/qcom,x1e80100-dispcc.h @@ -90,6 +90,9 @@ #define DISP_CC_MDSS_CORE_BCR 0 #define DISP_CC_MDSS_CORE_INT2_BCR 1 #define DISP_CC_MDSS_RSCC_BCR 2 +#define DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK_ARES 3 +#define DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK_ARES 4 +#define DISP_CC_MDSS_DPTX2_USB_ROUTER_LINK_INTF_CLK_ARES 5 /* DISP_CC GDSCR */ #define MDSS_GDSC 0 From 3664282f3345fdfa6a154feb6ed6c3217a8b3b0d Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 18 Nov 2025 18:33:12 +0100 Subject: [PATCH 397/684] clk: qcom: x1e80100-dispcc: Add USB4 router link resets The router link clock branches also feature some reset logic, which is required to properly power sequence the hardware for DP tunneling over USB4. Describe these missing resets. Signed-off-by: Konrad Dybcio Reviewed-by: Taniya Das Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251118-topic-usb4_x1e_dispcc-v1-2-14c68d842c71@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-x1e80100.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/dispcc-x1e80100.c b/drivers/clk/qcom/dispcc-x1e80100.c index 40069eba41f241..aa7fd43969f9c8 100644 --- a/drivers/clk/qcom/dispcc-x1e80100.c +++ b/drivers/clk/qcom/dispcc-x1e80100.c @@ -1618,6 +1618,9 @@ static struct clk_regmap *disp_cc_x1e80100_clocks[] = { static const struct qcom_reset_map disp_cc_x1e80100_resets[] = { [DISP_CC_MDSS_CORE_BCR] = { 0x8000 }, + [DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK_ARES] = { .reg = 0x8044, .bit = 2 }, + [DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK_ARES] = { .reg = 0x8068, .bit = 2 }, + [DISP_CC_MDSS_DPTX2_USB_ROUTER_LINK_INTF_CLK_ARES] = { .reg = 0x8088, .bit = 2 }, [DISP_CC_MDSS_CORE_INT2_BCR] = { 0xa000 }, [DISP_CC_MDSS_RSCC_BCR] = { 0xc000 }, }; From f2bd5a0f59d052d16749bccf637690e51947a5d6 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sat, 15 Nov 2025 18:00:00 +0800 Subject: [PATCH 398/684] pinctrl: airoha: fix pinctrl function mismatch issue The blamed commit made the following changes: -#define PINCTRL_FUNC_DESC(id)... - .desc = PINCTRL_PINFUNCTION(#id, ... +#define PINCTRL_FUNC_DESC(id, table)... + .desc = PINCTRL_PINFUNCTION(#id, ... - PINCTRL_FUNC_DESC(pon)... + PINCTRL_FUNC_DESC("pon", pon)... It's clear that the id of funcs doesn't match the definition. Remove redundant #string from the definition to fix this issue: pinctrl-airoha ...: invalid function mdio in map table Fixes: 4043b0c45f85 ("pinctrl: airoha: generalize pins/group/function/confs handling") Signed-off-by: Chukun Pan Acked-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index 983d96fd399a2d..2a5b9b6f08d9ea 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -35,7 +35,7 @@ #define PINCTRL_FUNC_DESC(id, table) \ { \ - .desc = PINCTRL_PINFUNCTION(#id, table##_groups, \ + .desc = PINCTRL_PINFUNCTION(id, table##_groups, \ ARRAY_SIZE(table##_groups)),\ .groups = table##_func_group, \ .group_size = ARRAY_SIZE(table##_func_group), \ From 0341d1b1ebf10bcbb9f35e174e83dbb21068387d Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 12 Nov 2025 11:44:30 -0700 Subject: [PATCH 399/684] pinctrl: airoha: Fix AIROHA_PINCTRL_CONFS_DRIVE_E2 in an7583_pinctrl_match_data Clang warns (or errors with CONFIG_WERROR=y / W=e): pinctrl/mediatek/pinctrl-airoha.c:2064:41: error: variable 'an7583_pinctrl_drive_e2_conf' is not needed and will not be emitted [-Werror,-Wunneeded-internal-declaration] 2064 | static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e2_conf[] = { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Due to a typo, an7583_pinctrl_drive_e2_conf is only used within ARRAY_SIZE() (hence no instance of -Wunused-variable), which is evaluated at compile time, so it will not be needed in the final object file. Fix the .confs assignment for AIROHA_PINCTRL_CONFS_DRIVE_E2 in an7583_pinctrl_match_data to clear up the warning. Closes: https://github.com/ClangBuiltLinux/linux/issues/2142 Fixes: 3ffeb17a9a27 ("pinctrl: airoha: add support for Airoha AN7583 PINs") Signed-off-by: Nathan Chancellor Acked-by: Christian Marangi Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-airoha.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c index 2a5b9b6f08d9ea..995ba6175c9504 100644 --- a/drivers/pinctrl/mediatek/pinctrl-airoha.c +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -2993,7 +2993,7 @@ static const struct airoha_pinctrl_match_data an7583_pinctrl_match_data = { .num_confs = ARRAY_SIZE(an7583_pinctrl_pulldown_conf), }, [AIROHA_PINCTRL_CONFS_DRIVE_E2] = { - .confs = en7581_pinctrl_drive_e2_conf, + .confs = an7583_pinctrl_drive_e2_conf, .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e2_conf), }, [AIROHA_PINCTRL_CONFS_DRIVE_E4] = { From 33e1fffea492b7158a168914dc0da6aedf78d08e Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:27 +0000 Subject: [PATCH 400/684] perf arm_spe: Fix memset subclass in operation The operation subclass is extracted from bits [7..1] of the payload. Since bit [0] is not parsed, there is no chance to match the memset type (0x25). As a result, the memset payload is never parsed successfully. Instead of extracting a unified bit field, change to extract the specific bits for each operation subclass. Fixes: 34fb60400e32 ("perf arm-spe: Add raw decoding for SPEv1.3 MTE and MOPS load/store") Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- .../arm-spe-decoder/arm-spe-pkt-decoder.c | 25 ++++++------------- .../arm-spe-decoder/arm-spe-pkt-decoder.h | 15 ++++++----- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 80561630253dd5..1a1ffe50ee73ab 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -371,31 +371,20 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, arm_spe_pkt_out_string(&err, &buf, &buf_len, " AR"); } - switch (SPE_OP_PKT_LDST_SUBCLASS_GET(payload)) { - case SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP: + if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " SIMD-FP"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_GP_REG: + else if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " GP-REG"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG: + else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " UNSPEC-REG"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG: + else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " NV-SYSREG"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG: + else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " MTE-TAG"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_MEMCPY: + else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMCPY"); - break; - case SPE_OP_PKT_LDST_SUBCLASS_MEMSET: + else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMSET"); - break; - default: - break; - } if (SPE_OP_PKT_IS_LDST_SVE(payload)) { /* SVE effective vector length */ diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index d00c2481712dcc..75e355fe3438cc 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -125,14 +125,13 @@ enum arm_spe_events { #define SPE_OP_PKT_IS_OTHER_SVE_OP(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8) -#define SPE_OP_PKT_LDST_SUBCLASS_GET(v) ((v) & GENMASK_ULL(7, 1)) -#define SPE_OP_PKT_LDST_SUBCLASS_GP_REG 0x0 -#define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP 0x4 -#define SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG 0x10 -#define SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG 0x30 -#define SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG 0x14 -#define SPE_OP_PKT_LDST_SUBCLASS_MEMCPY 0x20 -#define SPE_OP_PKT_LDST_SUBCLASS_MEMSET 0x25 +#define SPE_OP_PKT_LDST_SUBCLASS_GP_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x0) +#define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(v) (((v) & GENMASK_ULL(7, 1)) == 0x4) +#define SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x10) +#define SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(v) (((v) & GENMASK_ULL(7, 1)) == 0x30) +#define SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(v) (((v) & GENMASK_ULL(7, 1)) == 0x14) +#define SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(v) (((v) & GENMASK_ULL(7, 1)) == 0x20) +#define SPE_OP_PKT_LDST_SUBCLASS_MEMSET(v) (((v) & GENMASK_ULL(7, 0)) == 0x25) #define SPE_OP_PKT_IS_LDST_ATOMIC(v) (((v) & (GENMASK_ULL(7, 5) | BIT(1))) == 0x2) From b61ca7219db82f474e71ec5ab68eb5370ce18df2 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:28 +0000 Subject: [PATCH 401/684] perf arm_spe: Unify operation naming Rename extended subclass and SVE/SME register access subclass, so that the naming can be consistent cross all sub classes. Add an log "SVE-SME-REG" for the SVE/SME register access, this is easier for parsing. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- .../util/arm-spe-decoder/arm-spe-decoder.c | 2 +- .../arm-spe-decoder/arm-spe-pkt-decoder.c | 21 +++++++++---------- .../arm-spe-decoder/arm-spe-pkt-decoder.h | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 96eb7cced6fd15..b0fb896abad48d 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -200,7 +200,7 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_ST; else decoder->record.op |= ARM_SPE_OP_LD; - if (SPE_OP_PKT_IS_LDST_SVE(payload)) + if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) decoder->record.op |= ARM_SPE_OP_SVE_LDST; break; case SPE_OP_PKT_HDR_CLASS_OTHER: diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 1a1ffe50ee73ab..f6e9c58ce62f3a 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -362,31 +362,30 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, arm_spe_pkt_out_string(&err, &buf, &buf_len, payload & 0x1 ? "ST" : "LD"); - if (SPE_OP_PKT_IS_LDST_ATOMIC(payload)) { + if (SPE_OP_PKT_LDST_SUBCLASS_EXTENDED(payload)) { if (payload & SPE_OP_PKT_AT) arm_spe_pkt_out_string(&err, &buf, &buf_len, " AT"); if (payload & SPE_OP_PKT_EXCL) arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCL"); if (payload & SPE_OP_PKT_AR) arm_spe_pkt_out_string(&err, &buf, &buf_len, " AR"); - } - - if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " SIMD-FP"); - else if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " GP-REG"); - else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " UNSPEC-REG"); - else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " NV-SYSREG"); - else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " MTE-TAG"); - else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMCPY"); - else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) + } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, " MEMSET"); + } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) { + arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-SME-REG"); - if (SPE_OP_PKT_IS_LDST_SVE(payload)) { /* SVE effective vector length */ arm_spe_pkt_out_string(&err, &buf, &buf_len, " EVLEN %d", SPE_OP_PKG_SVE_EVL(payload)); diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index 75e355fe3438cc..cb947e62591892 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -133,14 +133,14 @@ enum arm_spe_events { #define SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(v) (((v) & GENMASK_ULL(7, 1)) == 0x20) #define SPE_OP_PKT_LDST_SUBCLASS_MEMSET(v) (((v) & GENMASK_ULL(7, 0)) == 0x25) -#define SPE_OP_PKT_IS_LDST_ATOMIC(v) (((v) & (GENMASK_ULL(7, 5) | BIT(1))) == 0x2) +#define SPE_OP_PKT_LDST_SUBCLASS_EXTENDED(v) (((v) & (GENMASK_ULL(7, 5) | BIT(1))) == 0x2) #define SPE_OP_PKT_AR BIT(4) #define SPE_OP_PKT_EXCL BIT(3) #define SPE_OP_PKT_AT BIT(2) #define SPE_OP_PKT_ST BIT(0) -#define SPE_OP_PKT_IS_LDST_SVE(v) (((v) & (BIT(3) | BIT(1))) == 0x8) +#define SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(v) (((v) & (BIT(3) | BIT(1))) == 0x8) #define SPE_OP_PKT_SVE_SG BIT(7) /* From b4eaece3d9df603772070f03d3086746c113ae2e Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:29 +0000 Subject: [PATCH 402/684] perf arm_spe: Decode GCS operation Decode a load or store from a GCS operation and the associated "common" field. After: . 00000000: 49 44 LD GCS COMM . 00000002: b2 18 3c d7 83 00 80 ff ff VA 0xffff800083d73c18 . 0000000b: 9a 00 00 LAT 0 XLAT . 0000000e: 43 00 DATA-SOURCE 0 Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 4 ++++ tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index f6e9c58ce62f3a..0046079edaccdd 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -394,6 +394,10 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED"); if (payload & SPE_OP_PKT_SVE_SG) arm_spe_pkt_out_string(&err, &buf, &buf_len, " SG"); + } else if (SPE_OP_PKT_LDST_SUBCLASS_GCS(payload)) { + arm_spe_pkt_out_string(&err, &buf, &buf_len, " GCS"); + if (payload & SPE_OP_PKT_GCS_COMM) + arm_spe_pkt_out_string(&err, &buf, &buf_len, " COMM"); } break; case SPE_OP_PKT_HDR_CLASS_BR_ERET: diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index cb947e62591892..94333e7bc382de 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -154,6 +154,10 @@ enum arm_spe_events { #define SPE_OP_PKT_SVE_PRED BIT(2) #define SPE_OP_PKT_SVE_FP BIT(1) +#define SPE_OP_PKT_LDST_SUBCLASS_GCS(v) (((v) & (GENMASK_ULL(7, 3) | BIT(1))) == 0x40) + +#define SPE_OP_PKT_GCS_COMM BIT(2) + #define SPE_OP_PKT_CR_MASK GENMASK_ULL(4, 3) #define SPE_OP_PKT_CR_BL(v) (FIELD_GET(SPE_OP_PKT_CR_MASK, (v)) == 1) #define SPE_OP_PKT_CR_RET(v) (FIELD_GET(SPE_OP_PKT_CR_MASK, (v)) == 2) From c8bf2a05dff4bbbfd1ffe1888de8bbd1bf4e2c3a Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:30 +0000 Subject: [PATCH 403/684] perf arm_spe: Rename SPE_OP_PKT_IS_OTHER_SVE_OP macro Rename the macro to SPE_OP_PKT_OTHER_SUBCLASS_SVE to unify naming. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 2 +- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 2 +- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index b0fb896abad48d..847c29385bea86 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -205,7 +205,7 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) break; case SPE_OP_PKT_HDR_CLASS_OTHER: decoder->record.op |= ARM_SPE_OP_OTHER; - if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) + if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) decoder->record.op |= ARM_SPE_OP_SVE_OTHER; break; case SPE_OP_PKT_HDR_CLASS_BR_ERET: diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 0046079edaccdd..533920b738cbcb 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -340,7 +340,7 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, switch (packet->index) { case SPE_OP_PKT_HDR_CLASS_OTHER: - if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) { + if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, "SVE-OTHER"); /* SVE effective vector length */ diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index 94333e7bc382de..48bd9e9ef132b1 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -123,7 +123,7 @@ enum arm_spe_events { #define SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC 0x1 #define SPE_OP_PKT_HDR_CLASS_BR_ERET 0x2 -#define SPE_OP_PKT_IS_OTHER_SVE_OP(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8) +#define SPE_OP_PKT_OTHER_SUBCLASS_SVE(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8) #define SPE_OP_PKT_LDST_SUBCLASS_GP_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x0) #define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(v) (((v) & GENMASK_ULL(7, 1)) == 0x4) From 876294a6455e9bba81391c76f78c4563c3b8bc1d Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:31 +0000 Subject: [PATCH 404/684] perf arm_spe: Decode ASE and FP fields in other operation Add a check for other operation, which prevents any incorrectly classifying. Parse the ASE and FP fields. After: . 0000002f: 48 06 OTHER ASE FP INSN-OTHER . 00000031: b2 08 80 48 01 08 00 ff ff VA 0xffff000801488008 . 0000003a: 9a 00 00 LAT 0 XLAT . 0000003d: 42 16 EV RETIRED L1D-ACCESS TLB-ACCESS Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 6 +++++- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 533920b738cbcb..21b65a9b40f481 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -351,8 +351,12 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP"); if (payload & SPE_OP_PKT_SVE_PRED) arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED"); - } else { + } else if (SPE_OP_PKT_OTHER_SUBCLASS_OTHER(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, "OTHER"); + if (payload & SPE_OP_PKT_OTHER_ASE) + arm_spe_pkt_out_string(&err, &buf, &buf_len, " ASE"); + if (payload & SPE_OP_PKT_OTHER_FP) + arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP"); arm_spe_pkt_out_string(&err, &buf, &buf_len, " %s", payload & SPE_OP_PKT_COND ? "COND-SELECT" : "INSN-OTHER"); diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index 48bd9e9ef132b1..704601c6dbe30e 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -123,8 +123,12 @@ enum arm_spe_events { #define SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC 0x1 #define SPE_OP_PKT_HDR_CLASS_BR_ERET 0x2 +#define SPE_OP_PKT_OTHER_SUBCLASS_OTHER(v) (((v) & GENMASK_ULL(7, 3)) == 0x0) #define SPE_OP_PKT_OTHER_SUBCLASS_SVE(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8) +#define SPE_OP_PKT_OTHER_ASE BIT(2) +#define SPE_OP_PKT_OTHER_FP BIT(1) + #define SPE_OP_PKT_LDST_SUBCLASS_GP_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x0) #define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(v) (((v) & GENMASK_ULL(7, 1)) == 0x4) #define SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x10) From c4cfe1bcebb05c3ab71dcd3f24cc9ed350d860c0 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:32 +0000 Subject: [PATCH 405/684] perf arm_spe: Decode SME data processing packet For SME data processing, decode its Effective vector length or Tile Size (ETS), and print out if a floating-point operation. After: . 00000000: 49 00 SME-OTHER ETS 1024 FP . 00000002: b2 18 3c d7 83 00 80 ff ff VA 0xffff800083d73c18 . 0000000b: 9a 00 00 LAT 0 XLAT . 0000000e: 43 00 DATA-SOURCE 0 Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 9 +++++++++ tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 21b65a9b40f481..5769ba2f414049 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -351,6 +351,15 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet, arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP"); if (payload & SPE_OP_PKT_SVE_PRED) arm_spe_pkt_out_string(&err, &buf, &buf_len, " PRED"); + } else if (SPE_OP_PKT_OTHER_SUBCLASS_SME(payload)) { + arm_spe_pkt_out_string(&err, &buf, &buf_len, "SME-OTHER"); + + /* SME effective vector length or tile size */ + arm_spe_pkt_out_string(&err, &buf, &buf_len, " ETS %d", + SPE_OP_PKG_SME_ETS(payload)); + + if (payload & SPE_OP_PKT_OTHER_FP) + arm_spe_pkt_out_string(&err, &buf, &buf_len, " FP"); } else if (SPE_OP_PKT_OTHER_SUBCLASS_OTHER(payload)) { arm_spe_pkt_out_string(&err, &buf, &buf_len, "OTHER"); if (payload & SPE_OP_PKT_OTHER_ASE) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index 704601c6dbe30e..adf4cde320aad0 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -125,10 +125,21 @@ enum arm_spe_events { #define SPE_OP_PKT_OTHER_SUBCLASS_OTHER(v) (((v) & GENMASK_ULL(7, 3)) == 0x0) #define SPE_OP_PKT_OTHER_SUBCLASS_SVE(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8) +#define SPE_OP_PKT_OTHER_SUBCLASS_SME(v) (((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x88) #define SPE_OP_PKT_OTHER_ASE BIT(2) #define SPE_OP_PKT_OTHER_FP BIT(1) +/* + * SME effective vector length or tile size (ETS) is stored in byte 0 + * bits [6:4,2]; the length is rounded up to a power of two and use 128 + * as one step, so ETS calculation is: + * + * 128 * (2 ^ bits [6:4,2]) = 32 << (bits [6:4,2]) + */ +#define SPE_OP_PKG_SME_ETS(v) (128 << (FIELD_GET(GENMASK_ULL(6, 4), (v)) << 1 | \ + (FIELD_GET(BIT(2), (v))))) + #define SPE_OP_PKT_LDST_SUBCLASS_GP_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x0) #define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(v) (((v) & GENMASK_ULL(7, 1)) == 0x4) #define SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(v) (((v) & GENMASK_ULL(7, 1)) == 0x10) From c7c198b3ed686300eaf84e679cee7e0f94befa8f Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:33 +0000 Subject: [PATCH 406/684] perf arm_spe: Remove unused operation types Remove unused SVE operation types. These operations will be reintroduced in subsequent refactoring, but with a different format. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index fbb57f8052371e..1259cbadfdc809 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -39,8 +39,6 @@ enum arm_spe_op_type { /* Second level operation type for OTHER */ ARM_SPE_OP_SVE_OTHER = 1 << 16, - ARM_SPE_OP_SVE_FP = 1 << 17, - ARM_SPE_OP_SVE_PRED_OTHER = 1 << 18, /* Second level operation type for LDST */ ARM_SPE_OP_LD = 1 << 16, @@ -53,8 +51,6 @@ enum arm_spe_op_type { ARM_SPE_OP_UNSPEC_REG = 1 << 23, ARM_SPE_OP_NV_SYSREG = 1 << 24, ARM_SPE_OP_SVE_LDST = 1 << 25, - ARM_SPE_OP_SVE_PRED_LDST = 1 << 26, - ARM_SPE_OP_SVE_SG = 1 << 27, /* Second level operation type for BRANCH_ERET */ ARM_SPE_OP_BR_COND = 1 << 16, From b64bf913b3da2ba7a00ae780cbf9612ab25d9891 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:34 +0000 Subject: [PATCH 407/684] perf arm_spe: Consolidate operation types Consolidate operation types in a way: (a) Extract the second-level types into separate enums. (b) The second-level types for memory and SIMD operations are classified by modules. E.g., an operation may relate to general register, SIMD/FP, SVE, etc. (c) The associated information tells details. E.g., an operation is load or store, whether it is atomic operation, etc. Start the enum items for the second-level types from 8 to accommodate more entries within a 32-bit integer. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- .../util/arm-spe-decoder/arm-spe-decoder.h | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 1259cbadfdc809..b555e2cc1dc36f 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -36,29 +36,31 @@ enum arm_spe_op_type { ARM_SPE_OP_OTHER = 1 << 0, ARM_SPE_OP_LDST = 1 << 1, ARM_SPE_OP_BRANCH_ERET = 1 << 2, +}; + +enum arm_spe_2nd_op_ldst { + ARM_SPE_OP_GP_REG = 1 << 8, + ARM_SPE_OP_UNSPEC_REG = 1 << 9, + ARM_SPE_OP_NV_SYSREG = 1 << 10, + ARM_SPE_OP_SIMD_FP = 1 << 11, + ARM_SPE_OP_SVE_OTHER = 1 << 12, + ARM_SPE_OP_SVE_LDST = 1 << 13, + + /* Assisted information for memory / SIMD */ + ARM_SPE_OP_LD = 1 << 20, + ARM_SPE_OP_ST = 1 << 21, + ARM_SPE_OP_ATOMIC = 1 << 22, + ARM_SPE_OP_EXCL = 1 << 23, + ARM_SPE_OP_AR = 1 << 24, +}; - /* Second level operation type for OTHER */ - ARM_SPE_OP_SVE_OTHER = 1 << 16, - - /* Second level operation type for LDST */ - ARM_SPE_OP_LD = 1 << 16, - ARM_SPE_OP_ST = 1 << 17, - ARM_SPE_OP_ATOMIC = 1 << 18, - ARM_SPE_OP_EXCL = 1 << 19, - ARM_SPE_OP_AR = 1 << 20, - ARM_SPE_OP_SIMD_FP = 1 << 21, - ARM_SPE_OP_GP_REG = 1 << 22, - ARM_SPE_OP_UNSPEC_REG = 1 << 23, - ARM_SPE_OP_NV_SYSREG = 1 << 24, - ARM_SPE_OP_SVE_LDST = 1 << 25, - - /* Second level operation type for BRANCH_ERET */ - ARM_SPE_OP_BR_COND = 1 << 16, - ARM_SPE_OP_BR_INDIRECT = 1 << 17, - ARM_SPE_OP_BR_GCS = 1 << 18, - ARM_SPE_OP_BR_CR_BL = 1 << 19, - ARM_SPE_OP_BR_CR_RET = 1 << 20, - ARM_SPE_OP_BR_CR_NON_BL_RET = 1 << 21, +enum arm_spe_2nd_op_branch { + ARM_SPE_OP_BR_COND = 1 << 8, + ARM_SPE_OP_BR_INDIRECT = 1 << 9, + ARM_SPE_OP_BR_GCS = 1 << 10, + ARM_SPE_OP_BR_CR_BL = 1 << 11, + ARM_SPE_OP_BR_CR_RET = 1 << 12, + ARM_SPE_OP_BR_CR_NON_BL_RET = 1 << 13, }; enum arm_spe_common_data_source { From cdc1aff17f1b72d112f508450f2d103b6b955b74 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:35 +0000 Subject: [PATCH 408/684] perf arm_spe: Introduce data processing macro for SVE operations Introduce the ARM_SPE_OP_DP (data processing) macro as associated information for SVE operations. For SVE register access, only ARM_SPE_OP_SVE is set; for SVE data processing, both ARM_SPE_OP_SVE and ARM_SPE_OP_DP are set together. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 4 ++-- tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 4 ++-- tools/perf/util/arm-spe.c | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 847c29385bea86..6974f594f37c99 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -201,12 +201,12 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) else decoder->record.op |= ARM_SPE_OP_LD; if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) - decoder->record.op |= ARM_SPE_OP_SVE_LDST; + decoder->record.op |= ARM_SPE_OP_SVE; break; case SPE_OP_PKT_HDR_CLASS_OTHER: decoder->record.op |= ARM_SPE_OP_OTHER; if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) - decoder->record.op |= ARM_SPE_OP_SVE_OTHER; + decoder->record.op |= ARM_SPE_OP_SVE | ARM_SPE_OP_DP; break; case SPE_OP_PKT_HDR_CLASS_BR_ERET: decoder->record.op |= ARM_SPE_OP_BRANCH_ERET; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index b555e2cc1dc36f..acab6d11096b19 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -43,8 +43,7 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_UNSPEC_REG = 1 << 9, ARM_SPE_OP_NV_SYSREG = 1 << 10, ARM_SPE_OP_SIMD_FP = 1 << 11, - ARM_SPE_OP_SVE_OTHER = 1 << 12, - ARM_SPE_OP_SVE_LDST = 1 << 13, + ARM_SPE_OP_SVE = 1 << 12, /* Assisted information for memory / SIMD */ ARM_SPE_OP_LD = 1 << 20, @@ -52,6 +51,7 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_ATOMIC = 1 << 22, ARM_SPE_OP_EXCL = 1 << 23, ARM_SPE_OP_AR = 1 << 24, + ARM_SPE_OP_DP = 1 << 25, /* Data processing */ }; enum arm_spe_2nd_op_branch { diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 614ce032f87e46..881257d3958705 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -346,10 +346,7 @@ static struct simd_flags arm_spe__synth_simd_flags(const struct arm_spe_record * { struct simd_flags simd_flags = {}; - if ((record->op & ARM_SPE_OP_LDST) && (record->op & ARM_SPE_OP_SVE_LDST)) - simd_flags.arch |= SIMD_OP_FLAGS_ARCH_SVE; - - if ((record->op & ARM_SPE_OP_OTHER) && (record->op & ARM_SPE_OP_SVE_OTHER)) + if (record->op & ARM_SPE_OP_SVE) simd_flags.arch |= SIMD_OP_FLAGS_ARCH_SVE; if (record->type & ARM_SPE_SVE_PARTIAL_PRED) From 77e4291eaf74bc6e297519d472cd46e6035d91be Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:36 +0000 Subject: [PATCH 409/684] perf arm_spe: Report register access in record Record register access info for load / store operations. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 6974f594f37c99..804dce129121b9 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -200,8 +200,19 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_ST; else decoder->record.op |= ARM_SPE_OP_LD; - if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) + + if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) { + decoder->record.op |= ARM_SPE_OP_GP_REG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) { + decoder->record.op |= ARM_SPE_OP_SIMD_FP; + } else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) { + decoder->record.op |= ARM_SPE_OP_UNSPEC_REG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) { + decoder->record.op |= ARM_SPE_OP_NV_SYSREG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) { decoder->record.op |= ARM_SPE_OP_SVE; + } + break; case SPE_OP_PKT_HDR_CLASS_OTHER: decoder->record.op |= ARM_SPE_OP_OTHER; From c462dc70b1dc2b3fbb95d2cd2748185edc5ae30b Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:37 +0000 Subject: [PATCH 410/684] perf arm_spe: Report MTE allocation tag in record Save MTE tag info in memory record. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 2 ++ tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 804dce129121b9..6696448bdf4f34 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -209,6 +209,8 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_UNSPEC_REG; } else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) { decoder->record.op |= ARM_SPE_OP_NV_SYSREG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) { + decoder->record.op |= ARM_SPE_OP_MTE_TAG; } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) { decoder->record.op |= ARM_SPE_OP_SVE; } diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index acab6d11096b19..7b4d26f2ebfe17 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -44,6 +44,7 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_NV_SYSREG = 1 << 10, ARM_SPE_OP_SIMD_FP = 1 << 11, ARM_SPE_OP_SVE = 1 << 12, + ARM_SPE_OP_MTE_TAG = 1 << 13, /* Assisted information for memory / SIMD */ ARM_SPE_OP_LD = 1 << 20, From f3b9bed72e37e5fa14184d8634a9c88117d1fcb1 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:38 +0000 Subject: [PATCH 411/684] perf arm_spe: Report extended memory operations in records Extended memory operations include atomic (AT), acquire/release (AR), and exclusive (EXCL) operations. Save the relevant information in the records. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 6696448bdf4f34..949c20816826a4 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -211,6 +211,13 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_NV_SYSREG; } else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) { decoder->record.op |= ARM_SPE_OP_MTE_TAG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_EXTENDED(payload)) { + if (payload & SPE_OP_PKT_AR) + decoder->record.op |= ARM_SPE_OP_AR; + if (payload & SPE_OP_PKT_EXCL) + decoder->record.op |= ARM_SPE_OP_EXCL; + if (payload & SPE_OP_PKT_AT) + decoder->record.op |= ARM_SPE_OP_ATOMIC; } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) { decoder->record.op |= ARM_SPE_OP_SVE; } From 6d47c32ccb0e85e484b523d324c471481b7ca9c1 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:39 +0000 Subject: [PATCH 412/684] perf arm_spe: Report associated info for SVE / SME operations SVE / SME operations can be predicated or Gather load / scatter store, save the relevant info into record. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 4 ++++ tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 949c20816826a4..5b214fc4ca9f67 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -220,6 +220,10 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_ATOMIC; } else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) { decoder->record.op |= ARM_SPE_OP_SVE; + if (payload & SPE_OP_PKT_SVE_PRED) + decoder->record.op |= ARM_SPE_OP_PRED; + if (payload & SPE_OP_PKT_SVE_SG) + decoder->record.op |= ARM_SPE_OP_SG; } break; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 7b4d26f2ebfe17..d14cf6b95507bc 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -53,6 +53,8 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_EXCL = 1 << 23, ARM_SPE_OP_AR = 1 << 24, ARM_SPE_OP_DP = 1 << 25, /* Data processing */ + ARM_SPE_OP_PRED = 1 << 26, /* Predicated */ + ARM_SPE_OP_SG = 1 << 27, /* Gather/Scatter */ }; enum arm_spe_2nd_op_branch { From d4b61de44f34589d5233f3e7dc445e06df6bb388 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:40 +0000 Subject: [PATCH 413/684] perf arm_spe: Report memset and memcpy in records Expose memset and memcpy related info in records. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 4 ++++ tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 5b214fc4ca9f67..6f0390d4089599 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -224,6 +224,10 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_PRED; if (payload & SPE_OP_PKT_SVE_SG) decoder->record.op |= ARM_SPE_OP_SG; + } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) { + decoder->record.op |= ARM_SPE_OP_MEMCPY; + } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) { + decoder->record.op |= ARM_SPE_OP_MEMSET; } break; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index d14cf6b95507bc..3f4dae589c062d 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -45,6 +45,8 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_SIMD_FP = 1 << 11, ARM_SPE_OP_SVE = 1 << 12, ARM_SPE_OP_MTE_TAG = 1 << 13, + ARM_SPE_OP_MEMCPY = 1 << 14, + ARM_SPE_OP_MEMSET = 1 << 15, /* Assisted information for memory / SIMD */ ARM_SPE_OP_LD = 1 << 20, From d67835cd5d0a5ac5490895c6a0eafc3bd8e96932 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:41 +0000 Subject: [PATCH 414/684] perf arm_spe: Report GCS in record Report GCS related info in records. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 4 ++++ tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 6f0390d4089599..649471abef6a43 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -228,6 +228,10 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) decoder->record.op |= ARM_SPE_OP_MEMCPY; } else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) { decoder->record.op |= ARM_SPE_OP_MEMSET; + } else if (SPE_OP_PKT_LDST_SUBCLASS_GCS(payload)) { + decoder->record.op |= ARM_SPE_OP_GCS; + if (payload & SPE_OP_PKT_GCS_COMM) + decoder->record.op |= ARM_SPE_OP_COMM; } break; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 3f4dae589c062d..b838e9c6168c6b 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -47,6 +47,7 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_MTE_TAG = 1 << 13, ARM_SPE_OP_MEMCPY = 1 << 14, ARM_SPE_OP_MEMSET = 1 << 15, + ARM_SPE_OP_GCS = 1 << 16, /* Assisted information for memory / SIMD */ ARM_SPE_OP_LD = 1 << 20, @@ -57,6 +58,7 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_DP = 1 << 25, /* Data processing */ ARM_SPE_OP_PRED = 1 << 26, /* Predicated */ ARM_SPE_OP_SG = 1 << 27, /* Gather/Scatter */ + ARM_SPE_OP_COMM = 1 << 28, /* Common */ }; enum arm_spe_2nd_op_branch { From b70aa41078a6ad044b655f124b6b431f916dfac5 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:42 +0000 Subject: [PATCH 415/684] perf arm_spe: Expose SIMD information in other operations The other operations contain SME data processing, ASE (Advanced SIMD) and floating-point operations. Expose these info in the records. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- .../util/arm-spe-decoder/arm-spe-decoder.c | 18 +++++++++++++++++- .../util/arm-spe-decoder/arm-spe-decoder.h | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 649471abef6a43..9e02b2bdd11771 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -237,8 +237,24 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) break; case SPE_OP_PKT_HDR_CLASS_OTHER: decoder->record.op |= ARM_SPE_OP_OTHER; - if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) + if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) { decoder->record.op |= ARM_SPE_OP_SVE | ARM_SPE_OP_DP; + if (payload & SPE_OP_PKT_OTHER_FP) + decoder->record.op |= ARM_SPE_OP_FP; + if (payload & SPE_OP_PKT_SVE_PRED) + decoder->record.op |= ARM_SPE_OP_PRED; + } else if (SPE_OP_PKT_OTHER_SUBCLASS_SME(payload)) { + decoder->record.op |= ARM_SPE_OP_SME; + if (payload & SPE_OP_PKT_OTHER_FP) + decoder->record.op |= ARM_SPE_OP_FP; + } else if (SPE_OP_PKT_OTHER_SUBCLASS_OTHER(payload)) { + if (payload & SPE_OP_PKT_OTHER_ASE) + decoder->record.op |= ARM_SPE_OP_ASE; + if (payload & SPE_OP_PKT_OTHER_FP) + decoder->record.op |= ARM_SPE_OP_FP; + if (payload & SPE_OP_PKT_COND) + decoder->record.op |= ARM_SPE_OP_COND; + } break; case SPE_OP_PKT_HDR_CLASS_BR_ERET: decoder->record.op |= ARM_SPE_OP_BRANCH_ERET; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index b838e9c6168c6b..3310e05122f02e 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -48,6 +48,8 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_MEMCPY = 1 << 14, ARM_SPE_OP_MEMSET = 1 << 15, ARM_SPE_OP_GCS = 1 << 16, + ARM_SPE_OP_SME = 1 << 17, + ARM_SPE_OP_ASE = 1 << 18, /* Assisted information for memory / SIMD */ ARM_SPE_OP_LD = 1 << 20, @@ -59,6 +61,8 @@ enum arm_spe_2nd_op_ldst { ARM_SPE_OP_PRED = 1 << 26, /* Predicated */ ARM_SPE_OP_SG = 1 << 27, /* Gather/Scatter */ ARM_SPE_OP_COMM = 1 << 28, /* Common */ + ARM_SPE_OP_FP = 1 << 29, /* Floating-point */ + ARM_SPE_OP_COND = 1 << 30, /* Conditional */ }; enum arm_spe_2nd_op_branch { From 87cc0b44fc3eba8c6909b3d36aeb8592e32b12d0 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 12 Nov 2025 18:24:43 +0000 Subject: [PATCH 416/684] perf arm_spe: Synthesize memory samples for SIMD operations Synthesize memory samples for SIMD operations (including Advanced SIMD, SVE, and SME). To provide complete information, also generate data source entries for SIMD operations. Since memory operations are not limited to load and store, set PERF_MEM_OP_STORE if the operation does not fall into these cases. Signed-off-by: Leo Yan Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 881257d3958705..6a9c61d4aeeb22 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -39,6 +39,11 @@ #define is_ldst_op(op) (!!((op) & ARM_SPE_OP_LDST)) +#define is_simd_op(op) (!!((op) & (ARM_SPE_OP_SIMD_FP | ARM_SPE_OP_SVE | \ + ARM_SPE_OP_SME | ARM_SPE_OP_ASE))) + +#define is_mem_op(op) (is_ldst_op(op) || is_simd_op(op)) + #define ARM_SPE_CACHE_EVENT(lvl) \ (ARM_SPE_##lvl##_ACCESS | ARM_SPE_##lvl##_MISS) @@ -986,8 +991,7 @@ arm_spe__synth_data_source(struct arm_spe_queue *speq, { union perf_mem_data_src data_src = {}; - /* Only synthesize data source for LDST operations */ - if (!is_ldst_op(record->op)) + if (!is_mem_op(record->op)) return data_src; if (record->op & ARM_SPE_OP_LD) @@ -995,7 +999,7 @@ arm_spe__synth_data_source(struct arm_spe_queue *speq, else if (record->op & ARM_SPE_OP_ST) data_src.mem_op = PERF_MEM_OP_STORE; else - return data_src; + data_src.mem_op = PERF_MEM_OP_NA; arm_spe__synth_ds(speq, record, &data_src); arm_spe__synth_memory_level(speq, record, &data_src); @@ -1096,11 +1100,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq) return err; } - /* - * When data_src is zero it means the record is not a memory operation, - * skip to synthesize memory sample for this case. - */ - if (spe->sample_memory && is_ldst_op(record->op)) { + if (spe->sample_memory && is_mem_op(record->op)) { err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src); if (err) return err; From 51d87d977ec4efe000ac662ac924f00b9d8a23ec Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 18 Nov 2025 13:13:24 -0800 Subject: [PATCH 417/684] perf stat: Read tool events last When reading a metric like memory bandwidth on multiple sockets, the additional sockets will be on CPUS > 0. Because of the affinity reading, the counters are read on CPU 0 along with the time, then the later sockets are read. This can lead to the later sockets having a bandwidth larger than is possible for the period of time. To avoid this move the reading of tool events to occur after all other events are read. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 45 +++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ca1c80c141b658..5c06e9b61821d9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -366,7 +366,7 @@ static int read_counter_cpu(struct evsel *counter, int cpu_map_idx) return 0; } -static int read_affinity_counters(void) +static int read_counters_with_affinity(void) { struct evlist_cpu_iterator evlist_cpu_itr; struct affinity saved_affinity, *affinity; @@ -387,6 +387,9 @@ static int read_affinity_counters(void) if (evsel__is_bpf(counter)) continue; + if (evsel__is_tool(counter)) + continue; + if (!counter->err) counter->err = read_counter_cpu(counter, evlist_cpu_itr.cpu_map_idx); } @@ -412,16 +415,46 @@ static int read_bpf_map_counters(void) return 0; } -static int read_counters(void) +static int read_tool_counters(void) { - if (!stat_config.stop_read_counter) { - if (read_bpf_map_counters() || - read_affinity_counters()) - return -1; + struct evsel *counter; + + evlist__for_each_entry(evsel_list, counter) { + int idx; + + if (!evsel__is_tool(counter)) + continue; + + perf_cpu_map__for_each_idx(idx, counter->core.cpus) { + if (!counter->err) + counter->err = read_counter_cpu(counter, idx); + } } return 0; } +static int read_counters(void) +{ + int ret; + + if (stat_config.stop_read_counter) + return 0; + + // Read all BPF counters first. + ret = read_bpf_map_counters(); + if (ret) + return ret; + + // Read non-BPF and non-tool counters next. + ret = read_counters_with_affinity(); + if (ret) + return ret; + + // Read the tool counters last. This way the duration_time counter + // should always be greater than any other counter's enabled time. + return read_tool_counters(); +} + static void process_counters(void) { struct evsel *counter; From a7840365d179af3002912af76b46d1a3f450ba57 Mon Sep 17 00:00:00 2001 From: Jacky Chou Date: Mon, 17 Nov 2025 20:37:50 +0800 Subject: [PATCH 418/684] dt-bindings: pinctrl: aspeed,ast2600-pinctrl: Add PCIe RC PERST# group Add PCIe PERST# group to support for PCIe RC. Signed-off-by: Jacky Chou Acked-by: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml index 80974c46f3ef9e..af8979af9b45ba 100644 --- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml @@ -141,6 +141,7 @@ additionalProperties: - NRTS3 - NRTS4 - OSCCLK + - PCIERC1 - PEWAKE - PWM0 - PWM1 @@ -369,6 +370,7 @@ additionalProperties: - NRTS3 - NRTS4 - OSCCLK + - PCIERC1 - PEWAKE - PWM0 - PWM1 From da53dcd54cc35efa7a8236846bb39d40deeee034 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 18 Nov 2025 13:11:24 +0100 Subject: [PATCH 419/684] dt-bindings: pinctrl: cix,sky1-pinctrl: Drop duplicate newline Fix the following DT schema check warning: ./Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml:68:1: [warning] too many blank lines (2 > 1) (empty-lines) One newline is enough. No functional change. Signed-off-by: Marek Vasut Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml index 36977b0d745bd2..8ed53496c386f7 100644 --- a/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml @@ -65,7 +65,6 @@ patternProperties: enum: [ 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 17, 18, 20, 21, 23, 24 ] - required: - pinmux From 245cfbcd3d3b298c75e01946262b3ff2cf7d0796 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 18 Nov 2025 21:05:54 -0800 Subject: [PATCH 420/684] perf maps: Avoid RC_CHK use after free The case of __maps__fixup_overlap_and_insert where the "new" maps covers existing mappings can create a use-after-free with reference count checking enabled. The issue is that "pos" holds a map pointer from maps_by_address that is put from maps_by_address but then used to look for a map in maps_by_name (the compared map is now a use-after-free). The issue stems from using maps__remove which redoes some of the searches already done by __maps__fixup_overlap_and_insert, so optimize the code (by avoiding repeated searches) and avoid the use-after-free by inlining the appropriate removal code. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202511141407.f9edcfa6-lkp@intel.com Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/maps.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c index 779f6230130af2..c321d4f4d84669 100644 --- a/tools/perf/util/maps.c +++ b/tools/perf/util/maps.c @@ -931,8 +931,9 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) return err; } else { struct map *next = NULL; + unsigned int nr_maps = maps__nr_maps(maps); - if (i + 1 < maps__nr_maps(maps)) + if (i + 1 < nr_maps) next = maps_by_address[i + 1]; if (!next || map__start(next) >= map__end(new)) { @@ -953,7 +954,24 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) check_invariants(maps); return err; } - __maps__remove(maps, pos); + /* + * pos fully covers the previous mapping so remove + * it. The following is an inlined version of + * maps__remove that reuses the already computed + * indices. + */ + map__put(maps_by_address[i]); + memmove(&maps_by_address[i], + &maps_by_address[i + 1], + (nr_maps - i - 1) * sizeof(*maps_by_address)); + + if (maps_by_name) { + map__put(maps_by_name[ni]); + memmove(&maps_by_name[ni], + &maps_by_name[ni + 1], + (nr_maps - ni - 1) * sizeof(*maps_by_name)); + } + --RC_CHK_ACCESS(maps)->nr_maps; check_invariants(maps); /* * Maps are ordered but no need to increase `i` as the From 36434959b6ea13d32343f4ec5fa3fb0d0120da2f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 18 Nov 2025 21:05:55 -0800 Subject: [PATCH 421/684] perf test maps: Additional maps__fixup_overlap_and_insert tests Add additional test to the maps covering maps__fixup_overlap_and_insert. Change the test suite to be for more than just 1 test. Signed-off-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/tests/builtin-test.c | 2 +- tools/perf/tests/maps.c | 82 ++++++++++++++++++++++++++++++++- tools/perf/tests/tests.h | 2 +- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0d2fb7a4ae5bd7..9090e8238a4478 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -126,7 +126,7 @@ static struct test_suite *generic_tests[] = { &suite__jit_write_elf, &suite__pfm, &suite__api_io, - &suite__maps__merge_in, + &suite__maps, &suite__demangle_java, &suite__demangle_ocaml, &suite__demangle_rust, diff --git a/tools/perf/tests/maps.c b/tools/perf/tests/maps.c index 4f1f9385ea9cec..2c05d62f40dcdf 100644 --- a/tools/perf/tests/maps.c +++ b/tools/perf/tests/maps.c @@ -162,4 +162,84 @@ static int test__maps__merge_in(struct test_suite *t __maybe_unused, int subtest return TEST_OK; } -DEFINE_SUITE("maps__merge_in", maps__merge_in); +static int test__maps__fixup_overlap_and_insert(struct test_suite *t __maybe_unused, + int subtest __maybe_unused) +{ + struct map_def initial_maps[] = { + { "target_map", 1000, 2000 }, + { "next_map", 3000, 4000 }, + }; + struct map_def insert_split = { "split_map", 1400, 1600 }; + struct map_def expected_after_split[] = { + { "target_map", 1000, 1400 }, + { "split_map", 1400, 1600 }, + { "target_map", 1600, 2000 }, + { "next_map", 3000, 4000 }, + }; + + struct map_def insert_eclipse = { "eclipse_map", 2500, 4500 }; + struct map_def expected_final[] = { + { "target_map", 1000, 1400 }, + { "split_map", 1400, 1600 }, + { "target_map", 1600, 2000 }, + { "eclipse_map", 2500, 4500 }, + /* "next_map" (3000-4000) is removed */ + }; + + struct map *map_split, *map_eclipse; + int ret; + unsigned int i; + struct maps *maps = maps__new(NULL); + + TEST_ASSERT_VAL("failed to create maps", maps); + + for (i = 0; i < ARRAY_SIZE(initial_maps); i++) { + struct map *map = dso__new_map(initial_maps[i].name); + + TEST_ASSERT_VAL("failed to create map", map); + map__set_start(map, initial_maps[i].start); + map__set_end(map, initial_maps[i].end); + TEST_ASSERT_VAL("failed to insert map", maps__insert(maps, map) == 0); + map__put(map); + } + + // Check splitting. + map_split = dso__new_map(insert_split.name); + TEST_ASSERT_VAL("failed to create split map", map_split); + map__set_start(map_split, insert_split.start); + map__set_end(map_split, insert_split.end); + + ret = maps__fixup_overlap_and_insert(maps, map_split); + TEST_ASSERT_VAL("failed to fixup and insert split map", !ret); + + map__zput(map_split); + ret = check_maps(expected_after_split, ARRAY_SIZE(expected_after_split), maps); + TEST_ASSERT_VAL("split check failed", !ret); + + // Check cover 1 map with another. + map_eclipse = dso__new_map(insert_eclipse.name); + TEST_ASSERT_VAL("failed to create eclipse map", map_eclipse); + map__set_start(map_eclipse, insert_eclipse.start); + map__set_end(map_eclipse, insert_eclipse.end); + + ret = maps__fixup_overlap_and_insert(maps, map_eclipse); + TEST_ASSERT_VAL("failed to fixup and insert eclipse map", !ret); + + map__zput(map_eclipse); + ret = check_maps(expected_final, ARRAY_SIZE(expected_final), maps); + TEST_ASSERT_VAL("eclipse check failed", !ret); + + maps__zput(maps); + return TEST_OK; +} + +static struct test_case tests__maps[] = { + TEST_CASE("Test merge_in interface", maps__merge_in), + TEST_CASE("Test fix up overlap interface", maps__fixup_overlap_and_insert), + { .name = NULL, } +}; + +struct test_suite suite__maps = { + .desc = "Maps - per process mmaps abstraction", + .test_cases = tests__maps, +}; diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 33de16dde737fa..f5fba95b6f3ffb 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -160,7 +160,7 @@ DECLARE_SUITE(bitmap_print); DECLARE_SUITE(perf_hooks); DECLARE_SUITE(unit_number__scnprint); DECLARE_SUITE(mem2node); -DECLARE_SUITE(maps__merge_in); +DECLARE_SUITE(maps); DECLARE_SUITE(time_utils); DECLARE_SUITE(jit_write_elf); DECLARE_SUITE(api_io); From 1a6b0deb2b71d6e94497a284b9babce80b18cc7c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 14 Nov 2025 14:05:45 -0800 Subject: [PATCH 422/684] perf header: Switch "cpu" for find_core_pmu in caps feature writing Writing currently fails on non-x86 and hybrid CPUs. Switch to the more regular find_core_pmu that is normally used in this case. Tested on hybrid alderlake system. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/header.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a2f808841b33ab..e69b271f8073db 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1560,7 +1560,7 @@ static int __write_pmu_caps(struct feat_fd *ff, struct perf_pmu *pmu, static int write_cpu_pmu_caps(struct feat_fd *ff, struct evlist *evlist __maybe_unused) { - struct perf_pmu *cpu_pmu = perf_pmus__find("cpu"); + struct perf_pmu *cpu_pmu = perf_pmus__find_core_pmu(); int ret; if (!cpu_pmu) From f0feb21e0a10c50e3a154e9bdf3fbb8a38480251 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 14 Nov 2025 14:05:46 -0800 Subject: [PATCH 423/684] perf pmu: Add PMU kind to simplify differentiating Rather than perf_pmu__is_xxx calls, and a notion of kind so that a single call can be used. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 1ebcf0242af854..cfcaba3e2e753b 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -37,6 +37,19 @@ struct perf_pmu_caps { struct list_head list; }; +enum pmu_kind { + /* A perf event syscall PMU. */ + PERF_PMU_KIND_PE, + /* A perf tool provided DRM PMU. */ + PERF_PMU_KIND_DRM, + /* A perf tool provided HWMON PMU. */ + PERF_PMU_KIND_HWMON, + /* Perf tool provided PMU for tool events like time. */ + PERF_PMU_KIND_TOOL, + /* A testing PMU kind. */ + PERF_PMU_KIND_FAKE +}; + enum { PERF_PMU_TYPE_PE_START = 0, PERF_PMU_TYPE_PE_END = 0xFFFDFFFF, @@ -306,4 +319,25 @@ void perf_pmu__delete(struct perf_pmu *pmu); const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config); bool perf_pmu__is_fake(const struct perf_pmu *pmu); +static inline enum pmu_kind perf_pmu__kind(const struct perf_pmu *pmu) +{ + __u32 type; + + if (!pmu) + return PERF_PMU_KIND_PE; + + type = pmu->type; + if (type <= PERF_PMU_TYPE_PE_END) + return PERF_PMU_KIND_PE; + if (type <= PERF_PMU_TYPE_DRM_END) + return PERF_PMU_KIND_DRM; + if (type <= PERF_PMU_TYPE_DRM_END) + return PERF_PMU_KIND_DRM; + if (type <= PERF_PMU_TYPE_HWMON_END) + return PERF_PMU_KIND_HWMON; + if (type == PERF_PMU_TYPE_TOOL) + return PERF_PMU_KIND_TOOL; + return PERF_PMU_KIND_FAKE; +} + #endif /* __PMU_H */ From d53b4996584b448c5427ba9ab3ec06ec43190043 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 14 Nov 2025 14:05:47 -0800 Subject: [PATCH 424/684] perf evsel: Skip store_evsel_ids for non-perf-event PMUs The IDs are associated with perf events and not applicable to non-perf event PMUs. The failure to generate the ids was causing perf stat record to fail. ``` $ perf stat record -a sleep 1 Performance counter stats for 'system wide': 47,941 context-switches # nan cs/sec cs_per_second 0.00 msec cpu-clock # 0.0 CPUs CPUs_utilized 3,261 cpu-migrations # nan migrations/sec migrations_per_second 516 page-faults # nan faults/sec page_faults_per_second 7,525,483 cpu_core/branch-misses/ # 2.3 % branch_miss_rate 322,069,004 cpu_core/branches/ # nan M/sec branch_frequency 1,895,684,291 cpu_core/cpu-cycles/ # nan GHz cycles_frequency 2,789,777,426 cpu_core/instructions/ # 1.5 instructions insn_per_cycle 7,074,765 cpu_atom/branch-misses/ # 3.2 % branch_miss_rate (49.89%) 224,225,412 cpu_atom/branches/ # nan M/sec branch_frequency (50.29%) 2,061,679,981 cpu_atom/cpu-cycles/ # nan GHz cycles_frequency (50.33%) 2,011,242,533 cpu_atom/instructions/ # 1.0 instructions insn_per_cycle (50.33%) TopdownL1 (cpu_core) # 9.0 % tma_bad_speculation # 28.3 % tma_frontend_bound # 35.2 % tma_backend_bound # 27.5 % tma_retiring TopdownL1 (cpu_atom) # 36.8 % tma_backend_bound (59.65%) # 22.8 % tma_frontend_bound (59.60%) # 11.6 % tma_bad_speculation # 28.8 % tma_retiring (59.59%) 1.006777519 seconds time elapsed $ perf stat report Performance counter stats for 'perf': 1,013,376,154 duration_time duration_time duration_time duration_time duration_time duration_time 47,941 context-switches 0.00 msec cpu-clock 3,261 cpu-migrations 516 page-faults 7,525,483 cpu_core/branch-misses/ 322,069,814 cpu_core/branches/ 322,069,004 cpu_core/branches/ 1,895,684,291 cpu_core/cpu-cycles/ 1,895,679,209 cpu_core/cpu-cycles/ 2,789,777,426 cpu_core/instructions/ cpu_core/cpu-cycles/ cpu_core/stalled-cycles-frontend/ cpu_core/cpu-cycles/ cpu_core/stalled-cycles-backend/ cpu_core/stalled-cycles-backend/ cpu_core/instructions/ cpu_core/stalled-cycles-frontend/ 7,074,765 cpu_atom/branch-misses/ (49.89%) 221,679,088 cpu_atom/branches/ (49.89%) 224,225,412 cpu_atom/branches/ (50.29%) 2,061,679,981 cpu_atom/cpu-cycles/ (50.33%) 2,016,259,567 cpu_atom/cpu-cycles/ (50.33%) 2,011,242,533 cpu_atom/instructions/ (50.33%) cpu_atom/cpu-cycles/ cpu_atom/stalled-cycles-frontend/ cpu_atom/cpu-cycles/ cpu_atom/stalled-cycles-backend/ cpu_atom/stalled-cycles-backend/ cpu_atom/instructions/ cpu_atom/stalled-cycles-frontend/ 17,145,113 cpu_core/INT_MISC.UOP_DROPPING/ 10,594,226,100 cpu_core/TOPDOWN.SLOTS/ 2,919,021,401 cpu_core/topdown-retiring/ 943,101,838 cpu_core/topdown-bad-spec/ 3,031,152,533 cpu_core/topdown-fe-bound/ 3,739,756,791 cpu_core/topdown-be-bound/ 1,909,501,648 cpu_atom/CPU_CLK_UNHALTED.CORE/ (60.04%) 3,516,608,359 cpu_atom/TOPDOWN_BE_BOUND.ALL/ (59.65%) 2,179,403,876 cpu_atom/TOPDOWN_FE_BOUND.ALL/ (59.60%) 2,745,732,458 cpu_atom/TOPDOWN_RETIRING.ALL/ (59.59%) 1.006777519 seconds time elapsed Some events weren't counted. Try disabling the NMI watchdog: echo 0 > /proc/sys/kernel/nmi_watchdog perf stat ... echo 1 > /proc/sys/kernel/nmi_watchdog ``` Reported-by: James Clark Closes: https://lore.kernel.org/lkml/ca0f0cd3-7335-48f9-8737-2f70a75b019a@linaro.org/ Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 989c56d4a23f74..aee42666e882da 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3974,6 +3974,9 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) if (evsel__is_retire_lat(evsel)) return 0; + if (perf_pmu__kind(evsel->pmu) != PERF_PMU_KIND_PE) + return 0; + for (cpu_map_idx = 0; cpu_map_idx < xyarray__max_x(evsel->core.fd); cpu_map_idx++) { for (thread = 0; thread < xyarray__max_y(evsel->core.fd); thread++) { From 81d75558406609f311766a37ec4b2c74d7b11ea0 Mon Sep 17 00:00:00 2001 From: Faisal Hassan Date: Mon, 22 Sep 2025 19:29:01 +0530 Subject: [PATCH 425/684] phy: qcom-qmp-combo: Use regulator_bulk_data with init_load_uA for regulator setup Replace the custom qmp_regulator_data structure with the standard regulator_bulk_data and use the init_load_uA field to set regulator load during initialization. This change simplifies the regulator setup by removing manual allocation and load configuration logic, and leverages devm_regulator_bulk_get_const() to automatically apply load settings before enabling regulators. Signed-off-by: Faisal Hassan Reviewed-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Reviewed-by: Bjorn Andersson Link: https://patch.msgid.link/20250922135901.2067-1-faisal.hassan@oss.qualcomm.com Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 49 +++-------------------- 1 file changed, 6 insertions(+), 43 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 7b5af30f1d028c..19a72fb1b83564 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -1643,14 +1643,9 @@ static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_usb_tbl[] = { }; /* list of regulators */ -struct qmp_regulator_data { - const char *name; - unsigned int enable_load; -}; - -static struct qmp_regulator_data qmp_phy_vreg_l[] = { - { .name = "vdda-phy", .enable_load = 21800 }, - { .name = "vdda-pll", .enable_load = 36000 }, +static struct regulator_bulk_data qmp_phy_vreg_l[] = { + { .supply = "vdda-phy", .init_load_uA = 21800, }, + { .supply = "vdda-pll", .init_load_uA = 36000, }, }; static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { @@ -1808,7 +1803,7 @@ struct qmp_phy_cfg { const char * const *reset_list; int num_resets; /* regulators to be requested */ - const struct qmp_regulator_data *vreg_list; + const struct regulator_bulk_data *vreg_list; int num_vregs; /* array of registers with different offsets */ @@ -3439,39 +3434,6 @@ static const struct dev_pm_ops qmp_combo_pm_ops = { qmp_combo_runtime_resume, NULL) }; -static int qmp_combo_vreg_init(struct qmp_combo *qmp) -{ - const struct qmp_phy_cfg *cfg = qmp->cfg; - struct device *dev = qmp->dev; - int num = cfg->num_vregs; - int ret, i; - - qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); - if (!qmp->vregs) - return -ENOMEM; - - for (i = 0; i < num; i++) - qmp->vregs[i].supply = cfg->vreg_list[i].name; - - ret = devm_regulator_bulk_get(dev, num, qmp->vregs); - if (ret) { - dev_err(dev, "failed at devm_regulator_bulk_get\n"); - return ret; - } - - for (i = 0; i < num; i++) { - ret = regulator_set_load(qmp->vregs[i].consumer, - cfg->vreg_list[i].enable_load); - if (ret) { - dev_err(dev, "failed to set load at %s\n", - qmp->vregs[i].supply); - return ret; - } - } - - return 0; -} - static int qmp_combo_reset_init(struct qmp_combo *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -4144,7 +4106,8 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) return ret; - ret = qmp_combo_vreg_init(qmp); + ret = devm_regulator_bulk_get_const(dev, qmp->cfg->num_vregs, + qmp->cfg->vreg_list, &qmp->vregs); if (ret) return ret; From 80ac0fba0f1a72be2c7b532b8e2ad61300a165c3 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sat, 15 Nov 2025 21:58:06 +0100 Subject: [PATCH 426/684] dt-bindings: phy: mediatek,tphy: Add support for MT7981 Add a compatible string for Filogic 820, this chip integrates a MediaTek generic T-PHY version 2 Acked-by: Conor Dooley Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Sjoerd Simons Link: https://patch.msgid.link/20251115-openwrt-one-network-v4-3-48cbda2969ac@collabora.com Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/phy/mediatek,tphy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml index b2218c15193917..ff5c77ef11765c 100644 --- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml +++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml @@ -80,6 +80,7 @@ properties: - mediatek,mt2712-tphy - mediatek,mt6893-tphy - mediatek,mt7629-tphy + - mediatek,mt7981-tphy - mediatek,mt7986-tphy - mediatek,mt8183-tphy - mediatek,mt8186-tphy From 323c5c05a0a07b931ede1fa0a3396a1a165ed798 Mon Sep 17 00:00:00 2001 From: Chaoyi Chen Date: Thu, 6 Nov 2025 10:06:25 +0800 Subject: [PATCH 427/684] dt-bindings: phy: rockchip-inno-dsidphy: Add compatible for rk3506 Document a compatible string for the rk3506 dsi-dphy. Signed-off-by: Chaoyi Chen Acked-by: Conor Dooley Link: https://patch.msgid.link/20251106020632.92-3-kernel@airkyi.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml b/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml index 46e64fa293d501..83e7c825860cb6 100644 --- a/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml +++ b/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml @@ -18,6 +18,7 @@ properties: - rockchip,px30-dsi-dphy - rockchip,rk3128-dsi-dphy - rockchip,rk3368-dsi-dphy + - rockchip,rk3506-dsi-dphy - rockchip,rk3568-dsi-dphy - rockchip,rv1126-dsi-dphy From 785a9d5bb145109558063080ebc9a3e8be86471d Mon Sep 17 00:00:00 2001 From: Chaoyi Chen Date: Thu, 6 Nov 2025 10:06:29 +0800 Subject: [PATCH 428/684] phy: rockchip: inno-dsidphy: Add support for rk3506 For MIPI mode, the inno-dsidphy found on RK3506 supports up to 2 lanes and a maximum data rate of 1.5GHz. Signed-off-by: Hongming Zou Signed-off-by: Chaoyi Chen Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251106020632.92-7-kernel@airkyi.com Signed-off-by: Vinod Koul --- .../phy/rockchip/phy-rockchip-inno-dsidphy.c | 91 ++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c index d5b1a4e2f7d343..30d5e5ddff4a14 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c @@ -99,10 +99,30 @@ #define VOD_MID_RANGE 0x3 #define VOD_BIG_RANGE 0x7 #define VOD_MAX_RANGE 0xf +/* Analog Register Part: reg18 */ +#define LANE0_PRE_EMPHASIS_ENABLE_MASK BIT(6) +#define LANE0_PRE_EMPHASIS_ENABLE BIT(6) +#define LANE0_PRE_EMPHASIS_DISABLE 0 +#define LANE1_PRE_EMPHASIS_ENABLE_MASK BIT(5) +#define LANE1_PRE_EMPHASIS_ENABLE BIT(5) +#define LANE1_PRE_EMPHASIS_DISABLE 0 +/* Analog Register Part: reg19 */ +#define PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6) +#define PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6) /* Analog Register Part: reg1E */ #define PLL_MODE_SEL_MASK GENMASK(6, 5) #define PLL_MODE_SEL_LVDS_MODE 0 #define PLL_MODE_SEL_MIPI_MODE BIT(5) +/* Analog Register Part: reg20 */ +#define LANE0_PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6) +#define LANE0_PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6) +/* Analog Register Part: reg21 */ +#define LANE1_PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6) +#define LANE1_PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6) +#define PRE_EMPHASIS_MIN_RANGE 0x0 +#define PRE_EMPHASIS_MID_RANGE 0x1 +#define PRE_EMPHASIS_MAX_RANGE 0x2 +#define PRE_EMPHASIS_RESERVED_RANGE 0x3 /* Digital Register Part: reg00 */ #define REG_DIG_RSTN_MASK BIT(0) #define REG_DIG_RSTN_NORMAL BIT(0) @@ -193,6 +213,7 @@ enum phy_max_rate { MAX_1GHZ, + MAX_1_5GHZ, MAX_2_5GHZ, }; @@ -200,6 +221,7 @@ struct inno_video_phy_plat_data { const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table; const unsigned int num_timings; enum phy_max_rate max_rate; + unsigned int max_lanes; }; struct inno_dsidphy { @@ -258,6 +280,24 @@ struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = { {1000000000, 0x0, 0x09, 0x20, 0x09, 0x27}, }; +static const +struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1_5ghz[] = { + { 110, 0x02, 0x7f, 0x16, 0x02, 0x02}, + { 150, 0x02, 0x7f, 0x16, 0x03, 0x02}, + { 200, 0x02, 0x7f, 0x17, 0x04, 0x02}, + { 250, 0x02, 0x7f, 0x17, 0x05, 0x04}, + { 300, 0x02, 0x7f, 0x18, 0x06, 0x04}, + { 400, 0x03, 0x7e, 0x19, 0x07, 0x04}, + { 500, 0x03, 0x7c, 0x1b, 0x07, 0x08}, + { 600, 0x03, 0x70, 0x1d, 0x08, 0x10}, + { 700, 0x05, 0x40, 0x1e, 0x08, 0x30}, + { 800, 0x05, 0x02, 0x1f, 0x09, 0x30}, + {1000, 0x05, 0x08, 0x20, 0x09, 0x30}, + {1200, 0x06, 0x03, 0x32, 0x14, 0x0f}, + {1400, 0x09, 0x03, 0x32, 0x14, 0x0f}, + {1500, 0x0d, 0x42, 0x36, 0x0e, 0x0f}, +}; + static const struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = { { 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02}, @@ -372,6 +412,7 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait; u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero; unsigned int i; + u32 val; timings = inno->pdata->inno_mipi_dphy_timing_table; @@ -393,6 +434,23 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b, CLOCK_LANE_VOD_RANGE_SET_MASK, CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE)); + } else if (inno->pdata->max_rate == MAX_1_5GHZ) { + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x18, + LANE0_PRE_EMPHASIS_ENABLE_MASK, LANE0_PRE_EMPHASIS_ENABLE); + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x18, + LANE1_PRE_EMPHASIS_ENABLE_MASK, LANE1_PRE_EMPHASIS_ENABLE); + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x19, + PRE_EMPHASIS_RANGE_SET_MASK, + PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE)); + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1a, + LANE0_PRE_EMPHASIS_RANGE_SET_MASK, + LANE0_PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE)); + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1b, + LANE1_PRE_EMPHASIS_RANGE_SET_MASK, + LANE1_PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE)); + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b, + CLOCK_LANE_VOD_RANGE_SET_MASK, + CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE)); } /* Enable PLL and LDO */ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01, @@ -518,10 +576,25 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) T_TA_WAIT_CNT(ta_wait)); } - /* Enable all lanes on analog part */ + /* Enable lanes on analog part */ + switch (inno->pdata->max_lanes) { + case 1: + val = LANE_EN_0; + break; + case 2: + val = LANE_EN_0 | LANE_EN_1; + break; + case 3: + val = LANE_EN_0 | LANE_EN_1 | LANE_EN_2; + break; + case 4: + default: + val = LANE_EN_0 | LANE_EN_1 | LANE_EN_2 | LANE_EN_3; + break; + } + phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, - LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 | - LANE_EN_1 | LANE_EN_0); + LANE_EN_MASK, LANE_EN_CK | val); } static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno) @@ -680,12 +753,21 @@ static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = { .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz, .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz), .max_rate = MAX_1GHZ, + .max_lanes = 4, +}; + +static const struct inno_video_phy_plat_data max_1_5ghz_video_phy_plat_data = { + .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1_5ghz, + .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1_5ghz), + .max_rate = MAX_1_5GHZ, + .max_lanes = 2, }; static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = { .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz, .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz), .max_rate = MAX_2_5GHZ, + .max_lanes = 4, }; static int inno_dsidphy_probe(struct platform_device *pdev) @@ -767,6 +849,9 @@ static const struct of_device_id inno_dsidphy_of_match[] = { }, { .compatible = "rockchip,rk3368-dsi-dphy", .data = &max_1ghz_video_phy_plat_data, + }, { + .compatible = "rockchip,rk3506-dsi-dphy", + .data = &max_1_5ghz_video_phy_plat_data, }, { .compatible = "rockchip,rk3568-dsi-dphy", .data = &max_2_5ghz_video_phy_plat_data, From 356d1924b9a6bc2164ce2bf1fad147b0c37ae085 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 17 Oct 2025 07:45:37 +0200 Subject: [PATCH 429/684] phy: broadcom: bcm63xx-usbh: fix section mismatches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform drivers can be probed after their init sections have been discarded (e.g. on probe deferral or manual rebind through sysfs) so the probe function and match table must not live in init. Fixes: 783f6d3dcf35 ("phy: bcm63xx-usbh: Add BCM63xx USBH driver") Cc: stable@vger.kernel.org # 5.9 Cc: Álvaro Fernández Rojas Signed-off-by: Johan Hovold Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251017054537.6884-1-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/phy/broadcom/phy-bcm63xx-usbh.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/phy/broadcom/phy-bcm63xx-usbh.c b/drivers/phy/broadcom/phy-bcm63xx-usbh.c index 647644de041bba..29fd6791bae642 100644 --- a/drivers/phy/broadcom/phy-bcm63xx-usbh.c +++ b/drivers/phy/broadcom/phy-bcm63xx-usbh.c @@ -375,7 +375,7 @@ static struct phy *bcm63xx_usbh_phy_xlate(struct device *dev, return of_phy_simple_xlate(dev, args); } -static int __init bcm63xx_usbh_phy_probe(struct platform_device *pdev) +static int bcm63xx_usbh_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct bcm63xx_usbh_phy *usbh; @@ -432,7 +432,7 @@ static int __init bcm63xx_usbh_phy_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id bcm63xx_usbh_phy_ids[] __initconst = { +static const struct of_device_id bcm63xx_usbh_phy_ids[] = { { .compatible = "brcm,bcm6318-usbh-phy", .data = &usbh_bcm6318 }, { .compatible = "brcm,bcm6328-usbh-phy", .data = &usbh_bcm6328 }, { .compatible = "brcm,bcm6358-usbh-phy", .data = &usbh_bcm6358 }, @@ -443,7 +443,7 @@ static const struct of_device_id bcm63xx_usbh_phy_ids[] __initconst = { }; MODULE_DEVICE_TABLE(of, bcm63xx_usbh_phy_ids); -static struct platform_driver bcm63xx_usbh_phy_driver __refdata = { +static struct platform_driver bcm63xx_usbh_phy_driver = { .driver = { .name = "bcm63xx-usbh-phy", .of_match_table = bcm63xx_usbh_phy_ids, From 5e428e45bf17a8f3784099ca5ded16e3b5d59766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Mon, 6 Oct 2025 09:07:12 +0100 Subject: [PATCH 430/684] phy: exynos5-usbdrd: fix clock prepare imbalance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f4fb9c4d7f94 ("phy: exynos5-usbdrd: allow DWC3 runtime suspend with UDC bound (E850+)") incorrectly added clk_bulk_disable() as the inverse of clk_bulk_prepare_enable() while it should have of course used clk_bulk_disable_unprepare(). This means incorrect reference counts to the CMU driver remain. Update the code accordingly. Fixes: f4fb9c4d7f94 ("phy: exynos5-usbdrd: allow DWC3 runtime suspend with UDC bound (E850+)") CC: stable@vger.kernel.org Signed-off-by: André Draszik Reviewed-by: Sam Protsenko Reviewed-by: Peter Griffin Link: https://patch.msgid.link/20251006-gs101-usb-phy-clk-imbalance-v1-1-205b206126cf@linaro.org Signed-off-by: Vinod Koul --- drivers/phy/samsung/phy-exynos5-usbdrd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index a88ba95bdc8f53..1c8bf80119f11e 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -1823,7 +1823,7 @@ static int exynos5_usbdrd_orien_sw_set(struct typec_switch_dev *sw, phy_drd->orientation = orientation; } - clk_bulk_disable(phy_drd->drv_data->n_clks, phy_drd->clks); + clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks); return 0; } From bc6f8b756c89d831c91a65ef9f3b5ceabdbae441 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 23 Oct 2025 16:58:04 +0300 Subject: [PATCH 431/684] dt-bindings: phy: renesas,usb2-phy: Mark resets as required for RZ/G3S The reset lines are mandatory for the Renesas RZ/G3S platform and must be explicitly defined in device tree. Fixes: f3c849855114 ("dt-bindings: phy: renesas,usb2-phy: Document RZ/G3S phy bindings") Reviewed-by: Geert Uytterhoeven Acked-by: Conor Dooley Signed-off-by: Claudiu Beznea Link: https://patch.msgid.link/20251023135810.1688415-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml b/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml index 179cb4bfc424c4..2bbec8702a1e08 100644 --- a/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml @@ -118,6 +118,7 @@ allOf: contains: enum: - renesas,usb2-phy-r9a09g057 + - renesas,usb2-phy-r9a08g045 - renesas,rzg2l-usb2-phy then: properties: From 662bb179d3381c7c069e44bb177396bcaee31cc8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 23 Oct 2025 16:58:05 +0300 Subject: [PATCH 432/684] phy: renesas: rcar-gen3-usb2: Fix an error handling path in rcar_gen3_phy_usb2_probe() If an error occurs after the reset_control_deassert(), reset_control_assert() must be called, as already done in the remove function. Use devm_add_action_or_reset() to add the missing call and simplify the .remove() function accordingly. While at it, drop struct rcar_gen3_chan::rstc as it is not used aymore. [claudiu.beznea: removed "struct reset_control *rstc = data;" from rcar_gen3_reset_assert(), dropped struct rcar_gen3_chan::rstc] Fixes: 4eae16375357 ("phy: renesas: rcar-gen3-usb2: Add support to initialize the bus") Signed-off-by: Christophe JAILLET Reviewed-by: Biju Das Reviewed-by: Geert Uytterhoeven Tested-by: Wolfram Sang Signed-off-by: Claudiu Beznea Link: https://patch.msgid.link/20251023135810.1688415-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Vinod Koul --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 3f6b480e109229..a38ead7c8055d0 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -134,7 +134,6 @@ struct rcar_gen3_chan { struct extcon_dev *extcon; struct rcar_gen3_phy rphys[NUM_OF_PHYS]; struct regulator *vbus; - struct reset_control *rstc; struct work_struct work; spinlock_t lock; /* protects access to hardware and driver data structure. */ enum usb_dr_mode dr_mode; @@ -771,21 +770,31 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np) return candidate; } +static void rcar_gen3_reset_assert(void *data) +{ + reset_control_assert(data); +} + static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel) { struct device *dev = channel->dev; + struct reset_control *rstc; int ret; u32 val; - channel->rstc = devm_reset_control_array_get_shared(dev); - if (IS_ERR(channel->rstc)) - return PTR_ERR(channel->rstc); + rstc = devm_reset_control_array_get_shared(dev); + if (IS_ERR(rstc)) + return PTR_ERR(rstc); ret = pm_runtime_resume_and_get(dev); if (ret) return ret; - ret = reset_control_deassert(channel->rstc); + ret = reset_control_deassert(rstc); + if (ret) + goto rpm_put; + + ret = devm_add_action_or_reset(dev, rcar_gen3_reset_assert, rstc); if (ret) goto rpm_put; @@ -924,7 +933,6 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev) if (channel->is_otg_channel) device_remove_file(&pdev->dev, &dev_attr_role); - reset_control_assert(channel->rstc); pm_runtime_disable(&pdev->dev); }; From 79d9db7f7a0c94b2b505666513879ac470c7e12f Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 19 Nov 2025 14:04:17 +0200 Subject: [PATCH 433/684] phy: renesas: rcar-gen3-usb2: Move phy_data->init_bus check Move the check of phy_data->init_bus from rcar_gen3_phy_usb2_init_bus() to rcar_gen3_phy_usb2_probe() to avoid having it duplicated in both the probe path and the upcoming resume code. This is a preparatory patch. Signed-off-by: Claudiu Beznea Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251119120418.686224-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Vinod Koul --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index a38ead7c8055d0..b9d5bb52e02c53 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -782,6 +782,9 @@ static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel) int ret; u32 val; + if (!channel->phy_data->init_bus) + return 0; + rstc = devm_reset_control_array_get_shared(dev); if (IS_ERR(rstc)) return PTR_ERR(rstc); @@ -861,11 +864,9 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, channel); channel->dev = dev; - if (channel->phy_data->init_bus) { - ret = rcar_gen3_phy_usb2_init_bus(channel); - if (ret) - goto error; - } + ret = rcar_gen3_phy_usb2_init_bus(channel); + if (ret) + goto error; spin_lock_init(&channel->lock); for (i = 0; i < NUM_OF_PHYS; i++) { From 942a7a6bf4c6a8661324539f686a34c9448610bd Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 19 Nov 2025 14:04:18 +0200 Subject: [PATCH 434/684] phy: renesas: rcar-gen3-usb2: Add suspend/resume support The Renesas RZ/G3S supports a power saving mode where power to most of the SoC components is turned off. The USB PHY is among these components. Because of this the settings applied in driver probe need to be executed also on resume path. On suspend path only reset signal need to be asserted. Add suspend/resume support. Signed-off-by: Claudiu Beznea Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251119120418.686224-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Vinod Koul --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 57 +++++++++++++++++------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index b9d5bb52e02c53..3c063e4dea41ad 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -132,6 +132,7 @@ struct rcar_gen3_chan { struct device *dev; /* platform_device's device */ const struct rcar_gen3_phy_drv_data *phy_data; struct extcon_dev *extcon; + struct reset_control *rstc; struct rcar_gen3_phy rphys[NUM_OF_PHYS]; struct regulator *vbus; struct work_struct work; @@ -778,38 +779,24 @@ static void rcar_gen3_reset_assert(void *data) static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel) { struct device *dev = channel->dev; - struct reset_control *rstc; int ret; u32 val; if (!channel->phy_data->init_bus) return 0; - rstc = devm_reset_control_array_get_shared(dev); - if (IS_ERR(rstc)) - return PTR_ERR(rstc); - ret = pm_runtime_resume_and_get(dev); if (ret) return ret; - ret = reset_control_deassert(rstc); - if (ret) - goto rpm_put; - - ret = devm_add_action_or_reset(dev, rcar_gen3_reset_assert, rstc); - if (ret) - goto rpm_put; - val = readl(channel->base + USB2_AHB_BUS_CTR); val &= ~USB2_AHB_BUS_CTR_MBL_MASK; val |= USB2_AHB_BUS_CTR_MBL_INCR4; writel(val, channel->base + USB2_AHB_BUS_CTR); -rpm_put: pm_runtime_put(dev); - return ret; + return 0; } static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) @@ -849,6 +836,18 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) } } + channel->rstc = devm_reset_control_array_get_optional_shared(dev); + if (IS_ERR(channel->rstc)) + return PTR_ERR(channel->rstc); + + ret = reset_control_deassert(channel->rstc); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, rcar_gen3_reset_assert, channel->rstc); + if (ret) + return ret; + /* * devm_phy_create() will call pm_runtime_enable(&phy->dev); * And then, phy-core will manage runtime pm for this device. @@ -937,10 +936,38 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); }; +static int rcar_gen3_phy_usb2_suspend(struct device *dev) +{ + struct rcar_gen3_chan *channel = dev_get_drvdata(dev); + + return reset_control_assert(channel->rstc); +} + +static int rcar_gen3_phy_usb2_resume(struct device *dev) +{ + struct rcar_gen3_chan *channel = dev_get_drvdata(dev); + int ret; + + ret = reset_control_deassert(channel->rstc); + if (ret) + return ret; + + ret = rcar_gen3_phy_usb2_init_bus(channel); + if (ret) + reset_control_assert(channel->rstc); + + return ret; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(rcar_gen3_phy_usb2_pm_ops, + rcar_gen3_phy_usb2_suspend, + rcar_gen3_phy_usb2_resume); + static struct platform_driver rcar_gen3_phy_usb2_driver = { .driver = { .name = "phy_rcar_gen3_usb2", .of_match_table = rcar_gen3_phy_usb2_match_table, + .pm = pm_ptr(&rcar_gen3_phy_usb2_pm_ops), }, .probe = rcar_gen3_phy_usb2_probe, .remove = rcar_gen3_phy_usb2_remove, From a2a18e5da64f8da306fa97c397b4c739ea776f37 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 18 Nov 2025 17:52:05 +0800 Subject: [PATCH 435/684] phy: rockchip: naneng-combphy: Fix PCIe L1ss support RK3528 When PCIe link enters L1 PM substates, the PHY will turn off its PLL for power-saving. However, it turns off the PLL too fast which leads the PHY to be broken. According to the PHY document, we need to delay PLL turnoff time. Fixes: bbcca4fac873 ("phy: rockchip: naneng-combphy: Add RK3528 support") Signed-off-by: Shawn Lin Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/1763459526-35004-1-git-send-email-shawn.lin@rock-chips.com Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index a3ef19807b9ef4..e303bec8a996fc 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -21,6 +21,9 @@ #define REF_CLOCK_100MHz (100 * HZ_PER_MHZ) /* RK3528 COMBO PHY REG */ +#define RK3528_PHYREG5 0x14 +#define RK3528_PHYREG5_GATE_TX_PCK_SEL BIT(3) +#define RK3528_PHYREG5_GATE_TX_PCK_DLY_PLL_OFF BIT(3) #define RK3528_PHYREG6 0x18 #define RK3528_PHYREG6_PLL_KVCO GENMASK(12, 10) #define RK3528_PHYREG6_PLL_KVCO_VALUE 0x2 @@ -504,6 +507,10 @@ static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv) case REF_CLOCK_100MHz: rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); if (priv->type == PHY_TYPE_PCIE) { + /* Gate_tx_pck_sel length select for L1ss support */ + rockchip_combphy_updatel(priv, RK3528_PHYREG5_GATE_TX_PCK_SEL, + RK3528_PHYREG5_GATE_TX_PCK_DLY_PLL_OFF, RK3528_PHYREG5); + /* PLL KVCO tuning fine */ val = FIELD_PREP(RK3528_PHYREG6_PLL_KVCO, RK3528_PHYREG6_PLL_KVCO_VALUE); rockchip_combphy_updatel(priv, RK3528_PHYREG6_PLL_KVCO, val, From be866e68966d20bcc4a73708093d577176f99c0c Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 18 Nov 2025 17:52:06 +0800 Subject: [PATCH 436/684] phy: rockchip: naneng-combphy: Fix PCIe L1ss support RK3562 When PCIe link enters L1 PM substates, the PHY will turn off its PLL for power-saving. However, it turns off the PLL too fast which leads the PHY to be broken. According to the PHY document, we need to delay PLL turnoff time. Fixes: f13bff25161b ("phy: rockchip-naneng-combo: Support rk3562") Signed-off-by: Shawn Lin Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/1763459526-35004-2-git-send-email-shawn.lin@rock-chips.com Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index e303bec8a996fc..7f8fc8e6d48905 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -106,6 +106,10 @@ #define RK3568_PHYREG18 0x44 #define RK3568_PHYREG18_PLL_LOOP 0x32 +#define RK3568_PHYREG30 0x74 +#define RK3568_PHYREG30_GATE_TX_PCK_SEL BIT(7) +#define RK3568_PHYREG30_GATE_TX_PCK_DLY_PLL_OFF BIT(7) + #define RK3568_PHYREG32 0x7C #define RK3568_PHYREG32_SSC_MASK GENMASK(7, 4) #define RK3568_PHYREG32_SSC_DIR_MASK GENMASK(5, 4) @@ -664,6 +668,10 @@ static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) case REF_CLOCK_100MHz: rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); if (priv->type == PHY_TYPE_PCIE) { + /* Gate_tx_pck_sel length select for L1ss support */ + rockchip_combphy_updatel(priv, RK3568_PHYREG30_GATE_TX_PCK_SEL, + RK3568_PHYREG30_GATE_TX_PCK_DLY_PLL_OFF, + RK3568_PHYREG30); /* PLL KVCO tuning fine */ val = FIELD_PREP(RK3568_PHYREG33_PLL_KVCO_MASK, RK3568_PHYREG33_PLL_KVCO_VALUE); From 3faa2d0e794093df21c96550829d67d7d38e24bb Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Nov 2025 09:45:40 +0100 Subject: [PATCH 437/684] dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Document lanes mapping when not using in USB-C complex The QMP USB3/DP Combo PHY hosts an USB3 phy and a DP PHY on top of a combo glue to route either lanes to the 4 shared physical lanes. The routing of the lanes can be: - 2 DP + 2 USB3 - 4 DP - 2 USB3 The layout of the lanes was designed to be mapped and swapped related to the USB-C Power Delivery negociation, so it supports a finite set of mappings inherited by the USB-C Altmode layouts. Nevertheless those QMP Comby PHY can be used to drive a DisplayPort connector, DP->HDMI bridge, USB3 A Connector, etc... without an USB-C connector and no PD events. Document the data-lanes on numbered port@0 out endpoints, allowing us to document the lanes mapping to DisplayPort and/or USB3 connectors/peripherals. Reviewed-by: Rob Herring (Arm) Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20251119-topic-x1e80100-hdmi-v7-1-2bee0e66cc1b@linaro.org Signed-off-by: Vinod Koul --- .../phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml index c8bc512df08b56..e0ec45b96bf5d7 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml @@ -78,10 +78,77 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports + properties: port@0: - $ref: /schemas/graph.yaml#/properties/port + $ref: /schemas/graph.yaml#/$defs/port-base description: Output endpoint of the PHY + unevaluatedProperties: false + + properties: + endpoint: + $ref: /schemas/graph.yaml#/$defs/endpoint-base + unevaluatedProperties: false + + endpoint@0: + $ref: /schemas/graph.yaml#/$defs/endpoint-base + description: Display Port Output lanes of the PHY when used with static mapping, + The entry index is the DP lanes index, and the number is the PHY + signal in the order RX0, TX0, TX1, RX1. + unevaluatedProperties: false + + properties: + # Static lane mappings are mutually exclusive with typec-mux/orientation-mux + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 4 + oneOf: + - items: # DisplayPort 1 lane, normal orientation + - const: 3 + - items: # DisplayPort 1 lane, flipped orientation + - const: 0 + - items: # DisplayPort 2 lanes, normal orientation + - const: 3 + - const: 2 + - items: # DisplayPort 2 lanes, flipped orientation + - const: 0 + - const: 1 + - items: # DisplayPort 4 lanes, normal orientation + - const: 3 + - const: 2 + - const: 1 + - const: 0 + - items: # DisplayPort 4 lanes, flipped orientation + - const: 0 + - const: 1 + - const: 2 + - const: 3 + required: + - data-lanes + + endpoint@1: + $ref: /schemas/graph.yaml#/$defs/endpoint-base + description: USB Output lanes of the PHY when used with static mapping. + The entry index is the USB3 lane in the order TX then RX, and the + number is the PHY signal in the order RX0, TX0, TX1, RX1. + unevaluatedProperties: false + + properties: + # Static lane mappings are mutually exclusive with typec-mux/orientation-mux + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + oneOf: + - items: # USB3, normal orientation + - const: 1 + - const: 0 + - items: # USB3, flipped orientation + - const: 2 + - const: 3 + + required: + - data-lanes port@1: $ref: /schemas/graph.yaml#/properties/port From f842daf740114a8783be566219db34c6a0f1d02c Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Nov 2025 09:45:41 +0100 Subject: [PATCH 438/684] phy: qcom: qmp-combo: get the USB3 & DisplayPort lanes mapping from DT The QMP USB3/DP Combo PHY hosts an USB3 phy and a DP PHY on top of a combo glue to route either lanes to the 4 shared physical lanes. The routing of the lanes can be: - 2 DP + 2 USB3 - 4 DP - 2 USB3 Get the lanes mapping from DT and stop registering the USB-C muxes in favor of a static mode and orientation detemined by the lanes mapping. This allows supporting boards with direct connection of USB3 and DisplayPort lanes to the QMP Combo PHY lanes, not using the USB-C Altmode feature. Reviewed-by: Dmitry Baryshkov Tested-by: Xilin Wu # qcs6490-radxa-dragon-q6a Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Neil Armstrong Link: https://patch.msgid.link/20251119-topic-x1e80100-hdmi-v7-2-2bee0e66cc1b@linaro.org Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 142 ++++++++++++++++++++-- 1 file changed, 134 insertions(+), 8 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 19a72fb1b83564..9e2a6c5d0f586b 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1739,6 +1740,26 @@ static const u8 qmp_dp_v6_pre_emphasis_hbr_rbr[4][4] = { { 0x22, 0xff, 0xff, 0xff } }; +struct qmp_combo_lane_mapping { + unsigned int lanes_count; + enum typec_orientation orientation; + u32 lanes[4]; +}; + +static const struct qmp_combo_lane_mapping usb3_data_lanes[] = { + { 2, TYPEC_ORIENTATION_NORMAL, { 1, 0 }}, + { 2, TYPEC_ORIENTATION_REVERSE, { 2, 3 }}, +}; + +static const struct qmp_combo_lane_mapping dp_data_lanes[] = { + { 1, TYPEC_ORIENTATION_NORMAL, { 3 }}, + { 1, TYPEC_ORIENTATION_REVERSE, { 0 }}, + { 2, TYPEC_ORIENTATION_NORMAL, { 3, 2 }}, + { 2, TYPEC_ORIENTATION_REVERSE, { 0, 1 }}, + { 4, TYPEC_ORIENTATION_NORMAL, { 3, 2, 1, 0 }}, + { 4, TYPEC_ORIENTATION_REVERSE, { 0, 1, 2, 3 }}, +}; + struct qmp_combo; struct qmp_combo_offsets { @@ -4079,6 +4100,84 @@ static struct phy *qmp_combo_phy_xlate(struct device *dev, const struct of_phand return ERR_PTR(-EINVAL); } +static void qmp_combo_find_lanes_orientation(const struct qmp_combo_lane_mapping *mapping, + unsigned int mapping_count, + u32 *lanes, unsigned int lanes_count, + enum typec_orientation *orientation) +{ + int i; + + for (i = 0; i < mapping_count; i++) { + if (mapping[i].lanes_count != lanes_count) + continue; + if (!memcmp(mapping[i].lanes, lanes, sizeof(u32) * lanes_count)) { + *orientation = mapping[i].orientation; + return; + } + } +} + +static int qmp_combo_get_dt_lanes_mapping(struct device *dev, unsigned int endpoint, + u32 *data_lanes, unsigned int max, + unsigned int *count) +{ + struct device_node *ep __free(device_node) = NULL; + int ret; + + ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, endpoint); + if (!ep) + return -EINVAL; + + ret = of_property_count_u32_elems(ep, "data-lanes"); + if (ret < 0) + return ret; + + *count = ret; + if (*count > max) + return -EINVAL; + + return of_property_read_u32_array(ep, "data-lanes", data_lanes, + min_t(unsigned int, *count, max)); +} + +static int qmp_combo_get_dt_dp_orientation(struct device *dev, + enum typec_orientation *orientation) +{ + unsigned int count; + u32 data_lanes[4]; + int ret; + + /* DP is described on the first endpoint of the first port */ + ret = qmp_combo_get_dt_lanes_mapping(dev, 0, data_lanes, 4, &count); + if (ret < 0) + return ret == -EINVAL ? 0 : ret; + + /* Search for a match and only update orientation if found */ + qmp_combo_find_lanes_orientation(dp_data_lanes, ARRAY_SIZE(dp_data_lanes), + data_lanes, count, orientation); + + return 0; +} + +static int qmp_combo_get_dt_usb3_orientation(struct device *dev, + enum typec_orientation *orientation) +{ + unsigned int count; + u32 data_lanes[2]; + int ret; + + /* USB3 is described on the second endpoint of the first port */ + ret = qmp_combo_get_dt_lanes_mapping(dev, 1, data_lanes, 2, &count); + if (ret < 0) + return ret == -EINVAL ? 0 : ret; + + /* Search for a match and only update orientation if found */ + qmp_combo_find_lanes_orientation(usb3_data_lanes, ARRAY_SIZE(usb3_data_lanes), + data_lanes, count, orientation); + + return 0; +} + static int qmp_combo_probe(struct platform_device *pdev) { struct qmp_combo *qmp; @@ -4130,9 +4229,41 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) goto err_node_put; - ret = qmp_combo_typec_register(qmp); - if (ret) - goto err_node_put; + qmp->qmpphy_mode = QMPPHY_MODE_USB3DP; + + if (of_property_present(dev->of_node, "mode-switch") || + of_property_present(dev->of_node, "orientation-switch")) { + ret = qmp_combo_typec_register(qmp); + if (ret) + goto err_node_put; + } else { + enum typec_orientation dp_orientation = TYPEC_ORIENTATION_NONE; + enum typec_orientation usb3_orientation = TYPEC_ORIENTATION_NONE; + + ret = qmp_combo_get_dt_dp_orientation(dev, &dp_orientation); + if (ret) + goto err_node_put; + + ret = qmp_combo_get_dt_usb3_orientation(dev, &usb3_orientation); + if (ret) + goto err_node_put; + + if (dp_orientation == TYPEC_ORIENTATION_NONE && + usb3_orientation != TYPEC_ORIENTATION_NONE) { + qmp->qmpphy_mode = QMPPHY_MODE_USB3_ONLY; + qmp->orientation = usb3_orientation; + } else if (usb3_orientation == TYPEC_ORIENTATION_NONE && + dp_orientation != TYPEC_ORIENTATION_NONE) { + qmp->qmpphy_mode = QMPPHY_MODE_DP_ONLY; + qmp->orientation = dp_orientation; + } else if (dp_orientation != TYPEC_ORIENTATION_NONE && + dp_orientation == usb3_orientation) { + qmp->qmpphy_mode = QMPPHY_MODE_USB3DP; + qmp->orientation = dp_orientation; + } else { + dev_warn(dev, "unable to determine orientation & mode from data-lanes"); + } + } ret = drm_aux_bridge_register(dev); if (ret) @@ -4152,11 +4283,6 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) goto err_node_put; - /* - * The hw default is USB3_ONLY, but USB3+DP mode lets us more easily - * check both sub-blocks' init tables for blunders at probe time. - */ - qmp->qmpphy_mode = QMPPHY_MODE_USB3DP; qmp->usb_phy = devm_phy_create(dev, usb_np, &qmp_combo_usb_phy_ops); if (IS_ERR(qmp->usb_phy)) { From 7044ed6749c8a7d49e67b2f07f42da2f29d26be6 Mon Sep 17 00:00:00 2001 From: Ronak Raheja Date: Fri, 19 Sep 2025 20:21:58 -0700 Subject: [PATCH 439/684] phy: qcom: m31-eusb2: Update init sequence to set PHY_ENABLE Certain platforms may not have the PHY_ENABLE bit set on power on reset. Update the current sequence to explicitly write to enable the PHY_ENABLE bit. This ensures that regardless of the platform, the PHY is properly enabled. Signed-off-by: Ronak Raheja Signed-off-by: Wesley Cheng Reviewed-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20250920032158.242725-1-wesley.cheng@oss.qualcomm.com Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c index 0a0d2d9fc84648..95cd3175926d56 100644 --- a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c @@ -25,6 +25,7 @@ #define POR BIT(1) #define USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) +#define PHY_ENABLE BIT(0) #define SIDDQ_SEL BIT(1) #define SIDDQ BIT(2) #define FSEL GENMASK(6, 4) @@ -81,6 +82,7 @@ struct m31_eusb2_priv_data { static const struct m31_phy_tbl_entry m31_eusb2_setup_tbl[] = { M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 1), M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, POR, 1), + M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, PHY_ENABLE, 1), M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG1, PLL_EN, 1), M31_EUSB_PHY_INIT_CFG(USB_PHY_FSEL_SEL, FSEL_SEL, 1), }; From ec5814578e3c36289c4992c466ae297e0b799c18 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Sep 2025 15:20:31 +0200 Subject: [PATCH 440/684] phy: renesas: Remove unneeded semicolons Semicolons after end of function braces are not needed, remove them. Signed-off-by: Geert Uytterhoeven Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/a8807dafa87fcc3abcafd34a1895e4c722c39793.1758719985.git.geert+renesas@glider.be Signed-off-by: Vinod Koul --- drivers/phy/renesas/phy-rcar-gen3-pcie.c | 2 +- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 2 +- drivers/phy/renesas/phy-rcar-gen3-usb3.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c index feca4cb2ff4d1e..c0e5a4ac82de2c 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-pcie.c +++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c @@ -128,7 +128,7 @@ static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev) static void rcar_gen3_phy_pcie_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); -}; +} static struct platform_driver rcar_gen3_phy_driver = { .driver = { diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 3c063e4dea41ad..582de10d5beb96 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -934,7 +934,7 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_role); pm_runtime_disable(&pdev->dev); -}; +} static int rcar_gen3_phy_usb2_suspend(struct device *dev) { diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c index 5c267d148c90be..0420f5b283ce42 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb3.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c @@ -202,7 +202,7 @@ static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev) static void rcar_gen3_phy_usb3_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); -}; +} static struct platform_driver rcar_gen3_phy_usb3_driver = { .driver = { From 95e5905698983df94069e185f9eb3c67c7cf75d5 Mon Sep 17 00:00:00 2001 From: Xiaolei Wang Date: Thu, 25 Sep 2025 09:38:06 +0800 Subject: [PATCH 441/684] phy: freescale: Initialize priv->lock Initialize priv->lock to fix the following warning. WARNING: CPU: 0 PID: 12 at kernel/locking/mutex.c:577 __mutex_lock+0x70c/0x8b8 Modules linked in: Hardware name: Freescale i.MX8QM MEK (DT) Call trace: __mutex_lock+0x70c/0x8b8 (P) mutex_lock_nested+0x24/0x30 imx_hsio_power_on+0x4c/0x764 phy_power_on+0x7c/0x12c imx_pcie_host_init+0x1d0/0x4d4 dw_pcie_host_init+0x188/0x4b0 imx_pcie_probe+0x324/0x6f4 platform_probe+0x5c/0x98 really_probe+0xbc/0x29c __driver_probe_device+0x78/0x12c driver_probe_device+0xd8/0x160 __device_attach_driver+0xb8/0x138 bus_for_each_drv+0x84/0xe4 __device_attach_async_helper+0xb8/0xdc async_run_entry_fn+0x34/0xe0 process_one_work+0x220/0x694 worker_thread+0x1c0/0x36c kthread+0x14c/0x224 Fixes: 82c56b6dd24f ("phy: freescale: imx8qm-hsio: Add i.MX8QM HSIO PHY driver support") Signed-off-by: Xiaolei Wang Reviewed-by: Frank Li Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20250925013806.569658-1-xiaolei.wang@windriver.com Signed-off-by: Vinod Koul --- drivers/phy/freescale/phy-fsl-imx8qm-hsio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c index 5dca93cd325c89..977d21d753a59a 100644 --- a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c +++ b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c @@ -533,7 +533,7 @@ static struct phy *imx_hsio_xlate(struct device *dev, static int imx_hsio_probe(struct platform_device *pdev) { - int i; + int i, ret; void __iomem *off; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -545,6 +545,9 @@ static int imx_hsio_probe(struct platform_device *pdev) return -ENOMEM; priv->dev = &pdev->dev; priv->drvdata = of_device_get_match_data(dev); + ret = devm_mutex_init(dev, &priv->lock); + if (ret) + return ret; /* Get HSIO configuration mode */ if (of_property_read_string(np, "fsl,hsio-cfg", &priv->hsio_cfg)) From a7f0d69ecdd2fec89ce1f9b600a5c721c017fa9c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Oct 2025 06:59:20 +0200 Subject: [PATCH 442/684] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Restrict resets per each device Bindings should be complete, thus complete the constraints for the resets by adding missing compatibles for devices with two resets and "else:" clause narrowing them for all other devices. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20251017045919.34599-2-krzysztof.kozlowski@linaro.org Signed-off-by: Vinod Koul --- .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 119b4ff36dbd66..9f5f9af6f6cd83 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -215,15 +215,23 @@ allOf: enum: - qcom,sm8550-qmp-gen4x2-pcie-phy - qcom,sm8650-qmp-gen4x2-pcie-phy + - qcom,x1e80100-qmp-gen3x2-pcie-phy - qcom,x1e80100-qmp-gen4x2-pcie-phy - qcom,x1e80100-qmp-gen4x4-pcie-phy - qcom,x1e80100-qmp-gen4x8-pcie-phy + - qcom,x1p42100-qmp-gen4x4-pcie-phy then: properties: resets: minItems: 2 reset-names: minItems: 2 + else: + properties: + resets: + maxItems: 1 + reset-names: + maxItems: 1 - if: properties: From d877f881cec508a46f76dbed7c46ab78bc1c0d87 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Mon, 3 Nov 2025 23:56:24 -0800 Subject: [PATCH 443/684] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Document the Glymur QMP PCIe PHY The fifth PCIe instance on Glymur has a Gen5 4-lane PHY. Document it as a separate compatible. Signed-off-by: Prudhvi Yarlagadda Signed-off-by: Wenbin Yao Acked-by: Rob Herring (Arm) Signed-off-by: Qiang Yu Link: https://patch.msgid.link/20251103-glymur-pcie-upstream-v6-1-18a5e0a538dc@oss.qualcomm.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 9f5f9af6f6cd83..48bd11410e8c2d 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -16,6 +16,7 @@ description: properties: compatible: enum: + - qcom,glymur-qmp-gen5x4-pcie-phy - qcom,qcs615-qmp-gen3x1-pcie-phy - qcom,qcs8300-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x2-pcie-phy @@ -178,6 +179,7 @@ allOf: compatible: contains: enum: + - qcom,glymur-qmp-gen5x4-pcie-phy - qcom,sa8775p-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x4-pcie-phy - qcom,sc8280xp-qmp-gen3x1-pcie-phy @@ -213,6 +215,7 @@ allOf: compatible: contains: enum: + - qcom,glymur-qmp-gen5x4-pcie-phy - qcom,sm8550-qmp-gen4x2-pcie-phy - qcom,sm8650-qmp-gen4x2-pcie-phy - qcom,x1e80100-qmp-gen3x2-pcie-phy From bc2ba6e3fb8a35cd83813be1bd4c5f066a401d8b Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Mon, 3 Nov 2025 23:56:25 -0800 Subject: [PATCH 444/684] phy: qcom-qmp: pcs: Add v8.50 register offsets The new Glymur SoC bumps up the HW version of QMP phy to v8.50 for PCIE g5x4. Add the new PCS offsets in a dedicated header file. Signed-off-by: Prudhvi Yarlagadda Signed-off-by: Wenbin Yao Reviewed-by: Dmitry Baryshkov Signed-off-by: Qiang Yu Link: https://patch.msgid.link/20251103-glymur-pcie-upstream-v6-2-18a5e0a538dc@oss.qualcomm.com Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8_50.h | 13 +++++++++++++ drivers/phy/qualcomm/phy-qcom-qmp.h | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8_50.h diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8_50.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8_50.h new file mode 100644 index 00000000000000..325c127e8eb7ad --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8_50.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef QCOM_PHY_QMP_PCS_V8_50_H_ +#define QCOM_PHY_QMP_PCS_V8_50_H_ + +#define QPHY_V8_50_PCS_STATUS1 0x010 +#define QPHY_V8_50_PCS_START_CONTROL 0x05c +#define QPHY_V8_50_PCS_POWER_DOWN_CONTROL 0x64 + +#endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index f58c82b2dd23e1..da2a7ad2cdccef 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -58,6 +58,8 @@ #include "phy-qcom-qmp-pcs-v8.h" +#include "phy-qcom-qmp-pcs-v8_50.h" + /* QPHY_SW_RESET bit */ #define SW_RESET BIT(0) /* QPHY_POWER_DOWN_CONTROL */ From 1797c6677ad6298ca463b6ee42245e19e9cc1206 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Mon, 3 Nov 2025 23:56:26 -0800 Subject: [PATCH 445/684] phy: qcom: qmp-pcie: Add support for Glymur PCIe Gen5x4 PHY Add support for Gen5 x4 PCIe QMP PHY found on Glymur platform. Signed-off-by: Prudhvi Yarlagadda Signed-off-by: Wenbin Yao Reviewed-by: Dmitry Baryshkov Acked-by: Manivannan Sadhasivam Signed-off-by: Qiang Yu Link: https://patch.msgid.link/20251103-glymur-pcie-upstream-v6-3-18a5e0a538dc@oss.qualcomm.com Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 62b1c845b6275d..86b1b7e2da86a8 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -100,6 +100,12 @@ static const unsigned int pciephy_v7_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V7_PCS_POWER_DOWN_CONTROL, }; +static const unsigned int pciephy_v8_50_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_START_CTRL] = QPHY_V8_50_PCS_START_CONTROL, + [QPHY_PCS_STATUS] = QPHY_V8_50_PCS_STATUS1, + [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V8_50_PCS_POWER_DOWN_CONTROL, +}; + static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), @@ -3072,6 +3078,7 @@ struct qmp_pcie_offsets { u16 rx2; u16 txz; u16 rxz; + u16 txrxz; u16 ln_shrd; }; @@ -3356,6 +3363,12 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_30 = { .ln_shrd = 0x8000, }; +static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_50 = { + .serdes = 0x8000, + .pcs = 0x9000, + .txrxz = 0xd000, +}; + static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { .lanes = 1, @@ -4412,6 +4425,22 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = { + .lanes = 4, + + .offsets = &qmp_pcie_offsets_v8_50, + + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + + .regs = pciephy_v8_50_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS_4_20, +}; + static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -5163,6 +5192,9 @@ static int qmp_pcie_probe(struct platform_device *pdev) static const struct of_device_id qmp_pcie_of_match_table[] = { { + .compatible = "qcom,glymur-qmp-gen5x4-pcie-phy", + .data = &glymur_qmp_gen5x4_pciephy_cfg, + }, { .compatible = "qcom,ipq6018-qmp-pcie-phy", .data = &ipq6018_pciephy_cfg, }, { From 9d3daf9ca3239042c2cf473a76db2a77e6de22c6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 17 Oct 2025 19:04:23 +0300 Subject: [PATCH 446/684] phy: ti: gmii-sel: Add a sanity check on the phy_id The "phy_id" comes from the device tree so it's going to be correct. But static checkers sometimes complain when we have an upper bounds check with no lower bounds check. Also it's a bit unusual that the lowest valid number is 1 instead of 0 so adding a check could potentially help someone. Signed-off-by: Dan Carpenter Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/aPJpB-QI8FMpFGOk@stanley.mountain Signed-off-by: Vinod Koul --- drivers/phy/ti/phy-gmii-sel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index 50adabb867cb12..6cfe2538d15b12 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -341,7 +341,7 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev, if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && args->args_count < 2) return ERR_PTR(-EINVAL); - if (phy_id > priv->num_ports) + if (phy_id < 1 || phy_id > priv->num_ports) return ERR_PTR(-EINVAL); if (phy_id != priv->if_phys[phy_id - 1].id) return ERR_PTR(-EINVAL); From 72126e9623e1696ea83c77ef6d0306a6263bdd6b Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 28 Oct 2025 10:00:54 +0200 Subject: [PATCH 447/684] phy: rockchip: samsung-hdptx: Fix reported clock rate in high bpc mode When making use of the clock provider functionality, the output clock does normally match the TMDS character rate, which is what the PHY PLL gets configured to. However, this is only applicable for default color depth of 8 bpc. For higher depths, the output clock is further divided by the hardware according to the formula: output_clock_rate = tmds_char_rate * 8 / bpc Since the existence of the clock divider wasn't taken into account when support for high bpc has been introduced, make the necessary adjustments to report the correct clock rate. Fixes: 9d0ec51d7c22 ("phy: rockchip: samsung-hdptx: Add high color depth management") Reported-by: Andy Yan Signed-off-by: Cristian Ciocaltea Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251028-phy-hdptx-fixes-v1-1-ecc642a59d94@collabora.com Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c index 01bbf668e05ef9..aee03e8655f66d 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -1037,7 +1037,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx) ret = rk_hdptx_post_enable_pll(hdptx); if (!ret) - hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate; + hdptx->hw_rate = DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.tmds_char_rate * 8, + hdptx->hdmi_cfg.bpc); return ret; } @@ -1895,19 +1896,20 @@ static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate, * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with * a different rate argument. */ - return hdptx->hdmi_cfg.tmds_char_rate; + return DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.tmds_char_rate * 8, hdptx->hdmi_cfg.bpc); } static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); + unsigned long long tmds_rate = DIV_ROUND_CLOSEST_ULL(rate * hdptx->hdmi_cfg.bpc, 8); /* Revert any unlikely TMDS char rate change since round_rate() */ - if (hdptx->hdmi_cfg.tmds_char_rate != rate) { - dev_warn(hdptx->dev, "Reverting unexpected rate change from %lu to %llu\n", - rate, hdptx->hdmi_cfg.tmds_char_rate); - hdptx->hdmi_cfg.tmds_char_rate = rate; + if (hdptx->hdmi_cfg.tmds_char_rate != tmds_rate) { + dev_warn(hdptx->dev, "Reverting unexpected rate change from %llu to %llu\n", + tmds_rate, hdptx->hdmi_cfg.tmds_char_rate); + hdptx->hdmi_cfg.tmds_char_rate = tmds_rate; } /* From 8daaced9f5eeb4a2c8ca08b0a8286b6a498a8387 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 28 Oct 2025 10:00:55 +0200 Subject: [PATCH 448/684] phy: rockchip: samsung-hdptx: Reduce ROPLL loop bandwidth Due to its relatively low frequency, a noise stemming from the 24MHz PLL reference clock may traverse the low-pass loop filter of ROPLL, which could potentially generate some HDMI flash artifacts. Reduce ROPLL loop bandwidth in an attempt to mitigate the problem. Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver") Co-developed-by: Algea Cao Signed-off-by: Algea Cao Signed-off-by: Cristian Ciocaltea Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251028-phy-hdptx-fixes-v1-2-ecc642a59d94@collabora.com Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c index aee03e8655f66d..8ba9b53c2309b2 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -500,9 +500,7 @@ static const struct reg_sequence rk_hdtpx_common_cmn_init_seq[] = { REG_SEQ0(CMN_REG(0043), 0x00), REG_SEQ0(CMN_REG(0044), 0x46), REG_SEQ0(CMN_REG(0045), 0x24), - REG_SEQ0(CMN_REG(0046), 0xff), REG_SEQ0(CMN_REG(0047), 0x00), - REG_SEQ0(CMN_REG(0048), 0x44), REG_SEQ0(CMN_REG(0049), 0xfa), REG_SEQ0(CMN_REG(004a), 0x08), REG_SEQ0(CMN_REG(004b), 0x00), @@ -575,6 +573,8 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { REG_SEQ0(CMN_REG(0034), 0x00), REG_SEQ0(CMN_REG(003d), 0x40), REG_SEQ0(CMN_REG(0042), 0x78), + REG_SEQ0(CMN_REG(0046), 0xdd), + REG_SEQ0(CMN_REG(0048), 0x11), REG_SEQ0(CMN_REG(004e), 0x34), REG_SEQ0(CMN_REG(005c), 0x25), REG_SEQ0(CMN_REG(005e), 0x4f), From 51023cf6cc5db3423dea6620746d9087e336e024 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 28 Oct 2025 10:00:56 +0200 Subject: [PATCH 449/684] phy: rockchip: samsung-hdptx: Prevent Inter-Pair Skew from exceeding the limits Fixup PHY deskew FIFO to prevent the phase of D2 lane going ahead of other lanes. It's worth noting this might only happen when dealing with HDMI 2.0 rates. Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver") Co-developed-by: Algea Cao Signed-off-by: Algea Cao Signed-off-by: Cristian Ciocaltea Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20251028-phy-hdptx-fixes-v1-3-ecc642a59d94@collabora.com Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c index 8ba9b53c2309b2..29de2f7bdae8a3 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -668,13 +668,9 @@ static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = { static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { REG_SEQ0(LANE_REG(0312), 0x00), - REG_SEQ0(LANE_REG(031e), 0x00), REG_SEQ0(LANE_REG(0412), 0x00), - REG_SEQ0(LANE_REG(041e), 0x00), REG_SEQ0(LANE_REG(0512), 0x00), - REG_SEQ0(LANE_REG(051e), 0x00), REG_SEQ0(LANE_REG(0612), 0x00), - REG_SEQ0(LANE_REG(061e), 0x08), REG_SEQ0(LANE_REG(0303), 0x2f), REG_SEQ0(LANE_REG(0403), 0x2f), REG_SEQ0(LANE_REG(0503), 0x2f), @@ -687,6 +683,11 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { REG_SEQ0(LANE_REG(0406), 0x1c), REG_SEQ0(LANE_REG(0506), 0x1c), REG_SEQ0(LANE_REG(0606), 0x1c), + /* Keep Inter-Pair Skew in the limits */ + REG_SEQ0(LANE_REG(031e), 0x02), + REG_SEQ0(LANE_REG(041e), 0x02), + REG_SEQ0(LANE_REG(051e), 0x02), + REG_SEQ0(LANE_REG(061e), 0x0a), }; static struct tx_drv_ctrl tx_drv_ctrl_rbr[4][4] = { From 0e8fe19c0292d9912460b25043292227d5f1fdb2 Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Tue, 18 Nov 2025 15:19:46 +0800 Subject: [PATCH 450/684] dt-bindings: phy: imx8mq-usb: add alternate reference clock Beside default 24MHz clock input, there is an optional additional 100Mhz clock input 'alt' for USB PHY reference clock. Reviewed-by: Frank Li Acked-by: Conor Dooley Signed-off-by: Xu Yang Link: https://patch.msgid.link/20251118071947.2504789-1-xu.yang_2@nxp.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml index 6a47e08e0e97b2..081deb502e2130 100644 --- a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml @@ -27,11 +27,16 @@ properties: const: 0 clocks: - maxItems: 1 + minItems: 1 + items: + - description: PHY configuration clock + - description: Alternate PHY reference clock clock-names: + minItems: 1 items: - const: phy + - const: alt power-domains: maxItems: 1 From 3b64ea4768e7e64b2d9ae5833dbcac19f6212145 Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Tue, 18 Nov 2025 15:19:47 +0800 Subject: [PATCH 451/684] phy: fsl-imx8mq-usb: support alternate reference clock This phy supports both 24MHz and 100MHz clock inputs. By default it's using XTAL 24MHz and the 100MHz clock is a alternate reference clock. Add supports to use alternate reference clock in case 24MHz clock can't work well. Reviewed-by: Frank Li Signed-off-by: Xu Yang Link: https://patch.msgid.link/20251118071947.2504789-2-xu.yang_2@nxp.com Signed-off-by: Vinod Koul --- drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c index b94f242420fc73..ad8a55012e42f2 100644 --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c @@ -16,6 +16,7 @@ #define PHY_CTRL0_REF_SSP_EN BIT(2) #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5) #define PHY_CTRL0_FSEL_24M 0x2a +#define PHY_CTRL0_FSEL_100M 0x27 #define PHY_CTRL1 0x4 #define PHY_CTRL1_RESET BIT(0) @@ -108,6 +109,7 @@ struct tca_blk { struct imx8mq_usb_phy { struct phy *phy; struct clk *clk; + struct clk *alt_clk; void __iomem *base; struct regulator *vbus; struct tca_blk *tca; @@ -582,7 +584,8 @@ static int imx8mp_usb_phy_init(struct phy *phy) /* USB3.0 PHY signal fsel for 24M ref */ value = readl(imx_phy->base + PHY_CTRL0); value &= ~PHY_CTRL0_FSEL_MASK; - value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M); + value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, imx_phy->alt_clk ? + PHY_CTRL0_FSEL_100M : PHY_CTRL0_FSEL_24M); writel(value, imx_phy->base + PHY_CTRL0); /* Disable alt_clk_en and use internal MPLL clocks */ @@ -626,13 +629,24 @@ static int imx8mq_phy_power_on(struct phy *phy) if (ret) return ret; - return clk_prepare_enable(imx_phy->clk); + ret = clk_prepare_enable(imx_phy->clk); + if (ret) + return ret; + + ret = clk_prepare_enable(imx_phy->alt_clk); + if (ret) { + clk_disable_unprepare(imx_phy->clk); + return ret; + } + + return ret; } static int imx8mq_phy_power_off(struct phy *phy) { struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); + clk_disable_unprepare(imx_phy->alt_clk); clk_disable_unprepare(imx_phy->clk); regulator_disable(imx_phy->vbus); @@ -681,6 +695,11 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(imx_phy->clk); } + imx_phy->alt_clk = devm_clk_get_optional(dev, "alt"); + if (IS_ERR(imx_phy->alt_clk)) + return dev_err_probe(dev, PTR_ERR(imx_phy->alt_clk), + "Failed to get alt clk\n"); + imx_phy->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imx_phy->base)) return PTR_ERR(imx_phy->base); From 41b67ab3d2f5be9d0b6e5ba9cbec97c820fc50e8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 19 Nov 2025 11:30:47 -0800 Subject: [PATCH 452/684] perf test all metrics: Fully ignore Default metric failures Determine if a metric is default from `perf list --raw-dump $m` eg: ``` $ perf list --raw-dump l1_prefetch_miss_rate Default4 l1_prefetch_miss_rate ``` If a metric has "not supported" or "no supported events" then ignore these failures for default metrics. Tidy up the skip/fail messages in the output to make them easier to spot/read. ``` $ perf list -vv "all metrics" ... Testing llc_miss_rate [Ignored llc_miss_rate] failed but as a Default metric this can be expected Error: No supported events found. The LLC-loads event is not supported. ... ``` Reported-by: Thomas Richter Closes: https://lore.kernel.org/linux-perf-users/20251119104751.51960-1-tmricht@linux.ibm.com/ Reported-by: Namhyung Kim Reported-by: James Clark Closes: https://lore.kernel.org/lkml/aRi9xnwdLh3Dir9f@google.com/ Signed-off-by: Ian Rogers Reviewed-by: James Clark Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat_all_metrics.sh | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tools/perf/tests/shell/stat_all_metrics.sh b/tools/perf/tests/shell/stat_all_metrics.sh index a7edf01b394336..3dabb39c7cc8c4 100755 --- a/tools/perf/tests/shell/stat_all_metrics.sh +++ b/tools/perf/tests/shell/stat_all_metrics.sh @@ -27,19 +27,20 @@ for m in $(perf list --raw-dump metrics); do fi if [[ "$result" =~ "Cannot resolve IDs for" || "$result" =~ "No supported events found" ]] then - if [[ "$m" == @(l1_prefetch_miss_rate|stalled_cycles_per_instruction) ]] + if [[ $(perf list --raw-dump $m) == "Default"* ]] then - # Default metrics that may use unsupported events. + echo "[Ignored $m] failed but as a Default metric this can be expected" + echo $result continue fi - echo "Metric contains missing events" + echo "[Failed $m] Metric contains missing events" echo $result err=1 # Fail continue elif [[ "$result" =~ \ "Access to performance monitoring and observability operations is limited" ]] then - echo "Permission failure" + echo "[Skipped $m] Permission failure" echo $result if [[ $err -eq 0 ]] then @@ -48,7 +49,7 @@ for m in $(perf list --raw-dump metrics); do continue elif [[ "$result" =~ "in per-thread mode, enable system wide" ]] then - echo "Permissions - need system wide mode" + echo "[Skipped $m] Permissions - need system wide mode" echo $result if [[ $err -eq 0 ]] then @@ -57,7 +58,13 @@ for m in $(perf list --raw-dump metrics); do continue elif [[ "$result" =~ "" ]] then - echo "Not supported events" + if [[ $(perf list --raw-dump $m) == "Default"* ]] + then + echo "[Ignored $m] failed but as a Default metric this can be expected" + echo $result + continue + fi + echo "[Skipped $m] Not supported events" echo $result if [[ $err -eq 0 ]] then @@ -66,7 +73,7 @@ for m in $(perf list --raw-dump metrics); do continue elif [[ "$result" =~ "" ]] then - echo "Not counted events" + echo "[Skipped $m] Not counted events" echo $result if [[ $err -eq 0 ]] then @@ -75,7 +82,7 @@ for m in $(perf list --raw-dump metrics); do continue elif [[ "$result" =~ "FP_ARITH" || "$result" =~ "AMX" ]] then - echo "FP issues" + echo "[Skipped $m] FP issues" echo $result if [[ $err -eq 0 ]] then @@ -84,7 +91,7 @@ for m in $(perf list --raw-dump metrics); do continue elif [[ "$result" =~ "PMM" ]] then - echo "Optane memory issues" + echo "[Skipped $m] Optane memory issues" echo $result if [[ $err -eq 0 ]] then @@ -101,7 +108,7 @@ for m in $(perf list --raw-dump metrics); do # No error result and metric shown. continue fi - echo "Metric '$m' has non-zero error '$result_err' or not printed in:" + echo "[Failed $m] has non-zero error '$result_err' or not printed in:" echo "$result" err=1 done From 8cf9cca7f687044702228c51b8e3bb853a0e1b54 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Nov 2025 16:47:24 -0800 Subject: [PATCH 453/684] perf list: Print matching PMU events for --unit When --unit option is used, pmu_glob is set to the argument. It should match with event PMU and display the matching ones only. But it also shows raw events and metrics after that. $ perf list --unit tool List of pre-defined events (to be used in -e or -M): tool: core_wide [1 if not SMT,if SMT are events being gathered on all SMT threads 1 otherwise 0. Unit: tool] duration_time [Wall clock interval time in nanoseconds. Unit: tool] has_pmem [1 if persistent memory installed otherwise 0. Unit: tool] num_cores [Number of cores. A core consists of 1 or more thread,with each thread being associated with a logical Linux CPU. Unit: tool] num_cpus [Number of logical Linux CPUs. There may be multiple such CPUs on a core. Unit: tool] ... rNNN [Raw event descriptor] cpu/event=0..255,pc,edge,.../modifier [Raw event descriptor] [(see 'man perf-list' or 'man perf-record' on how to encode it)] breakpoint//modifier [Raw event descriptor] cstate_core/event=0..0xffffffffffffffff/modifier [Raw event descriptor] cstate_pkg/event=0..0xffffffffffffffff/modifier [Raw event descriptor] drm_i915//modifier [Raw event descriptor] hwmon_acpitz//modifier [Raw event descriptor] hwmon_ac//modifier [Raw event descriptor] hwmon_bat0//modifier [Raw event descriptor] hwmon_coretemp//modifier [Raw event descriptor] ... Metric Groups: Backend: [Grouping from Top-down Microarchitecture Analysis Metrics spreadsheet] tma_core_bound [This metric represents fraction of slots where Core non-memory issues were of a bottleneck] tma_info_core_ilp [Instruction-Level-Parallelism (average number of uops executed when there is execution) per thread (logical-processor)] tma_info_memory_l2mpki [L2 cache true misses per kilo instruction for retired demand loads] ... This change makes it print the tool PMU events only. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-list.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 16400366f8276a..28bf1fc7f5eeff 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -130,7 +130,7 @@ static void default_print_event(void *ps, const char *topic, if (deprecated && !print_state->deprecated) return; - if (print_state->pmu_glob && pmu_name && !strglobmatch(pmu_name, print_state->pmu_glob)) + if (print_state->pmu_glob && (!pmu_name || !strglobmatch(pmu_name, print_state->pmu_glob))) return; if (print_state->exclude_abi && pmu_type < PERF_TYPE_MAX && pmu_type != PERF_TYPE_RAW) @@ -612,8 +612,10 @@ int cmd_list(int argc, const char **argv) print_cb.print_start(ps); if (argc == 0) { - default_ps.metrics = true; - default_ps.metricgroups = true; + if (!unit_name) { + default_ps.metrics = true; + default_ps.metricgroups = true; + } print_events(&print_cb, ps); goto out; } From 58e0a81e76bf274afe7d24d80d7855a7642bb52a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Nov 2025 16:47:25 -0800 Subject: [PATCH 454/684] perf list: Share print state with JSON output The JSON print state has only one different field (need_sep). Let's add the default print state to the json state and use it. Then we can use the 'ps' variable to update the state properly. This is a preparation for the next commit. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-list.c | 127 +++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 28bf1fc7f5eeff..6c5913f129f39c 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -283,8 +283,8 @@ static void default_print_metric(void *ps, } struct json_print_state { - /** @fp: File to write output to. */ - FILE *fp; + /** The shared print_state */ + struct print_state common; /** Should a separator be printed prior to the next item? */ bool need_sep; }; @@ -292,7 +292,7 @@ struct json_print_state { static void json_print_start(void *ps) { struct json_print_state *print_state = ps; - FILE *fp = print_state->fp; + FILE *fp = print_state->common.fp; fprintf(fp, "[\n"); } @@ -300,7 +300,7 @@ static void json_print_start(void *ps) static void json_print_end(void *ps) { struct json_print_state *print_state = ps; - FILE *fp = print_state->fp; + FILE *fp = print_state->common.fp; fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : ""); } @@ -370,7 +370,7 @@ static void json_print_event(void *ps, const char *topic, { struct json_print_state *print_state = ps; bool need_sep = false; - FILE *fp = print_state->fp; + FILE *fp = print_state->common.fp; struct strbuf buf; strbuf_init(&buf, 0); @@ -446,7 +446,7 @@ static void json_print_metric(void *ps __maybe_unused, const char *group, { struct json_print_state *print_state = ps; bool need_sep = false; - FILE *fp = print_state->fp; + FILE *fp = print_state->common.fp; struct strbuf buf; strbuf_init(&buf, 0); @@ -521,10 +521,12 @@ int cmd_list(int argc, const char **argv) .fp = stdout, .desc = true, }; - struct print_state json_ps = { - .fp = stdout, + struct json_print_state json_ps = { + .common = { + .fp = stdout, + }, }; - void *ps = &default_ps; + struct print_state *ps = &default_ps; struct print_callbacks print_cb = { .print_start = default_print_start, .print_end = default_print_end, @@ -572,9 +574,11 @@ int cmd_list(int argc, const char **argv) argc = parse_options(argc, argv, list_options, list_usage, PARSE_OPT_STOP_AT_NON_OPTION); + if (json) + ps = &json_ps.common; + if (output_path) { - default_ps.fp = fopen(output_path, "w"); - json_ps.fp = default_ps.fp; + ps->fp = fopen(output_path, "w"); } setup_pager(); @@ -590,14 +594,13 @@ int cmd_list(int argc, const char **argv) .print_metric = json_print_metric, .skip_duplicate_pmus = json_skip_duplicate_pmus, }; - ps = &json_ps; } else { - default_ps.last_topic = strdup(""); - assert(default_ps.last_topic); - default_ps.visited_metrics = strlist__new(NULL, NULL); - assert(default_ps.visited_metrics); + ps->last_topic = strdup(""); + assert(ps->last_topic); + ps->visited_metrics = strlist__new(NULL, NULL); + assert(ps->visited_metrics); if (unit_name) - default_ps.pmu_glob = strdup(unit_name); + ps->pmu_glob = strdup(unit_name); else if (cputype) { const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype); @@ -606,15 +609,15 @@ int cmd_list(int argc, const char **argv) ret = -1; goto out; } - default_ps.pmu_glob = strdup(pmu->name); + ps->pmu_glob = strdup(pmu->name); } } print_cb.print_start(ps); if (argc == 0) { if (!unit_name) { - default_ps.metrics = true; - default_ps.metricgroups = true; + ps->metrics = true; + ps->metricgroups = true; } print_events(&print_cb, ps); goto out; @@ -636,57 +639,57 @@ int cmd_list(int argc, const char **argv) default_ps.pmu_glob = old_pmu_glob; } else if (strcmp(argv[i], "hw") == 0 || strcmp(argv[i], "hardware") == 0) { - char *old_event_glob = default_ps.event_glob; + char *old_event_glob = ps->event_glob; - default_ps.event_glob = strdup("legacy hardware"); - if (!default_ps.event_glob) { + ps->event_glob = strdup("legacy hardware"); + if (!ps->event_glob) { ret = -1; goto out; } perf_pmus__print_pmu_events(&print_cb, ps); - zfree(&default_ps.event_glob); - default_ps.event_glob = old_event_glob; + zfree(&ps->event_glob); + ps->event_glob = old_event_glob; } else if (strcmp(argv[i], "sw") == 0 || strcmp(argv[i], "software") == 0) { - char *old_pmu_glob = default_ps.pmu_glob; + char *old_pmu_glob = ps->pmu_glob; static const char * const sw_globs[] = { "software", "tool" }; for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) { - default_ps.pmu_glob = strdup(sw_globs[j]); - if (!default_ps.pmu_glob) { + ps->pmu_glob = strdup(sw_globs[j]); + if (!ps->pmu_glob) { ret = -1; goto out; } perf_pmus__print_pmu_events(&print_cb, ps); - zfree(&default_ps.pmu_glob); + zfree(&ps->pmu_glob); } - default_ps.pmu_glob = old_pmu_glob; + ps->pmu_glob = old_pmu_glob; } else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) { - char *old_event_glob = default_ps.event_glob; + char *old_event_glob = ps->event_glob; - default_ps.event_glob = strdup("legacy cache"); - if (!default_ps.event_glob) { + ps->event_glob = strdup("legacy cache"); + if (!ps->event_glob) { ret = -1; goto out; } perf_pmus__print_pmu_events(&print_cb, ps); - zfree(&default_ps.event_glob); - default_ps.event_glob = old_event_glob; + zfree(&ps->event_glob); + ps->event_glob = old_event_glob; } else if (strcmp(argv[i], "pmu") == 0) { - default_ps.exclude_abi = true; + ps->exclude_abi = true; perf_pmus__print_pmu_events(&print_cb, ps); - default_ps.exclude_abi = false; + ps->exclude_abi = false; } else if (strcmp(argv[i], "sdt") == 0) print_sdt_events(&print_cb, ps); else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { - default_ps.metricgroups = false; - default_ps.metrics = true; + ps->metricgroups = false; + ps->metrics = true; metricgroup__print(&print_cb, ps); } else if (strcmp(argv[i], "metricgroup") == 0 || strcmp(argv[i], "metricgroups") == 0) { - default_ps.metricgroups = true; - default_ps.metrics = false; + ps->metricgroups = true; + ps->metrics = false; metricgroup__print(&print_cb, ps); } #ifdef HAVE_LIBPFM @@ -694,40 +697,40 @@ int cmd_list(int argc, const char **argv) print_libpfm_events(&print_cb, ps); #endif else if ((sep = strchr(argv[i], ':')) != NULL) { - char *old_pmu_glob = default_ps.pmu_glob; - char *old_event_glob = default_ps.event_glob; + char *old_pmu_glob = ps->pmu_glob; + char *old_event_glob = ps->event_glob; - default_ps.event_glob = strdup(argv[i]); - if (!default_ps.event_glob) { + ps->event_glob = strdup(argv[i]); + if (!ps->event_glob) { ret = -1; goto out; } - default_ps.pmu_glob = strdup("tracepoint"); - if (!default_ps.pmu_glob) { - zfree(&default_ps.event_glob); + ps->pmu_glob = strdup("tracepoint"); + if (!ps->pmu_glob) { + zfree(&ps->event_glob); ret = -1; goto out; } perf_pmus__print_pmu_events(&print_cb, ps); - zfree(&default_ps.pmu_glob); - default_ps.pmu_glob = old_pmu_glob; + zfree(&ps->pmu_glob); + ps->pmu_glob = old_pmu_glob; print_sdt_events(&print_cb, ps); - default_ps.metrics = true; - default_ps.metricgroups = true; + ps->metrics = true; + ps->metricgroups = true; metricgroup__print(&print_cb, ps); - zfree(&default_ps.event_glob); - default_ps.event_glob = old_event_glob; + zfree(&ps->event_glob); + ps->event_glob = old_event_glob; } else { if (asprintf(&s, "*%s*", argv[i]) < 0) { printf("Critical: Not enough memory! Trying to continue...\n"); continue; } - default_ps.event_glob = s; + ps->event_glob = s; perf_pmus__print_pmu_events(&print_cb, ps); print_sdt_events(&print_cb, ps); - default_ps.metrics = true; - default_ps.metricgroups = true; + ps->metrics = true; + ps->metricgroups = true; metricgroup__print(&print_cb, ps); free(s); } @@ -735,12 +738,12 @@ int cmd_list(int argc, const char **argv) out: print_cb.print_end(ps); - free(default_ps.pmu_glob); - free(default_ps.last_topic); - free(default_ps.last_metricgroups); - strlist__delete(default_ps.visited_metrics); + free(ps->pmu_glob); + free(ps->last_topic); + free(ps->last_metricgroups); + strlist__delete(ps->visited_metrics); if (output_path) - fclose(default_ps.fp); + fclose(ps->fp); return ret; } From 3ce77655f026a316442f23d47da6c5cd89c1fdac Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Nov 2025 16:47:26 -0800 Subject: [PATCH 455/684] perf list: Support filtering in JSON output Like regular output mode, it should honor command line arguments to limit to a certain type of PMUs or events. $ perf list -j hw [ { "Unit": "cpu", "Topic": "legacy hardware", "EventName": "branch-instructions", "EventType": "Kernel PMU event", "BriefDescription": "Retired branch instructions [This event is an alias of branches]", "Encoding": "cpu/event=0xc4\n/" }, { "Unit": "cpu", "Topic": "legacy hardware", "EventName": "branch-misses", "EventType": "Kernel PMU event", "BriefDescription": "Mispredicted branch instructions", "Encoding": "cpu/event=0xc5\n/" }, ... Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 6c5913f129f39c..5cbca0bacd3523 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic, FILE *fp = print_state->common.fp; struct strbuf buf; + if (deprecated && !print_state->common.deprecated) + return; + + if (print_state->common.pmu_glob && + (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob))) + return; + + if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX && + pmu_type != PERF_TYPE_RAW) + return; + + if (print_state->common.event_glob && + (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) && + (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) && + (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob))) + return; + strbuf_init(&buf, 0); fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); print_state->need_sep = true; @@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group, FILE *fp = print_state->common.fp; struct strbuf buf; + if (print_state->common.event_glob && + (!print_state->common.metrics || !name || + !strglobmatch(name, print_state->common.event_glob)) && + (!print_state->common.metricgroups || !group || + !strglobmatch(group, print_state->common.event_glob))) + return; + strbuf_init(&buf, 0); fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); print_state->need_sep = true; From 9bef5cead63d5d8fad3ba7ebaf26f3f4ee172c82 Mon Sep 17 00:00:00 2001 From: Hrishikesh Suresh Date: Wed, 19 Nov 2025 23:16:10 -0500 Subject: [PATCH 456/684] perf: replace strcpy() with strncpy() in util/jitdump.c Usage of strcpy() can lead to buffer overflows. Therefore, it has been replaced with strncpy(). The output file path is provided as a parameter and might be restricted by command-line by default. But this defensive patch will prevent any potential overflow, making the code more robust against future changes in input handling. Testing: - ran perf test from tools/perf and did not observe any regression with the earlier code Signed-off-by: Hrishikesh Suresh Signed-off-by: Namhyung Kim --- tools/perf/util/jitdump.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index b062b1f234b62d..496ca2d2bfdb82 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -233,7 +233,8 @@ jit_open(struct jit_buf_desc *jd, const char *name) /* * keep dirname for generating files and mmap records */ - strcpy(jd->dir, name); + strncpy(jd->dir, name, PATH_MAX); + jd->dir[PATH_MAX - 1] = '\0'; dirname(jd->dir); free(buf); From 826eaa8f5bac6e919cf7c0b4161b2d783fdc45b3 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 11 Nov 2025 10:57:34 +0800 Subject: [PATCH 457/684] clk: rockchip: Implement rockchip_clk_register_armclk_multi_pll() The current path will have an independent PLL(LPLL\BPLL) exclusively for the CPU to use. As follows: |-\ --lpll--| \ |mux|--[gate]--[div]--clk_core-- --gpll--| / |-/ The new chip does not have a dedicated PLL for the cpu; it is distributed nearby from the common PLL. If there are special frequency requirements that require the use of pvtpll, explanations will be submitted later. The clock path of new soc CPU simplified as follows: --gpll--|--\ | \ | \ | \ --v0pll--| mux |--[gate]--[div]--clk_core-- | / | / --v1pll--| / |--/ Signed-off-by: Elaine Zhang Link: https://patch.msgid.link/20251111025738.869847-2-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 165 +++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.c | 24 +++++ drivers/clk/rockchip/clk.h | 15 +++ 3 files changed, 204 insertions(+) diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index dcc9dcb597ae11..6e91a3041a03c5 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -396,3 +396,168 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, kfree(cpuclk); return ERR_PTR(ret); } + +static int rockchip_cpuclk_multi_pll_pre_rate_change(struct rockchip_cpuclk *cpuclk, + struct clk_notifier_data *ndata) +{ + unsigned long new_rate = roundup(ndata->new_rate, 1000); + const struct rockchip_cpuclk_rate_table *rate; + unsigned long flags; + + rate = rockchip_get_cpuclk_settings(cpuclk, new_rate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for cpuclk\n", + __func__, new_rate); + return -EINVAL; + } + + if (new_rate > ndata->old_rate) { + spin_lock_irqsave(cpuclk->lock, flags); + rockchip_cpuclk_set_dividers(cpuclk, rate); + spin_unlock_irqrestore(cpuclk->lock, flags); + } + + return 0; +} + +static int rockchip_cpuclk_multi_pll_post_rate_change(struct rockchip_cpuclk *cpuclk, + struct clk_notifier_data *ndata) +{ + unsigned long new_rate = roundup(ndata->new_rate, 1000); + const struct rockchip_cpuclk_rate_table *rate; + unsigned long flags; + + rate = rockchip_get_cpuclk_settings(cpuclk, new_rate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for cpuclk\n", + __func__, new_rate); + return -EINVAL; + } + + if (new_rate < ndata->old_rate) { + spin_lock_irqsave(cpuclk->lock, flags); + rockchip_cpuclk_set_dividers(cpuclk, rate); + spin_unlock_irqrestore(cpuclk->lock, flags); + } + + return 0; +} + +static int rockchip_cpuclk_multi_pll_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_nb(nb); + int ret = 0; + + pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", + __func__, event, ndata->old_rate, ndata->new_rate); + if (event == PRE_RATE_CHANGE) + ret = rockchip_cpuclk_multi_pll_pre_rate_change(cpuclk, ndata); + else if (event == POST_RATE_CHANGE) + ret = rockchip_cpuclk_multi_pll_post_rate_change(cpuclk, ndata); + + return notifier_from_errno(ret); +} + +struct clk *rockchip_clk_register_cpuclk_multi_pll(const char *name, + const char *const *parent_names, + u8 num_parents, void __iomem *base, + int muxdiv_offset, u8 mux_shift, + u8 mux_width, u8 mux_flags, + int div_offset, u8 div_shift, + u8 div_width, u8 div_flags, + unsigned long flags, spinlock_t *lock, + const struct rockchip_cpuclk_rate_table *rates, + int nrates) +{ + struct rockchip_cpuclk *cpuclk; + struct clk_hw *hw; + struct clk_mux *mux = NULL; + struct clk_divider *div = NULL; + const struct clk_ops *mux_ops = NULL, *div_ops = NULL; + int ret; + + if (num_parents > 1) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = base + muxdiv_offset; + mux->shift = mux_shift; + mux->mask = BIT(mux_width) - 1; + mux->flags = mux_flags; + mux->lock = lock; + mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops + : &clk_mux_ops; + } + + if (div_width > 0) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) { + ret = -ENOMEM; + goto free_mux; + } + + div->flags = div_flags; + if (div_offset) + div->reg = base + div_offset; + else + div->reg = base + muxdiv_offset; + div->shift = div_shift; + div->width = div_width; + div->lock = lock; + div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) + ? &clk_divider_ro_ops + : &clk_divider_ops; + } + + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux ? &mux->hw : NULL, mux_ops, + div ? &div->hw : NULL, div_ops, + NULL, NULL, flags); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto free_div; + } + + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL); + if (!cpuclk) { + ret = -ENOMEM; + goto unregister_clk; + } + + cpuclk->reg_base = base; + cpuclk->lock = lock; + cpuclk->clk_nb.notifier_call = rockchip_cpuclk_multi_pll_notifier_cb; + ret = clk_notifier_register(hw->clk, &cpuclk->clk_nb); + if (ret) { + pr_err("%s: failed to register clock notifier for %s\n", + __func__, name); + goto free_cpuclk; + } + + if (nrates > 0) { + cpuclk->rate_count = nrates; + cpuclk->rate_table = kmemdup(rates, + sizeof(*rates) * nrates, + GFP_KERNEL); + if (!cpuclk->rate_table) { + ret = -ENOMEM; + goto free_cpuclk; + } + } + + return hw->clk; + +free_cpuclk: + kfree(cpuclk); +unregister_clk: + clk_hw_unregister_composite(hw); +free_div: + kfree(div); +free_mux: + kfree(mux); + + return ERR_PTR(ret); +} diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 19caf26c991bd5..2601df3b1066b1 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -722,6 +722,30 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, } EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk); +void rockchip_clk_register_armclk_multi_pll(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, + const struct rockchip_cpuclk_rate_table *rates, + int nrates) +{ + struct clk *clk; + + clk = rockchip_clk_register_cpuclk_multi_pll(list->name, list->parent_names, + list->num_parents, ctx->reg_base, + list->muxdiv_offset, list->mux_shift, + list->mux_width, list->mux_flags, + list->div_offset, list->div_shift, + list->div_width, list->div_flags, + list->flags, &ctx->lock, rates, nrates); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s: %ld\n", + __func__, list->name, PTR_ERR(clk)); + return; + } + + rockchip_clk_set_lookup(ctx, clk, list->id); +} +EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk_multi_pll); + void rockchip_clk_protect_critical(const char *const clocks[], int nclocks) { diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 7c5e74c7a2e210..23653a942403af 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -622,6 +622,17 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, const struct rockchip_cpuclk_rate_table *rates, int nrates, void __iomem *reg_base, spinlock_t *lock); +struct clk *rockchip_clk_register_cpuclk_multi_pll(const char *name, + const char *const *parent_names, + u8 num_parents, void __iomem *base, + int muxdiv_offset, u8 mux_shift, + u8 mux_width, u8 mux_flags, + int div_offset, u8 div_shift, + u8 div_width, u8 div_flags, + unsigned long flags, spinlock_t *lock, + const struct rockchip_cpuclk_rate_table *rates, + int nrates); + struct clk *rockchip_clk_register_mmc(const char *name, const char *const *parent_names, u8 num_parents, void __iomem *reg, @@ -1208,6 +1219,10 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, int nrates); +void rockchip_clk_register_armclk_multi_pll(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, + const struct rockchip_cpuclk_rate_table *rates, + int nrates); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, unsigned int reg, void (*cb)(void)); From d0d9a9629f505ac70e1ffd172e092ff71f5d989a Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 11 Nov 2025 10:57:35 +0800 Subject: [PATCH 458/684] dt-bindings: clock, reset: Add support for rv1126b Add clock and reset ID defines for rv1126b. Also add documentation for the rv1126b CRU core. Signed-off-by: Elaine Zhang Acked-by: Conor Dooley Link: https://patch.msgid.link/20251111025738.869847-3-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- .../bindings/clock/rockchip,rv1126b-cru.yaml | 52 +++ .../dt-bindings/clock/rockchip,rv1126b-cru.h | 392 +++++++++++++++++ .../dt-bindings/reset/rockchip,rv1126b-cru.h | 405 ++++++++++++++++++ 3 files changed, 849 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rv1126b-cru.yaml create mode 100644 include/dt-bindings/clock/rockchip,rv1126b-cru.h create mode 100644 include/dt-bindings/reset/rockchip,rv1126b-cru.h diff --git a/Documentation/devicetree/bindings/clock/rockchip,rv1126b-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rv1126b-cru.yaml new file mode 100644 index 00000000000000..04b0a5c51e4e0f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rv1126b-cru.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rv1126b-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RV1126B Clock and Reset Unit + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: + The rv1126b clock controller generates the clock and also implements a + reset controller for SoC peripherals. + +properties: + compatible: + enum: + - rockchip,rv1126b-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + clock-controller@20000000 { + compatible = "rockchip,rv1126b-cru"; + reg = <0x20000000 0xc0000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/clock/rockchip,rv1126b-cru.h b/include/dt-bindings/clock/rockchip,rv1126b-cru.h new file mode 100644 index 00000000000000..721d50a1419fb1 --- /dev/null +++ b/include/dt-bindings/clock/rockchip,rv1126b-cru.h @@ -0,0 +1,392 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * Author: Elaine Zhang + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1126B_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RV1126B_H + +/* pll clocks */ +#define PLL_GPLL 0 +#define PLL_CPLL 1 +#define PLL_AUPLL 2 +#define ARMCLK 3 +#define SCLK_DDR 4 + +/* clk (clocks) */ +#define CLK_CPLL_DIV20 5 +#define CLK_CPLL_DIV10 6 +#define CLK_CPLL_DIV8 7 +#define CLK_GPLL_DIV8 8 +#define CLK_GPLL_DIV6 9 +#define CLK_GPLL_DIV4 10 +#define CLK_CPLL_DIV3 11 +#define CLK_GPLL_DIV3 12 +#define CLK_CPLL_DIV2 13 +#define CLK_GPLL_DIV2 14 +#define CLK_CM_FRAC0 15 +#define CLK_CM_FRAC1 16 +#define CLK_CM_FRAC2 17 +#define CLK_UART_FRAC0 18 +#define CLK_UART_FRAC1 19 +#define CLK_AUDIO_FRAC0 20 +#define CLK_AUDIO_FRAC1 21 +#define CLK_AUDIO_INT0 22 +#define CLK_AUDIO_INT1 23 +#define SCLK_UART0_SRC 24 +#define SCLK_UART1 25 +#define SCLK_UART2 26 +#define SCLK_UART3 27 +#define SCLK_UART4 28 +#define SCLK_UART5 29 +#define SCLK_UART6 30 +#define SCLK_UART7 31 +#define MCLK_SAI0 32 +#define MCLK_SAI1 33 +#define MCLK_SAI2 34 +#define MCLK_PDM 35 +#define CLKOUT_PDM 36 +#define MCLK_ASRC0 37 +#define MCLK_ASRC1 38 +#define MCLK_ASRC2 39 +#define MCLK_ASRC3 40 +#define CLK_ASRC0 41 +#define CLK_ASRC1 42 +#define CLK_CORE_PLL 43 +#define CLK_NPU_PLL 44 +#define CLK_VEPU_PLL 45 +#define CLK_ISP_PLL 46 +#define CLK_AISP_PLL 47 +#define CLK_SARADC0_SRC 48 +#define CLK_SARADC1_SRC 49 +#define CLK_SARADC2_SRC 50 +#define HCLK_NPU_ROOT 51 +#define PCLK_NPU_ROOT 52 +#define ACLK_VEPU_ROOT 53 +#define HCLK_VEPU_ROOT 54 +#define PCLK_VEPU_ROOT 55 +#define CLK_CORE_RGA_SRC 56 +#define ACLK_GMAC_ROOT 57 +#define ACLK_VI_ROOT 58 +#define HCLK_VI_ROOT 59 +#define PCLK_VI_ROOT 60 +#define DCLK_VICAP_ROOT 61 +#define CLK_SYS_DSMC_ROOT 62 +#define ACLK_VDO_ROOT 63 +#define ACLK_RKVDEC_ROOT 64 +#define HCLK_VDO_ROOT 65 +#define PCLK_VDO_ROOT 66 +#define DCLK_OOC_SRC 67 +#define DCLK_VOP 68 +#define DCLK_DECOM_SRC 69 +#define PCLK_DDR_ROOT 70 +#define ACLK_SYSMEM_SRC 71 +#define ACLK_TOP_ROOT 72 +#define ACLK_BUS_ROOT 73 +#define HCLK_BUS_ROOT 74 +#define PCLK_BUS_ROOT 75 +#define CCLK_SDMMC0 76 +#define CCLK_SDMMC1 77 +#define CCLK_EMMC 78 +#define SCLK_2X_FSPI0 79 +#define CLK_GMAC_PTP_REF_SRC 80 +#define CLK_GMAC_125M 81 +#define CLK_TIMER_ROOT 82 +#define TCLK_WDT_NS_SRC 83 +#define TCLK_WDT_S_SRC 84 +#define TCLK_WDT_HPMCU 85 +#define CLK_CAN0 86 +#define CLK_CAN1 87 +#define PCLK_PERI_ROOT 88 +#define ACLK_PERI_ROOT 89 +#define CLK_I2C_BUS_SRC 90 +#define CLK_SPI0 91 +#define CLK_SPI1 92 +#define BUSCLK_PMU_SRC 93 +#define CLK_PWM0 94 +#define CLK_PWM2 95 +#define CLK_PWM3 96 +#define CLK_PKA_RKCE_SRC 97 +#define ACLK_RKCE_SRC 98 +#define ACLK_VCP_ROOT 99 +#define HCLK_VCP_ROOT 100 +#define PCLK_VCP_ROOT 101 +#define CLK_CORE_FEC_SRC 102 +#define CLK_CORE_AVSP_SRC 103 +#define CLK_50M_GMAC_IOBUF_VI 104 +#define PCLK_TOP_ROOT 105 +#define CLK_MIPI0_OUT2IO 106 +#define CLK_MIPI1_OUT2IO 107 +#define CLK_MIPI2_OUT2IO 108 +#define CLK_MIPI3_OUT2IO 109 +#define CLK_CIF_OUT2IO 110 +#define CLK_MAC_OUT2IO 111 +#define MCLK_SAI0_OUT2IO 112 +#define MCLK_SAI1_OUT2IO 113 +#define MCLK_SAI2_OUT2IO 114 +#define CLK_CM_FRAC0_SRC 115 +#define CLK_CM_FRAC1_SRC 116 +#define CLK_CM_FRAC2_SRC 117 +#define CLK_UART_FRAC0_SRC 118 +#define CLK_UART_FRAC1_SRC 119 +#define CLK_AUDIO_FRAC0_SRC 120 +#define CLK_AUDIO_FRAC1_SRC 121 +#define ACLK_NPU_ROOT 122 +#define HCLK_RKNN 123 +#define ACLK_RKNN 124 +#define PCLK_GPIO3 125 +#define DBCLK_GPIO3 126 +#define PCLK_IOC_VCCIO3 127 +#define PCLK_SARADC0 128 +#define CLK_SARADC0 129 +#define HCLK_SDMMC1 130 +#define HCLK_VEPU 131 +#define ACLK_VEPU 132 +#define CLK_CORE_VEPU 133 +#define HCLK_FEC 134 +#define ACLK_FEC 135 +#define CLK_CORE_FEC 136 +#define HCLK_AVSP 137 +#define ACLK_AVSP 138 +#define BUSCLK_PMU1_ROOT 139 +#define HCLK_AISP 140 +#define ACLK_AISP 141 +#define CLK_CORE_AISP 142 +#define CLK_CORE_ISP_ROOT 143 +#define PCLK_DSMC 144 +#define ACLK_DSMC 145 +#define HCLK_CAN0 146 +#define HCLK_CAN1 147 +#define PCLK_GPIO2 148 +#define DBCLK_GPIO2 149 +#define PCLK_GPIO4 150 +#define DBCLK_GPIO4 151 +#define PCLK_GPIO5 152 +#define DBCLK_GPIO5 153 +#define PCLK_GPIO6 154 +#define DBCLK_GPIO6 155 +#define PCLK_GPIO7 156 +#define DBCLK_GPIO7 157 +#define PCLK_IOC_VCCIO2 158 +#define PCLK_IOC_VCCIO4 159 +#define PCLK_IOC_VCCIO5 160 +#define PCLK_IOC_VCCIO6 161 +#define PCLK_IOC_VCCIO7 162 +#define HCLK_ISP 163 +#define ACLK_ISP 164 +#define CLK_CORE_ISP 165 +#define HCLK_VICAP 166 +#define ACLK_VICAP 167 +#define DCLK_VICAP 168 +#define ISP0CLK_VICAP 169 +#define HCLK_VPSS 170 +#define ACLK_VPSS 171 +#define CLK_CORE_VPSS 172 +#define PCLK_CSI2HOST0 173 +#define DCLK_CSI2HOST0 174 +#define PCLK_CSI2HOST1 175 +#define DCLK_CSI2HOST1 176 +#define PCLK_CSI2HOST2 177 +#define DCLK_CSI2HOST2 178 +#define PCLK_CSI2HOST3 179 +#define DCLK_CSI2HOST3 180 +#define HCLK_SDMMC0 181 +#define ACLK_GMAC 182 +#define PCLK_GMAC 183 +#define CLK_GMAC_PTP_REF 184 +#define PCLK_CSIPHY0 185 +#define PCLK_CSIPHY1 186 +#define PCLK_MACPHY 187 +#define PCLK_SARADC1 188 +#define CLK_SARADC1 189 +#define PCLK_SARADC2 190 +#define CLK_SARADC2 191 +#define ACLK_RKVDEC 192 +#define HCLK_RKVDEC 193 +#define CLK_HEVC_CA_RKVDEC 194 +#define ACLK_VOP 195 +#define HCLK_VOP 196 +#define HCLK_RKJPEG 197 +#define ACLK_RKJPEG 198 +#define ACLK_RKMMU_DECOM 199 +#define HCLK_RKMMU_DECOM 200 +#define DCLK_DECOM 201 +#define ACLK_DECOM 202 +#define PCLK_DECOM 203 +#define PCLK_MIPI_DSI 204 +#define PCLK_DSIPHY 205 +#define ACLK_OOC 206 +#define ACLK_SYSMEM 207 +#define PCLK_DDRC 208 +#define PCLK_DDRMON 209 +#define CLK_TIMER_DDRMON 210 +#define PCLK_DFICTRL 211 +#define PCLK_DDRPHY 212 +#define PCLK_DMA2DDR 213 +#define CLK_RCOSC_SRC 214 +#define BUSCLK_PMU_MUX 215 +#define BUSCLK_PMU_ROOT 216 +#define PCLK_PMU 217 +#define CLK_XIN_RC_DIV 218 +#define CLK_32K 219 +#define PCLK_PMU_GPIO0 220 +#define DBCLK_PMU_GPIO0 221 +#define PCLK_PMU_HP_TIMER 222 +#define CLK_PMU_HP_TIMER 223 +#define CLK_PMU_32K_HP_TIMER 224 +#define PCLK_PWM1 225 +#define CLK_PWM1 226 +#define CLK_OSC_PWM1 227 +#define CLK_RC_PWM1 228 +#define CLK_FREQ_PWM1 229 +#define CLK_COUNTER_PWM1 230 +#define PCLK_I2C2 231 +#define CLK_I2C2 232 +#define PCLK_UART0 233 +#define SCLK_UART0 234 +#define PCLK_RCOSC_CTRL 235 +#define CLK_OSC_RCOSC_CTRL 236 +#define CLK_REF_RCOSC_CTRL 237 +#define PCLK_IOC_PMUIO0 238 +#define CLK_REFOUT 239 +#define CLK_PREROLL 240 +#define CLK_PREROLL_32K 241 +#define HCLK_PMU_SRAM 242 +#define PCLK_WDT_LPMCU 243 +#define TCLK_WDT_LPMCU 244 +#define CLK_LPMCU 245 +#define CLK_LPMCU_RTC 246 +#define PCLK_LPMCU_MAILBOX 247 +#define HCLK_OOC 248 +#define PCLK_SPI2AHB 249 +#define HCLK_SPI2AHB 250 +#define HCLK_FSPI1 251 +#define HCLK_XIP_FSPI1 252 +#define SCLK_1X_FSPI1 253 +#define PCLK_IOC_PMUIO1 254 +#define PCLK_AUDIO_ADC_PMU 255 +#define MCLK_AUDIO_ADC_PMU 256 +#define MCLK_AUDIO_ADC_DIV4_PMU 257 +#define MCLK_LPSAI 258 +#define ACLK_GIC400 259 +#define PCLK_WDT_NS 260 +#define TCLK_WDT_NS 261 +#define PCLK_WDT_HPMCU 262 +#define HCLK_CACHE 263 +#define PCLK_HPMCU_MAILBOX 264 +#define PCLK_HPMCU_INTMUX 265 +#define CLK_HPMCU 266 +#define CLK_HPMCU_RTC 267 +#define PCLK_RKDMA 268 +#define ACLK_RKDMA 269 +#define PCLK_DCF 270 +#define ACLK_DCF 271 +#define HCLK_RGA 272 +#define ACLK_RGA 273 +#define CLK_CORE_RGA 274 +#define PCLK_TIMER 275 +#define CLK_TIMER0 276 +#define CLK_TIMER1 277 +#define CLK_TIMER2 278 +#define CLK_TIMER3 279 +#define CLK_TIMER4 280 +#define CLK_TIMER5 281 +#define PCLK_I2C0 282 +#define CLK_I2C0 283 +#define PCLK_I2C1 284 +#define CLK_I2C1 285 +#define PCLK_I2C3 286 +#define CLK_I2C3 287 +#define PCLK_I2C4 288 +#define CLK_I2C4 289 +#define PCLK_I2C5 290 +#define CLK_I2C5 291 +#define PCLK_SPI0 292 +#define PCLK_SPI1 293 +#define PCLK_PWM0 294 +#define CLK_OSC_PWM0 295 +#define CLK_RC_PWM0 296 +#define PCLK_PWM2 297 +#define CLK_OSC_PWM2 298 +#define CLK_RC_PWM2 299 +#define PCLK_PWM3 300 +#define CLK_OSC_PWM3 301 +#define CLK_RC_PWM3 302 +#define PCLK_UART1 303 +#define PCLK_UART2 304 +#define PCLK_UART3 305 +#define PCLK_UART4 306 +#define PCLK_UART5 307 +#define PCLK_UART6 308 +#define PCLK_UART7 309 +#define PCLK_TSADC 310 +#define CLK_TSADC 311 +#define HCLK_SAI0 312 +#define HCLK_SAI1 313 +#define HCLK_SAI2 314 +#define HCLK_RKDSM 315 +#define MCLK_RKDSM 316 +#define HCLK_PDM 317 +#define HCLK_ASRC0 318 +#define HCLK_ASRC1 319 +#define PCLK_AUDIO_ADC_BUS 320 +#define MCLK_AUDIO_ADC_BUS 321 +#define MCLK_AUDIO_ADC_DIV4_BUS 322 +#define PCLK_RKCE 323 +#define HCLK_NS_RKCE 324 +#define PCLK_OTPC_NS 325 +#define CLK_SBPI_OTPC_NS 326 +#define CLK_USER_OTPC_NS 327 +#define CLK_OTPC_ARB 328 +#define PCLK_OTP_MASK 329 +#define CLK_TSADC_PHYCTRL 330 +#define LRCK_SRC_ASRC0 331 +#define LRCK_DST_ASRC0 332 +#define LRCK_SRC_ASRC1 333 +#define LRCK_DST_ASRC1 334 +#define PCLK_KEY_READER 335 +#define ACLK_NSRKCE 336 +#define CLK_PKA_NSRKCE 337 +#define PCLK_RTC_ROOT 338 +#define PCLK_GPIO1 339 +#define DBCLK_GPIO1 340 +#define PCLK_IOC_VCCIO1 341 +#define ACLK_USB3OTG 342 +#define CLK_REF_USB3OTG 343 +#define CLK_SUSPEND_USB3OTG 344 +#define HCLK_USB2HOST 345 +#define HCLK_ARB_USB2HOST 346 +#define PCLK_RTC_TEST 347 +#define HCLK_EMMC 348 +#define HCLK_FSPI0 349 +#define HCLK_XIP_FSPI0 350 +#define PCLK_PIPEPHY 351 +#define PCLK_USB2PHY 352 +#define CLK_REF_PIPEPHY_CPLL_SRC 353 +#define CLK_REF_PIPEPHY 354 +#define HCLK_VPSL 355 +#define ACLK_VPSL 356 +#define CLK_CORE_VPSL 357 +#define CLK_MACPHY 358 +#define HCLK_RKRNG_NS 359 +#define HCLK_RKRNG_S_NS 360 +#define CLK_AISP_PLL_SRC 361 + +/* secure clks */ +#define CLK_USER_OTPC_S 362 +#define CLK_SBPI_OTPC_S 363 +#define PCLK_OTPC_S 364 +#define PCLK_KEY_READER_S 365 +#define HCLK_KL_RKCE_S 366 +#define HCLK_RKCE_S 367 +#define PCLK_WDT_S 368 +#define TCLK_WDT_S 369 +#define CLK_STIMER0 370 +#define CLK_STIMER1 371 +#define PLK_STIMER 372 +#define HCLK_RKRNG_S 373 +#define CLK_PKA_RKCE_S 374 +#define ACLK_RKCE_S 375 + +#endif diff --git a/include/dt-bindings/reset/rockchip,rv1126b-cru.h b/include/dt-bindings/reset/rockchip,rv1126b-cru.h new file mode 100644 index 00000000000000..a7712db319d03c --- /dev/null +++ b/include/dt-bindings/reset/rockchip,rv1126b-cru.h @@ -0,0 +1,405 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * Author: Elaine Zhang + */ + +#ifndef _DT_BINDINGS_RESET_ROCKCHIP_RV1126B_H +#define _DT_BINDINGS_RESET_ROCKCHIP_RV1126B_H + +/* ==========================list all of reset fields id=========================== */ +/* TOPCRU-->SOFTRST_CON00 */ + +/* TOPCRU-->SOFTRST_CON15 */ +#define SRST_P_CRU 0 +#define SRST_P_CRU_BIU 1 + +/* BUSCRU-->SOFTRST_CON00 */ +#define SRST_A_TOP_BIU 2 +#define SRST_A_RKCE_BIU 3 +#define SRST_A_BUS_BIU 4 +#define SRST_H_BUS_BIU 5 +#define SRST_P_BUS_BIU 6 +#define SRST_P_CRU_BUS 7 +#define SRST_P_SYS_GRF 8 +#define SRST_H_BOOTROM 9 +#define SRST_A_GIC400 10 +#define SRST_A_SPINLOCK 11 +#define SRST_P_WDT_NS 12 +#define SRST_T_WDT_NS 13 + +/* BUSCRU-->SOFTRST_CON01 */ +#define SRST_P_WDT_HPMCU 14 +#define SRST_T_WDT_HPMCU 15 +#define SRST_H_CACHE 16 +#define SRST_P_HPMCU_MAILBOX 17 +#define SRST_P_HPMCU_INTMUX 18 +#define SRST_HPMCU_FULL_CLUSTER 19 +#define SRST_HPMCU_PWUP 20 +#define SRST_HPMCU_ONLY_CORE 21 +#define SRST_T_HPMCU_JTAG 22 +#define SRST_P_RKDMA 23 +#define SRST_A_RKDMA 24 + +/* BUSCRU-->SOFTRST_CON02 */ +#define SRST_P_DCF 25 +#define SRST_A_DCF 26 +#define SRST_H_RGA 27 +#define SRST_A_RGA 28 +#define SRST_CORE_RGA 29 +#define SRST_P_TIMER 30 +#define SRST_TIMER0 31 +#define SRST_TIMER1 32 +#define SRST_TIMER2 33 +#define SRST_TIMER3 34 +#define SRST_TIMER4 35 +#define SRST_TIMER5 36 +#define SRST_A_RKCE 37 +#define SRST_PKA_RKCE 38 +#define SRST_H_RKRNG_S 39 +#define SRST_H_RKRNG_NS 40 + +/* BUSCRU-->SOFTRST_CON03 */ +#define SRST_P_I2C0 41 +#define SRST_I2C0 42 +#define SRST_P_I2C1 43 +#define SRST_I2C1 44 +#define SRST_P_I2C3 45 +#define SRST_I2C3 46 +#define SRST_P_I2C4 47 +#define SRST_I2C4 48 +#define SRST_P_I2C5 49 +#define SRST_I2C5 50 +#define SRST_P_SPI0 51 +#define SRST_SPI0 52 +#define SRST_P_SPI1 53 +#define SRST_SPI1 54 + +/* BUSCRU-->SOFTRST_CON04 */ +#define SRST_P_PWM0 55 +#define SRST_PWM0 56 +#define SRST_P_PWM2 57 +#define SRST_PWM2 58 +#define SRST_P_PWM3 59 +#define SRST_PWM3 60 + +/* BUSCRU-->SOFTRST_CON05 */ +#define SRST_P_UART1 61 +#define SRST_S_UART1 62 +#define SRST_P_UART2 63 +#define SRST_S_UART2 64 +#define SRST_P_UART3 65 +#define SRST_S_UART3 66 +#define SRST_P_UART4 67 +#define SRST_S_UART4 68 +#define SRST_P_UART5 69 +#define SRST_S_UART5 70 +#define SRST_P_UART6 71 +#define SRST_S_UART6 72 +#define SRST_P_UART7 73 +#define SRST_S_UART7 74 + +/* BUSCRU-->SOFTRST_CON06 */ +#define SRST_P_TSADC 75 +#define SRST_TSADC 76 +#define SRST_H_SAI0 77 +#define SRST_M_SAI0 78 +#define SRST_H_SAI1 79 +#define SRST_M_SAI1 80 +#define SRST_H_SAI2 81 +#define SRST_M_SAI2 82 +#define SRST_H_RKDSM 83 +#define SRST_M_RKDSM 84 +#define SRST_H_PDM 85 +#define SRST_M_PDM 86 +#define SRST_PDM 87 + +/* BUSCRU-->SOFTRST_CON07 */ +#define SRST_H_ASRC0 88 +#define SRST_ASRC0 89 +#define SRST_H_ASRC1 90 +#define SRST_ASRC1 91 +#define SRST_P_AUDIO_ADC_BUS 92 +#define SRST_M_AUDIO_ADC_BUS 93 +#define SRST_P_RKCE 94 +#define SRST_H_NS_RKCE 95 +#define SRST_P_OTPC_NS 96 +#define SRST_SBPI_OTPC_NS 97 +#define SRST_USER_OTPC_NS 98 +#define SRST_OTPC_ARB 99 +#define SRST_P_OTP_MASK 100 + +/* PERICRU-->SOFTRST_CON00 */ +#define SRST_A_PERI_BIU 101 +#define SRST_P_PERI_BIU 102 +#define SRST_P_RTC_BIU 103 +#define SRST_P_CRU_PERI 104 +#define SRST_P_PERI_GRF 105 +#define SRST_P_GPIO1 106 +#define SRST_DB_GPIO1 107 +#define SRST_P_IOC_VCCIO1 108 +#define SRST_A_USB3OTG 109 +#define SRST_H_USB2HOST 110 +#define SRST_H_ARB_USB2HOST 111 +#define SRST_P_RTC_TEST 112 + +/* PERICRU-->SOFTRST_CON01 */ +#define SRST_H_EMMC 113 +#define SRST_H_FSPI0 114 +#define SRST_H_XIP_FSPI0 115 +#define SRST_S_2X_FSPI0 116 +#define SRST_UTMI_USB2HOST 117 +#define SRST_REF_PIPEPHY 118 +#define SRST_P_PIPEPHY 119 +#define SRST_P_PIPEPHY_GRF 120 +#define SRST_P_USB2PHY 121 +#define SRST_POR_USB2PHY 122 +#define SRST_OTG_USB2PHY 123 +#define SRST_HOST_USB2PHY 124 + +/* CORECRU-->SOFTRST_CON00 */ +#define SRST_REF_PVTPLL_CORE 125 +#define SRST_NCOREPORESET0 126 +#define SRST_NCORESET0 127 +#define SRST_NCOREPORESET1 128 +#define SRST_NCORESET1 129 +#define SRST_NCOREPORESET2 130 +#define SRST_NCORESET2 131 +#define SRST_NCOREPORESET3 132 +#define SRST_NCORESET3 133 +#define SRST_NDBGRESET 134 +#define SRST_NL2RESET 135 + +/* CORECRU-->SOFTRST_CON01 */ +#define SRST_A_CORE_BIU 136 +#define SRST_P_CORE_BIU 137 +#define SRST_H_CORE_BIU 138 +#define SRST_P_DBG 139 +#define SRST_POT_DBG 140 +#define SRST_NT_DBG 141 +#define SRST_P_CORE_PVTPLL 142 +#define SRST_P_CRU_CORE 143 +#define SRST_P_CORE_GRF 144 +#define SRST_P_DFT2APB 145 + +/* PMUCRU-->SOFTRST_CON00 */ +#define SRST_H_PMU_BIU 146 +#define SRST_P_PMU_GPIO0 147 +#define SRST_DB_PMU_GPIO0 148 +#define SRST_P_PMU_HP_TIMER 149 +#define SRST_PMU_HP_TIMER 150 +#define SRST_PMU_32K_HP_TIMER 151 + +/* PMUCRU-->SOFTRST_CON01 */ +#define SRST_P_PWM1 152 +#define SRST_PWM1 153 +#define SRST_P_I2C2 154 +#define SRST_I2C2 155 +#define SRST_P_UART0 156 +#define SRST_S_UART0 157 + +/* PMUCRU-->SOFTRST_CON02 */ +#define SRST_P_RCOSC_CTRL 158 +#define SRST_REF_RCOSC_CTRL 159 +#define SRST_P_IOC_PMUIO0 160 +#define SRST_P_CRU_PMU 161 +#define SRST_P_PMU_GRF 162 +#define SRST_PREROLL 163 +#define SRST_PREROLL_32K 164 +#define SRST_H_PMU_SRAM 165 + +/* PMUCRU-->SOFTRST_CON03 */ +#define SRST_P_WDT_LPMCU 166 +#define SRST_T_WDT_LPMCU 167 +#define SRST_LPMCU_FULL_CLUSTER 168 +#define SRST_LPMCU_PWUP 169 +#define SRST_LPMCU_ONLY_CORE 170 +#define SRST_T_LPMCU_JTAG 171 +#define SRST_P_LPMCU_MAILBOX 172 + +/* PMU1CRU-->SOFTRST_CON00 */ +#define SRST_P_SPI2AHB 173 +#define SRST_H_SPI2AHB 174 +#define SRST_H_FSPI1 175 +#define SRST_H_XIP_FSPI1 176 +#define SRST_S_1X_FSPI1 177 +#define SRST_P_IOC_PMUIO1 178 +#define SRST_P_CRU_PMU1 179 +#define SRST_P_AUDIO_ADC_PMU 180 +#define SRST_M_AUDIO_ADC_PMU 181 +#define SRST_H_PMU1_BIU 182 + +/* PMU1CRU-->SOFTRST_CON01 */ +#define SRST_P_LPDMA 183 +#define SRST_A_LPDMA 184 +#define SRST_H_LPSAI 185 +#define SRST_M_LPSAI 186 +#define SRST_P_AOA_TDD 187 +#define SRST_P_AOA_FE 188 +#define SRST_P_AOA_AAD 189 +#define SRST_P_AOA_APB 190 +#define SRST_P_AOA_SRAM 191 + +/* DDRCRU-->SOFTRST_CON00 */ +#define SRST_P_DDR_BIU 192 +#define SRST_P_DDRC 193 +#define SRST_P_DDRMON 194 +#define SRST_TIMER_DDRMON 195 +#define SRST_P_DFICTRL 196 +#define SRST_P_DDR_GRF 197 +#define SRST_P_CRU_DDR 198 +#define SRST_P_DDRPHY 199 +#define SRST_P_DMA2DDR 200 + +/* SUBDDRCRU-->SOFTRST_CON00 */ +#define SRST_A_SYSMEM_BIU 201 +#define SRST_A_SYSMEM 202 +#define SRST_A_DDR_BIU 203 +#define SRST_A_DDRSCH0_CPU 204 +#define SRST_A_DDRSCH1_NPU 205 +#define SRST_A_DDRSCH2_POE 206 +#define SRST_A_DDRSCH3_VI 207 +#define SRST_CORE_DDRC 208 +#define SRST_DDRMON 209 +#define SRST_DFICTRL 210 +#define SRST_RS 211 +#define SRST_A_DMA2DDR 212 +#define SRST_DDRPHY 213 + +/* VICRU-->SOFTRST_CON00 */ +#define SRST_REF_PVTPLL_ISP 214 +#define SRST_A_GMAC_BIU 215 +#define SRST_A_VI_BIU 216 +#define SRST_H_VI_BIU 217 +#define SRST_P_VI_BIU 218 +#define SRST_P_CRU_VI 219 +#define SRST_P_VI_GRF 220 +#define SRST_P_VI_PVTPLL 221 +#define SRST_P_DSMC 222 +#define SRST_A_DSMC 223 +#define SRST_H_CAN0 224 +#define SRST_CAN0 225 +#define SRST_H_CAN1 226 +#define SRST_CAN1 227 + +/* VICRU-->SOFTRST_CON01 */ +#define SRST_P_GPIO2 228 +#define SRST_DB_GPIO2 229 +#define SRST_P_GPIO4 230 +#define SRST_DB_GPIO4 231 +#define SRST_P_GPIO5 232 +#define SRST_DB_GPIO5 233 +#define SRST_P_GPIO6 234 +#define SRST_DB_GPIO6 235 +#define SRST_P_GPIO7 236 +#define SRST_DB_GPIO7 237 +#define SRST_P_IOC_VCCIO2 238 +#define SRST_P_IOC_VCCIO4 239 +#define SRST_P_IOC_VCCIO5 240 +#define SRST_P_IOC_VCCIO6 241 +#define SRST_P_IOC_VCCIO7 242 + +/* VICRU-->SOFTRST_CON02 */ +#define SRST_CORE_ISP 243 +#define SRST_H_VICAP 244 +#define SRST_A_VICAP 245 +#define SRST_D_VICAP 246 +#define SRST_ISP0_VICAP 247 +#define SRST_CORE_VPSS 248 +#define SRST_CORE_VPSL 249 +#define SRST_P_CSI2HOST0 250 +#define SRST_P_CSI2HOST1 251 +#define SRST_P_CSI2HOST2 252 +#define SRST_P_CSI2HOST3 253 +#define SRST_H_SDMMC0 254 +#define SRST_A_GMAC 255 +#define SRST_P_CSIPHY0 256 +#define SRST_P_CSIPHY1 257 + +/* VICRU-->SOFTRST_CON03 */ +#define SRST_P_MACPHY 258 +#define SRST_MACPHY 259 +#define SRST_P_SARADC1 260 +#define SRST_SARADC1 261 +#define SRST_P_SARADC2 262 +#define SRST_SARADC2 263 + +/* VEPUCRU-->SOFTRST_CON00 */ +#define SRST_REF_PVTPLL_VEPU 264 +#define SRST_A_VEPU_BIU 265 +#define SRST_H_VEPU_BIU 266 +#define SRST_P_VEPU_BIU 267 +#define SRST_P_CRU_VEPU 268 +#define SRST_P_VEPU_GRF 269 +#define SRST_P_GPIO3 270 +#define SRST_DB_GPIO3 271 +#define SRST_P_IOC_VCCIO3 272 +#define SRST_P_SARADC0 273 +#define SRST_SARADC0 274 +#define SRST_H_SDMMC1 275 + +/* VEPUCRU-->SOFTRST_CON01 */ +#define SRST_P_VEPU_PVTPLL 276 +#define SRST_H_VEPU 277 +#define SRST_A_VEPU 278 +#define SRST_CORE_VEPU 279 + +/* NPUCRU-->SOFTRST_CON00 */ +#define SRST_REF_PVTPLL_NPU 280 +#define SRST_A_NPU_BIU 281 +#define SRST_H_NPU_BIU 282 +#define SRST_P_NPU_BIU 283 +#define SRST_P_CRU_NPU 284 +#define SRST_P_NPU_GRF 285 +#define SRST_P_NPU_PVTPLL 286 +#define SRST_H_RKNN 287 +#define SRST_A_RKNN 288 + +/* VDOCRU-->SOFTRST_CON00 */ +#define SRST_A_RKVDEC_BIU 289 +#define SRST_A_VDO_BIU 290 +#define SRST_H_VDO_BIU 291 +#define SRST_P_VDO_BIU 292 +#define SRST_P_CRU_VDO 293 +#define SRST_P_VDO_GRF 294 +#define SRST_A_RKVDEC 295 +#define SRST_H_RKVDEC 296 +#define SRST_HEVC_CA_RKVDEC 297 +#define SRST_A_VOP 298 +#define SRST_H_VOP 299 +#define SRST_D_VOP 300 +#define SRST_A_OOC 301 +#define SRST_H_OOC 302 +#define SRST_D_OOC 303 + +/* VDOCRU-->SOFTRST_CON01 */ +#define SRST_H_RKJPEG 304 +#define SRST_A_RKJPEG 305 +#define SRST_A_RKMMU_DECOM 306 +#define SRST_H_RKMMU_DECOM 307 +#define SRST_D_DECOM 308 +#define SRST_A_DECOM 309 +#define SRST_P_DECOM 310 +#define SRST_P_MIPI_DSI 311 +#define SRST_P_DSIPHY 312 + +/* VCPCRU-->SOFTRST_CON00 */ +#define SRST_REF_PVTPLL_VCP 313 +#define SRST_A_VCP_BIU 314 +#define SRST_H_VCP_BIU 315 +#define SRST_P_VCP_BIU 316 +#define SRST_P_CRU_VCP 317 +#define SRST_P_VCP_GRF 318 +#define SRST_P_VCP_PVTPLL 319 +#define SRST_A_AISP_BIU 320 +#define SRST_H_AISP_BIU 321 +#define SRST_CORE_AISP 322 + +/* VCPCRU-->SOFTRST_CON01 */ +#define SRST_H_FEC 323 +#define SRST_A_FEC 324 +#define SRST_CORE_FEC 325 +#define SRST_H_AVSP 326 +#define SRST_A_AVSP 327 + +#endif From 652c108cc44cd961b58b2998ff429f11ee60c9fd Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 11 Nov 2025 10:57:36 +0800 Subject: [PATCH 459/684] clk: rockchip: Add clock controller for the RV1126B Add the clock and reset tree definitions for the new rv1126b SoC. Signed-off-by: Elaine Zhang Link: https://patch.msgid.link/20251111025738.869847-4-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/Kconfig | 7 + drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk-rv1126b.c | 1117 ++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 68 ++ drivers/clk/rockchip/rst-rv1126b.c | 443 +++++++++++ 5 files changed, 1636 insertions(+) create mode 100644 drivers/clk/rockchip/clk-rv1126b.c create mode 100644 drivers/clk/rockchip/rst-rv1126b.c diff --git a/drivers/clk/rockchip/Kconfig b/drivers/clk/rockchip/Kconfig index febb7944f34bbe..e1ea0a098ca9f7 100644 --- a/drivers/clk/rockchip/Kconfig +++ b/drivers/clk/rockchip/Kconfig @@ -30,6 +30,13 @@ config CLK_RV1126 help Build the driver for RV1126 Clock Driver. +config CLK_RV1126B + bool "Rockchip RV1126B clock controller support" + depends on ARM64 || COMPILE_TEST + default y + help + Build the driver for RV1126B Clock Driver. + config CLK_RK3036 bool "Rockchip RK3036 clock controller support" depends on ARM || COMPILE_TEST diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index c281a9738d9f47..82b4b29ad036b8 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -20,6 +20,7 @@ clk-rockchip-$(CONFIG_RESET_CONTROLLER) += softrst.o obj-$(CONFIG_CLK_PX30) += clk-px30.o obj-$(CONFIG_CLK_RV110X) += clk-rv1108.o obj-$(CONFIG_CLK_RV1126) += clk-rv1126.o +obj-$(CONFIG_CLK_RV1126B) += clk-rv1126b.o rst-rv1126b.o obj-$(CONFIG_CLK_RK3036) += clk-rk3036.o obj-$(CONFIG_CLK_RK312X) += clk-rk3128.o obj-$(CONFIG_CLK_RK3188) += clk-rk3188.o diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c new file mode 100644 index 00000000000000..3e27bfc14854ff --- /dev/null +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -0,0 +1,1117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * Author: Elaine Zhang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" + +#define RV1126B_FRAC_MAX_PRATE 1200000000 + +#define PVTPLL_SRC_SEL_PVTPLL (BIT(0) | BIT(16)) + +enum rv1126b_plls { + gpll, cpll, aupll, dpll +}; + +static struct rockchip_pll_rate_table rv1126b_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), + RK3036_PLL_RATE(1179648000, 1, 49, 1, 1, 0, 2550137), + RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0), + RK3036_PLL_RATE(993484800, 1, 41, 1, 1, 0, 6630355), + RK3036_PLL_RATE(983040000, 1, 40, 1, 1, 0, 16106127), + RK3036_PLL_RATE(903168000, 1, 75, 2, 1, 0, 4429185), + { /* sentinel */ }, +}; + +#define RV1126B_DIV_ACLK_CORE_MASK 0x1f +#define RV1126B_DIV_ACLK_CORE_SHIFT 0 +#define RV1126B_DIV_PCLK_CORE_MASK 0x1f +#define RV1126B_DIV_PCLK_CORE_SHIFT 8 +#define RV1126B_CORE_SEL_MASK 0x1 +#define RV1126B_CORE_SEL_SHIFT 1 + +#define RV1126B_CLKSEL0(_aclk_core) \ +{ \ + .reg = RV1126B_CORECLKSEL_CON(2), \ + .val = HIWORD_UPDATE(_aclk_core - 1, RV1126B_DIV_ACLK_CORE_MASK, \ + RV1126B_DIV_ACLK_CORE_SHIFT), \ +} + +#define RV1126B_CLKSEL1(_pclk_dbg) \ +{ \ + .reg = RV1126B_CORECLKSEL_CON(2), \ + .val = HIWORD_UPDATE(_pclk_dbg - 1, RV1126B_DIV_PCLK_CORE_MASK, \ + RV1126B_DIV_PCLK_CORE_SHIFT), \ +} + +#define RV1126B_CPUCLK_RATE(_prate, _aclk_core, _pclk_dbg) \ +{ \ + .prate = _prate, \ + .divs = { \ + RV1126B_CLKSEL0(_aclk_core), \ + RV1126B_CLKSEL1(_pclk_dbg), \ + }, \ +} + +static struct rockchip_cpuclk_rate_table rv1126b_cpuclk_rates[] __initdata = { + RV1126B_CPUCLK_RATE(1608000000, 4, 10), + RV1126B_CPUCLK_RATE(1512000000, 4, 10), + RV1126B_CPUCLK_RATE(1416000000, 4, 10), + RV1126B_CPUCLK_RATE(1296000000, 3, 10), + RV1126B_CPUCLK_RATE(1200000000, 3, 10), + RV1126B_CPUCLK_RATE(1188000000, 3, 8), + RV1126B_CPUCLK_RATE(1104000000, 2, 8), + RV1126B_CPUCLK_RATE(1008000000, 2, 8), + RV1126B_CPUCLK_RATE(816000000, 2, 6), + RV1126B_CPUCLK_RATE(600000000, 2, 4), + RV1126B_CPUCLK_RATE(594000000, 2, 4), + RV1126B_CPUCLK_RATE(408000000, 1, 3), + RV1126B_CPUCLK_RATE(396000000, 1, 3), +}; + +PNAME(mux_pll_p) = { "xin24m" }; +PNAME(mux_gpll_cpll_p) = { "gpll", "cpll" }; +PNAME(mux_gpll_aupll_p) = { "gpll", "aupll" }; +PNAME(mux_gpll_aupll_cpll_p) = { "gpll", "aupll", "cpll" }; +PNAME(mux_gpll_cpll_24m_p) = { "gpll", "cpll", "xin24m" }; +PNAME(mux_cpll_24m_p) = { "cpll", "xin24m" }; +PNAME(mux_24m_gpll_aupll_cpll_p) = { "xin24m", "gpll", "aupll", "cpll" }; +PNAME(mux_24m_gpll_cpll_p) = { "xin24m", "gpll", "cpll" }; +PNAME(mux_24m_gpll_aupll_p) = { "xin24m", "gpll", "aupll" }; +PNAME(mux_sclk_uart_src_p) = { "xin24m", "clk_cm_frac0", "clk_cm_frac1", + "clk_cm_frac2", "clk_uart_frac0", "clk_uart_frac1" }; +PNAME(mclk_sai0_src_p) = { "xin24m", "clk_cm_frac0", "clk_cm_frac1", + "clk_cm_frac2", "clk_audio_frac0", "clk_audio_frac1", + "clk_audio_int0", "clk_audio_int1", + "mclk_sai0_from_io" }; +PNAME(mclk_sai1_src_p) = { "xin24m", "clk_cm_frac0", "clk_cm_frac1", + "clk_cm_frac2", "clk_audio_frac0", "clk_audio_frac1", + "clk_audio_int0", "clk_audio_int1", + "mclk_sai1_from_io" }; +PNAME(mclk_sai2_src_p) = { "xin24m", "clk_cm_frac0", "clk_cm_frac1", + "clk_cm_frac2", "clk_audio_frac0", "clk_audio_frac1", + "clk_audio_int0", "clk_audio_int1", + "mclk_sai2_from_io" }; +PNAME(mux_sai_src_p) = { "xin24m", "clk_cm_frac0", "clk_cm_frac1", + "clk_cm_frac2", "clk_audio_frac0", "clk_audio_frac1", + "clk_audio_int0", "clk_audio_int1", "mclk_sai0_from_io", + "mclk_sai1_from_io", "mclk_sai2_from_io"}; +PNAME(mux_100m_24m_p) = { "clk_cpll_div10", "xin24m" }; +PNAME(mux_200m_24m_p) = { "clk_gpll_div6", "xin24m" }; +PNAME(mux_500m_400m_200m_p) = { "clk_cpll_div2", "clk_gpll_div3", "clk_gpll_div6" }; +PNAME(mux_300m_200m_p) = { "clk_gpll_div4", "clk_gpll_div6" }; +PNAME(mux_500m_400m_300m_p) = { "clk_cpll_div2", "clk_gpll_div3", "clk_gpll_div4" }; +PNAME(mux_333m_200m_p) = { "clk_cpll_div3", "clk_gpll_div6" }; +PNAME(mux_600m_400m_200m_p) = { "clk_gpll_div2", "clk_gpll_div3", "clk_gpll_div6" }; +PNAME(mux_400m_300m_200m_p) = { "clk_gpll_div3", "clk_gpll_div4", "clk_gpll_div6" }; +PNAME(mux_200m_100m_p) = { "clk_gpll_div6", "clk_cpll_div10" }; +PNAME(mux_200m_100m_50m_24m_p) = { "clk_gpll_div6", "clk_cpll_div10", "clk_cpll_div20", + "xin24m" }; +PNAME(mux_600m_24m_p) = { "clk_gpll_div2", "xin24m" }; +PNAME(mux_armclk_p) = { "clk_core_pll", "clk_core_pvtpll" }; +PNAME(aclk_npu_root_p) = { "clk_npu_pll", "clk_npu_pvtpll" }; +PNAME(clk_saradc0_p) = { "clk_saradc0_src", "clk_saradc0_rcosc_io" }; +PNAME(clk_core_vepu_p) = { "clk_vepu_pll", "clk_vepu_pvtpll" }; +PNAME(clk_core_fec_p) = { "clk_core_fec_src", "clk_vcp_pvtpll" }; +PNAME(clk_core_aisp_p) = { "clk_aisp_pll", "clk_vcp_pvtpll" }; +PNAME(clk_core_isp_root_p) = { "clk_isp_pll", "clk_isp_pvtpll" }; +PNAME(clk_gmac_ptp_ref_p) = { "clk_gmac_ptp_ref_src", "clk_gmac_ptp_from_io" }; +PNAME(clk_saradc1_p) = { "clk_saradc1_src", "clk_saradc1_rcosc_io" }; +PNAME(clk_saradc2_p) = { "clk_saradc2_src", "clk_saradc2_rcosc_io" }; +PNAME(clk_rcosc_src_p) = { "xin24m", "clk_rcosc", "clk_rcosc_div2", + "clk_rcosc_div3", "clk_rcosc_div4" }; +PNAME(busclk_pmu_mux_p) = { "clk_cpll_div10", "clk_rcosc_src" }; +PNAME(clk_xin_rc_div_p) = { "xin24m", "clk_rcosc_src" }; +PNAME(clk_32k_p) = { "clk_xin_rc_div", "clk_32k_rtc", "clk_32k_io" }; +PNAME(mux_24m_32k_p) = { "xin24m", "clk_32k" }; +PNAME(mux_24m_rcosc_buspmu_p) = { "xin24m", "clk_rcosc_src", "busclk_pmu_src" }; +PNAME(mux_24m_rcosc_buspmu_32k_p) = { "xin24m", "clk_rcosc_src", "busclk_pmu_src", + "clk_32k" }; +PNAME(sclk_uart0_p) = { "sclk_uart0_src", "xin24m", "clk_rcosc_src" }; +PNAME(clk_osc_rcosc_ctrl_p) = { "clk_rcosc_src", "clk_testout_out" }; +PNAME(lrck_src_asrc_p) = { "mclk_asrc0", "mclk_asrc1", "mclk_asrc2", "mclk_asrc3", + "fs_inter_from_sai0", "fs_inter_from_sai1", + "fs_inter_from_sai2", "clkout_pdm"}; +PNAME(clk_ref_pipephy_p) = { "clk_ref_pipephy_cpll_src", "xin24m" }; +PNAME(clk_timer0_parents_p) = { "clk_timer_root", "mclk_sai0_from_io", + "sclk_sai0_from_io" }; +PNAME(clk_timer1_parents_p) = { "clk_timer_root", "mclk_sai1_from_io", + "sclk_sai1_from_io" }; +PNAME(clk_timer2_parents_p) = { "clk_timer_root", "mclk_sai2_from_io", + "sclk_sai2_from_io" }; +PNAME(clk_timer3_parents_p) = { "clk_timer_root", "mclk_asrc0", "mclk_asrc1" }; +PNAME(clk_timer4_parents_p) = { "clk_timer_root", "mclk_asrc2", "mclk_asrc3" }; +PNAME(clk_macphy_p) = { "xin24m", "clk_cpll_div20" }; +PNAME(clk_cpll_div10_p) = { "gpll", "clk_aisp_pll_src" }; + +static struct rockchip_pll_clock rv1126b_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, + CLK_IS_CRITICAL, RV1126B_PLL_CON(8), + RV1126B_MODE_CON, 2, 10, 0, rv1126b_pll_rates), + [aupll] = PLL(pll_rk3328, PLL_AUPLL, "aupll", mux_pll_p, + CLK_IS_CRITICAL, RV1126B_PLL_CON(0), + RV1126B_MODE_CON, 0, 10, 0, rv1126b_pll_rates), + [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p, + CLK_IS_CRITICAL, RV1126B_PERIPLL_CON(0), + RV1126B_MODE_CON, 4, 10, 0, rv1126b_pll_rates), + [dpll] = PLL(pll_rk3328, 0, "dpll", mux_pll_p, + CLK_IS_CRITICAL, RV1126B_SUBDDRPLL_CON(0), + RV1126B_MODE_CON, 2, 10, 0, rv1126b_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +static struct rockchip_clk_branch rv1126b_rcdiv_pmu_fracmux __initdata = + MUX(CLK_32K, "clk_32k", clk_32k_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RV1126B_PMUCLKSEL_CON(2), 1, 2, MFLAGS); + +static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { + + FACTOR(0, "clk_rcosc_div2", "clk_rcosc", 0, 1, 2), + FACTOR(0, "clk_rcosc_div3", "clk_rcosc", 0, 1, 3), + FACTOR(0, "clk_rcosc_div4", "clk_rcosc", 0, 1, 4), + + /* Clock Definition */ + COMPOSITE_NODIV(CLK_AISP_PLL_SRC, "clk_aisp_pll_src", mux_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(62), 4, 2, MFLAGS, + RV1126B_CLKGATE_CON(5), 4, GFLAGS), + DIV(CLK_AISP_PLL, "clk_aisp_pll", "clk_aisp_pll_src", 0, + RV1126B_CLKSEL_CON(62), 0, 3, DFLAGS), + + COMPOSITE(CLK_CPLL_DIV10, "clk_cpll_div10", clk_cpll_div10_p, 0, + RV1126B_CLKSEL_CON(1), 15, 1, MFLAGS, 5, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 1, GFLAGS), + COMPOSITE_NOMUX(CLK_CPLL_DIV20, "clk_cpll_div20", "cpll", 0, + RV1126B_CLKSEL_CON(1), 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 0, GFLAGS), + COMPOSITE_NOMUX(CLK_CPLL_DIV8, "clk_cpll_div8", "cpll", 0, + RV1126B_CLKSEL_CON(1), 10, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 2, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV8, "clk_gpll_div8", "gpll", 0, + RV1126B_CLKSEL_CON(2), 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 3, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV6, "clk_gpll_div6", "gpll", 0, + RV1126B_CLKSEL_CON(2), 5, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 4, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV4, "clk_gpll_div4", "gpll", 0, + RV1126B_CLKSEL_CON(2), 10, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(CLK_CPLL_DIV3, "clk_cpll_div3", "cpll", 0, + RV1126B_CLKSEL_CON(3), 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV3, "clk_gpll_div3", "gpll", 0, + RV1126B_CLKSEL_CON(3), 5, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_NOMUX(CLK_CPLL_DIV2, "clk_cpll_div2", "cpll", 0, + RV1126B_CLKSEL_CON(3), 10, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV2, "clk_gpll_div2", "gpll", 0, + RV1126B_CLKSEL_CON(4), 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 9, GFLAGS), + MUX(CLK_CM_FRAC0_SRC, "clk_cm_frac0_src", mux_24m_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(10), 0, 2, MFLAGS), + COMPOSITE_FRAC(CLK_CM_FRAC0, "clk_cm_frac0", "clk_cm_frac0_src", 0, + RV1126B_CLKSEL_CON(25), 0, + RV1126B_CLKGATE_CON(1), 0, GFLAGS), + MUX(CLK_CM_FRAC1_SRC, "clk_cm_frac1_src", mux_24m_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(10), 2, 2, MFLAGS), + COMPOSITE_FRAC(CLK_CM_FRAC1, "clk_cm_frac1", "clk_cm_frac1_src", 0, + RV1126B_CLKSEL_CON(26), 0, + RV1126B_CLKGATE_CON(1), 1, GFLAGS), + MUX(CLK_CM_FRAC2_SRC, "clk_cm_frac2_src", mux_24m_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(10), 4, 2, MFLAGS), + COMPOSITE_FRAC(CLK_CM_FRAC2, "clk_cm_frac2", "clk_cm_frac2_src", 0, + RV1126B_CLKSEL_CON(27), 0, + RV1126B_CLKGATE_CON(1), 2, GFLAGS), + MUX(CLK_UART_FRAC0_SRC, "clk_uart_frac0_src", mux_24m_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(10), 6, 2, MFLAGS), + COMPOSITE_FRAC(CLK_UART_FRAC0, "clk_uart_frac0", "clk_uart_frac0_src", 0, + RV1126B_CLKSEL_CON(28), 0, + RV1126B_CLKGATE_CON(1), 3, GFLAGS), + MUX(CLK_UART_FRAC1_SRC, "clk_uart_frac1_src", mux_24m_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(10), 8, 2, MFLAGS), + COMPOSITE_FRAC(CLK_UART_FRAC1, "clk_uart_frac1", "clk_uart_frac1_src", 0, + RV1126B_CLKSEL_CON(29), 0, + RV1126B_CLKGATE_CON(1), 4, GFLAGS), + MUX(CLK_AUDIO_FRAC0_SRC, "clk_audio_frac0_src", mux_24m_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(10), 10, 2, MFLAGS), + COMPOSITE_FRAC(CLK_AUDIO_FRAC0, "clk_audio_frac0", "clk_audio_frac0_src", 0, + RV1126B_CLKSEL_CON(30), 0, + RV1126B_CLKGATE_CON(1), 5, GFLAGS), + MUX(CLK_AUDIO_FRAC1_SRC, "clk_audio_frac1_src", mux_24m_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(10), 12, 2, MFLAGS), + COMPOSITE_FRAC(CLK_AUDIO_FRAC1, "clk_audio_frac1", "clk_audio_frac1_src", 0, + RV1126B_CLKSEL_CON(31), 0, + RV1126B_CLKGATE_CON(1), 6, GFLAGS), + COMPOSITE(CLK_AUDIO_INT0, "clk_audio_int0", mux_24m_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 7, GFLAGS), + COMPOSITE(CLK_AUDIO_INT1, "clk_audio_int1", mux_24m_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE(SCLK_UART0_SRC, "sclk_uart0_src", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(12), 5, 3, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 9, GFLAGS), + COMPOSITE(SCLK_UART1, "sclk_uart1", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(12), 13, 3, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 10, GFLAGS), + COMPOSITE(SCLK_UART2, "sclk_uart2", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 11, GFLAGS), + COMPOSITE(SCLK_UART3, "sclk_uart3", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(13), 13, 3, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 12, GFLAGS), + COMPOSITE(SCLK_UART4, "sclk_uart4", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(14), 5, 3, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 13, GFLAGS), + COMPOSITE(SCLK_UART5, "sclk_uart5", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(14), 13, 3, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(1), 14, GFLAGS), + COMPOSITE(SCLK_UART6, "sclk_uart6", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(15), 5, 3, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(2), 0, GFLAGS), + COMPOSITE(SCLK_UART7, "sclk_uart7", mux_sclk_uart_src_p, 0, + RV1126B_CLKSEL_CON(15), 13, 3, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(2), 1, GFLAGS), + COMPOSITE(MCLK_SAI0, "mclk_sai0", mclk_sai0_src_p, 0, + RV1126B_CLKSEL_CON(16), 8, 4, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(2), 2, GFLAGS), + COMPOSITE(MCLK_SAI1, "mclk_sai1", mclk_sai1_src_p, 0, + RV1126B_CLKSEL_CON(17), 8, 4, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(2), 3, GFLAGS), + COMPOSITE(MCLK_SAI2, "mclk_sai2", mclk_sai2_src_p, 0, + RV1126B_CLKSEL_CON(18), 8, 4, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(2), 4, GFLAGS), + COMPOSITE(MCLK_PDM, "mclk_pdm", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(19), 6, 4, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(2), 5, GFLAGS), + COMPOSITE_NOGATE(0, "clkout_pdm_src", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(20), 8, 4, MFLAGS, 0, 8, DFLAGS), + GATE(CLKOUT_PDM, "clkout_pdm", "clkout_pdm_src", 0, + RV1126B_CLKGATE_CON(2), 6, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC0, "mclk_asrc0", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(16), 12, 4, MFLAGS, + RV1126B_CLKGATE_CON(2), 7, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC1, "mclk_asrc1", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(17), 12, 4, MFLAGS, + RV1126B_CLKGATE_CON(2), 8, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC2, "mclk_asrc2", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(18), 12, 4, MFLAGS, + RV1126B_CLKGATE_CON(2), 9, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC3, "mclk_asrc3", mux_sai_src_p, 0, + RV1126B_CLKSEL_CON(19), 12, 4, MFLAGS, + RV1126B_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE(CLK_ASRC0, "clk_asrc0", mux_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(21), 6, 1, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(2), 11, GFLAGS), + COMPOSITE(CLK_ASRC1, "clk_asrc1", mux_gpll_aupll_p, 0, + RV1126B_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(2), 12, GFLAGS), + COMPOSITE_NOMUX(CLK_CORE_PLL, "clk_core_pll", "gpll", CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(60), 0, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 0, GFLAGS), + COMPOSITE_NOMUX(CLK_NPU_PLL, "clk_npu_pll", "gpll", CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(60), 6, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 1, GFLAGS), + COMPOSITE(CLK_VEPU_PLL, "clk_vepu_pll", mux_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(61), 4, 2, MFLAGS, 0, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 2, GFLAGS), + COMPOSITE(CLK_ISP_PLL, "clk_isp_pll", mux_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(61), 10, 2, MFLAGS, 6, 4, DFLAGS, + RV1126B_CLKGATE_CON(5), 3, GFLAGS), + COMPOSITE(CLK_SARADC0_SRC, "clk_saradc0_src", mux_200m_24m_p, 0, + RV1126B_CLKSEL_CON(63), 12, 1, MFLAGS, 0, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 6, GFLAGS), + COMPOSITE(CLK_SARADC1_SRC, "clk_saradc1_src", mux_200m_24m_p, 0, + RV1126B_CLKSEL_CON(63), 13, 1, MFLAGS, 4, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 7, GFLAGS), + COMPOSITE(CLK_SARADC2_SRC, "clk_saradc2_src", mux_200m_24m_p, 0, + RV1126B_CLKSEL_CON(63), 14, 1, MFLAGS, 8, 3, DFLAGS, + RV1126B_CLKGATE_CON(5), 8, GFLAGS), + GATE(HCLK_RKNN, "hclk_rknn", "clk_gpll_div8", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(5), 10, GFLAGS), + GATE(PCLK_NPU_ROOT, "pclk_npu_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(5), 11, GFLAGS), + COMPOSITE_NODIV(ACLK_VEPU_ROOT, "aclk_vepu_root", mux_500m_400m_200m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(40), 0, 2, MFLAGS, + RV1126B_CLKGATE_CON(5), 12, GFLAGS), + GATE(HCLK_VEPU_ROOT, "hclk_vepu_root", "clk_gpll_div8", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(5), 13, GFLAGS), + GATE(PCLK_VEPU_ROOT, "pclk_vepu_root", "clk_cpll_div10", 0, + RV1126B_CLKGATE_CON(5), 14, GFLAGS), + COMPOSITE(CLK_CORE_RGA_SRC, "clk_core_rga_src", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(40), 5, 1, MFLAGS, 2, 3, DFLAGS, + RV1126B_CLKGATE_CON(6), 0, GFLAGS), + COMPOSITE_NODIV(ACLK_GMAC_ROOT, "aclk_gmac_root", mux_300m_200m_p, 0, + RV1126B_CLKSEL_CON(40), 6, 1, MFLAGS, + RV1126B_CLKGATE_CON(6), 1, GFLAGS), + COMPOSITE_NODIV(ACLK_VI_ROOT, "aclk_vi_root", mux_500m_400m_300m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(40), 7, 2, MFLAGS, + RV1126B_CLKGATE_CON(6), 2, GFLAGS), + GATE(HCLK_VI_ROOT, "hclk_vi_root", "clk_gpll_div8", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(6), 3, GFLAGS), + GATE(PCLK_VI_ROOT, "pclk_vi_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(6), 4, GFLAGS), + COMPOSITE_NODIV(DCLK_VICAP_ROOT, "dclk_vicap_root", mux_333m_200m_p, 0, + RV1126B_CLKSEL_CON(42), 5, 1, MFLAGS, + RV1126B_CLKGATE_CON(6), 5, GFLAGS), + COMPOSITE(CLK_SYS_DSMC_ROOT, "clk_sys_dsmc_root", mux_24m_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(40), 14, 2, MFLAGS, 9, 5, DFLAGS, + RV1126B_CLKGATE_CON(6), 6, GFLAGS), + COMPOSITE(ACLK_VDO_ROOT, "aclk_vdo_root", mux_gpll_cpll_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(42), 4, 1, MFLAGS, 0, 4, DFLAGS, + RV1126B_CLKGATE_CON(6), 7, GFLAGS), + COMPOSITE(ACLK_RKVDEC_ROOT, "aclk_rkvdec_root", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(42), 10, 1, MFLAGS, 6, 4, DFLAGS, + RV1126B_CLKGATE_CON(6), 8, GFLAGS), + GATE(HCLK_VDO_ROOT, "hclk_vdo_root", "clk_gpll_div8", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(6), 9, GFLAGS), + GATE(PCLK_VDO_ROOT, "pclk_vdo_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(6), 10, GFLAGS), + COMPOSITE(DCLK_VOP, "dclk_vop", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(43), 8, 1, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(6), 12, GFLAGS), + COMPOSITE(DCLK_OOC_SRC, "dclk_ooc_src", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(62), 7, 1, MFLAGS, 8, 8, DFLAGS, + RV1126B_CLKGATE_CON(6), 13, GFLAGS), + GATE(DCLK_DECOM_SRC, "dclk_decom_src", "clk_gpll_div3", 0, + RV1126B_CLKGATE_CON(6), 14, GFLAGS), + GATE(PCLK_DDR_ROOT, "pclk_ddr_root", "clk_cpll_div10", 0, + RV1126B_CLKGATE_CON(7), 0, GFLAGS), + COMPOSITE(ACLK_SYSMEM, "aclk_sysmem", mux_gpll_cpll_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(44), 3, 1, MFLAGS, 0, 3, DFLAGS, + RV1126B_CLKGATE_CON(7), 1, GFLAGS), + COMPOSITE_NODIV(ACLK_TOP_ROOT, "aclk_top_root", mux_600m_400m_200m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(44), 6, 2, MFLAGS, + RV1126B_CLKGATE_CON(7), 3, GFLAGS), + COMPOSITE_NODIV(ACLK_BUS_ROOT, "aclk_bus_root", mux_400m_300m_200m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(44), 8, 2, MFLAGS, + RV1126B_CLKGATE_CON(7), 4, GFLAGS), + COMPOSITE_NODIV(HCLK_BUS_ROOT, "hclk_bus_root", mux_200m_100m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(44), 10, 1, MFLAGS, + RV1126B_CLKGATE_CON(7), 5, GFLAGS), + GATE(PCLK_BUS_ROOT, "pclk_bus_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(7), 6, GFLAGS), + COMPOSITE(CCLK_SDMMC0, "cclk_sdmmc0", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(45), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(7), 7, GFLAGS), + COMPOSITE(CCLK_SDMMC1, "cclk_sdmmc1", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(46), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(7), 8, GFLAGS), + COMPOSITE(CCLK_EMMC, "cclk_emmc", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(47), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(7), 9, GFLAGS), + COMPOSITE(SCLK_2X_FSPI0, "sclk_2x_fspi0", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(48), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1126B_CLKGATE_CON(7), 10, GFLAGS), + COMPOSITE(CLK_GMAC_PTP_REF_SRC, "clk_gmac_ptp_ref_src", mux_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(45), 10, 1, MFLAGS, 11, 5, DFLAGS, + RV1126B_CLKGATE_CON(7), 11, GFLAGS), + GATE(CLK_GMAC_125M, "clk_gmac_125m", "clk_cpll_div8", 0, + RV1126B_CLKGATE_CON(7), 12, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER_ROOT, "clk_timer_root", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(46), 11, 1, MFLAGS, + RV1126B_CLKGATE_CON(7), 13, GFLAGS), + COMPOSITE_NODIV(TCLK_WDT_NS_SRC, "tclk_wdt_ns_src", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(46), 12, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 0, GFLAGS), + COMPOSITE_NODIV(TCLK_WDT_S_SRC, "tclk_wdt_s_src", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(46), 13, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 1, GFLAGS), + COMPOSITE_NODIV(TCLK_WDT_HPMCU, "tclk_wdt_hpmcu", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(46), 14, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 2, GFLAGS), + COMPOSITE(CLK_CAN0, "clk_can0", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(49), 6, 2, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(8), 4, GFLAGS), + COMPOSITE(CLK_CAN1, "clk_can1", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(49), 14, 2, MFLAGS, 8, 5, DFLAGS, + RV1126B_CLKGATE_CON(8), 5, GFLAGS), + COMPOSITE_NODIV(PCLK_PERI_ROOT, "pclk_peri_root", mux_100m_24m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(47), 12, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 6, GFLAGS), + COMPOSITE_NODIV(ACLK_PERI_ROOT, "aclk_peri_root", mux_200m_24m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(47), 13, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 7, GFLAGS), + COMPOSITE_NODIV(CLK_I2C_BUS_SRC, "clk_i2c_bus_src", mux_200m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 1, 1, MFLAGS, + RV1126B_CLKGATE_CON(8), 9, GFLAGS), + COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", mux_200m_100m_50m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 2, 2, MFLAGS, + RV1126B_CLKGATE_CON(8), 10, GFLAGS), + COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", mux_200m_100m_50m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 4, 2, MFLAGS, + RV1126B_CLKGATE_CON(8), 11, GFLAGS), + GATE(BUSCLK_PMU_SRC, "busclk_pmu_src", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(8), 12, GFLAGS), + COMPOSITE_NODIV(CLK_PWM0, "clk_pwm0", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 8, 1, MFLAGS, + RV1126B_CLKGATE_CON(9), 0, GFLAGS), + COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 10, 1, MFLAGS, + RV1126B_CLKGATE_CON(9), 2, GFLAGS), + COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", mux_100m_24m_p, 0, + RV1126B_CLKSEL_CON(50), 11, 1, MFLAGS, + RV1126B_CLKGATE_CON(9), 3, GFLAGS), + COMPOSITE_NODIV(CLK_PKA_RKCE_SRC, "clk_pka_rkce_src", mux_300m_200m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(50), 12, 1, MFLAGS, + RV1126B_CLKGATE_CON(9), 4, GFLAGS), + COMPOSITE_NODIV(ACLK_RKCE_SRC, "aclk_rkce_src", mux_200m_24m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(50), 13, 1, MFLAGS, + RV1126B_CLKGATE_CON(9), 5, GFLAGS), + COMPOSITE_NODIV(ACLK_VCP_ROOT, "aclk_vcp_root", mux_500m_400m_200m_p, CLK_IS_CRITICAL, + RV1126B_CLKSEL_CON(48), 12, 2, MFLAGS, + RV1126B_CLKGATE_CON(9), 6, GFLAGS), + GATE(HCLK_VCP_ROOT, "hclk_vcp_root", "clk_gpll_div8", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(9), 7, GFLAGS), + GATE(PCLK_VCP_ROOT, "pclk_vcp_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(9), 8, GFLAGS), + COMPOSITE(CLK_CORE_FEC_SRC, "clk_core_fec_src", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(51), 3, 1, MFLAGS, 0, 3, DFLAGS, + RV1126B_CLKGATE_CON(9), 9, GFLAGS), + GATE(CLK_50M_GMAC_IOBUF_VI, "clk_50m_gmac_iobuf_vi", "clk_cpll_div20", 0, + RV1126B_CLKGATE_CON(9), 11, GFLAGS), + GATE(PCLK_TOP_ROOT, "pclk_top_root", "clk_cpll_div10", CLK_IS_CRITICAL, + RV1126B_CLKGATE_CON(15), 0, GFLAGS), + COMPOSITE(CLK_MIPI0_OUT2IO, "clk_mipi0_out2io", mux_600m_24m_p, 0, + RV1126B_CLKSEL_CON(67), 11, 1, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(15), 3, GFLAGS), + COMPOSITE(CLK_MIPI1_OUT2IO, "clk_mipi1_out2io", mux_600m_24m_p, 0, + RV1126B_CLKSEL_CON(67), 12, 1, MFLAGS, 6, 5, DFLAGS, + RV1126B_CLKGATE_CON(15), 4, GFLAGS), + COMPOSITE(CLK_MIPI2_OUT2IO, "clk_mipi2_out2io", mux_600m_24m_p, 0, + RV1126B_CLKSEL_CON(68), 11, 1, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(15), 5, GFLAGS), + COMPOSITE(CLK_MIPI3_OUT2IO, "clk_mipi3_out2io", mux_600m_24m_p, 0, + RV1126B_CLKSEL_CON(68), 12, 1, MFLAGS, 6, 5, DFLAGS, + RV1126B_CLKGATE_CON(15), 6, GFLAGS), + COMPOSITE(CLK_CIF_OUT2IO, "clk_cif_out2io", mux_600m_24m_p, 0, + RV1126B_CLKSEL_CON(69), 5, 1, MFLAGS, 0, 5, DFLAGS, + RV1126B_CLKGATE_CON(15), 7, GFLAGS), + COMPOSITE(CLK_MAC_OUT2IO, "clk_mac_out2io", mux_gpll_cpll_24m_p, 0, + RV1126B_CLKSEL_CON(69), 6, 2, MFLAGS, 8, 7, DFLAGS, + RV1126B_CLKGATE_CON(15), 8, GFLAGS), + COMPOSITE_NOMUX(MCLK_SAI0_OUT2IO, "mclk_sai0_out2io", "mclk_sai0", CLK_SET_RATE_PARENT, + RV1126B_CLKSEL_CON(70), 0, 4, DFLAGS, + RV1126B_CLKGATE_CON(15), 9, GFLAGS), + COMPOSITE_NOMUX(MCLK_SAI1_OUT2IO, "mclk_sai1_out2io", "mclk_sai1", CLK_SET_RATE_PARENT, + RV1126B_CLKSEL_CON(70), 5, 4, DFLAGS, + RV1126B_CLKGATE_CON(15), 10, GFLAGS), + COMPOSITE_NOMUX(MCLK_SAI2_OUT2IO, "mclk_sai2_out2io", "mclk_sai2", CLK_SET_RATE_PARENT, + RV1126B_CLKSEL_CON(70), 10, 4, DFLAGS, + RV1126B_CLKGATE_CON(15), 11, GFLAGS), + + /* pd _npu */ + MUX(ACLK_RKNN, "aclk_rknn", aclk_npu_root_p, CLK_SET_RATE_PARENT, + RV1126B_NPUCLKSEL_CON(0), 1, 1, MFLAGS), + + /* pd_vepu */ + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_vepu_root", 0, + RV1126B_VEPUCLKGATE_CON(0), 7, GFLAGS), + GATE(DBCLK_GPIO3, "dbclk_gpio3", "xin24m", 0, + RV1126B_VEPUCLKGATE_CON(0), 8, GFLAGS), + GATE(PCLK_IOC_VCCIO3, "pclk_ioc_vccio3", "pclk_vepu_root", CLK_IS_CRITICAL, + RV1126B_VEPUCLKGATE_CON(0), 9, GFLAGS), + GATE(PCLK_SARADC0, "pclk_saradc0", "pclk_vepu_root", 0, + RV1126B_VEPUCLKGATE_CON(0), 10, GFLAGS), + MUX(CLK_SARADC0, "clk_saradc0", clk_saradc0_p, CLK_SET_RATE_PARENT, + RV1126B_VEPUCLKSEL_CON(0), 2, 1, MFLAGS), + GATE(HCLK_SDMMC1, "hclk_sdmmc1", "hclk_vepu_root", 0, + RV1126B_VEPUCLKGATE_CON(0), 12, GFLAGS), + GATE(HCLK_VEPU, "hclk_vepu", "hclk_vepu_root", 0, + RV1126B_VEPUCLKGATE_CON(1), 1, GFLAGS), + GATE(ACLK_VEPU, "aclk_vepu", "aclk_vepu_root", 0, + RV1126B_VEPUCLKGATE_CON(1), 2, GFLAGS), + COMPOSITE_NODIV(CLK_CORE_VEPU, "clk_core_vepu", clk_core_vepu_p, CLK_SET_RATE_PARENT, + RV1126B_VEPUCLKSEL_CON(0), 1, 1, MFLAGS, + RV1126B_VEPUCLKGATE_CON(1), 3, GFLAGS), + + /* pd_vcp */ + GATE(HCLK_FEC, "hclk_fec", "hclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(1), 0, GFLAGS), + GATE(ACLK_FEC, "aclk_fec", "aclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(1), 1, GFLAGS), + COMPOSITE_NODIV(CLK_CORE_FEC, "clk_core_fec", clk_core_fec_p, CLK_SET_RATE_PARENT, + RV1126B_VCPCLKSEL_CON(0), 13, 1, MFLAGS, + RV1126B_VCPCLKGATE_CON(1), 2, GFLAGS), + GATE(HCLK_AVSP, "hclk_avsp", "hclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(1), 3, GFLAGS), + GATE(ACLK_AVSP, "aclk_avsp", "aclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(1), 4, GFLAGS), + GATE(HCLK_AISP, "hclk_aisp", "hclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(0), 11, GFLAGS), + GATE(ACLK_AISP, "aclk_aisp", "aclk_vcp_root", 0, + RV1126B_VCPCLKGATE_CON(0), 12, GFLAGS), + COMPOSITE_NODIV(CLK_CORE_AISP, "clk_core_aisp", clk_core_aisp_p, CLK_SET_RATE_PARENT, + RV1126B_VCPCLKSEL_CON(0), 15, 1, MFLAGS, + RV1126B_VCPCLKGATE_CON(0), 13, GFLAGS), + + /* pd_vi */ + MUX(CLK_CORE_ISP_ROOT, "clk_core_isp_root", clk_core_isp_root_p, CLK_SET_RATE_PARENT, + RV1126B_VICLKSEL_CON(0), 1, 1, MFLAGS), + GATE(PCLK_DSMC, "pclk_dsmc", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(0), 8, GFLAGS), + GATE(ACLK_DSMC, "aclk_dsmc", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(0), 9, GFLAGS), + GATE(HCLK_CAN0, "hclk_can0", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(0), 10, GFLAGS), + GATE(HCLK_CAN1, "hclk_can1", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(0), 11, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(1), 0, GFLAGS), + GATE(DBCLK_GPIO2, "dbclk_gpio2", "xin24m", 0, + RV1126B_VICLKGATE_CON(1), 1, GFLAGS), + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(1), 2, GFLAGS), + GATE(DBCLK_GPIO4, "dbclk_gpio4", "xin24m", 0, + RV1126B_VICLKGATE_CON(1), 3, GFLAGS), + GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(1), 4, GFLAGS), + GATE(DBCLK_GPIO5, "dbclk_gpio5", "xin24m", 0, + RV1126B_VICLKGATE_CON(1), 5, GFLAGS), + GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(1), 6, GFLAGS), + GATE(DBCLK_GPIO6, "dbclk_gpio6", "xin24m", 0, + RV1126B_VICLKGATE_CON(1), 7, GFLAGS), + GATE(PCLK_GPIO7, "pclk_gpio7", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(1), 8, GFLAGS), + GATE(DBCLK_GPIO7, "dbclk_gpio7", "xin24m", 0, + RV1126B_VICLKGATE_CON(1), 9, GFLAGS), + GATE(PCLK_IOC_VCCIO2, "pclk_ioc_vccio2", "pclk_vi_root", CLK_IS_CRITICAL, + RV1126B_VICLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_IOC_VCCIO4, "pclk_ioc_vccio4", "pclk_vi_root", CLK_IS_CRITICAL, + RV1126B_VICLKGATE_CON(1), 11, GFLAGS), + GATE(PCLK_IOC_VCCIO5, "pclk_ioc_vccio5", "pclk_vi_root", CLK_IS_CRITICAL, + RV1126B_VICLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_IOC_VCCIO6, "pclk_ioc_vccio6", "pclk_vi_root", CLK_IS_CRITICAL, + RV1126B_VICLKGATE_CON(1), 13, GFLAGS), + GATE(PCLK_IOC_VCCIO7, "pclk_ioc_vccio7", "pclk_vi_root", CLK_IS_CRITICAL, + RV1126B_VICLKGATE_CON(1), 14, GFLAGS), + GATE(HCLK_ISP, "hclk_isp", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 0, GFLAGS), + GATE(ACLK_ISP, "aclk_isp", "aclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 1, GFLAGS), + GATE(CLK_CORE_ISP, "clk_core_isp", "clk_core_isp_root", 0, + RV1126B_VICLKGATE_CON(2), 2, GFLAGS), + GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 3, GFLAGS), + GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 4, GFLAGS), + GATE(DCLK_VICAP, "dclk_vicap", "dclk_vicap_root", 0, + RV1126B_VICLKGATE_CON(2), 5, GFLAGS), + GATE(ISP0CLK_VICAP, "isp0clk_vicap", "clk_core_isp_root", 0, + RV1126B_VICLKGATE_CON(2), 6, GFLAGS), + GATE(HCLK_VPSS, "hclk_vpss", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 7, GFLAGS), + GATE(ACLK_VPSS, "aclk_vpss", "aclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 8, GFLAGS), + GATE(CLK_CORE_VPSS, "clk_core_vpss", "clk_core_isp_root", 0, + RV1126B_VICLKGATE_CON(2), 9, GFLAGS), + GATE(HCLK_VPSL, "hclk_vpsl", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 10, GFLAGS), + GATE(ACLK_VPSL, "aclk_vpsl", "aclk_vi_root", 0, + RV1126B_VICLKGATE_CON(2), 11, GFLAGS), + GATE(CLK_CORE_VPSL, "clk_core_vpsl", "clk_core_isp_root", 0, + RV1126B_VICLKGATE_CON(2), 12, GFLAGS), + GATE(PCLK_CSI2HOST0, "pclk_csi2host0", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 0, GFLAGS), + GATE(DCLK_CSI2HOST0, "dclk_csi2host0", "dclk_vicap_root", 0, + RV1126B_VICLKGATE_CON(3), 1, GFLAGS), + GATE(PCLK_CSI2HOST1, "pclk_csi2host1", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 2, GFLAGS), + GATE(DCLK_CSI2HOST1, "dclk_csi2host1", "dclk_vicap_root", 0, + RV1126B_VICLKGATE_CON(3), 3, GFLAGS), + GATE(PCLK_CSI2HOST2, "pclk_csi2host2", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 4, GFLAGS), + GATE(DCLK_CSI2HOST2, "dclk_csi2host2", "dclk_vicap_root", 0, + RV1126B_VICLKGATE_CON(3), 5, GFLAGS), + GATE(PCLK_CSI2HOST3, "pclk_csi2host3", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 6, GFLAGS), + GATE(DCLK_CSI2HOST3, "dclk_csi2host3", "dclk_vicap_root", 0, + RV1126B_VICLKGATE_CON(3), 7, GFLAGS), + GATE(HCLK_SDMMC0, "hclk_sdmmc0", "hclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 8, GFLAGS), + GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_root", 0, + RV1126B_VICLKGATE_CON(3), 9, GFLAGS), + GATE(PCLK_GMAC, "pclk_gmac", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 10, GFLAGS), + MUX(CLK_GMAC_PTP_REF, "clk_gmac_ptp_ref", clk_gmac_ptp_ref_p, CLK_SET_RATE_PARENT, + RV1126B_VICLKSEL_CON(0), 14, 1, MFLAGS), + GATE(PCLK_CSIPHY0, "pclk_csiphy0", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 11, GFLAGS), + GATE(PCLK_CSIPHY1, "pclk_csiphy1", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 12, GFLAGS), + GATE(PCLK_MACPHY, "pclk_macphy", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(3), 13, GFLAGS), + GATE(PCLK_SARADC1, "pclk_saradc1", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(4), 0, GFLAGS), + MUX(CLK_SARADC1, "clk_saradc1", clk_saradc1_p, CLK_SET_RATE_PARENT, + RV1126B_VICLKSEL_CON(0), 2, 1, MFLAGS), + GATE(PCLK_SARADC2, "pclk_saradc2", "pclk_vi_root", 0, + RV1126B_VICLKGATE_CON(4), 2, GFLAGS), + MUX(CLK_SARADC2, "clk_saradc2", clk_saradc2_p, CLK_SET_RATE_PARENT, + RV1126B_VICLKSEL_CON(0), 3, 1, MFLAGS), + COMPOSITE_NODIV(CLK_MACPHY, "clk_macphy", clk_macphy_p, 0, + RV1126B_VICLKSEL_CON(1), 1, 1, MFLAGS, + RV1126B_VICLKGATE_CON(0), 12, GFLAGS), + + /* pd_vdo */ + GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_root", 0, + RV1126B_VDOCLKGATE_CON(0), 7, GFLAGS), + GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(0), 8, GFLAGS), + GATE(CLK_HEVC_CA_RKVDEC, "clk_hevc_ca_rkvdec", "aclk_rkvdec_root", 0, + RV1126B_VDOCLKGATE_CON(0), 9, GFLAGS), + GATE(ACLK_VOP, "aclk_vop", "aclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(0), 10, GFLAGS), + GATE(HCLK_VOP, "hclk_vop", "hclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(0), 11, GFLAGS), + GATE(ACLK_OOC, "aclk_ooc", "aclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(0), 13, GFLAGS), + GATE(HCLK_OOC, "hclk_ooc", "hclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(0), 14, GFLAGS), + GATE(HCLK_RKJPEG, "hclk_rkjpeg", "hclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 3, GFLAGS), + GATE(ACLK_RKJPEG, "aclk_rkjpeg", "aclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 4, GFLAGS), + GATE(ACLK_RKMMU_DECOM, "aclk_rkmmu_decom", "aclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 5, GFLAGS), + GATE(HCLK_RKMMU_DECOM, "hclk_rkmmu_decom", "hclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 6, GFLAGS), + GATE(DCLK_DECOM, "dclk_decom", "dclk_decom_src", 0, + RV1126B_VDOCLKGATE_CON(1), 8, GFLAGS), + GATE(ACLK_DECOM, "aclk_decom", "aclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 9, GFLAGS), + GATE(PCLK_DECOM, "pclk_decom", "pclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_MIPI_DSI, "pclk_mipi_dsi", "pclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_DSIPHY, "pclk_dsiphy", "pclk_vdo_root", 0, + RV1126B_VDOCLKGATE_CON(1), 13, GFLAGS), + + /* pd_ddr */ + GATE(PCLK_DDRC, "pclk_ddrc", "pclk_ddr_root", CLK_IS_CRITICAL, + RV1126B_DDRCLKGATE_CON(0), 2, GFLAGS), + GATE(PCLK_DDRMON, "pclk_ddrmon", "pclk_ddr_root", CLK_IS_CRITICAL, + RV1126B_DDRCLKGATE_CON(0), 3, GFLAGS), + GATE(CLK_TIMER_DDRMON, "clk_timer_ddrmon", "xin24m", 0, + RV1126B_DDRCLKGATE_CON(0), 4, GFLAGS), + GATE(PCLK_DFICTRL, "pclk_dfictrl", "pclk_ddr_root", CLK_IS_CRITICAL, + RV1126B_DDRCLKGATE_CON(0), 5, GFLAGS), + GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_ddr_root", CLK_IS_CRITICAL, + RV1126B_DDRCLKGATE_CON(0), 8, GFLAGS), + GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_ddr_root", CLK_IS_CRITICAL, + RV1126B_DDRCLKGATE_CON(0), 9, GFLAGS), + + /* pd_pmu*/ + COMPOSITE_NODIV(CLK_RCOSC_SRC, "clk_rcosc_src", clk_rcosc_src_p, 0, + RV1126B_PMUCLKSEL_CON(1), 0, 3, MFLAGS, + RV1126B_PMUCLKGATE_CON(0), 0, GFLAGS), + COMPOSITE_NOGATE(BUSCLK_PMU_MUX, "busclk_pmu_mux", busclk_pmu_mux_p, 0, + RV1126B_PMUCLKSEL_CON(1), 3, 1, MFLAGS, 4, 2, DFLAGS), + GATE(BUSCLK_PMU_ROOT, "busclk_pmu_root", "busclk_pmu_mux", 0, + RV1126B_PMUCLKGATE_CON(0), 1, GFLAGS), + GATE(BUSCLK_PMU1_ROOT, "busclk_pmu1_root", "busclk_pmu_mux", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(3), 11, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(0), 6, GFLAGS), + MUX(0, "xin_rc_src", clk_xin_rc_div_p, 0, + RV1126B_PMUCLKSEL_CON(2), 0, 1, MFLAGS), + COMPOSITE_FRACMUX_NOGATE(CLK_XIN_RC_DIV, "clk_xin_rc_div", "xin_rc_src", CLK_SET_RATE_PARENT, + RV1126B_PMUCLKSEL_CON(8), 0, + &rv1126b_rcdiv_pmu_fracmux), + GATE(PCLK_PMU_GPIO0, "pclk_pmu_gpio0", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_NODIV(DBCLK_PMU_GPIO0, "dbclk_pmu_gpio0", mux_24m_32k_p, 0, + RV1126B_PMUCLKSEL_CON(2), 4, 1, MFLAGS, + RV1126B_PMUCLKGATE_CON(0), 8, GFLAGS), + GATE(PCLK_PMU_HP_TIMER, "pclk_pmu_hp_timer", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(0), 10, GFLAGS), + COMPOSITE(CLK_PMU_HP_TIMER, "clk_pmu_hp_timer", mux_cpll_24m_p, CLK_IS_CRITICAL, + RV1126B_PMUCLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS, + RV1126B_PMUCLKGATE_CON(0), 11, GFLAGS), + GATE(CLK_PMU_32K_HP_TIMER, "clk_pmu_32k_hp_timer", "clk_32k", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(0), 13, GFLAGS), + GATE(PCLK_PWM1, "pclk_pwm1", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(1), 0, GFLAGS), + COMPOSITE(CLK_PWM1, "clk_pwm1", mux_24m_rcosc_buspmu_p, 0, + RV1126B_PMUCLKSEL_CON(2), 8, 2, MFLAGS, 6, 2, DFLAGS, + RV1126B_PMUCLKGATE_CON(1), 1, GFLAGS), + GATE(CLK_OSC_PWM1, "clk_osc_pwm1", "xin24m", 0, + RV1126B_PMUCLKGATE_CON(1), 2, GFLAGS), + GATE(CLK_RC_PWM1, "clk_rc_pwm1", "clk_32k", 0, + RV1126B_PMUCLKGATE_CON(1), 3, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(1), 6, GFLAGS), + COMPOSITE(CLK_I2C2, "clk_i2c2", mux_24m_rcosc_buspmu_p, 0, + RV1126B_PMUCLKSEL_CON(2), 14, 2, MFLAGS, 12, 2, DFLAGS, + RV1126B_PMUCLKGATE_CON(1), 7, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_NODIV(SCLK_UART0, "sclk_uart0", sclk_uart0_p, CLK_SET_RATE_PARENT, + RV1126B_PMUCLKSEL_CON(3), 0, 2, MFLAGS, + RV1126B_PMUCLKGATE_CON(1), 11, GFLAGS), + GATE(PCLK_RCOSC_CTRL, "pclk_rcosc_ctrl", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(2), 0, GFLAGS), + COMPOSITE_NODIV(CLK_OSC_RCOSC_CTRL, "clk_osc_rcosc_ctrl", clk_osc_rcosc_ctrl_p, CLK_IS_CRITICAL, + RV1126B_PMUCLKSEL_CON(3), 2, 1, MFLAGS, + RV1126B_PMUCLKGATE_CON(2), 1, GFLAGS), + GATE(CLK_REF_RCOSC_CTRL, "clk_ref_rcosc_ctrl", "xin24m", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(2), 2, GFLAGS), + GATE(PCLK_IOC_PMUIO0, "pclk_ioc_pmuio0", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(2), 3, GFLAGS), + GATE(CLK_REFOUT, "clk_refout", "xin24m", 0, + RV1126B_PMUCLKGATE_CON(2), 6, GFLAGS), + GATE(CLK_PREROLL, "clk_preroll", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(2), 7, GFLAGS), + GATE(CLK_PREROLL_32K, "clk_preroll_32k", "clk_32k", 0, + RV1126B_PMUCLKGATE_CON(2), 8, GFLAGS), + GATE(HCLK_PMU_SRAM, "hclk_pmu_sram", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMUCLKGATE_CON(2), 9, GFLAGS), + GATE(PCLK_WDT_LPMCU, "pclk_wdt_lpmcu", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(3), 0, GFLAGS), + COMPOSITE_NODIV(TCLK_WDT_LPMCU, "tclk_wdt_lpmcu", mux_24m_rcosc_buspmu_32k_p, 0, + RV1126B_PMUCLKSEL_CON(3), 6, 2, MFLAGS, + RV1126B_PMUCLKGATE_CON(3), 1, GFLAGS), + GATE(CLK_LPMCU, "clk_lpmcu", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(3), 2, GFLAGS), + GATE(CLK_LPMCU_RTC, "clk_lpmcu_rtc", "xin24m", 0, + RV1126B_PMUCLKGATE_CON(3), 3, GFLAGS), + GATE(PCLK_LPMCU_MAILBOX, "pclk_lpmcu_mailbox", "busclk_pmu_root", 0, + RV1126B_PMUCLKGATE_CON(3), 4, GFLAGS), + + /* pd_pmu1 */ + GATE(PCLK_SPI2AHB, "pclk_spi2ahb", "busclk_pmu_root", 0, + RV1126B_PMU1CLKGATE_CON(0), 0, GFLAGS), + GATE(HCLK_SPI2AHB, "hclk_spi2ahb", "busclk_pmu_root", 0, + RV1126B_PMU1CLKGATE_CON(0), 1, GFLAGS), + GATE(HCLK_FSPI1, "hclk_fspi1", "busclk_pmu_root", 0, + RV1126B_PMU1CLKGATE_CON(0), 2, GFLAGS), + GATE(HCLK_XIP_FSPI1, "hclk_xip_fspi1", "busclk_pmu_root", 0, + RV1126B_PMU1CLKGATE_CON(0), 3, GFLAGS), + COMPOSITE(SCLK_1X_FSPI1, "sclk_1x_fspi1", mux_24m_rcosc_buspmu_p, 0, + RV1126B_PMU1CLKSEL_CON(0), 0, 2, MFLAGS, 2, 3, DFLAGS, + RV1126B_PMU1CLKGATE_CON(0), 4, GFLAGS), + GATE(PCLK_IOC_PMUIO1, "pclk_ioc_pmuio1", "busclk_pmu_root", CLK_IS_CRITICAL, + RV1126B_PMU1CLKGATE_CON(0), 5, GFLAGS), + GATE(PCLK_AUDIO_ADC_PMU, "pclk_audio_adc_pmu", "busclk_pmu_root", 0, + RV1126B_PMU1CLKGATE_CON(0), 8, GFLAGS), + + COMPOSITE(MCLK_LPSAI, "mclk_lpsai", mux_24m_rcosc_buspmu_p, 0, + RV1126B_PMU1CLKSEL_CON(0), 6, 2, MFLAGS, 8, 5, DFLAGS, + RV1126B_PMU1CLKGATE_CON(1), 3, GFLAGS), + GATE(MCLK_AUDIO_ADC_PMU, "mclk_audio_adc_pmu", "mclk_lpsai", CLK_IS_CRITICAL, + RV1126B_PMU1CLKGATE_CON(0), 9, GFLAGS), + FACTOR(MCLK_AUDIO_ADC_DIV4_PMU, "mclk_audio_adc_div4_pmu", "mclk_audio_adc_pmu", 0, 1, 4), + + /* pd_bus */ + GATE(ACLK_GIC400, "aclk_gic400", "hclk_bus_root", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(0), 8, GFLAGS), + GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(0), 10, GFLAGS), + GATE(TCLK_WDT_NS, "tclk_wdt_ns", "tclk_wdt_ns_src", 0, + RV1126B_BUSCLKGATE_CON(0), 11, GFLAGS), + GATE(PCLK_WDT_HPMCU, "pclk_wdt_hpmcu", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 0, GFLAGS), + GATE(HCLK_CACHE, "hclk_cache", "aclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 2, GFLAGS), + GATE(PCLK_HPMCU_MAILBOX, "pclk_hpmcu_mailbox", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 3, GFLAGS), + GATE(PCLK_HPMCU_INTMUX, "pclk_hpmcu_intmux", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 4, GFLAGS), + GATE(CLK_HPMCU, "clk_hpmcu", "aclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 5, GFLAGS), + GATE(CLK_HPMCU_RTC, "clk_hpmcu_rtc", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_RKDMA, "pclk_rkdma", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 11, GFLAGS), + GATE(ACLK_RKDMA, "aclk_rkdma", "aclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_DCF, "pclk_dcf", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 0, GFLAGS), + GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 1, GFLAGS), + GATE(HCLK_RGA, "hclk_rga", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 2, GFLAGS), + GATE(ACLK_RGA, "aclk_rga", "aclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 3, GFLAGS), + GATE(CLK_CORE_RGA, "clk_core_rga", "clk_core_rga_src", 0, + RV1126B_BUSCLKGATE_CON(2), 4, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 5, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0, "clk_timer0", clk_timer0_parents_p, 0, + RV1126B_BUSCLKSEL_CON(2), 0, 2, MFLAGS, + RV1126B_BUSCLKGATE_CON(2), 6, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER1, "clk_timer1", clk_timer1_parents_p, 0, + RV1126B_BUSCLKSEL_CON(2), 2, 2, MFLAGS, + RV1126B_BUSCLKGATE_CON(2), 7, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER2, "clk_timer2", clk_timer2_parents_p, 0, + RV1126B_BUSCLKSEL_CON(2), 4, 2, MFLAGS, + RV1126B_BUSCLKGATE_CON(2), 8, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER3, "clk_timer3", clk_timer3_parents_p, 0, + RV1126B_BUSCLKSEL_CON(2), 6, 2, MFLAGS, + RV1126B_BUSCLKGATE_CON(2), 9, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER4, "clk_timer4", clk_timer4_parents_p, 0, + RV1126B_BUSCLKSEL_CON(2), 8, 2, MFLAGS, + RV1126B_BUSCLKGATE_CON(2), 10, GFLAGS), + GATE(HCLK_RKRNG_S_NS, "hclk_rkrng_s_ns", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 14, GFLAGS), + GATE(HCLK_RKRNG_NS, "hclk_rkrng_ns", "hclk_rkrng_s_ns", 0, + RV1126B_BUSCLKGATE_CON(2), 15, GFLAGS), + GATE(CLK_TIMER5, "clk_timer5", "clk_timer_root", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(2), 11, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 0, GFLAGS), + GATE(CLK_I2C0, "clk_i2c0", "clk_i2c_bus_src", 0, + RV1126B_BUSCLKGATE_CON(3), 1, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 2, GFLAGS), + GATE(CLK_I2C1, "clk_i2c1", "clk_i2c_bus_src", 0, + RV1126B_BUSCLKGATE_CON(3), 3, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 4, GFLAGS), + GATE(CLK_I2C3, "clk_i2c3", "clk_i2c_bus_src", 0, + RV1126B_BUSCLKGATE_CON(3), 5, GFLAGS), + GATE(PCLK_I2C4, "pclk_i2c4", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 6, GFLAGS), + GATE(CLK_I2C4, "clk_i2c4", "clk_i2c_bus_src", 0, + RV1126B_BUSCLKGATE_CON(3), 7, GFLAGS), + GATE(PCLK_I2C5, "pclk_i2c5", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 8, GFLAGS), + GATE(CLK_I2C5, "clk_i2c5", "clk_i2c_bus_src", 0, + RV1126B_BUSCLKGATE_CON(3), 9, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 10, GFLAGS), + GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(3), 12, GFLAGS), + GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 0, GFLAGS), + GATE(CLK_OSC_PWM0, "clk_osc_pwm0", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 1, GFLAGS), + GATE(CLK_RC_PWM0, "clk_rc_pwm0", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 2, GFLAGS), + GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 3, GFLAGS), + GATE(CLK_OSC_PWM2, "clk_osc_pwm2", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 4, GFLAGS), + GATE(CLK_RC_PWM2, "clk_rc_pwm2", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 5, GFLAGS), + GATE(PCLK_PWM3, "pclk_pwm3", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 6, GFLAGS), + GATE(CLK_OSC_PWM3, "clk_osc_pwm3", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 7, GFLAGS), + GATE(CLK_RC_PWM3, "clk_rc_pwm3", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(4), 8, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 9, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 10, GFLAGS), + GATE(PCLK_UART3, "pclk_uart3", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 11, GFLAGS), + GATE(PCLK_UART4, "pclk_uart4", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 12, GFLAGS), + GATE(PCLK_UART5, "pclk_uart5", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 13, GFLAGS), + GATE(PCLK_UART6, "pclk_uart6", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 14, GFLAGS), + GATE(PCLK_UART7, "pclk_uart7", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(4), 15, GFLAGS), + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_root", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(5), 0, GFLAGS), + GATE(CLK_TSADC, "clk_tsadc", "xin24m", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(5), 1, GFLAGS), + GATE(HCLK_SAI0, "hclk_sai0", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 2, GFLAGS), + GATE(HCLK_SAI1, "hclk_sai1", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 4, GFLAGS), + GATE(HCLK_SAI2, "hclk_sai2", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 6, GFLAGS), + GATE(HCLK_RKDSM, "hclk_rkdsm", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 8, GFLAGS), + GATE(MCLK_RKDSM, "mclk_rkdsm", "mclk_sai2", 0, + RV1126B_BUSCLKGATE_CON(5), 9, GFLAGS), + GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 10, GFLAGS), + GATE(HCLK_ASRC0, "hclk_asrc0", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 11, GFLAGS), + GATE(HCLK_ASRC1, "hclk_asrc1", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 12, GFLAGS), + GATE(PCLK_AUDIO_ADC_BUS, "pclk_audio_adc_bus", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(5), 13, GFLAGS), + GATE(MCLK_AUDIO_ADC_BUS, "mclk_audio_adc_bus", "mclk_sai2", 0, + RV1126B_BUSCLKGATE_CON(5), 14, GFLAGS), + FACTOR(MCLK_AUDIO_ADC_DIV4_BUS, "mclk_audio_adc_div4_bus", "mclk_audio_adc_bus", 0, 1, 4), + GATE(PCLK_RKCE, "pclk_rkce", "pclk_bus_root", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(6), 0, GFLAGS), + GATE(HCLK_NS_RKCE, "hclk_ns_rkce", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(6), 1, GFLAGS), + GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(6), 2, GFLAGS), + GATE(CLK_SBPI_OTPC_NS, "clk_sbpi_otpc_ns", "xin24m", 0, + RV1126B_BUSCLKGATE_CON(6), 3, GFLAGS), + COMPOSITE_NOMUX(CLK_USER_OTPC_NS, "clk_user_otpc_ns", "xin24m", 0, + RV1126B_BUSCLKSEL_CON(2), 12, 3, DFLAGS, + RV1126B_BUSCLKGATE_CON(6), 4, GFLAGS), + GATE(PCLK_OTP_MASK, "pclk_otp_mask", "pclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(6), 6, GFLAGS), + GATE(CLK_TSADC_PHYCTRL, "clk_tsadc_phyctrl", "xin24m", CLK_IS_CRITICAL, + RV1126B_BUSCLKGATE_CON(6), 8, GFLAGS), + MUX(LRCK_SRC_ASRC0, "lrck_src_asrc0", lrck_src_asrc_p, 0, + RV1126B_BUSCLKSEL_CON(3), 0, 3, MFLAGS), + MUX(LRCK_DST_ASRC0, "lrck_dst_asrc0", lrck_src_asrc_p, 0, + RV1126B_BUSCLKSEL_CON(3), 4, 3, MFLAGS), + MUX(LRCK_SRC_ASRC1, "lrck_src_asrc1", lrck_src_asrc_p, 0, + RV1126B_BUSCLKSEL_CON(3), 8, 3, MFLAGS), + MUX(LRCK_DST_ASRC1, "lrck_dst_asrc1", lrck_src_asrc_p, 0, + RV1126B_BUSCLKSEL_CON(3), 12, 3, MFLAGS), + GATE(ACLK_NSRKCE, "aclk_nsrkce", "aclk_rkce_src", 0, + RV1126B_BUSCLKGATE_CON(2), 12, GFLAGS), + GATE(CLK_PKA_NSRKCE, "clk_pka_nsrkce", "clk_pka_rkce_src", 0, + RV1126B_BUSCLKGATE_CON(2), 13, GFLAGS), + + /* pd_peri */ + DIV(PCLK_RTC_ROOT, "pclk_rtc_root", "pclk_peri_root", 0, + RV1126B_PERICLKSEL_CON(0), 0, 2, DFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(0), 5, GFLAGS), + GATE(DBCLK_GPIO1, "dbclk_gpio1", "xin24m", 0, + RV1126B_PERICLKGATE_CON(0), 6, GFLAGS), + GATE(PCLK_IOC_VCCIO1, "pclk_ioc_vccio1", "pclk_peri_root", CLK_IS_CRITICAL, + RV1126B_PERICLKGATE_CON(0), 7, GFLAGS), + GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(0), 8, GFLAGS), + GATE(CLK_REF_USB3OTG, "clk_ref_usb3otg", "xin24m", 0, + RV1126B_PERICLKGATE_CON(0), 9, GFLAGS), + GATE(CLK_SUSPEND_USB3OTG, "clk_suspend_usb3otg", "xin24m", 0, + RV1126B_PERICLKGATE_CON(0), 10, GFLAGS), + GATE(HCLK_USB2HOST, "hclk_usb2host", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(0), 11, GFLAGS), + GATE(HCLK_ARB_USB2HOST, "hclk_arb_usb2host", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(0), 12, GFLAGS), + GATE(PCLK_RTC_TEST, "pclk_rtc_test", "pclk_rtc_root", 0, + RV1126B_PERICLKGATE_CON(0), 13, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(1), 0, GFLAGS), + GATE(HCLK_FSPI0, "hclk_fspi0", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(1), 1, GFLAGS), + GATE(HCLK_XIP_FSPI0, "hclk_xip_fspi0", "aclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(1), 2, GFLAGS), + GATE(PCLK_PIPEPHY, "pclk_pipephy", "pclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(1), 8, GFLAGS), + GATE(PCLK_USB2PHY, "pclk_usb2phy", "pclk_peri_root", 0, + RV1126B_PERICLKGATE_CON(1), 10, GFLAGS), + COMPOSITE_NOMUX(CLK_REF_PIPEPHY_CPLL_SRC, "clk_ref_pipephy_cpll_src", "cpll", 0, + RV1126B_PERICLKSEL_CON(1), 0, 6, DFLAGS, + RV1126B_PERICLKGATE_CON(1), 14, GFLAGS), + MUX(CLK_REF_PIPEPHY, "clk_ref_pipephy", clk_ref_pipephy_p, 0, + RV1126B_PERICLKSEL_CON(1), 12, 1, MFLAGS), +}; + +static struct rockchip_clk_branch rv1126b_armclk __initdata = + MUX(ARMCLK, "armclk", mux_armclk_p, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + RV1126B_CORECLKSEL_CON(0), 1, 1, MFLAGS); + +static void __init rv1126b_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + unsigned long clk_nr_clks; + + clk_nr_clks = rockchip_clk_find_max_clk_id(rv1126b_clk_branches, + ARRAY_SIZE(rv1126b_clk_branches)) + 1; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, clk_nr_clks); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); + return; + } + + rockchip_clk_register_plls(ctx, rv1126b_pll_clks, + ARRAY_SIZE(rv1126b_pll_clks), + 0); + + rockchip_clk_register_branches(ctx, rv1126b_clk_branches, + ARRAY_SIZE(rv1126b_clk_branches)); + + rockchip_clk_register_armclk_multi_pll(ctx, &rv1126b_armclk, + rv1126b_cpuclk_rates, + ARRAY_SIZE(rv1126b_cpuclk_rates)); + + rv1126b_rst_init(np, reg_base); + + rockchip_register_restart_notifier(ctx, RV1126B_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); + + /* pvtpll src init */ + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1126B_CORECLKSEL_CON(0)); + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1126B_NPUCLKSEL_CON(0)); + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1126B_VICLKSEL_CON(0)); + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1126B_VEPUCLKSEL_CON(0)); + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1126B_VCPCLKSEL_CON(0)); +} + +CLK_OF_DECLARE(rv1126b_cru, "rockchip,rv1126b-cru", rv1126b_clk_init); + +struct clk_rv1126b_inits { + void (*inits)(struct device_node *np); +}; + +static const struct clk_rv1126b_inits clk_rv1126b_init = { + .inits = rv1126b_clk_init, +}; + +static const struct of_device_id clk_rv1126b_match_table[] = { + { + .compatible = "rockchip,rv1126b-cru", + .data = &clk_rv1126b_init, + }, + { } +}; + +static int clk_rv1126b_probe(struct platform_device *pdev) +{ + const struct clk_rv1126b_inits *init_data; + struct device *dev = &pdev->dev; + + init_data = device_get_match_data(dev); + if (!init_data) + return -EINVAL; + + if (init_data->inits) + init_data->inits(dev->of_node); + + return 0; +} + +static struct platform_driver clk_rv1126b_driver = { + .probe = clk_rv1126b_probe, + .driver = { + .name = "clk-rv1126b", + .of_match_table = clk_rv1126b_match_table, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver_probe(clk_rv1126b_driver, clk_rv1126b_probe); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 23653a942403af..87f09320b942be 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -99,6 +99,73 @@ struct clk; #define RV1126_EMMC_CON0 0x450 #define RV1126_EMMC_CON1 0x454 +#define RV1126B_TOPCRU_BASE 0x0 +#define RV1126B_BUSCRU_BASE 0x10000 +#define RV1126B_PERICRU_BASE 0x20000 +#define RV1126B_CORECRU_BASE 0x30000 +#define RV1126B_PMUCRU_BASE 0x40000 +#define RV1126B_PMU1CRU_BASE 0x50000 +#define RV1126B_DDRCRU_BASE 0x60000 +#define RV1126B_SUBDDRCRU_BASE 0x68000 +#define RV1126B_VICRU_BASE 0x70000 +#define RV1126B_VEPUCRU_BASE 0x80000 +#define RV1126B_NPUCRU_BASE 0x90000 +#define RV1126B_VDOCRU_BASE 0xA0000 +#define RV1126B_VCPCRU_BASE 0xB0000 + +#define RV1126B_PLL_CON(x) ((x) * 0x4 + RV1126B_TOPCRU_BASE) +#define RV1126B_MODE_CON (0x280 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_TOPCRU_BASE) +#define RV1126B_SOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_TOPCRU_BASE) +#define RV1126B_GLB_SRST_FST (0xc08 + RV1126B_TOPCRU_BASE) +#define RV1126B_GLB_SRST_SND (0xc0c + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_CM_FRAC0_DIV_H (0xcc0 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_CM_FRAC1_DIV_H (0xcc4 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_CM_FRAC2_DIV_H (0xcc8 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_UART_FRAC0_DIV_H (0xccc + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_UART_FRAC1_DIV_H (0xcd0 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_AUDIO_FRAC0_DIV_H (0xcd4 + RV1126B_TOPCRU_BASE) +#define RV1126B_CLK_AUDIO_FRAC1_DIV_H (0xcd8 + RV1126B_TOPCRU_BASE) +#define RV1126B_BUSCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_BUSCRU_BASE) +#define RV1126B_BUSCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_BUSCRU_BASE) +#define RV1126B_BUSSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_BUSCRU_BASE) +#define RV1126B_PERIPLL_CON(x) ((x) * 0x4 + RV1126B_PERICRU_BASE) +#define RV1126B_PERICLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_PERICRU_BASE) +#define RV1126B_PERICLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_PERICRU_BASE) +#define RV1126B_PERISOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_PERICRU_BASE) +#define RV1126B_CORECLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_CORECRU_BASE) +#define RV1126B_CORECLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_CORECRU_BASE) +#define RV1126B_CORESOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_CORECRU_BASE) +#define RV1126B_PMUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_PMUCRU_BASE) +#define RV1126B_PMUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_PMUCRU_BASE) +#define RV1126B_PMUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_PMUCRU_BASE) +#define RV1126B_PMU1CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_PMU1CRU_BASE) +#define RV1126B_PMU1CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_PMU1CRU_BASE) +#define RV1126B_PMU1SOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_PMU1CRU_BASE) +#define RV1126B_DDRCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_DDRCRU_BASE) +#define RV1126B_DDRCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_DDRCRU_BASE) +#define RV1126B_DDRSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_DDRCRU_BASE) +#define RV1126B_SUBDDRPLL_CON(x) ((x) * 0x4 + RV1126B_SUBDDRCRU_BASE) +#define RV1126B_SUBDDRCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_SUBDDRCRU_BASE) +#define RV1126B_SUBDDRCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_SUBDDRCRU_BASE) +#define RV1126B_SUBDDRSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_SUBDDRCRU_BASE) +#define RV1126B_VICLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_VICRU_BASE) +#define RV1126B_VICLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_VICRU_BASE) +#define RV1126B_VISOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_VICRU_BASE) +#define RV1126B_VEPUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_VEPUCRU_BASE) +#define RV1126B_VEPUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_VEPUCRU_BASE) +#define RV1126B_VEPUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_VEPUCRU_BASE) +#define RV1126B_NPUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_NPUCRU_BASE) +#define RV1126B_NPUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_NPUCRU_BASE) +#define RV1126B_NPUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_NPUCRU_BASE) +#define RV1126B_VDOCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_VDOCRU_BASE) +#define RV1126B_VDOCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_VDOCRU_BASE) +#define RV1126B_VDOSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_VDOCRU_BASE) +#define RV1126B_VCPCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1126B_VCPCRU_BASE) +#define RV1126B_VCPCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1126B_VCPCRU_BASE) +#define RV1126B_VCPSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1126B_VCPCRU_BASE) + #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) @@ -1261,6 +1328,7 @@ static inline void rockchip_register_softrst(struct device_node *np, return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags); } +void rv1126b_rst_init(struct device_node *np, void __iomem *reg_base); void rk3528_rst_init(struct device_node *np, void __iomem *reg_base); void rk3562_rst_init(struct device_node *np, void __iomem *reg_base); void rk3576_rst_init(struct device_node *np, void __iomem *reg_base); diff --git a/drivers/clk/rockchip/rst-rv1126b.c b/drivers/clk/rockchip/rst-rv1126b.c new file mode 100644 index 00000000000000..c75b0d885ca235 --- /dev/null +++ b/drivers/clk/rockchip/rst-rv1126b.c @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * Author: Elaine Zhang + */ + +#include +#include +#include +#include "clk.h" + +/* 0x20000000 + 0x0A00 */ +#define TOPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x0 * 4 + reg * 16 + bit) +/* 0x20010000 + 0x0A00 */ +#define BUSCRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000 * 4 + reg * 16 + bit) +/* 0x20020000 + 0x0A00 */ +#define PERICRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000 * 4 + reg * 16 + bit) +/* 0x20030000 + 0x0A00 */ +#define CORECRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000 * 4 + reg * 16 + bit) +/* 0x20040000 + 0x0A00 */ +#define PMUCRU_RESET_OFFSET(id, reg, bit) [id] = (0x40000 * 4 + reg * 16 + bit) +/* 0x20050000 + 0x0A00 */ +#define PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x50000 * 4 + reg * 16 + bit) +/* 0x20060000 + 0x0A00 */ +#define DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x60000 * 4 + reg * 16 + bit) +/* 0x20068000 + 0x0A00 */ +#define SUBDDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x68000 * 4 + reg * 16 + bit) +/* 0x20070000 + 0x0A00 */ +#define VICRU_RESET_OFFSET(id, reg, bit) [id] = (0x70000 * 4 + reg * 16 + bit) +/* 0x20080000 + 0x0A00 */ +#define VEPUCRU_RESET_OFFSET(id, reg, bit) [id] = (0x80000 * 4 + reg * 16 + bit) +/* 0x20090000 + 0x0A00 */ +#define NPUCRU_RESET_OFFSET(id, reg, bit) [id] = (0x90000 * 4 + reg * 16 + bit) +/* 0x200A0000 + 0x0A00 */ +#define VDOCRU_RESET_OFFSET(id, reg, bit) [id] = (0xA0000 * 4 + reg * 16 + bit) +/* 0x200B0000 + 0x0A00 */ +#define VCPCRU_RESET_OFFSET(id, reg, bit) [id] = (0xB0000 * 4 + reg * 16 + bit) + +/* =================mapping table for reset ID to register offset================== */ +static const int rv1126b_register_offset[] = { + /* TOPCRU-->SOFTRST_CON00 */ + + /* TOPCRU-->SOFTRST_CON15 */ + TOPCRU_RESET_OFFSET(SRST_P_CRU, 15, 1), + TOPCRU_RESET_OFFSET(SRST_P_CRU_BIU, 15, 2), + + /* BUSCRU-->SOFTRST_CON00 */ + BUSCRU_RESET_OFFSET(SRST_A_TOP_BIU, 0, 0), + BUSCRU_RESET_OFFSET(SRST_A_RKCE_BIU, 0, 1), + BUSCRU_RESET_OFFSET(SRST_A_BUS_BIU, 0, 2), + BUSCRU_RESET_OFFSET(SRST_H_BUS_BIU, 0, 3), + BUSCRU_RESET_OFFSET(SRST_P_BUS_BIU, 0, 4), + BUSCRU_RESET_OFFSET(SRST_P_CRU_BUS, 0, 5), + BUSCRU_RESET_OFFSET(SRST_P_SYS_GRF, 0, 6), + BUSCRU_RESET_OFFSET(SRST_H_BOOTROM, 0, 7), + BUSCRU_RESET_OFFSET(SRST_A_GIC400, 0, 8), + BUSCRU_RESET_OFFSET(SRST_A_SPINLOCK, 0, 9), + BUSCRU_RESET_OFFSET(SRST_P_WDT_NS, 0, 10), + BUSCRU_RESET_OFFSET(SRST_T_WDT_NS, 0, 11), + + /* BUSCRU-->SOFTRST_CON01 */ + BUSCRU_RESET_OFFSET(SRST_P_WDT_HPMCU, 1, 0), + BUSCRU_RESET_OFFSET(SRST_T_WDT_HPMCU, 1, 1), + BUSCRU_RESET_OFFSET(SRST_H_CACHE, 1, 2), + BUSCRU_RESET_OFFSET(SRST_P_HPMCU_MAILBOX, 1, 3), + BUSCRU_RESET_OFFSET(SRST_P_HPMCU_INTMUX, 1, 4), + BUSCRU_RESET_OFFSET(SRST_HPMCU_FULL_CLUSTER, 1, 5), + BUSCRU_RESET_OFFSET(SRST_HPMCU_PWUP, 1, 6), + BUSCRU_RESET_OFFSET(SRST_HPMCU_ONLY_CORE, 1, 7), + BUSCRU_RESET_OFFSET(SRST_T_HPMCU_JTAG, 1, 8), + BUSCRU_RESET_OFFSET(SRST_P_RKDMA, 1, 11), + BUSCRU_RESET_OFFSET(SRST_A_RKDMA, 1, 12), + + /* BUSCRU-->SOFTRST_CON02 */ + BUSCRU_RESET_OFFSET(SRST_P_DCF, 2, 0), + BUSCRU_RESET_OFFSET(SRST_A_DCF, 2, 1), + BUSCRU_RESET_OFFSET(SRST_H_RGA, 2, 2), + BUSCRU_RESET_OFFSET(SRST_A_RGA, 2, 3), + BUSCRU_RESET_OFFSET(SRST_CORE_RGA, 2, 4), + BUSCRU_RESET_OFFSET(SRST_P_TIMER, 2, 5), + BUSCRU_RESET_OFFSET(SRST_TIMER0, 2, 6), + BUSCRU_RESET_OFFSET(SRST_TIMER1, 2, 7), + BUSCRU_RESET_OFFSET(SRST_TIMER2, 2, 8), + BUSCRU_RESET_OFFSET(SRST_TIMER3, 2, 9), + BUSCRU_RESET_OFFSET(SRST_TIMER4, 2, 10), + BUSCRU_RESET_OFFSET(SRST_TIMER5, 2, 11), + BUSCRU_RESET_OFFSET(SRST_A_RKCE, 2, 12), + BUSCRU_RESET_OFFSET(SRST_PKA_RKCE, 2, 13), + BUSCRU_RESET_OFFSET(SRST_H_RKRNG_S, 2, 14), + BUSCRU_RESET_OFFSET(SRST_H_RKRNG_NS, 2, 15), + + /* BUSCRU-->SOFTRST_CON03 */ + BUSCRU_RESET_OFFSET(SRST_P_I2C0, 3, 0), + BUSCRU_RESET_OFFSET(SRST_I2C0, 3, 1), + BUSCRU_RESET_OFFSET(SRST_P_I2C1, 3, 2), + BUSCRU_RESET_OFFSET(SRST_I2C1, 3, 3), + BUSCRU_RESET_OFFSET(SRST_P_I2C3, 3, 4), + BUSCRU_RESET_OFFSET(SRST_I2C3, 3, 5), + BUSCRU_RESET_OFFSET(SRST_P_I2C4, 3, 6), + BUSCRU_RESET_OFFSET(SRST_I2C4, 3, 7), + BUSCRU_RESET_OFFSET(SRST_P_I2C5, 3, 8), + BUSCRU_RESET_OFFSET(SRST_I2C5, 3, 9), + BUSCRU_RESET_OFFSET(SRST_P_SPI0, 3, 10), + BUSCRU_RESET_OFFSET(SRST_SPI0, 3, 11), + BUSCRU_RESET_OFFSET(SRST_P_SPI1, 3, 12), + BUSCRU_RESET_OFFSET(SRST_SPI1, 3, 13), + + /* BUSCRU-->SOFTRST_CON04 */ + BUSCRU_RESET_OFFSET(SRST_P_PWM0, 4, 0), + BUSCRU_RESET_OFFSET(SRST_PWM0, 4, 1), + BUSCRU_RESET_OFFSET(SRST_P_PWM2, 4, 4), + BUSCRU_RESET_OFFSET(SRST_PWM2, 4, 5), + BUSCRU_RESET_OFFSET(SRST_P_PWM3, 4, 8), + BUSCRU_RESET_OFFSET(SRST_PWM3, 4, 9), + + /* BUSCRU-->SOFTRST_CON05 */ + BUSCRU_RESET_OFFSET(SRST_P_UART1, 5, 0), + BUSCRU_RESET_OFFSET(SRST_S_UART1, 5, 1), + BUSCRU_RESET_OFFSET(SRST_P_UART2, 5, 2), + BUSCRU_RESET_OFFSET(SRST_S_UART2, 5, 3), + BUSCRU_RESET_OFFSET(SRST_P_UART3, 5, 4), + BUSCRU_RESET_OFFSET(SRST_S_UART3, 5, 5), + BUSCRU_RESET_OFFSET(SRST_P_UART4, 5, 6), + BUSCRU_RESET_OFFSET(SRST_S_UART4, 5, 7), + BUSCRU_RESET_OFFSET(SRST_P_UART5, 5, 8), + BUSCRU_RESET_OFFSET(SRST_S_UART5, 5, 9), + BUSCRU_RESET_OFFSET(SRST_P_UART6, 5, 10), + BUSCRU_RESET_OFFSET(SRST_S_UART6, 5, 11), + BUSCRU_RESET_OFFSET(SRST_P_UART7, 5, 12), + BUSCRU_RESET_OFFSET(SRST_S_UART7, 5, 13), + + /* BUSCRU-->SOFTRST_CON06 */ + BUSCRU_RESET_OFFSET(SRST_P_TSADC, 6, 0), + BUSCRU_RESET_OFFSET(SRST_TSADC, 6, 1), + BUSCRU_RESET_OFFSET(SRST_H_SAI0, 6, 2), + BUSCRU_RESET_OFFSET(SRST_M_SAI0, 6, 3), + BUSCRU_RESET_OFFSET(SRST_H_SAI1, 6, 4), + BUSCRU_RESET_OFFSET(SRST_M_SAI1, 6, 5), + BUSCRU_RESET_OFFSET(SRST_H_SAI2, 6, 6), + BUSCRU_RESET_OFFSET(SRST_M_SAI2, 6, 7), + BUSCRU_RESET_OFFSET(SRST_H_RKDSM, 6, 8), + BUSCRU_RESET_OFFSET(SRST_M_RKDSM, 6, 9), + BUSCRU_RESET_OFFSET(SRST_H_PDM, 6, 10), + BUSCRU_RESET_OFFSET(SRST_M_PDM, 6, 11), + BUSCRU_RESET_OFFSET(SRST_PDM, 6, 12), + + /* BUSCRU-->SOFTRST_CON07 */ + BUSCRU_RESET_OFFSET(SRST_H_ASRC0, 7, 0), + BUSCRU_RESET_OFFSET(SRST_ASRC0, 7, 1), + BUSCRU_RESET_OFFSET(SRST_H_ASRC1, 7, 2), + BUSCRU_RESET_OFFSET(SRST_ASRC1, 7, 3), + BUSCRU_RESET_OFFSET(SRST_P_AUDIO_ADC_BUS, 7, 4), + BUSCRU_RESET_OFFSET(SRST_M_AUDIO_ADC_BUS, 7, 5), + BUSCRU_RESET_OFFSET(SRST_P_RKCE, 7, 6), + BUSCRU_RESET_OFFSET(SRST_H_NS_RKCE, 7, 7), + BUSCRU_RESET_OFFSET(SRST_P_OTPC_NS, 7, 8), + BUSCRU_RESET_OFFSET(SRST_SBPI_OTPC_NS, 7, 9), + BUSCRU_RESET_OFFSET(SRST_USER_OTPC_NS, 7, 10), + BUSCRU_RESET_OFFSET(SRST_OTPC_ARB, 7, 11), + BUSCRU_RESET_OFFSET(SRST_P_OTP_MASK, 7, 12), + + /* PERICRU-->SOFTRST_CON00 */ + PERICRU_RESET_OFFSET(SRST_A_PERI_BIU, 0, 0), + PERICRU_RESET_OFFSET(SRST_P_PERI_BIU, 0, 1), + PERICRU_RESET_OFFSET(SRST_P_RTC_BIU, 0, 2), + PERICRU_RESET_OFFSET(SRST_P_CRU_PERI, 0, 3), + PERICRU_RESET_OFFSET(SRST_P_PERI_GRF, 0, 4), + PERICRU_RESET_OFFSET(SRST_P_GPIO1, 0, 5), + PERICRU_RESET_OFFSET(SRST_DB_GPIO1, 0, 6), + PERICRU_RESET_OFFSET(SRST_P_IOC_VCCIO1, 0, 7), + PERICRU_RESET_OFFSET(SRST_A_USB3OTG, 0, 8), + PERICRU_RESET_OFFSET(SRST_H_USB2HOST, 0, 11), + PERICRU_RESET_OFFSET(SRST_H_ARB_USB2HOST, 0, 12), + PERICRU_RESET_OFFSET(SRST_P_RTC_TEST, 0, 13), + + /* PERICRU-->SOFTRST_CON01 */ + PERICRU_RESET_OFFSET(SRST_H_EMMC, 1, 0), + PERICRU_RESET_OFFSET(SRST_H_FSPI0, 1, 1), + PERICRU_RESET_OFFSET(SRST_H_XIP_FSPI0, 1, 2), + PERICRU_RESET_OFFSET(SRST_S_2X_FSPI0, 1, 3), + PERICRU_RESET_OFFSET(SRST_UTMI_USB2HOST, 1, 5), + PERICRU_RESET_OFFSET(SRST_REF_PIPEPHY, 1, 7), + PERICRU_RESET_OFFSET(SRST_P_PIPEPHY, 1, 8), + PERICRU_RESET_OFFSET(SRST_P_PIPEPHY_GRF, 1, 9), + PERICRU_RESET_OFFSET(SRST_P_USB2PHY, 1, 10), + PERICRU_RESET_OFFSET(SRST_POR_USB2PHY, 1, 11), + PERICRU_RESET_OFFSET(SRST_OTG_USB2PHY, 1, 12), + PERICRU_RESET_OFFSET(SRST_HOST_USB2PHY, 1, 13), + + /* CORECRU-->SOFTRST_CON00 */ + CORECRU_RESET_OFFSET(SRST_REF_PVTPLL_CORE, 0, 0), + CORECRU_RESET_OFFSET(SRST_NCOREPORESET0, 0, 1), + CORECRU_RESET_OFFSET(SRST_NCORESET0, 0, 2), + CORECRU_RESET_OFFSET(SRST_NCOREPORESET1, 0, 3), + CORECRU_RESET_OFFSET(SRST_NCORESET1, 0, 4), + CORECRU_RESET_OFFSET(SRST_NCOREPORESET2, 0, 5), + CORECRU_RESET_OFFSET(SRST_NCORESET2, 0, 6), + CORECRU_RESET_OFFSET(SRST_NCOREPORESET3, 0, 7), + CORECRU_RESET_OFFSET(SRST_NCORESET3, 0, 8), + CORECRU_RESET_OFFSET(SRST_NDBGRESET, 0, 9), + CORECRU_RESET_OFFSET(SRST_NL2RESET, 0, 10), + + /* CORECRU-->SOFTRST_CON01 */ + CORECRU_RESET_OFFSET(SRST_A_CORE_BIU, 1, 0), + CORECRU_RESET_OFFSET(SRST_P_CORE_BIU, 1, 1), + CORECRU_RESET_OFFSET(SRST_H_CORE_BIU, 1, 2), + CORECRU_RESET_OFFSET(SRST_P_DBG, 1, 3), + CORECRU_RESET_OFFSET(SRST_POT_DBG, 1, 4), + CORECRU_RESET_OFFSET(SRST_NT_DBG, 1, 5), + CORECRU_RESET_OFFSET(SRST_P_CORE_PVTPLL, 1, 6), + CORECRU_RESET_OFFSET(SRST_P_CRU_CORE, 1, 7), + CORECRU_RESET_OFFSET(SRST_P_CORE_GRF, 1, 8), + CORECRU_RESET_OFFSET(SRST_P_DFT2APB, 1, 10), + + /* PMUCRU-->SOFTRST_CON00 */ + PMUCRU_RESET_OFFSET(SRST_H_PMU_BIU, 0, 0), + PMUCRU_RESET_OFFSET(SRST_P_PMU_GPIO0, 0, 7), + PMUCRU_RESET_OFFSET(SRST_DB_PMU_GPIO0, 0, 8), + PMUCRU_RESET_OFFSET(SRST_P_PMU_HP_TIMER, 0, 10), + PMUCRU_RESET_OFFSET(SRST_PMU_HP_TIMER, 0, 11), + PMUCRU_RESET_OFFSET(SRST_PMU_32K_HP_TIMER, 0, 12), + + /* PMUCRU-->SOFTRST_CON01 */ + PMUCRU_RESET_OFFSET(SRST_P_PWM1, 1, 0), + PMUCRU_RESET_OFFSET(SRST_PWM1, 1, 1), + PMUCRU_RESET_OFFSET(SRST_P_I2C2, 1, 2), + PMUCRU_RESET_OFFSET(SRST_I2C2, 1, 3), + PMUCRU_RESET_OFFSET(SRST_P_UART0, 1, 4), + PMUCRU_RESET_OFFSET(SRST_S_UART0, 1, 5), + + /* PMUCRU-->SOFTRST_CON02 */ + PMUCRU_RESET_OFFSET(SRST_P_RCOSC_CTRL, 2, 0), + PMUCRU_RESET_OFFSET(SRST_REF_RCOSC_CTRL, 2, 2), + PMUCRU_RESET_OFFSET(SRST_P_IOC_PMUIO0, 2, 3), + PMUCRU_RESET_OFFSET(SRST_P_CRU_PMU, 2, 4), + PMUCRU_RESET_OFFSET(SRST_P_PMU_GRF, 2, 5), + PMUCRU_RESET_OFFSET(SRST_PREROLL, 2, 7), + PMUCRU_RESET_OFFSET(SRST_PREROLL_32K, 2, 8), + PMUCRU_RESET_OFFSET(SRST_H_PMU_SRAM, 2, 9), + + /* PMUCRU-->SOFTRST_CON03 */ + PMUCRU_RESET_OFFSET(SRST_P_WDT_LPMCU, 3, 0), + PMUCRU_RESET_OFFSET(SRST_T_WDT_LPMCU, 3, 1), + PMUCRU_RESET_OFFSET(SRST_LPMCU_FULL_CLUSTER, 3, 2), + PMUCRU_RESET_OFFSET(SRST_LPMCU_PWUP, 3, 3), + PMUCRU_RESET_OFFSET(SRST_LPMCU_ONLY_CORE, 3, 4), + PMUCRU_RESET_OFFSET(SRST_T_LPMCU_JTAG, 3, 5), + PMUCRU_RESET_OFFSET(SRST_P_LPMCU_MAILBOX, 3, 6), + + /* PMU1CRU-->SOFTRST_CON00 */ + PMU1CRU_RESET_OFFSET(SRST_P_SPI2AHB, 0, 0), + PMU1CRU_RESET_OFFSET(SRST_H_SPI2AHB, 0, 1), + PMU1CRU_RESET_OFFSET(SRST_H_FSPI1, 0, 2), + PMU1CRU_RESET_OFFSET(SRST_H_XIP_FSPI1, 0, 3), + PMU1CRU_RESET_OFFSET(SRST_S_1X_FSPI1, 0, 4), + PMU1CRU_RESET_OFFSET(SRST_P_IOC_PMUIO1, 0, 5), + PMU1CRU_RESET_OFFSET(SRST_P_CRU_PMU1, 0, 6), + PMU1CRU_RESET_OFFSET(SRST_P_AUDIO_ADC_PMU, 0, 7), + PMU1CRU_RESET_OFFSET(SRST_M_AUDIO_ADC_PMU, 0, 8), + PMU1CRU_RESET_OFFSET(SRST_H_PMU1_BIU, 0, 9), + + /* PMU1CRU-->SOFTRST_CON01 */ + PMU1CRU_RESET_OFFSET(SRST_P_LPDMA, 1, 0), + PMU1CRU_RESET_OFFSET(SRST_A_LPDMA, 1, 1), + PMU1CRU_RESET_OFFSET(SRST_H_LPSAI, 1, 2), + PMU1CRU_RESET_OFFSET(SRST_M_LPSAI, 1, 3), + PMU1CRU_RESET_OFFSET(SRST_P_AOA_TDD, 1, 4), + PMU1CRU_RESET_OFFSET(SRST_P_AOA_FE, 1, 5), + PMU1CRU_RESET_OFFSET(SRST_P_AOA_AAD, 1, 6), + PMU1CRU_RESET_OFFSET(SRST_P_AOA_APB, 1, 7), + PMU1CRU_RESET_OFFSET(SRST_P_AOA_SRAM, 1, 8), + + /* DDRCRU-->SOFTRST_CON00 */ + DDRCRU_RESET_OFFSET(SRST_P_DDR_BIU, 0, 1), + DDRCRU_RESET_OFFSET(SRST_P_DDRC, 0, 2), + DDRCRU_RESET_OFFSET(SRST_P_DDRMON, 0, 3), + DDRCRU_RESET_OFFSET(SRST_TIMER_DDRMON, 0, 4), + DDRCRU_RESET_OFFSET(SRST_P_DFICTRL, 0, 5), + DDRCRU_RESET_OFFSET(SRST_P_DDR_GRF, 0, 6), + DDRCRU_RESET_OFFSET(SRST_P_CRU_DDR, 0, 7), + DDRCRU_RESET_OFFSET(SRST_P_DDRPHY, 0, 8), + DDRCRU_RESET_OFFSET(SRST_P_DMA2DDR, 0, 9), + + /* SUBDDRCRU-->SOFTRST_CON00 */ + SUBDDRCRU_RESET_OFFSET(SRST_A_SYSMEM_BIU, 0, 0), + SUBDDRCRU_RESET_OFFSET(SRST_A_SYSMEM, 0, 1), + SUBDDRCRU_RESET_OFFSET(SRST_A_DDR_BIU, 0, 2), + SUBDDRCRU_RESET_OFFSET(SRST_A_DDRSCH0_CPU, 0, 3), + SUBDDRCRU_RESET_OFFSET(SRST_A_DDRSCH1_NPU, 0, 4), + SUBDDRCRU_RESET_OFFSET(SRST_A_DDRSCH2_POE, 0, 5), + SUBDDRCRU_RESET_OFFSET(SRST_A_DDRSCH3_VI, 0, 6), + SUBDDRCRU_RESET_OFFSET(SRST_CORE_DDRC, 0, 7), + SUBDDRCRU_RESET_OFFSET(SRST_DDRMON, 0, 8), + SUBDDRCRU_RESET_OFFSET(SRST_DFICTRL, 0, 9), + SUBDDRCRU_RESET_OFFSET(SRST_RS, 0, 11), + SUBDDRCRU_RESET_OFFSET(SRST_A_DMA2DDR, 0, 12), + SUBDDRCRU_RESET_OFFSET(SRST_DDRPHY, 0, 13), + + /* VICRU-->SOFTRST_CON00 */ + VICRU_RESET_OFFSET(SRST_REF_PVTPLL_ISP, 0, 0), + VICRU_RESET_OFFSET(SRST_A_GMAC_BIU, 0, 1), + VICRU_RESET_OFFSET(SRST_A_VI_BIU, 0, 2), + VICRU_RESET_OFFSET(SRST_H_VI_BIU, 0, 3), + VICRU_RESET_OFFSET(SRST_P_VI_BIU, 0, 4), + VICRU_RESET_OFFSET(SRST_P_CRU_VI, 0, 5), + VICRU_RESET_OFFSET(SRST_P_VI_GRF, 0, 6), + VICRU_RESET_OFFSET(SRST_P_VI_PVTPLL, 0, 7), + VICRU_RESET_OFFSET(SRST_P_DSMC, 0, 8), + VICRU_RESET_OFFSET(SRST_A_DSMC, 0, 9), + VICRU_RESET_OFFSET(SRST_H_CAN0, 0, 10), + VICRU_RESET_OFFSET(SRST_CAN0, 0, 11), + VICRU_RESET_OFFSET(SRST_H_CAN1, 0, 12), + VICRU_RESET_OFFSET(SRST_CAN1, 0, 13), + + /* VICRU-->SOFTRST_CON01 */ + VICRU_RESET_OFFSET(SRST_P_GPIO2, 1, 0), + VICRU_RESET_OFFSET(SRST_DB_GPIO2, 1, 1), + VICRU_RESET_OFFSET(SRST_P_GPIO4, 1, 2), + VICRU_RESET_OFFSET(SRST_DB_GPIO4, 1, 3), + VICRU_RESET_OFFSET(SRST_P_GPIO5, 1, 4), + VICRU_RESET_OFFSET(SRST_DB_GPIO5, 1, 5), + VICRU_RESET_OFFSET(SRST_P_GPIO6, 1, 6), + VICRU_RESET_OFFSET(SRST_DB_GPIO6, 1, 7), + VICRU_RESET_OFFSET(SRST_P_GPIO7, 1, 8), + VICRU_RESET_OFFSET(SRST_DB_GPIO7, 1, 9), + VICRU_RESET_OFFSET(SRST_P_IOC_VCCIO2, 1, 10), + VICRU_RESET_OFFSET(SRST_P_IOC_VCCIO4, 1, 11), + VICRU_RESET_OFFSET(SRST_P_IOC_VCCIO5, 1, 12), + VICRU_RESET_OFFSET(SRST_P_IOC_VCCIO6, 1, 13), + VICRU_RESET_OFFSET(SRST_P_IOC_VCCIO7, 1, 14), + + /* VICRU-->SOFTRST_CON02 */ + VICRU_RESET_OFFSET(SRST_CORE_ISP, 2, 0), + VICRU_RESET_OFFSET(SRST_H_VICAP, 2, 1), + VICRU_RESET_OFFSET(SRST_A_VICAP, 2, 2), + VICRU_RESET_OFFSET(SRST_D_VICAP, 2, 3), + VICRU_RESET_OFFSET(SRST_ISP0_VICAP, 2, 4), + VICRU_RESET_OFFSET(SRST_CORE_VPSS, 2, 5), + VICRU_RESET_OFFSET(SRST_CORE_VPSL, 2, 6), + VICRU_RESET_OFFSET(SRST_P_CSI2HOST0, 2, 7), + VICRU_RESET_OFFSET(SRST_P_CSI2HOST1, 2, 8), + VICRU_RESET_OFFSET(SRST_P_CSI2HOST2, 2, 9), + VICRU_RESET_OFFSET(SRST_P_CSI2HOST3, 2, 10), + VICRU_RESET_OFFSET(SRST_H_SDMMC0, 2, 11), + VICRU_RESET_OFFSET(SRST_A_GMAC, 2, 12), + VICRU_RESET_OFFSET(SRST_P_CSIPHY0, 2, 13), + VICRU_RESET_OFFSET(SRST_P_CSIPHY1, 2, 14), + + /* VICRU-->SOFTRST_CON03 */ + VICRU_RESET_OFFSET(SRST_P_MACPHY, 3, 0), + VICRU_RESET_OFFSET(SRST_MACPHY, 3, 1), + VICRU_RESET_OFFSET(SRST_P_SARADC1, 3, 2), + VICRU_RESET_OFFSET(SRST_SARADC1, 3, 3), + VICRU_RESET_OFFSET(SRST_P_SARADC2, 3, 5), + VICRU_RESET_OFFSET(SRST_SARADC2, 3, 6), + + /* VEPUCRU-->SOFTRST_CON00 */ + VEPUCRU_RESET_OFFSET(SRST_REF_PVTPLL_VEPU, 0, 0), + VEPUCRU_RESET_OFFSET(SRST_A_VEPU_BIU, 0, 1), + VEPUCRU_RESET_OFFSET(SRST_H_VEPU_BIU, 0, 2), + VEPUCRU_RESET_OFFSET(SRST_P_VEPU_BIU, 0, 3), + VEPUCRU_RESET_OFFSET(SRST_P_CRU_VEPU, 0, 4), + VEPUCRU_RESET_OFFSET(SRST_P_VEPU_GRF, 0, 5), + VEPUCRU_RESET_OFFSET(SRST_P_GPIO3, 0, 7), + VEPUCRU_RESET_OFFSET(SRST_DB_GPIO3, 0, 8), + VEPUCRU_RESET_OFFSET(SRST_P_IOC_VCCIO3, 0, 9), + VEPUCRU_RESET_OFFSET(SRST_P_SARADC0, 0, 10), + VEPUCRU_RESET_OFFSET(SRST_SARADC0, 0, 11), + VEPUCRU_RESET_OFFSET(SRST_H_SDMMC1, 0, 13), + + /* VEPUCRU-->SOFTRST_CON01 */ + VEPUCRU_RESET_OFFSET(SRST_P_VEPU_PVTPLL, 1, 0), + VEPUCRU_RESET_OFFSET(SRST_H_VEPU, 1, 1), + VEPUCRU_RESET_OFFSET(SRST_A_VEPU, 1, 2), + VEPUCRU_RESET_OFFSET(SRST_CORE_VEPU, 1, 3), + + /* NPUCRU-->SOFTRST_CON00 */ + NPUCRU_RESET_OFFSET(SRST_REF_PVTPLL_NPU, 0, 0), + NPUCRU_RESET_OFFSET(SRST_A_NPU_BIU, 0, 2), + NPUCRU_RESET_OFFSET(SRST_H_NPU_BIU, 0, 3), + NPUCRU_RESET_OFFSET(SRST_P_NPU_BIU, 0, 4), + NPUCRU_RESET_OFFSET(SRST_P_CRU_NPU, 0, 5), + NPUCRU_RESET_OFFSET(SRST_P_NPU_GRF, 0, 6), + NPUCRU_RESET_OFFSET(SRST_P_NPU_PVTPLL, 0, 8), + NPUCRU_RESET_OFFSET(SRST_H_RKNN, 0, 9), + NPUCRU_RESET_OFFSET(SRST_A_RKNN, 0, 10), + + /* VDOCRU-->SOFTRST_CON00 */ + VDOCRU_RESET_OFFSET(SRST_A_RKVDEC_BIU, 0, 0), + VDOCRU_RESET_OFFSET(SRST_A_VDO_BIU, 0, 1), + VDOCRU_RESET_OFFSET(SRST_H_VDO_BIU, 0, 3), + VDOCRU_RESET_OFFSET(SRST_P_VDO_BIU, 0, 4), + VDOCRU_RESET_OFFSET(SRST_P_CRU_VDO, 0, 5), + VDOCRU_RESET_OFFSET(SRST_P_VDO_GRF, 0, 6), + VDOCRU_RESET_OFFSET(SRST_A_RKVDEC, 0, 7), + VDOCRU_RESET_OFFSET(SRST_H_RKVDEC, 0, 8), + VDOCRU_RESET_OFFSET(SRST_HEVC_CA_RKVDEC, 0, 9), + VDOCRU_RESET_OFFSET(SRST_A_VOP, 0, 10), + VDOCRU_RESET_OFFSET(SRST_H_VOP, 0, 11), + VDOCRU_RESET_OFFSET(SRST_D_VOP, 0, 12), + VDOCRU_RESET_OFFSET(SRST_A_OOC, 0, 13), + VDOCRU_RESET_OFFSET(SRST_H_OOC, 0, 14), + VDOCRU_RESET_OFFSET(SRST_D_OOC, 0, 15), + + /* VDOCRU-->SOFTRST_CON01 */ + VDOCRU_RESET_OFFSET(SRST_H_RKJPEG, 1, 3), + VDOCRU_RESET_OFFSET(SRST_A_RKJPEG, 1, 4), + VDOCRU_RESET_OFFSET(SRST_A_RKMMU_DECOM, 1, 5), + VDOCRU_RESET_OFFSET(SRST_H_RKMMU_DECOM, 1, 6), + VDOCRU_RESET_OFFSET(SRST_D_DECOM, 1, 8), + VDOCRU_RESET_OFFSET(SRST_A_DECOM, 1, 9), + VDOCRU_RESET_OFFSET(SRST_P_DECOM, 1, 10), + VDOCRU_RESET_OFFSET(SRST_P_MIPI_DSI, 1, 12), + VDOCRU_RESET_OFFSET(SRST_P_DSIPHY, 1, 13), + + /* VCPCRU-->SOFTRST_CON00 */ + VCPCRU_RESET_OFFSET(SRST_REF_PVTPLL_VCP, 0, 0), + VCPCRU_RESET_OFFSET(SRST_A_VCP_BIU, 0, 1), + VCPCRU_RESET_OFFSET(SRST_H_VCP_BIU, 0, 2), + VCPCRU_RESET_OFFSET(SRST_P_VCP_BIU, 0, 3), + VCPCRU_RESET_OFFSET(SRST_P_CRU_VCP, 0, 4), + VCPCRU_RESET_OFFSET(SRST_P_VCP_GRF, 0, 5), + VCPCRU_RESET_OFFSET(SRST_P_VCP_PVTPLL, 0, 7), + VCPCRU_RESET_OFFSET(SRST_A_AISP_BIU, 0, 8), + VCPCRU_RESET_OFFSET(SRST_H_AISP_BIU, 0, 9), + VCPCRU_RESET_OFFSET(SRST_CORE_AISP, 0, 13), + + /* VCPCRU-->SOFTRST_CON01 */ + VCPCRU_RESET_OFFSET(SRST_H_FEC, 1, 0), + VCPCRU_RESET_OFFSET(SRST_A_FEC, 1, 1), + VCPCRU_RESET_OFFSET(SRST_CORE_FEC, 1, 2), + VCPCRU_RESET_OFFSET(SRST_H_AVSP, 1, 3), + VCPCRU_RESET_OFFSET(SRST_A_AVSP, 1, 4), +}; + +void rv1126b_rst_init(struct device_node *np, void __iomem *reg_base) +{ + rockchip_register_softrst_lut(np, + rv1126b_register_offset, + ARRAY_SIZE(rv1126b_register_offset), + reg_base + RV1126B_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); +} From 67e41dbc268a521a61acca25b6cbc70592488b19 Mon Sep 17 00:00:00 2001 From: Yuji Ishikawa Date: Fri, 14 Nov 2025 15:53:57 +0900 Subject: [PATCH 460/684] clk: visconti: Do not define number of clocks in bindings Remove use of TMPV770X_NR_CLK. Instead, define number of clocks inside the driver directory. The same for TMPV770X_NR_RESET and TMPV770X_NR_PLL. Signed-off-by: Yuji Ishikawa Signed-off-by: Stephen Boyd --- drivers/clk/visconti/clkc-tmpv770x.c | 8 ++++++-- drivers/clk/visconti/pll-tmpv770x.c | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/clk/visconti/clkc-tmpv770x.c b/drivers/clk/visconti/clkc-tmpv770x.c index 6c753b2cb558f9..94a736da6fea07 100644 --- a/drivers/clk/visconti/clkc-tmpv770x.c +++ b/drivers/clk/visconti/clkc-tmpv770x.c @@ -17,6 +17,10 @@ #include "clkc.h" #include "reset.h" +/* Must be equal to the last clock/reset ID increased by one */ +#define CLKS_NR (TMPV770X_CLK_BUSLCK + 1) +#define RESETS_NR (TMPV770X_RESET_SBUSCLK + 1) + static DEFINE_SPINLOCK(tmpv770x_clk_lock); static DEFINE_SPINLOCK(tmpv770x_rst_lock); @@ -234,12 +238,12 @@ static int visconti_clk_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ctx = visconti_init_clk(dev, regmap, TMPV770X_NR_CLK); + ctx = visconti_init_clk(dev, regmap, CLKS_NR); if (IS_ERR(ctx)) return PTR_ERR(ctx); ret = visconti_register_reset_controller(dev, regmap, clk_reset_data, - TMPV770X_NR_RESET, + RESETS_NR, &visconti_reset_ops, &tmpv770x_rst_lock); if (ret) { diff --git a/drivers/clk/visconti/pll-tmpv770x.c b/drivers/clk/visconti/pll-tmpv770x.c index 8360ccf888672a..a2208c5fc12e00 100644 --- a/drivers/clk/visconti/pll-tmpv770x.c +++ b/drivers/clk/visconti/pll-tmpv770x.c @@ -16,6 +16,9 @@ #include "pll.h" +/* Must be equal to the last pll ID increased by one */ +#define PLLS_NR (TMPV770X_PLL_PIIMGERPLL + 1) + static DEFINE_SPINLOCK(tmpv770x_pll_lock); static const struct visconti_pll_rate_table pipll0_rates[] __initconst = { @@ -66,7 +69,7 @@ static void __init tmpv770x_setup_plls(struct device_node *np) if (!reg_base) return; - ctx = visconti_init_pll(np, reg_base, TMPV770X_NR_PLL); + ctx = visconti_init_pll(np, reg_base, PLLS_NR); if (IS_ERR(ctx)) { iounmap(reg_base); return; From d10f26a7abbd3dd5d59bac1acdca117385b54ea9 Mon Sep 17 00:00:00 2001 From: Yuji Ishikawa Date: Fri, 14 Nov 2025 15:53:58 +0900 Subject: [PATCH 461/684] dt-bindings: clock: tmpv770x: Remove definition of number of clocks Remove the definitions of number of clocks from bindings because they prevent adding new clocks. Since the previous patch removed all refereces within the driver, they can now be deleted. The same for resets and plls. Signed-off-by: Yuji Ishikawa Acked-by: Conor Dooley Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/toshiba,tmpv770x.h | 3 --- include/dt-bindings/reset/toshiba,tmpv770x.h | 1 - 2 files changed, 4 deletions(-) diff --git a/include/dt-bindings/clock/toshiba,tmpv770x.h b/include/dt-bindings/clock/toshiba,tmpv770x.h index 5fce713001fdd2..89189c4f6a52df 100644 --- a/include/dt-bindings/clock/toshiba,tmpv770x.h +++ b/include/dt-bindings/clock/toshiba,tmpv770x.h @@ -11,7 +11,6 @@ #define TMPV770X_PLL_PIDDRCPLL 4 #define TMPV770X_PLL_PIVOIFPLL 5 #define TMPV770X_PLL_PIIMGERPLL 6 -#define TMPV770X_NR_PLL 7 /* Clocks */ #define TMPV770X_CLK_PIPLL1_DIV1 0 @@ -141,7 +140,6 @@ #define TMPV770X_CLK_PIREFCLK 124 #define TMPV770X_CLK_SBUS 125 #define TMPV770X_CLK_BUSLCK 126 -#define TMPV770X_NR_CLK 127 /* Reset */ #define TMPV770X_RESET_PIETHER_2P5M 0 @@ -176,6 +174,5 @@ #define TMPV770X_RESET_PIPCMIF 29 #define TMPV770X_RESET_PICKMON 30 #define TMPV770X_RESET_SBUSCLK 31 -#define TMPV770X_NR_RESET 32 #endif /*_DT_BINDINGS_CLOCK_TOSHIBA_TMPV770X_H_ */ diff --git a/include/dt-bindings/reset/toshiba,tmpv770x.h b/include/dt-bindings/reset/toshiba,tmpv770x.h index c1007acb19418c..bedfe253fa3637 100644 --- a/include/dt-bindings/reset/toshiba,tmpv770x.h +++ b/include/dt-bindings/reset/toshiba,tmpv770x.h @@ -36,6 +36,5 @@ #define TMPV770X_RESET_PIPCMIF 29 #define TMPV770X_RESET_PICKMON 30 #define TMPV770X_RESET_SBUSCLK 31 -#define TMPV770X_NR_RESET 32 #endif /*_DT_BINDINGS_RESET_TOSHIBA_TMPV770X_H_ */ From beeff790c5679b3eacc8ee7021f775f447f47603 Mon Sep 17 00:00:00 2001 From: Yuji Ishikawa Date: Fri, 14 Nov 2025 16:05:11 +0900 Subject: [PATCH 462/684] dt-bindings: clock: tmpv770x: Add VIIF clocks Add clock and reset identifiers for the Video Input Interface. These identifiers support two instances: VIIF0 and VIIF1. Signed-off-by: Yuji Ishikawa Acked-by: Conor Dooley Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/toshiba,tmpv770x.h | 11 +++++++++++ include/dt-bindings/reset/toshiba,tmpv770x.h | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/include/dt-bindings/clock/toshiba,tmpv770x.h b/include/dt-bindings/clock/toshiba,tmpv770x.h index 89189c4f6a52df..a36c8926668640 100644 --- a/include/dt-bindings/clock/toshiba,tmpv770x.h +++ b/include/dt-bindings/clock/toshiba,tmpv770x.h @@ -140,6 +140,9 @@ #define TMPV770X_CLK_PIREFCLK 124 #define TMPV770X_CLK_SBUS 125 #define TMPV770X_CLK_BUSLCK 126 +#define TMPV770X_CLK_VIIFBS1_L2ISP 127 +#define TMPV770X_CLK_VIIFBS1_L1ISP 128 +#define TMPV770X_CLK_VIIFBS1_PROC 129 /* Reset */ #define TMPV770X_RESET_PIETHER_2P5M 0 @@ -174,5 +177,13 @@ #define TMPV770X_RESET_PIPCMIF 29 #define TMPV770X_RESET_PICKMON 30 #define TMPV770X_RESET_SBUSCLK 31 +#define TMPV770X_RESET_VIIFBS0 32 +#define TMPV770X_RESET_VIIFBS0_APB 33 +#define TMPV770X_RESET_VIIFBS0_L2ISP 34 +#define TMPV770X_RESET_VIIFBS0_L1ISP 35 +#define TMPV770X_RESET_VIIFBS1 36 +#define TMPV770X_RESET_VIIFBS1_APB 37 +#define TMPV770X_RESET_VIIFBS1_L2ISP 38 +#define TMPV770X_RESET_VIIFBS1_L1ISP 39 #endif /*_DT_BINDINGS_CLOCK_TOSHIBA_TMPV770X_H_ */ diff --git a/include/dt-bindings/reset/toshiba,tmpv770x.h b/include/dt-bindings/reset/toshiba,tmpv770x.h index bedfe253fa3637..9452bef314252f 100644 --- a/include/dt-bindings/reset/toshiba,tmpv770x.h +++ b/include/dt-bindings/reset/toshiba,tmpv770x.h @@ -36,5 +36,13 @@ #define TMPV770X_RESET_PIPCMIF 29 #define TMPV770X_RESET_PICKMON 30 #define TMPV770X_RESET_SBUSCLK 31 +#define TMPV770X_RESET_VIIFBS0 32 +#define TMPV770X_RESET_VIIFBS0_APB 33 +#define TMPV770X_RESET_VIIFBS0_L2ISP 34 +#define TMPV770X_RESET_VIIFBS0_L1ISP 35 +#define TMPV770X_RESET_VIIFBS1 36 +#define TMPV770X_RESET_VIIFBS1_APB 37 +#define TMPV770X_RESET_VIIFBS1_L2ISP 38 +#define TMPV770X_RESET_VIIFBS1_L1ISP 39 #endif /*_DT_BINDINGS_RESET_TOSHIBA_TMPV770X_H_ */ From b65e179b986a4812ed38486050a438ce57a873b9 Mon Sep 17 00:00:00 2001 From: Yuji Ishikawa Date: Fri, 14 Nov 2025 16:05:12 +0900 Subject: [PATCH 463/684] clk: visconti: Add VIIF clocks Add the control sequence of register bits to handle the clocks and the resets of Video Input Interface. Signed-off-by: Yuji Ishikawa Signed-off-by: Stephen Boyd --- drivers/clk/visconti/clkc-tmpv770x.c | 75 +++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/clk/visconti/clkc-tmpv770x.c b/drivers/clk/visconti/clkc-tmpv770x.c index 94a736da6fea07..1e2e8d6437fe75 100644 --- a/drivers/clk/visconti/clkc-tmpv770x.c +++ b/drivers/clk/visconti/clkc-tmpv770x.c @@ -18,8 +18,8 @@ #include "reset.h" /* Must be equal to the last clock/reset ID increased by one */ -#define CLKS_NR (TMPV770X_CLK_BUSLCK + 1) -#define RESETS_NR (TMPV770X_RESET_SBUSCLK + 1) +#define CLKS_NR (TMPV770X_CLK_VIIFBS1_PROC + 1) +#define RESETS_NR (TMPV770X_RESET_VIIFBS1_L1ISP + 1) static DEFINE_SPINLOCK(tmpv770x_clk_lock); static DEFINE_SPINLOCK(tmpv770x_rst_lock); @@ -32,6 +32,10 @@ static const struct clk_parent_data pietherplls_parent_data[] = { { .fw_name = "pietherpll", .name = "pietherpll", }, }; +static const struct clk_parent_data pidnnplls_parent_data[] = { + { .fw_name = "pidnnpll", .name = "pidnnpll", }, +}; + static const struct visconti_fixed_clk fixed_clk_tables[] = { /* PLL1 */ /* PICMPT0/1, PITSC, PIUWDT, PISWDT, PISBUS, PIPMU, PIGPMU, PITMU */ @@ -68,6 +72,41 @@ static const struct visconti_clk_gate_table pietherpll_clk_gate_tables[] = { TMPV770X_RESET_PIETHER_125M, }, }; +static const struct visconti_clk_gate_table pidnnpll_clk_gate_tables[] = { + { TMPV770X_CLK_VIIFBS0, "viifbs0", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 1, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS0_PROC, "viifbs0_proc", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 18, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS0_L1ISP, "viifbs0_l1isp", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 17, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS0_L2ISP, "viifbs0_l2isp", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 16, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS1, "viifbs1", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 5, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS1_PROC, "viifbs1_proc", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 22, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS1_L1ISP, "viifbs1_l1isp", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 21, 1, + NO_RESET, }, + { TMPV770X_CLK_VIIFBS1_L2ISP, "viifbs1_l2isp", + pidnnplls_parent_data, ARRAY_SIZE(pidnnplls_parent_data), + 0, 0x58, 0x158, 20, 1, + NO_RESET, }, +}; + static const struct visconti_clk_gate_table clk_gate_tables[] = { { TMPV770X_CLK_HOX, "hox", clks_parent_data, ARRAY_SIZE(clks_parent_data), @@ -189,6 +228,22 @@ static const struct visconti_clk_gate_table clk_gate_tables[] = { clks_parent_data, ARRAY_SIZE(clks_parent_data), 0, 0x14, 0x114, 0, 4, TMPV770X_RESET_SBUSCLK, }, + { TMPV770X_CLK_VIIF0_CFGCLK, "csi2rx0cfg", + clks_parent_data, ARRAY_SIZE(clks_parent_data), + 0, 0x58, 0x158, 0, 24, + NO_RESET, }, + { TMPV770X_CLK_VIIF0_APBCLK, "csi2rx0apb", + clks_parent_data, ARRAY_SIZE(clks_parent_data), + 0, 0x58, 0x158, 2, 4, + NO_RESET, }, + { TMPV770X_CLK_VIIF1_CFGCLK, "csi2rx1cfg", + clks_parent_data, ARRAY_SIZE(clks_parent_data), + 0, 0x58, 0x158, 4, 24, + NO_RESET, }, + { TMPV770X_CLK_VIIF1_APBCLK, "csi2rx1apb", + clks_parent_data, ARRAY_SIZE(clks_parent_data), + 0, 0x58, 0x158, 6, 4, + NO_RESET, }, }; static const struct visconti_reset_data clk_reset_data[] = { @@ -224,6 +279,14 @@ static const struct visconti_reset_data clk_reset_data[] = { [TMPV770X_RESET_PIPCMIF] = { 0x464, 0x564, 0, }, [TMPV770X_RESET_PICKMON] = { 0x410, 0x510, 8, }, [TMPV770X_RESET_SBUSCLK] = { 0x414, 0x514, 0, }, + [TMPV770X_RESET_VIIFBS0] = { 0x458, 0x558, 0, }, + [TMPV770X_RESET_VIIFBS0_APB] = { 0x458, 0x558, 1, }, + [TMPV770X_RESET_VIIFBS0_L2ISP] = { 0x458, 0x558, 16, }, + [TMPV770X_RESET_VIIFBS0_L1ISP] = { 0x458, 0x558, 17, }, + [TMPV770X_RESET_VIIFBS1] = { 0x458, 0x558, 4, }, + [TMPV770X_RESET_VIIFBS1_APB] = { 0x458, 0x558, 5, }, + [TMPV770X_RESET_VIIFBS1_L2ISP] = { 0x458, 0x558, 20, }, + [TMPV770X_RESET_VIIFBS1_L1ISP] = { 0x458, 0x558, 21, }, }; static int visconti_clk_probe(struct platform_device *pdev) @@ -276,6 +339,14 @@ static int visconti_clk_probe(struct platform_device *pdev) return ret; } + ret = visconti_clk_register_gates(ctx, pidnnpll_clk_gate_tables, + ARRAY_SIZE(pidnnpll_clk_gate_tables), + clk_reset_data, &tmpv770x_clk_lock); + if (ret) { + dev_err(dev, "Failed to register pidnnpll clock gate: %d\n", ret); + return ret; + } + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &ctx->clk_data); } From 23b2d2fb136959fd0a8e309c70be83d9b8841c7e Mon Sep 17 00:00:00 2001 From: Charles Mirabile Date: Mon, 17 Nov 2025 14:03:29 -0500 Subject: [PATCH 464/684] clk: spacemit: Set clk_hw_onecell_data::num before using flex array When booting with KASAN enabled the following splat is encountered during probe of the k1 clock driver: UBSAN: array-index-out-of-bounds in drivers/clk/spacemit/ccu-k1.c:1044:16 index 0 is out of range for type 'clk_hw *[*]' CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc5+ #1 PREEMPT(lazy) Hardware name: Unknown Unknown Product/Unknown Product, BIOS 2022.10spacemit 10/01/2022 Call Trace: [] dump_backtrace+0x28/0x38 [] show_stack+0x3a/0x50 [] dump_stack_lvl+0x5a/0x80 [] dump_stack+0x18/0x20 [] ubsan_epilogue+0x10/0x48 [] __ubsan_handle_out_of_bounds+0xa6/0xa8 [] k1_ccu_probe+0x37e/0x420 [] platform_probe+0x56/0x98 [] really_probe+0x9e/0x350 [] __driver_probe_device+0x80/0x138 [] driver_probe_device+0x3a/0xd0 [] __driver_attach+0xac/0x1b8 [] bus_for_each_dev+0x6c/0xc8 [] driver_attach+0x26/0x38 [] bus_add_driver+0x13e/0x268 [] driver_register+0x52/0x100 [] __platform_driver_register+0x28/0x38 [] k1_ccu_driver_init+0x22/0x38 [] do_one_initcall+0x62/0x2a0 [] do_initcalls+0x170/0x1a8 [] kernel_init_freeable+0x16a/0x1e0 [] kernel_init+0x2c/0x180 [] ret_from_fork_kernel+0x16/0x1d8 [] ret_from_fork_kernel_asm+0x16/0x18 ---[ end trace ]--- This is bogus and is simply a result of KASAN consulting the `.num` member of the struct for bounds information (as it should due to `__counted_by`) and finding 0 set by kzalloc() because it has not been initialized before the loop that fills in the array. The easy fix is to just move the line that sets `num` to before the loop that fills the array so that KASAN has the information it needs to accurately conclude that the access is valid. Fixes: 1b72c59db0add ("clk: spacemit: Add clock support for SpacemiT K1 SoC") Tested-by: Yanko Kaneti Signed-off-by: Charles Mirabile Reviewed-by: Alex Elder Reviewed-by: Troy Mitchell Reviewed-by: Yixun Lan Signed-off-by: Stephen Boyd --- drivers/clk/spacemit/ccu-k1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/spacemit/ccu-k1.c b/drivers/clk/spacemit/ccu-k1.c index f5a9fe6ba18591..4761bc1e3b6e60 100644 --- a/drivers/clk/spacemit/ccu-k1.c +++ b/drivers/clk/spacemit/ccu-k1.c @@ -1018,6 +1018,8 @@ static int spacemit_ccu_register(struct device *dev, if (!clk_data) return -ENOMEM; + clk_data->num = data->num; + for (i = 0; i < data->num; i++) { struct clk_hw *hw = data->hws[i]; struct ccu_common *common; @@ -1044,8 +1046,6 @@ static int spacemit_ccu_register(struct device *dev, clk_data->hws[i] = hw; } - clk_data->num = data->num; - ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data); if (ret) dev_err(dev, "failed to add clock hardware provider (%d)\n", ret); From 1749001151d11b5296754a99f0e845cd2d904a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Barna=C5=9B?= Date: Tue, 28 Oct 2025 15:20:11 +0000 Subject: [PATCH 465/684] clk: actions: Fix discarding const qualifier by 'container_of' macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove const qualifier from functions parameter because it was discarded when container_of was called. Received pointer had mutable access to it through received container. Signed-off-by: Adrian Barnaś Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-common.h | 2 +- drivers/clk/actions/owl-composite.h | 2 +- drivers/clk/actions/owl-divider.h | 2 +- drivers/clk/actions/owl-factor.h | 2 +- drivers/clk/actions/owl-gate.h | 2 +- drivers/clk/actions/owl-mux.h | 2 +- drivers/clk/actions/owl-pll.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/actions/owl-common.h b/drivers/clk/actions/owl-common.h index 8fb65f3e82d797..5768a2e0f6a071 100644 --- a/drivers/clk/actions/owl-common.h +++ b/drivers/clk/actions/owl-common.h @@ -32,7 +32,7 @@ struct owl_clk_desc { }; static inline struct owl_clk_common * - hw_to_owl_clk_common(const struct clk_hw *hw) + hw_to_owl_clk_common(struct clk_hw *hw) { return container_of(hw, struct owl_clk_common, hw); } diff --git a/drivers/clk/actions/owl-composite.h b/drivers/clk/actions/owl-composite.h index bca38bf8f218c7..6d7c6f0c47c8b7 100644 --- a/drivers/clk/actions/owl-composite.h +++ b/drivers/clk/actions/owl-composite.h @@ -108,7 +108,7 @@ struct owl_composite { }, \ } -static inline struct owl_composite *hw_to_owl_comp(const struct clk_hw *hw) +static inline struct owl_composite *hw_to_owl_comp(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); diff --git a/drivers/clk/actions/owl-divider.h b/drivers/clk/actions/owl-divider.h index 083be6d80954d7..d76f58782c5288 100644 --- a/drivers/clk/actions/owl-divider.h +++ b/drivers/clk/actions/owl-divider.h @@ -49,7 +49,7 @@ struct owl_divider { }, \ } -static inline struct owl_divider *hw_to_owl_divider(const struct clk_hw *hw) +static inline struct owl_divider *hw_to_owl_divider(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); diff --git a/drivers/clk/actions/owl-factor.h b/drivers/clk/actions/owl-factor.h index 04b89cbfdccbb0..24c704d409258e 100644 --- a/drivers/clk/actions/owl-factor.h +++ b/drivers/clk/actions/owl-factor.h @@ -57,7 +57,7 @@ struct owl_factor { #define div_mask(d) ((1 << ((d)->width)) - 1) -static inline struct owl_factor *hw_to_owl_factor(const struct clk_hw *hw) +static inline struct owl_factor *hw_to_owl_factor(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); diff --git a/drivers/clk/actions/owl-gate.h b/drivers/clk/actions/owl-gate.h index c2f161c93fda5a..ac458d4385ee79 100644 --- a/drivers/clk/actions/owl-gate.h +++ b/drivers/clk/actions/owl-gate.h @@ -56,7 +56,7 @@ struct owl_gate { }, \ } \ -static inline struct owl_gate *hw_to_owl_gate(const struct clk_hw *hw) +static inline struct owl_gate *hw_to_owl_gate(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); diff --git a/drivers/clk/actions/owl-mux.h b/drivers/clk/actions/owl-mux.h index 53b9ab665294ca..dc0ecc2d5e10aa 100644 --- a/drivers/clk/actions/owl-mux.h +++ b/drivers/clk/actions/owl-mux.h @@ -44,7 +44,7 @@ struct owl_mux { }, \ } -static inline struct owl_mux *hw_to_owl_mux(const struct clk_hw *hw) +static inline struct owl_mux *hw_to_owl_mux(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); diff --git a/drivers/clk/actions/owl-pll.h b/drivers/clk/actions/owl-pll.h index 78e5fc360b03b5..58e19f1ade43f0 100644 --- a/drivers/clk/actions/owl-pll.h +++ b/drivers/clk/actions/owl-pll.h @@ -98,7 +98,7 @@ struct owl_pll { #define mul_mask(m) ((1 << ((m)->width)) - 1) -static inline struct owl_pll *hw_to_owl_pll(const struct clk_hw *hw) +static inline struct owl_pll *hw_to_owl_pll(struct clk_hw *hw) { struct owl_clk_common *common = hw_to_owl_clk_common(hw); From 938eae912ac52f8e9e5f2463e2db30cfe6f895d5 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 5 Nov 2025 18:24:04 -0800 Subject: [PATCH 466/684] dmaengine: at_hdmac: fix formats under 64-bit size_t formats under 32-bit evaluate to the same thing and GCC does not warn against it. Not the case with 64-bit. Signed-off-by: Rosen Penev Reviewed-by: Eugen Hristev Link: https://patch.msgid.link/20251106022405.85604-2-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 2d147712cbc69b..7d226453961f82 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -887,7 +887,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan, first = xt->sgl; dev_info(chan2dev(chan), - "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n", + "%s: src=%pad, dest=%pad, numf=%zu, frame_size=%zu, flags=0x%lx\n", __func__, &xt->src_start, &xt->dst_start, xt->numf, xt->frame_size, flags); @@ -1174,7 +1174,7 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, int i; int ret; - dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%zx f0x%lx\n", __func__, + dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%x f0x%lx\n", __func__, value, sg_len, flags); if (unlikely(!sgl || !sg_len)) { @@ -1503,7 +1503,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, unsigned int periods = buf_len / period_len; unsigned int i; - dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%d/%d)\n", + dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%zu/%zu)\n", direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", &buf_addr, periods, buf_len, period_len); From 5d8c5bea0da97809813b5f702700019cfffb6085 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 5 Nov 2025 18:24:05 -0800 Subject: [PATCH 467/684] dmaengine: at_hdmac: add COMPILE_TEST support Allows the buildbot to detect potential issues with the code on various platforms. Signed-off-by: Rosen Penev Reviewed-by: Eugen Hristev Link: https://patch.msgid.link/20251106022405.85604-3-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index b8a74b1798ba1d..c06327be82685f 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -102,7 +102,7 @@ config ARM_DMA350 config AT_HDMAC tristate "Atmel AHB DMA support" - depends on ARCH_AT91 + depends on ARCH_AT91 || COMPILE_TEST select DMA_ENGINE select DMA_VIRTUAL_CHANNELS help From bfab38bee5652f335c5d693d54eb61bc25850518 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:16 +0100 Subject: [PATCH 468/684] dmaengine: bcm2835: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120114524.8431-2-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 0117bb2e8591be..321748e2983e5d 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -1060,7 +1060,6 @@ static struct platform_driver bcm2835_dma_driver = { module_platform_driver(bcm2835_dma_driver); -MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); MODULE_AUTHOR("Florian Meier "); MODULE_LICENSE("GPL"); From 660c40702d9073035c61a9573b299481b9c7f3cd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:17 +0100 Subject: [PATCH 469/684] dmaengine: dw: drop unused module alias The driver does not support anything but OF and ACPI probe since commit b3757413b91e ("dmaengine: dw: platform: Use struct dw_dma_chip_pdata") so drop the unused platform module alias along with the now unnecessary driver name define. Signed-off-by: Johan Hovold Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20251120114524.8431-3-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index cee56cd31a611c..c63fa52036d7ff 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -21,8 +21,6 @@ #include "internal.h" -#define DRV_NAME "dw_dmac" - static int dw_probe(struct platform_device *pdev) { const struct dw_dma_chip_pdata *match; @@ -190,7 +188,7 @@ static struct platform_driver dw_driver = { .remove = dw_remove, .shutdown = dw_shutdown, .driver = { - .name = DRV_NAME, + .name = "dw_dmac", .pm = pm_sleep_ptr(&dw_dev_pm_ops), .of_match_table = of_match_ptr(dw_dma_of_id_table), .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), @@ -211,4 +209,3 @@ module_exit(dw_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver"); -MODULE_ALIAS("platform:" DRV_NAME); From 03adb0eb0ed64a1e13e04c0fb57a073896efe6ca Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:18 +0100 Subject: [PATCH 470/684] dmaengine: fsl-edma: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Reviewed-by: Frank Li Link: https://patch.msgid.link/20251120114524.8431-4-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c index 97583c7d51a2e8..a753b7cbfa7a33 100644 --- a/drivers/dma/fsl-edma-main.c +++ b/drivers/dma/fsl-edma-main.c @@ -999,6 +999,5 @@ static void __exit fsl_edma_exit(void) } module_exit(fsl_edma_exit); -MODULE_ALIAS("platform:fsl-edma"); MODULE_DESCRIPTION("Freescale eDMA engine driver"); MODULE_LICENSE("GPL v2"); From 9180a66fb43214ae02311176e43eec361ff80d67 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:19 +0100 Subject: [PATCH 471/684] dmaengine: fsl-qdma: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Reviewed-by: Frank Li Link: https://patch.msgid.link/20251120114524.8431-5-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/fsl-qdma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c index 21e13f1207cbe6..6ace5bf80c40be 100644 --- a/drivers/dma/fsl-qdma.c +++ b/drivers/dma/fsl-qdma.c @@ -1296,6 +1296,5 @@ static struct platform_driver fsl_qdma_driver = { module_platform_driver(fsl_qdma_driver); -MODULE_ALIAS("platform:fsl-qdma"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("NXP Layerscape qDMA engine driver"); From 73b77c3d80031b4636a24912962ffeb295438b0a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:20 +0100 Subject: [PATCH 472/684] dmaengine: k3dma: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120114524.8431-6-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/k3dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index acc2983e28e0dd..0f9cd7815f880e 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -1034,5 +1034,4 @@ static struct platform_driver k3_pdma_driver = { module_platform_driver(k3_pdma_driver); MODULE_DESCRIPTION("HiSilicon k3 DMA Driver"); -MODULE_ALIAS("platform:k3dma"); MODULE_LICENSE("GPL v2"); From 73391fecf23860804bceb6670cef74a3626ecf92 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:21 +0100 Subject: [PATCH 473/684] dmaengine: mmp_tdma: drop unused module alias The driver does not support anything but OF probe since commit 3b0f4a54f247 ("dma:mmp_tdma: get sram pool through device tree") so drop the unused platform module alias. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120114524.8431-7-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/mmp_tdma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index b7fb843c67a6f2..6186b9dc5457a7 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -743,6 +743,5 @@ module_platform_driver(mmp_tdma_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MMP Two-Channel DMA Driver"); -MODULE_ALIAS("platform:mmp-tdma"); MODULE_AUTHOR("Leo Yan "); MODULE_AUTHOR("Zhangfei Gao "); From 3b7b0bbdcba984287225bb373e52845c23dadb93 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:22 +0100 Subject: [PATCH 474/684] dmaengine: mmp_tdma: drop unnecessary OF node check in remove The driver does not support anything but OF probe since commit 3b0f4a54f247 ("dma:mmp_tdma: get sram pool through device tree"). Commit a67ba97dfb30 ("dmaengine: Use device_get_match_data()") later removed most remnants of platform probing except for an unnecessary OF node check in remove(). Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120114524.8431-8-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/mmp_tdma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 6186b9dc5457a7..ba03321eeff799 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -554,8 +554,7 @@ static void mmp_tdma_issue_pending(struct dma_chan *chan) static void mmp_tdma_remove(struct platform_device *pdev) { - if (pdev->dev.of_node) - of_dma_controller_free(pdev->dev.of_node); + of_dma_controller_free(pdev->dev.of_node); } static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, From 1911f507a54b42bd01ae30590c06d8140beee424 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:23 +0100 Subject: [PATCH 475/684] dmaengine: sprd: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120114524.8431-9-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/sprd-dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 187a090463cedf..6207e0b185e1d5 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -1311,4 +1311,3 @@ MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DMA driver for Spreadtrum"); MODULE_AUTHOR("Baolin Wang "); MODULE_AUTHOR("Eric Long "); -MODULE_ALIAS("platform:sprd-dma"); From e0aef2a5c33680bbd332e5b5f64afc8dde8d46f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:45:24 +0100 Subject: [PATCH 476/684] dmaengine: tegra210-adma: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20251120114524.8431-10-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/tegra210-adma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index fad896ff29a2d3..d0e8bb27a03b87 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -1230,7 +1230,6 @@ static struct platform_driver tegra_admac_driver = { module_platform_driver(tegra_admac_driver); -MODULE_ALIAS("platform:tegra210-adma"); MODULE_DESCRIPTION("NVIDIA Tegra ADMA driver"); MODULE_AUTHOR("Dara Ramesh "); MODULE_AUTHOR("Jon Hunter "); From d3e1935fba8d71ef1889cbc2d6e2447cb829070f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 12:50:16 +0100 Subject: [PATCH 477/684] dmaengine: bcm2835: enable compile testing There seems to be nothing preventing the driver from being compile tested so enable that for wider build coverage. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120115016.8967-1-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index c06327be82685f..8bb0a119ecd48a 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -143,7 +143,7 @@ config BCM_SBA_RAID config DMA_BCM2835 tristate "BCM2835 DMA engine support" - depends on ARCH_BCM2835 + depends on ARCH_BCM2835 || COMPILE_TEST select DMA_ENGINE select DMA_VIRTUAL_CHANNELS From cd3ba117688f7694f000293fd5c034f9f842dbb2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 20 Nov 2025 17:49:07 +0100 Subject: [PATCH 478/684] dmaengine: st_fdma: drop unused module alias The driver has never supported anything but OF probe so drop the unused platform module alias. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20251120164907.28007-1-johan@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/st_fdma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c index c65ee0c7bfbdb2..dc2ab7d16cf2ae 100644 --- a/drivers/dma/st_fdma.c +++ b/drivers/dma/st_fdma.c @@ -866,4 +866,3 @@ MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver"); MODULE_AUTHOR("Ludovic.barre "); MODULE_AUTHOR("Peter Griffin "); -MODULE_ALIAS("platform:" DRIVER_NAME); From 1ecd8b6016c07da162175c708666762e058a0b29 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Wed, 19 Nov 2025 10:32:55 -0600 Subject: [PATCH 479/684] dmaengine: fsl-edma: configure tcd attr with separate src and dst settings Set the edma tcd transfer attribution settings for the src and dst based on their respective dma_addr values, to remove the previous 32-byte alignment limitation in the EDMA memcpy function. Signed-off-by: Han Xu Reviewed-by: Frank Li Link: https://patch.msgid.link/20251119163255.502070-1-han.xu@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-common.c | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c index 4976d7dde08090..a5921275802996 100644 --- a/drivers/dma/fsl-edma-common.c +++ b/drivers/dma/fsl-edma-common.c @@ -206,15 +206,19 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan, mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable); } -static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth addr_width) +static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth src_addr_width, + enum dma_slave_buswidth dst_addr_width) { - u32 val; + u32 src_val, dst_val; - if (addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) - addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) + src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) + dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - val = ffs(addr_width) - 1; - return val | (val << 8); + src_val = ffs(src_addr_width) - 1; + dst_val = ffs(dst_addr_width) - 1; + return dst_val | (src_val << 8); } void fsl_edma_free_desc(struct virt_dma_desc *vdesc) @@ -612,13 +616,19 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic( dma_buf_next = dma_addr; if (direction == DMA_MEM_TO_DEV) { + if (!fsl_chan->cfg.src_addr_width) + fsl_chan->cfg.src_addr_width = fsl_chan->cfg.dst_addr_width; fsl_chan->attr = - fsl_edma_get_tcd_attr(fsl_chan->cfg.dst_addr_width); + fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width, + fsl_chan->cfg.dst_addr_width); nbytes = fsl_chan->cfg.dst_addr_width * fsl_chan->cfg.dst_maxburst; } else { + if (!fsl_chan->cfg.dst_addr_width) + fsl_chan->cfg.dst_addr_width = fsl_chan->cfg.src_addr_width; fsl_chan->attr = - fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width); + fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width, + fsl_chan->cfg.dst_addr_width); nbytes = fsl_chan->cfg.src_addr_width * fsl_chan->cfg.src_maxburst; } @@ -689,13 +699,19 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg( fsl_desc->dirn = direction; if (direction == DMA_MEM_TO_DEV) { + if (!fsl_chan->cfg.src_addr_width) + fsl_chan->cfg.src_addr_width = fsl_chan->cfg.dst_addr_width; fsl_chan->attr = - fsl_edma_get_tcd_attr(fsl_chan->cfg.dst_addr_width); + fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width, + fsl_chan->cfg.dst_addr_width); nbytes = fsl_chan->cfg.dst_addr_width * fsl_chan->cfg.dst_maxburst; } else { + if (!fsl_chan->cfg.dst_addr_width) + fsl_chan->cfg.dst_addr_width = fsl_chan->cfg.src_addr_width; fsl_chan->attr = - fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width); + fsl_edma_get_tcd_attr(fsl_chan->cfg.src_addr_width, + fsl_chan->cfg.dst_addr_width); nbytes = fsl_chan->cfg.src_addr_width * fsl_chan->cfg.src_maxburst; } @@ -766,6 +782,10 @@ struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan, { struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); struct fsl_edma_desc *fsl_desc; + u32 src_bus_width, dst_bus_width; + + src_bus_width = min_t(u32, DMA_SLAVE_BUSWIDTH_32_BYTES, 1 << (ffs(dma_src) - 1)); + dst_bus_width = min_t(u32, DMA_SLAVE_BUSWIDTH_32_BYTES, 1 << (ffs(dma_dst) - 1)); fsl_desc = fsl_edma_alloc_desc(fsl_chan, 1); if (!fsl_desc) @@ -778,8 +798,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan, /* To match with copy_align and max_seg_size so 1 tcd is enough */ fsl_edma_fill_tcd(fsl_chan, fsl_desc->tcd[0].vtcd, dma_src, dma_dst, - fsl_edma_get_tcd_attr(DMA_SLAVE_BUSWIDTH_32_BYTES), - 32, len, 0, 1, 1, 32, 0, true, true, false); + fsl_edma_get_tcd_attr(src_bus_width, dst_bus_width), + src_bus_width, len, 0, 1, 1, dst_bus_width, 0, true, + true, false); return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags); } From 2b11e7403a8ed816fce38b57cb88e04d997aa7af Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 15 Nov 2025 13:21:22 +0100 Subject: [PATCH 480/684] dt-bindings: dma: xilinx: Simplify dma-coherent property Common boolean properties need to be only allowed in the binding (":true"), because their type is already defined by core DT schema. Simplify dma-coherent property to match common syntax. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Harini Katakam Link: https://patch.msgid.link/20251115122120.35315-5-krzk@kernel.org Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml index b5399c65a7315b..2da86037ad79ee 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml +++ b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml @@ -59,8 +59,7 @@ properties: power-domains: maxItems: 1 - dma-coherent: - description: present if dma operations are coherent + dma-coherent: true required: - "#dma-cells" From 84898f8e9cea06f8178fc5ca53f068180f7bfba0 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 21 Nov 2025 15:53:49 +0800 Subject: [PATCH 481/684] dt-bindings: clock: rockchip: Add RK3506 clock and reset unit Add device tree bindings for clock and reset unit on RK3506 SoC. Add clock and reset IDs for RK3506 SoC. Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang Reviewed-by: Conor Dooley Link: https://patch.msgid.link/20251121075350.2564860-2-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- .../bindings/clock/rockchip,rk3506-cru.yaml | 55 ++++ .../dt-bindings/clock/rockchip,rk3506-cru.h | 285 ++++++++++++++++++ .../dt-bindings/reset/rockchip,rk3506-cru.h | 211 +++++++++++++ 3 files changed, 551 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3506-cru.yaml create mode 100644 include/dt-bindings/clock/rockchip,rk3506-cru.h create mode 100644 include/dt-bindings/reset/rockchip,rk3506-cru.h diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3506-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3506-cru.yaml new file mode 100644 index 00000000000000..ca940475336ce7 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3506-cru.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3506-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3506 Clock and Reset Unit (CRU) + +maintainers: + - Finley Xiao + - Heiko Stuebner + +description: + The RK3506 CRU generates the clock and also implements reset for SoC + peripherals. + +properties: + compatible: + const: rockchip,rk3506-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + clock-controller@ff9a0000 { + compatible = "rockchip,rk3506-cru"; + reg = <0xff9a0000 0x20000>; + #clock-cells = <1>; + #reset-cells = <1>; + clocks = <&xin24m>; + clock-names = "xin"; + }; diff --git a/include/dt-bindings/clock/rockchip,rk3506-cru.h b/include/dt-bindings/clock/rockchip,rk3506-cru.h new file mode 100644 index 00000000000000..71d7dda23cc93f --- /dev/null +++ b/include/dt-bindings/clock/rockchip,rk3506-cru.h @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023-2025 Rockchip Electronics Co., Ltd. + * Author: Finley Xiao + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3506_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3506_H + +/* cru plls */ +#define PLL_GPLL 0 +#define PLL_V0PLL 1 +#define PLL_V1PLL 2 + +/* cru-clocks indices */ +#define ARMCLK 3 +#define CLK_DDR 4 +#define XIN24M_GATE 5 +#define CLK_GPLL_GATE 6 +#define CLK_V0PLL_GATE 7 +#define CLK_V1PLL_GATE 8 +#define CLK_GPLL_DIV 9 +#define CLK_GPLL_DIV_100M 10 +#define CLK_V0PLL_DIV 11 +#define CLK_V1PLL_DIV 12 +#define CLK_INT_VOICE_MATRIX0 13 +#define CLK_INT_VOICE_MATRIX1 14 +#define CLK_INT_VOICE_MATRIX2 15 +#define CLK_FRAC_UART_MATRIX0_MUX 16 +#define CLK_FRAC_UART_MATRIX1_MUX 17 +#define CLK_FRAC_VOICE_MATRIX0_MUX 18 +#define CLK_FRAC_VOICE_MATRIX1_MUX 19 +#define CLK_FRAC_COMMON_MATRIX0_MUX 20 +#define CLK_FRAC_COMMON_MATRIX1_MUX 21 +#define CLK_FRAC_COMMON_MATRIX2_MUX 22 +#define CLK_FRAC_UART_MATRIX0 23 +#define CLK_FRAC_UART_MATRIX1 24 +#define CLK_FRAC_VOICE_MATRIX0 25 +#define CLK_FRAC_VOICE_MATRIX1 26 +#define CLK_FRAC_COMMON_MATRIX0 27 +#define CLK_FRAC_COMMON_MATRIX1 28 +#define CLK_FRAC_COMMON_MATRIX2 29 +#define CLK_REF_USBPHY_TOP 30 +#define CLK_REF_DPHY_TOP 31 +#define ACLK_CORE_ROOT 32 +#define PCLK_CORE_ROOT 33 +#define PCLK_DBG 34 +#define PCLK_CORE_GRF 35 +#define PCLK_CORE_CRU 36 +#define CLK_CORE_EMA_DETECT 37 +#define CLK_REF_PVTPLL_CORE 38 +#define PCLK_GPIO1 39 +#define DBCLK_GPIO1 40 +#define ACLK_CORE_PERI_ROOT 41 +#define HCLK_CORE_PERI_ROOT 42 +#define PCLK_CORE_PERI_ROOT 43 +#define CLK_DSMC 44 +#define ACLK_DSMC 45 +#define PCLK_DSMC 46 +#define CLK_FLEXBUS_TX 47 +#define CLK_FLEXBUS_RX 48 +#define ACLK_FLEXBUS 49 +#define HCLK_FLEXBUS 50 +#define ACLK_DSMC_SLV 51 +#define HCLK_DSMC_SLV 52 +#define ACLK_BUS_ROOT 53 +#define HCLK_BUS_ROOT 54 +#define PCLK_BUS_ROOT 55 +#define ACLK_SYSRAM 56 +#define HCLK_SYSRAM 57 +#define ACLK_DMAC0 58 +#define ACLK_DMAC1 59 +#define HCLK_M0 60 +#define PCLK_BUS_GRF 61 +#define PCLK_TIMER 62 +#define CLK_TIMER0_CH0 63 +#define CLK_TIMER0_CH1 64 +#define CLK_TIMER0_CH2 65 +#define CLK_TIMER0_CH3 66 +#define CLK_TIMER0_CH4 67 +#define CLK_TIMER0_CH5 68 +#define PCLK_WDT0 69 +#define TCLK_WDT0 70 +#define PCLK_WDT1 71 +#define TCLK_WDT1 72 +#define PCLK_MAILBOX 73 +#define PCLK_INTMUX 74 +#define PCLK_SPINLOCK 75 +#define PCLK_DDRC 76 +#define HCLK_DDRPHY 77 +#define PCLK_DDRMON 78 +#define CLK_DDRMON_OSC 79 +#define PCLK_STDBY 80 +#define HCLK_USBOTG0 81 +#define HCLK_USBOTG0_PMU 82 +#define CLK_USBOTG0_ADP 83 +#define HCLK_USBOTG1 84 +#define HCLK_USBOTG1_PMU 85 +#define CLK_USBOTG1_ADP 86 +#define PCLK_USBPHY 87 +#define ACLK_DMA2DDR 88 +#define PCLK_DMA2DDR 89 +#define STCLK_M0 90 +#define CLK_DDRPHY 91 +#define CLK_DDRC_SRC 92 +#define ACLK_DDRC_0 93 +#define ACLK_DDRC_1 94 +#define CLK_DDRC 95 +#define CLK_DDRMON 96 +#define HCLK_LSPERI_ROOT 97 +#define PCLK_LSPERI_ROOT 98 +#define PCLK_UART0 99 +#define PCLK_UART1 100 +#define PCLK_UART2 101 +#define PCLK_UART3 102 +#define PCLK_UART4 103 +#define SCLK_UART0 104 +#define SCLK_UART1 105 +#define SCLK_UART2 106 +#define SCLK_UART3 107 +#define SCLK_UART4 108 +#define PCLK_I2C0 109 +#define CLK_I2C0 110 +#define PCLK_I2C1 111 +#define CLK_I2C1 112 +#define PCLK_I2C2 113 +#define CLK_I2C2 114 +#define PCLK_PWM1 115 +#define CLK_PWM1 116 +#define CLK_OSC_PWM1 117 +#define CLK_RC_PWM1 118 +#define CLK_FREQ_PWM1 119 +#define CLK_COUNTER_PWM1 120 +#define PCLK_SPI0 121 +#define CLK_SPI0 122 +#define PCLK_SPI1 123 +#define CLK_SPI1 124 +#define PCLK_GPIO2 125 +#define DBCLK_GPIO2 126 +#define PCLK_GPIO3 127 +#define DBCLK_GPIO3 128 +#define PCLK_GPIO4 129 +#define DBCLK_GPIO4 130 +#define HCLK_CAN0 131 +#define CLK_CAN0 132 +#define HCLK_CAN1 133 +#define CLK_CAN1 134 +#define HCLK_PDM 135 +#define MCLK_PDM 136 +#define CLKOUT_PDM 137 +#define MCLK_SPDIFTX 138 +#define HCLK_SPDIFTX 139 +#define HCLK_SPDIFRX 140 +#define MCLK_SPDIFRX 141 +#define MCLK_SAI0 142 +#define HCLK_SAI0 143 +#define MCLK_OUT_SAI0 144 +#define MCLK_SAI1 145 +#define HCLK_SAI1 146 +#define MCLK_OUT_SAI1 147 +#define HCLK_ASRC0 148 +#define CLK_ASRC0 149 +#define HCLK_ASRC1 150 +#define CLK_ASRC1 151 +#define PCLK_CRU 152 +#define PCLK_PMU_ROOT 153 +#define MCLK_ASRC0 154 +#define MCLK_ASRC1 155 +#define MCLK_ASRC2 156 +#define MCLK_ASRC3 157 +#define LRCK_ASRC0_SRC 158 +#define LRCK_ASRC0_DST 159 +#define LRCK_ASRC1_SRC 160 +#define LRCK_ASRC1_DST 161 +#define ACLK_HSPERI_ROOT 162 +#define HCLK_HSPERI_ROOT 163 +#define PCLK_HSPERI_ROOT 164 +#define CCLK_SRC_SDMMC 165 +#define HCLK_SDMMC 166 +#define HCLK_FSPI 167 +#define SCLK_FSPI 168 +#define PCLK_SPI2 169 +#define ACLK_MAC0 170 +#define ACLK_MAC1 171 +#define PCLK_MAC0 172 +#define PCLK_MAC1 173 +#define CLK_MAC_ROOT 174 +#define CLK_MAC0 175 +#define CLK_MAC1 176 +#define MCLK_SAI2 177 +#define HCLK_SAI2 178 +#define MCLK_OUT_SAI2 179 +#define MCLK_SAI3_SRC 180 +#define HCLK_SAI3 181 +#define MCLK_SAI3 182 +#define MCLK_OUT_SAI3 183 +#define MCLK_SAI4_SRC 184 +#define HCLK_SAI4 185 +#define MCLK_SAI4 186 +#define HCLK_DSM 187 +#define MCLK_DSM 188 +#define PCLK_AUDIO_ADC 189 +#define MCLK_AUDIO_ADC 190 +#define MCLK_AUDIO_ADC_DIV4 191 +#define PCLK_SARADC 192 +#define CLK_SARADC 193 +#define PCLK_OTPC_NS 194 +#define CLK_SBPI_OTPC_NS 195 +#define CLK_USER_OTPC_NS 196 +#define PCLK_UART5 197 +#define SCLK_UART5 198 +#define PCLK_GPIO234_IOC 199 +#define CLK_MAC_PTP_ROOT 200 +#define CLK_MAC0_PTP 201 +#define CLK_MAC1_PTP 202 +#define CLK_SPI2 203 +#define ACLK_VIO_ROOT 204 +#define HCLK_VIO_ROOT 205 +#define PCLK_VIO_ROOT 206 +#define HCLK_RGA 207 +#define ACLK_RGA 208 +#define CLK_CORE_RGA 209 +#define ACLK_VOP 210 +#define HCLK_VOP 211 +#define DCLK_VOP 212 +#define PCLK_DPHY 213 +#define PCLK_DSI_HOST 214 +#define PCLK_TSADC 215 +#define CLK_TSADC 216 +#define CLK_TSADC_TSEN 217 +#define PCLK_GPIO1_IOC 218 +#define PCLK_OTPC_S 219 +#define CLK_SBPI_OTPC_S 220 +#define CLK_USER_OTPC_S 221 +#define PCLK_OTP_MASK 222 +#define PCLK_KEYREADER 223 +#define HCLK_BOOTROM 224 +#define PCLK_DDR_SERVICE 225 +#define HCLK_CRYPTO_S 226 +#define HCLK_KEYLAD 227 +#define CLK_CORE_CRYPTO 228 +#define CLK_PKA_CRYPTO 229 +#define CLK_CORE_CRYPTO_S 230 +#define CLK_PKA_CRYPTO_S 231 +#define ACLK_CRYPTO_S 232 +#define HCLK_RNG_S 233 +#define CLK_CORE_CRYPTO_NS 234 +#define CLK_PKA_CRYPTO_NS 235 +#define ACLK_CRYPTO_NS 236 +#define HCLK_CRYPTO_NS 237 +#define HCLK_RNG 238 +#define CLK_PMU 239 +#define PCLK_PMU 240 +#define CLK_PMU_32K 241 +#define PCLK_PMU_CRU 242 +#define PCLK_PMU_GRF 243 +#define PCLK_GPIO0_IOC 244 +#define PCLK_GPIO0 245 +#define DBCLK_GPIO0 246 +#define PCLK_GPIO1_SHADOW 247 +#define DBCLK_GPIO1_SHADOW 248 +#define PCLK_PMU_HP_TIMER 249 +#define CLK_PMU_HP_TIMER 250 +#define CLK_PMU_HP_TIMER_32K 251 +#define PCLK_PWM0 252 +#define CLK_PWM0 253 +#define CLK_OSC_PWM0 254 +#define CLK_RC_PWM0 255 +#define CLK_MAC_OUT 256 +#define CLK_REF_OUT0 257 +#define CLK_REF_OUT1 258 +#define CLK_32K_FRAC 259 +#define CLK_32K_RC 260 +#define CLK_32K 261 +#define CLK_32K_PMU 262 +#define PCLK_TOUCH_KEY 263 +#define CLK_TOUCH_KEY 264 +#define CLK_REF_PHY_PLL 265 +#define CLK_REF_PHY_PMU_MUX 266 +#define CLK_WIFI_OUT 267 +#define CLK_V0PLL_REF 268 +#define CLK_V1PLL_REF 269 +#define CLK_32K_FRAC_MUX 270 + +#endif diff --git a/include/dt-bindings/reset/rockchip,rk3506-cru.h b/include/dt-bindings/reset/rockchip,rk3506-cru.h new file mode 100644 index 00000000000000..31c0d4aa410f68 --- /dev/null +++ b/include/dt-bindings/reset/rockchip,rk3506-cru.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023-2025 Rockchip Electronics Co., Ltd. + * Author: Finley Xiao + */ + +#ifndef _DT_BINDINGS_REST_ROCKCHIP_RK3506_H +#define _DT_BINDINGS_REST_ROCKCHIP_RK3506_H + +/* CRU-->SOFTRST_CON00 */ +#define SRST_NCOREPORESET0_AC 0 +#define SRST_NCOREPORESET1_AC 1 +#define SRST_NCOREPORESET2_AC 2 +#define SRST_NCORESET0_AC 3 +#define SRST_NCORESET1_AC 4 +#define SRST_NCORESET2_AC 5 +#define SRST_NL2RESET_AC 6 +#define SRST_A_CORE_BIU_AC 7 +#define SRST_H_M0_AC 8 + +/* CRU-->SOFTRST_CON02 */ +#define SRST_NDBGRESET 9 +#define SRST_P_CORE_BIU 10 +#define SRST_PMU 11 + +/* CRU-->SOFTRST_CON03 */ +#define SRST_P_DBG 12 +#define SRST_POT_DBG 13 +#define SRST_P_CORE_GRF 14 +#define SRST_CORE_EMA_DETECT 15 +#define SRST_REF_PVTPLL_CORE 16 +#define SRST_P_GPIO1 17 +#define SRST_DB_GPIO1 18 + +/* CRU-->SOFTRST_CON04 */ +#define SRST_A_CORE_PERI_BIU 19 +#define SRST_A_DSMC 20 +#define SRST_P_DSMC 21 +#define SRST_FLEXBUS 22 +#define SRST_A_FLEXBUS 23 +#define SRST_H_FLEXBUS 24 +#define SRST_A_DSMC_SLV 25 +#define SRST_H_DSMC_SLV 26 +#define SRST_DSMC_SLV 27 + +/* CRU-->SOFTRST_CON05 */ +#define SRST_A_BUS_BIU 28 +#define SRST_H_BUS_BIU 29 +#define SRST_P_BUS_BIU 30 +#define SRST_A_SYSRAM 31 +#define SRST_H_SYSRAM 32 +#define SRST_A_DMAC0 33 +#define SRST_A_DMAC1 34 +#define SRST_H_M0 35 +#define SRST_M0_JTAG 36 +#define SRST_H_CRYPTO 37 + +/* CRU-->SOFTRST_CON06 */ +#define SRST_H_RNG 38 +#define SRST_P_BUS_GRF 39 +#define SRST_P_TIMER0 40 +#define SRST_TIMER0_CH0 41 +#define SRST_TIMER0_CH1 42 +#define SRST_TIMER0_CH2 43 +#define SRST_TIMER0_CH3 44 +#define SRST_TIMER0_CH4 45 +#define SRST_TIMER0_CH5 46 +#define SRST_P_WDT0 47 +#define SRST_T_WDT0 48 +#define SRST_P_WDT1 49 +#define SRST_T_WDT1 50 +#define SRST_P_MAILBOX 51 +#define SRST_P_INTMUX 52 +#define SRST_P_SPINLOCK 53 + +/* CRU-->SOFTRST_CON07 */ +#define SRST_P_DDRC 54 +#define SRST_H_DDRPHY 55 +#define SRST_P_DDRMON 56 +#define SRST_DDRMON_OSC 57 +#define SRST_P_DDR_LPC 58 +#define SRST_H_USBOTG0 59 +#define SRST_USBOTG0_ADP 60 +#define SRST_H_USBOTG1 61 +#define SRST_USBOTG1_ADP 62 +#define SRST_P_USBPHY 63 +#define SRST_USBPHY_POR 64 +#define SRST_USBPHY_OTG0 65 +#define SRST_USBPHY_OTG1 66 + +/* CRU-->SOFTRST_CON08 */ +#define SRST_A_DMA2DDR 67 +#define SRST_P_DMA2DDR 68 + +/* CRU-->SOFTRST_CON09 */ +#define SRST_USBOTG0_UTMI 69 +#define SRST_USBOTG1_UTMI 70 + +/* CRU-->SOFTRST_CON10 */ +#define SRST_A_DDRC_0 71 +#define SRST_A_DDRC_1 72 +#define SRST_A_DDR_BIU 73 +#define SRST_DDRC 74 +#define SRST_DDRMON 75 + +/* CRU-->SOFTRST_CON11 */ +#define SRST_H_LSPERI_BIU 76 +#define SRST_P_UART0 77 +#define SRST_P_UART1 78 +#define SRST_P_UART2 79 +#define SRST_P_UART3 80 +#define SRST_P_UART4 81 +#define SRST_UART0 82 +#define SRST_UART1 83 +#define SRST_UART2 84 +#define SRST_UART3 85 +#define SRST_UART4 86 +#define SRST_P_I2C0 87 +#define SRST_I2C0 88 + +/* CRU-->SOFTRST_CON12 */ +#define SRST_P_I2C1 89 +#define SRST_I2C1 90 +#define SRST_P_I2C2 91 +#define SRST_I2C2 92 +#define SRST_P_PWM1 93 +#define SRST_PWM1 94 +#define SRST_P_SPI0 95 +#define SRST_SPI0 96 +#define SRST_P_SPI1 97 +#define SRST_SPI1 98 +#define SRST_P_GPIO2 99 +#define SRST_DB_GPIO2 100 + +/* CRU-->SOFTRST_CON13 */ +#define SRST_P_GPIO3 101 +#define SRST_DB_GPIO3 102 +#define SRST_P_GPIO4 103 +#define SRST_DB_GPIO4 104 +#define SRST_H_CAN0 105 +#define SRST_CAN0 106 +#define SRST_H_CAN1 107 +#define SRST_CAN1 108 +#define SRST_H_PDM 109 +#define SRST_M_PDM 110 +#define SRST_PDM 111 +#define SRST_SPDIFTX 112 +#define SRST_H_SPDIFTX 113 +#define SRST_H_SPDIFRX 114 +#define SRST_SPDIFRX 115 +#define SRST_M_SAI0 116 + +/* CRU-->SOFTRST_CON14 */ +#define SRST_H_SAI0 117 +#define SRST_M_SAI1 118 +#define SRST_H_SAI1 119 +#define SRST_H_ASRC0 120 +#define SRST_ASRC0 121 +#define SRST_H_ASRC1 122 +#define SRST_ASRC1 123 + +/* CRU-->SOFTRST_CON17 */ +#define SRST_H_HSPERI_BIU 124 +#define SRST_H_SDMMC 125 +#define SRST_H_FSPI 126 +#define SRST_S_FSPI 127 +#define SRST_P_SPI2 128 +#define SRST_A_MAC0 129 +#define SRST_A_MAC1 130 + +/* CRU-->SOFTRST_CON18 */ +#define SRST_M_SAI2 131 +#define SRST_H_SAI2 132 +#define SRST_H_SAI3 133 +#define SRST_M_SAI3 134 +#define SRST_H_SAI4 135 +#define SRST_M_SAI4 136 +#define SRST_H_DSM 137 +#define SRST_M_DSM 138 +#define SRST_P_AUDIO_ADC 139 +#define SRST_M_AUDIO_ADC 140 + +/* CRU-->SOFTRST_CON19 */ +#define SRST_P_SARADC 141 +#define SRST_SARADC 142 +#define SRST_SARADC_PHY 143 +#define SRST_P_OTPC_NS 144 +#define SRST_SBPI_OTPC_NS 145 +#define SRST_USER_OTPC_NS 146 +#define SRST_P_UART5 147 +#define SRST_UART5 148 +#define SRST_P_GPIO234_IOC 149 + +/* CRU-->SOFTRST_CON21 */ +#define SRST_A_VIO_BIU 150 +#define SRST_H_VIO_BIU 151 +#define SRST_H_RGA 152 +#define SRST_A_RGA 153 +#define SRST_CORE_RGA 154 +#define SRST_A_VOP 155 +#define SRST_H_VOP 156 +#define SRST_VOP 157 +#define SRST_P_DPHY 158 +#define SRST_P_DSI_HOST 159 +#define SRST_P_TSADC 160 +#define SRST_TSADC 161 + +/* CRU-->SOFTRST_CON22 */ +#define SRST_P_GPIO1_IOC 162 + +#endif From 18191dd750e6c9e17fabefd09ff418dd587bcdb9 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Fri, 21 Nov 2025 15:53:50 +0800 Subject: [PATCH 482/684] clk: rockchip: Add clock and reset driver for RK3506 Add the clock and reset tree definitions for the new RK3506 SoC. Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang Link: https://patch.msgid.link/20251121075350.2564860-3-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/Kconfig | 7 + drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk-rk3506.c | 869 ++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 13 + drivers/clk/rockchip/rst-rk3506.c | 226 ++++++++ 5 files changed, 1116 insertions(+) create mode 100644 drivers/clk/rockchip/clk-rk3506.c create mode 100644 drivers/clk/rockchip/rst-rk3506.c diff --git a/drivers/clk/rockchip/Kconfig b/drivers/clk/rockchip/Kconfig index e1ea0a098ca9f7..5cf1e0fd6fb322 100644 --- a/drivers/clk/rockchip/Kconfig +++ b/drivers/clk/rockchip/Kconfig @@ -100,6 +100,13 @@ config CLK_RK3399 help Build the driver for RK3399 Clock Driver. +config CLK_RK3506 + bool "Rockchip RK3506 clock controller support" + depends on ARM || COMPILE_TEST + default y + help + Build the driver for RK3506 Clock Driver. + config CLK_RK3528 bool "Rockchip RK3528 clock controller support" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 82b4b29ad036b8..4d8cbb2044c7c3 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_CLK_RK3308) += clk-rk3308.o obj-$(CONFIG_CLK_RK3328) += clk-rk3328.o obj-$(CONFIG_CLK_RK3368) += clk-rk3368.o obj-$(CONFIG_CLK_RK3399) += clk-rk3399.o +obj-$(CONFIG_CLK_RK3506) += clk-rk3506.o rst-rk3506.o obj-$(CONFIG_CLK_RK3528) += clk-rk3528.o rst-rk3528.o obj-$(CONFIG_CLK_RK3562) += clk-rk3562.o rst-rk3562.o obj-$(CONFIG_CLK_RK3568) += clk-rk3568.o diff --git a/drivers/clk/rockchip/clk-rk3506.c b/drivers/clk/rockchip/clk-rk3506.c new file mode 100644 index 00000000000000..dd59bd60382ef0 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3506.c @@ -0,0 +1,869 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023-2025 Rockchip Electronics Co., Ltd. + * Author: Finley Xiao + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" + +#define PVTPLL_SRC_SEL_PVTPLL (BIT(7) | BIT(23)) + +enum rk3506_plls { + gpll, v0pll, v1pll, +}; + +/* + * [FRAC PLL]: GPLL, V0PLL, V1PLL + * - VCO Frequency: 950MHz to 3800MHZ + * - Output Frequency: 19MHz to 3800MHZ + * - refdiv: 1 to 63 (Int Mode), 1 to 2 (Frac Mode) + * - fbdiv: 16 to 3800 (Int Mode), 20 to 380 (Frac Mode) + * - post1div: 1 to 7 + * - post2div: 1 to 7 + */ +static struct rockchip_pll_rate_table rk3506_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), + RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), + RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK3036_PLL_RATE(1350000000, 4, 225, 1, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), + RK3036_PLL_RATE(1179648000, 1, 49, 1, 1, 0, 2550137), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 3, 125, 1, 1, 1, 0), + RK3036_PLL_RATE(993484800, 1, 41, 1, 1, 0, 6630355), + RK3036_PLL_RATE(983040000, 1, 40, 1, 1, 0, 16106127), + RK3036_PLL_RATE(960000000, 1, 80, 2, 1, 1, 0), + RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE(903168000, 1, 75, 2, 1, 0, 4429185), + RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0), + RK3036_PLL_RATE(600000000, 1, 50, 2, 1, 1, 0), + RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0), + RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE(96000000, 1, 48, 6, 2, 1, 0), + { /* sentinel */ }, +}; + +#define RK3506_DIV_ACLK_CORE_MASK 0xf +#define RK3506_DIV_ACLK_CORE_SHIFT 9 +#define RK3506_DIV_PCLK_CORE_MASK 0xf +#define RK3506_DIV_PCLK_CORE_SHIFT 0 + +#define RK3506_CLKSEL15(_aclk_core_div) \ +{ \ + .reg = RK3506_CLKSEL_CON(15), \ + .val = HIWORD_UPDATE(_aclk_core_div, RK3506_DIV_ACLK_CORE_MASK, \ + RK3506_DIV_ACLK_CORE_SHIFT), \ +} + +#define RK3506_CLKSEL16(_pclk_core_div) \ +{ \ + .reg = RK3506_CLKSEL_CON(16), \ + .val = HIWORD_UPDATE(_pclk_core_div, RK3506_DIV_PCLK_CORE_MASK, \ + RK3506_DIV_PCLK_CORE_SHIFT), \ +} + +/* SIGN-OFF: aclk_core: 500M, pclk_core: 125M, */ +#define RK3506_CPUCLK_RATE(_prate, _aclk_core_div, _pclk_core_div) \ +{ \ + .prate = _prate, \ + .divs = { \ + RK3506_CLKSEL15(_aclk_core_div), \ + RK3506_CLKSEL16(_pclk_core_div), \ + }, \ +} + +static struct rockchip_cpuclk_rate_table rk3506_cpuclk_rates[] __initdata = { + RK3506_CPUCLK_RATE(1608000000, 3, 12), + RK3506_CPUCLK_RATE(1512000000, 3, 12), + RK3506_CPUCLK_RATE(1416000000, 2, 11), + RK3506_CPUCLK_RATE(1296000000, 2, 10), + RK3506_CPUCLK_RATE(1200000000, 2, 9), + RK3506_CPUCLK_RATE(1179648000, 2, 9), + RK3506_CPUCLK_RATE(1008000000, 1, 7), + RK3506_CPUCLK_RATE(903168000, 1, 7), + RK3506_CPUCLK_RATE(800000000, 1, 6), + RK3506_CPUCLK_RATE(750000000, 1, 5), + RK3506_CPUCLK_RATE(589824000, 1, 4), + RK3506_CPUCLK_RATE(400000000, 1, 3), + RK3506_CPUCLK_RATE(200000000, 1, 1), +}; + +PNAME(mux_pll_p) = { "xin24m" }; +PNAME(gpll_v0pll_v1pll_parents_p) = { "gpll", "v0pll", "v1pll" }; +PNAME(gpll_v0pll_v1pll_g_parents_p) = { "clk_gpll_gate", "clk_v0pll_gate", "clk_v1pll_gate" }; +PNAME(gpll_v0pll_v1pll_div_parents_p) = { "clk_gpll_div", "clk_v0pll_div", "clk_v1pll_div" }; +PNAME(xin24m_gpll_v0pll_v1pll_g_parents_p) = { "xin24m", "clk_gpll_gate", "clk_v0pll_gate", "clk_v1pll_gate" }; +PNAME(xin24m_g_gpll_v0pll_v1pll_g_parents_p) = { "xin24m_gate", "clk_gpll_gate", "clk_v0pll_gate", "clk_v1pll_gate" }; +PNAME(xin24m_g_gpll_v0pll_v1pll_div_parents_p) = { "xin24m_gate", "clk_gpll_div", "clk_v0pll_div", "clk_v1pll_div" }; +PNAME(xin24m_400k_32k_parents_p) = { "xin24m", "clk_rc", "clk_32k" }; +PNAME(clk_frac_uart_matrix0_mux_parents_p) = { "xin24m", "gpll", "clk_v0pll_gate", "clk_v1pll_gate" }; +PNAME(clk_timer0_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "sai0_mclk_in", "sai0_sclk_in" }; +PNAME(clk_timer1_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "sai1_mclk_in", "sai1_sclk_in" }; +PNAME(clk_timer2_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "sai2_mclk_in", "sai2_sclk_in" }; +PNAME(clk_timer3_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "sai3_mclk_in", "sai3_sclk_in" }; +PNAME(clk_timer4_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "mclk_asrc0" }; +PNAME(clk_timer5_parents_p) = { "xin24m", "clk_gpll_div_100m", "clk_32k", "clk_core_pvtpll", "mclk_asrc1" }; +PNAME(sclk_uart_parents_p) = { "xin24m", "clk_gpll_gate", "clk_v0pll_gate", "clk_frac_uart_matrix0", "clk_frac_uart_matrix1", + "clk_frac_common_matrix0", "clk_frac_common_matrix1", "clk_frac_common_matrix2" }; +PNAME(clk_mac_ptp_root_parents_p) = { "gpll", "v0pll", "v1pll" }; +PNAME(clk_pwm_parents_p) = { "clk_rc", "sai0_mclk_in", "sai1_mclk_in", "sai2_mclk_in", "sai3_mclk_in", "sai0_sclk_in", "sai1_sclk_in", + "sai2_sclk_in", "sai3_sclk_in", "mclk_asrc0", "mclk_asrc1" }; +PNAME(clk_can_parents_p) = { "xin24m", "gpll", "clk_v0pll_gate", "clk_v1pll_gate", "clk_frac_voice_matrix1", + "clk_frac_common_matrix0", "clk_frac_common_matrix1", "clk_frac_common_matrix2" }; +PNAME(clk_pdm_parents_p) = { "xin24m_gate", "clk_int_voice_matrix0", "clk_int_voice_matrix1", "clk_int_voice_matrix2", + "clk_frac_voice_matrix0", "clk_frac_voice_matrix1", "clk_frac_common_matrix0", "clk_frac_common_matrix1", + "clk_frac_common_matrix2", "sai0_mclk_in", "sai1_mclk_in", "sai2_mclk_in", "sai3_mclk_in", "clk_gpll_div" }; +PNAME(mclk_sai_asrc_parents_p) = { "xin24m_gate", "clk_int_voice_matrix0", "clk_int_voice_matrix1", "clk_int_voice_matrix2", + "clk_frac_voice_matrix0", "clk_frac_voice_matrix1", "clk_frac_common_matrix0", "clk_frac_common_matrix1", + "clk_frac_common_matrix2", "sai0_mclk_in", "sai1_mclk_in", "sai2_mclk_in", "sai3_mclk_in" }; +PNAME(lrck_asrc_parents_p) = { "mclk_asrc0", "mclk_asrc1", "mclk_asrc2", "mclk_asrc3", "mclk_spdiftx", "clk_spdifrx_to_asrc", "clkout_pdm", + "sai0_fs", "sai1_fs", "sai2_fs", "sai3_fs", "sai4_fs" }; +PNAME(cclk_src_sdmmc_parents_p) = { "xin24m_gate", "gpll", "clk_v0pll_gate", "clk_v1pll_gate" }; +PNAME(dclk_vop_parents_p) = { "xin24m_gate", "clk_gpll_gate", "clk_v0pll_gate", "clk_v1pll_gate", "dummy_vop_dclk", + "dummy_vop_dclk", "dummy_vop_dclk", "dummy_vop_dclk" }; +PNAME(dbclk_gpio0_parents_p) = { "xin24m", "clk_rc", "clk_32k_pmu" }; +PNAME(clk_pmu_hp_timer_parents_p) = { "xin24m", "gpll_div_100m", "clk_core_pvtpll" }; +PNAME(clk_ref_out_parents_p) = { "xin24m", "gpll", "v0pll", "v1pll" }; +PNAME(clk_32k_frac_parents_p) = { "xin24m", "v0pll", "v1pll", "clk_rc" }; +PNAME(clk_32k_parents_p) = { "xin32k", "clk_32k_rc", "clk_32k_frac" }; +PNAME(clk_ref_phy_pmu_mux_parents_p) = { "xin24m", "clk_ref_phy_pll" }; +PNAME(clk_vpll_ref_parents_p) = { "xin24m", "clk_pll_ref_io" }; +PNAME(mux_armclk_p) = { "armclk_pll", "clk_core_pvtpll" }; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +static struct rockchip_pll_clock rk3506_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, + CLK_IS_CRITICAL, RK3506_PLL_CON(0), + RK3506_MODE_CON, 0, 2, 0, rk3506_pll_rates), + [v0pll] = PLL(pll_rk3328, PLL_V0PLL, "v0pll", mux_pll_p, + CLK_IS_CRITICAL, RK3506_PLL_CON(8), + RK3506_MODE_CON, 2, 0, 0, rk3506_pll_rates), + [v1pll] = PLL(pll_rk3328, PLL_V1PLL, "v1pll", mux_pll_p, + CLK_IS_CRITICAL, RK3506_PLL_CON(16), + RK3506_MODE_CON, 4, 1, 0, rk3506_pll_rates), +}; + +static struct rockchip_clk_branch rk3506_armclk __initdata = + MUX(ARMCLK, "armclk", mux_armclk_p, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + RK3506_CLKSEL_CON(15), 8, 1, MFLAGS); + +static struct rockchip_clk_branch rk3506_clk_branches[] __initdata = { + /* + * CRU Clock-Architecture + */ + /* top */ + GATE(XIN24M_GATE, "xin24m_gate", "xin24m", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(0), 1, GFLAGS), + GATE(CLK_GPLL_GATE, "clk_gpll_gate", "gpll", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(0), 2, GFLAGS), + GATE(CLK_V0PLL_GATE, "clk_v0pll_gate", "v0pll", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(0), 3, GFLAGS), + GATE(CLK_V1PLL_GATE, "clk_v1pll_gate", "v1pll", 0, + RK3506_CLKGATE_CON(0), 4, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV, "clk_gpll_div", "clk_gpll_gate", CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(0), 6, 4, DFLAGS, + RK3506_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(CLK_GPLL_DIV_100M, "clk_gpll_div_100m", "clk_gpll_div", 0, + RK3506_CLKSEL_CON(0), 10, 4, DFLAGS, + RK3506_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(CLK_V0PLL_DIV, "clk_v0pll_div", "clk_v0pll_gate", CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(1), 0, 4, DFLAGS, + RK3506_CLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_NOMUX(CLK_V1PLL_DIV, "clk_v1pll_div", "clk_v1pll_gate", 0, + RK3506_CLKSEL_CON(1), 4, 4, DFLAGS, + RK3506_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NOMUX(CLK_INT_VOICE_MATRIX0, "clk_int_voice_matrix0", "clk_v0pll_gate", 0, + RK3506_CLKSEL_CON(1), 8, 5, DFLAGS, + RK3506_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_NOMUX(CLK_INT_VOICE_MATRIX1, "clk_int_voice_matrix1", "clk_v1pll_gate", 0, + RK3506_CLKSEL_CON(2), 0, 5, DFLAGS, + RK3506_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE_NOMUX(CLK_INT_VOICE_MATRIX2, "clk_int_voice_matrix2", "clk_v0pll_gate", 0, + RK3506_CLKSEL_CON(2), 5, 5, DFLAGS, + RK3506_CLKGATE_CON(0), 11, GFLAGS), + MUX(CLK_FRAC_UART_MATRIX0_MUX, "clk_frac_uart_matrix0_mux", clk_frac_uart_matrix0_mux_parents_p, 0, + RK3506_CLKSEL_CON(3), 9, 2, MFLAGS), + MUX(CLK_FRAC_UART_MATRIX1_MUX, "clk_frac_uart_matrix1_mux", xin24m_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(3), 11, 2, MFLAGS), + MUX(CLK_FRAC_VOICE_MATRIX0_MUX, "clk_frac_voice_matrix0_mux", xin24m_g_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(3), 13, 2, MFLAGS), + MUX(CLK_FRAC_VOICE_MATRIX1_MUX, "clk_frac_voice_matrix1_mux", xin24m_g_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(4), 0, 2, MFLAGS), + MUX(CLK_FRAC_COMMON_MATRIX0_MUX, "clk_frac_common_matrix0_mux", xin24m_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(4), 2, 2, MFLAGS), + MUX(CLK_FRAC_COMMON_MATRIX1_MUX, "clk_frac_common_matrix1_mux", xin24m_g_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(4), 4, 2, MFLAGS), + MUX(CLK_FRAC_COMMON_MATRIX2_MUX, "clk_frac_common_matrix2_mux", xin24m_g_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(4), 6, 2, MFLAGS), + COMPOSITE_FRAC(CLK_FRAC_UART_MATRIX0, "clk_frac_uart_matrix0", "clk_frac_uart_matrix0_mux", 0, + RK3506_CLKSEL_CON(5), 0, + RK3506_CLKGATE_CON(0), 13, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_UART_MATRIX1, "clk_frac_uart_matrix1", "clk_frac_uart_matrix1_mux", 0, + RK3506_CLKSEL_CON(6), 0, + RK3506_CLKGATE_CON(0), 14, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_VOICE_MATRIX0, "clk_frac_voice_matrix0", "clk_frac_voice_matrix0_mux", 0, + RK3506_CLKSEL_CON(7), 0, + RK3506_CLKGATE_CON(0), 15, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_VOICE_MATRIX1, "clk_frac_voice_matrix1", "clk_frac_voice_matrix1_mux", 0, + RK3506_CLKSEL_CON(9), 0, + RK3506_CLKGATE_CON(1), 0, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_COMMON_MATRIX0, "clk_frac_common_matrix0", "clk_frac_common_matrix0_mux", 0, + RK3506_CLKSEL_CON(11), 0, + RK3506_CLKGATE_CON(1), 1, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_COMMON_MATRIX1, "clk_frac_common_matrix1", "clk_frac_common_matrix1_mux", 0, + RK3506_CLKSEL_CON(12), 0, + RK3506_CLKGATE_CON(1), 2, GFLAGS), + COMPOSITE_FRAC(CLK_FRAC_COMMON_MATRIX2, "clk_frac_common_matrix2", "clk_frac_common_matrix2_mux", 0, + RK3506_CLKSEL_CON(13), 0, + RK3506_CLKGATE_CON(1), 3, GFLAGS), + GATE(CLK_REF_USBPHY_TOP, "clk_ref_usbphy_top", "xin24m", 0, + RK3506_CLKGATE_CON(1), 4, GFLAGS), + GATE(CLK_REF_DPHY_TOP, "clk_ref_dphy_top", "xin24m", 0, + RK3506_CLKGATE_CON(1), 5, GFLAGS), + + /* core */ + COMPOSITE_NOGATE(0, "armclk_pll", gpll_v0pll_v1pll_parents_p, CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(15), 5, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(ACLK_CORE_ROOT, "aclk_core_root", "armclk", CLK_IGNORE_UNUSED, + RK3506_CLKSEL_CON(15), 9, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3506_CLKGATE_CON(2), 11, GFLAGS), + COMPOSITE_NOMUX(PCLK_CORE_ROOT, "pclk_core_root", "armclk", CLK_IGNORE_UNUSED, + RK3506_CLKSEL_CON(16), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3506_CLKGATE_CON(2), 12, GFLAGS), + GATE(PCLK_DBG, "pclk_dbg", "pclk_core_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(3), 1, GFLAGS), + GATE(PCLK_CORE_GRF, "pclk_core_grf", "pclk_core_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(3), 4, GFLAGS), + GATE(PCLK_CORE_CRU, "pclk_core_cru", "pclk_core_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(3), 5, GFLAGS), + GATE(CLK_CORE_EMA_DETECT, "clk_core_ema_detect", "xin24m_gate", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(3), 6, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "aclk_core_root", 0, + RK3506_CLKGATE_CON(3), 8, GFLAGS), + GATE(DBCLK_GPIO1, "dbclk_gpio1", "xin24m_gate", 0, + RK3506_CLKGATE_CON(3), 9, GFLAGS), + + /* core peri */ + COMPOSITE(ACLK_CORE_PERI_ROOT, "aclk_core_peri_root", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(18), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(4), 0, GFLAGS), + GATE(HCLK_CORE_PERI_ROOT, "hclk_core_peri_root", "aclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 1, GFLAGS), + GATE(PCLK_CORE_PERI_ROOT, "pclk_core_peri_root", "aclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 2, GFLAGS), + COMPOSITE(CLK_DSMC, "clk_dsmc", xin24m_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(18), 12, 2, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(4), 4, GFLAGS), + GATE(ACLK_DSMC, "aclk_dsmc", "aclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 5, GFLAGS), + GATE(PCLK_DSMC, "pclk_dsmc", "pclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 6, GFLAGS), + COMPOSITE(CLK_FLEXBUS_TX, "clk_flexbus_tx", xin24m_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(19), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(4), 7, GFLAGS), + COMPOSITE(CLK_FLEXBUS_RX, "clk_flexbus_rx", xin24m_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(19), 12, 2, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(4), 8, GFLAGS), + GATE(ACLK_FLEXBUS, "aclk_flexbus", "aclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 9, GFLAGS), + GATE(HCLK_FLEXBUS, "hclk_flexbus", "hclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 10, GFLAGS), + GATE(ACLK_DSMC_SLV, "aclk_dsmc_slv", "aclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 11, GFLAGS), + GATE(HCLK_DSMC_SLV, "hclk_dsmc_slv", "hclk_core_peri_root", 0, + RK3506_CLKGATE_CON(4), 12, GFLAGS), + + /* bus */ + COMPOSITE(ACLK_BUS_ROOT, "aclk_bus_root", gpll_v0pll_v1pll_div_parents_p, CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(21), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(5), 0, GFLAGS), + COMPOSITE(HCLK_BUS_ROOT, "hclk_bus_root", gpll_v0pll_v1pll_div_parents_p, CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(21), 12, 2, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(5), 1, GFLAGS), + COMPOSITE(PCLK_BUS_ROOT, "pclk_bus_root", gpll_v0pll_v1pll_div_parents_p, CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(22), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(5), 2, GFLAGS), + GATE(ACLK_SYSRAM, "aclk_sysram", "aclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(5), 6, GFLAGS), + GATE(HCLK_SYSRAM, "hclk_sysram", "aclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(5), 7, GFLAGS), + GATE(ACLK_DMAC0, "aclk_dmac0", "aclk_bus_root", 0, + RK3506_CLKGATE_CON(5), 8, GFLAGS), + GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_bus_root", 0, + RK3506_CLKGATE_CON(5), 9, GFLAGS), + GATE(HCLK_M0, "hclk_m0", "aclk_bus_root", 0, + RK3506_CLKGATE_CON(5), 10, GFLAGS), + GATE(ACLK_CRYPTO_NS, "aclk_crypto_ns", "aclk_bus_root", 0, + RK3506_CLKGATE_CON(5), 14, GFLAGS), + GATE(HCLK_CRYPTO_NS, "hclk_crypto_ns", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(5), 15, GFLAGS), + GATE(HCLK_RNG, "hclk_rng", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 0, GFLAGS), + GATE(PCLK_BUS_GRF, "pclk_bus_grf", "pclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(6), 1, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 2, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH0, "clk_timer0_ch0", clk_timer0_parents_p, 0, + RK3506_CLKSEL_CON(22), 7, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 3, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH1, "clk_timer0_ch1", clk_timer1_parents_p, 0, + RK3506_CLKSEL_CON(22), 10, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 4, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH2, "clk_timer0_ch2", clk_timer2_parents_p, 0, + RK3506_CLKSEL_CON(22), 13, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 5, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH3, "clk_timer0_ch3", clk_timer3_parents_p, 0, + RK3506_CLKSEL_CON(23), 0, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 6, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH4, "clk_timer0_ch4", clk_timer4_parents_p, 0, + RK3506_CLKSEL_CON(23), 3, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 7, GFLAGS), + COMPOSITE_NODIV(CLK_TIMER0_CH5, "clk_timer0_ch5", clk_timer5_parents_p, 0, + RK3506_CLKSEL_CON(23), 6, 3, MFLAGS, + RK3506_CLKGATE_CON(6), 8, GFLAGS), + GATE(PCLK_WDT0, "pclk_wdt0", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 9, GFLAGS), + GATE(TCLK_WDT0, "tclk_wdt0", "xin24m_gate", 0, + RK3506_CLKGATE_CON(6), 10, GFLAGS), + GATE(PCLK_WDT1, "pclk_wdt1", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 11, GFLAGS), + GATE(TCLK_WDT1, "tclk_wdt1", "xin24m_gate", 0, + RK3506_CLKGATE_CON(6), 12, GFLAGS), + GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 13, GFLAGS), + GATE(PCLK_INTMUX, "pclk_intmux", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 14, GFLAGS), + GATE(PCLK_SPINLOCK, "pclk_spinlock", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(6), 15, GFLAGS), + GATE(PCLK_DDRC, "pclk_ddrc", "pclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(7), 0, GFLAGS), + GATE(HCLK_DDRPHY, "hclk_ddrphy", "hclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(7), 1, GFLAGS), + GATE(PCLK_DDRMON, "pclk_ddrmon", "pclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(7), 2, GFLAGS), + GATE(CLK_DDRMON_OSC, "clk_ddrmon_osc", "xin24m_gate", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(7), 3, GFLAGS), + GATE(PCLK_STDBY, "pclk_stdby", "pclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(7), 4, GFLAGS), + GATE(HCLK_USBOTG0, "hclk_usbotg0", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(7), 5, GFLAGS), + GATE(HCLK_USBOTG0_PMU, "hclk_usbotg0_pmu", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(7), 6, GFLAGS), + GATE(CLK_USBOTG0_ADP, "clk_usbotg0_adp", "clk_32k", 0, + RK3506_CLKGATE_CON(7), 7, GFLAGS), + GATE(HCLK_USBOTG1, "hclk_usbotg1", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(7), 8, GFLAGS), + GATE(HCLK_USBOTG1_PMU, "hclk_usbotg1_pmu", "hclk_bus_root", 0, + RK3506_CLKGATE_CON(7), 9, GFLAGS), + GATE(CLK_USBOTG1_ADP, "clk_usbotg1_adp", "clk_32k", 0, + RK3506_CLKGATE_CON(7), 10, GFLAGS), + GATE(PCLK_USBPHY, "pclk_usbphy", "pclk_bus_root", 0, + RK3506_CLKGATE_CON(7), 11, GFLAGS), + GATE(ACLK_DMA2DDR, "aclk_dma2ddr", "aclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(8), 0, GFLAGS), + GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_bus_root", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(8), 1, GFLAGS), + COMPOSITE_NOMUX(STCLK_M0, "stclk_m0", "xin24m_gate", 0, + RK3506_CLKSEL_CON(23), 9, 6, DFLAGS, + RK3506_CLKGATE_CON(8), 2, GFLAGS), + COMPOSITE(CLK_DDRPHY, "clk_ddrphy", gpll_v0pll_v1pll_parents_p, CLK_IGNORE_UNUSED, + RK3506_PMU_CLKSEL_CON(4), 4, 2, MFLAGS, 0, 4, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 10, GFLAGS), + FACTOR(CLK_DDRC_SRC, "clk_ddrc_src", "clk_ddrphy", 0, 1, 4), + GATE(ACLK_DDRC_0, "aclk_ddrc_0", "clk_ddrc_src", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(10), 0, GFLAGS), + GATE(ACLK_DDRC_1, "aclk_ddrc_1", "clk_ddrc_src", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(10), 1, GFLAGS), + GATE(CLK_DDRC, "clk_ddrc", "clk_ddrc_src", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(10), 3, GFLAGS), + GATE(CLK_DDRMON, "clk_ddrmon", "clk_ddrc_src", CLK_IGNORE_UNUSED, + RK3506_CLKGATE_CON(10), 4, GFLAGS), + + /* ls peri */ + COMPOSITE(HCLK_LSPERI_ROOT, "hclk_lsperi_root", gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(29), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 0, GFLAGS), + GATE(PCLK_LSPERI_ROOT, "pclk_lsperi_root", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 1, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 4, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 5, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 6, GFLAGS), + GATE(PCLK_UART3, "pclk_uart3", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 7, GFLAGS), + GATE(PCLK_UART4, "pclk_uart4", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 8, GFLAGS), + COMPOSITE(SCLK_UART0, "sclk_uart0", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(29), 12, 3, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 9, GFLAGS), + COMPOSITE(SCLK_UART1, "sclk_uart1", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(30), 5, 3, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 10, GFLAGS), + COMPOSITE(SCLK_UART2, "sclk_uart2", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(30), 13, 3, MFLAGS, 8, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 11, GFLAGS), + COMPOSITE(SCLK_UART3, "sclk_uart3", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(31), 5, 3, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 12, GFLAGS), + COMPOSITE(SCLK_UART4, "sclk_uart4", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(31), 13, 3, MFLAGS, 8, 5, DFLAGS, + RK3506_CLKGATE_CON(11), 13, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(11), 14, GFLAGS), + COMPOSITE(CLK_I2C0, "clk_i2c0", xin24m_g_gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(32), 4, 2, MFLAGS, 0, 4, DFLAGS, + RK3506_CLKGATE_CON(11), 15, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 0, GFLAGS), + COMPOSITE(CLK_I2C1, "clk_i2c1", xin24m_g_gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(32), 10, 2, MFLAGS, 6, 4, DFLAGS, + RK3506_CLKGATE_CON(12), 1, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 2, GFLAGS), + COMPOSITE(CLK_I2C2, "clk_i2c2", xin24m_g_gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(33), 4, 2, MFLAGS, 0, 4, DFLAGS, + RK3506_CLKGATE_CON(12), 3, GFLAGS), + GATE(PCLK_PWM1, "pclk_pwm1", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 4, GFLAGS), + COMPOSITE(CLK_PWM1, "clk_pwm1", gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(33), 10, 2, MFLAGS, 6, 4, DFLAGS, + RK3506_CLKGATE_CON(12), 5, GFLAGS), + GATE(CLK_OSC_PWM1, "clk_osc_pwm1", "xin24m", 0, + RK3506_CLKGATE_CON(12), 6, GFLAGS), + GATE(CLK_RC_PWM1, "clk_rc_pwm1", "clk_rc", 0, + RK3506_CLKGATE_CON(12), 7, GFLAGS), + COMPOSITE_NODIV(CLK_FREQ_PWM1, "clk_freq_pwm1", clk_pwm_parents_p, 0, + RK3506_CLKSEL_CON(33), 12, 4, MFLAGS, + RK3506_CLKGATE_CON(12), 8, GFLAGS), + COMPOSITE_NODIV(CLK_COUNTER_PWM1, "clk_counter_pwm1", clk_pwm_parents_p, 0, + RK3506_CLKSEL_CON(34), 0, 4, MFLAGS, + RK3506_CLKGATE_CON(12), 9, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 10, GFLAGS), + COMPOSITE(CLK_SPI0, "clk_spi0", xin24m_g_gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(34), 8, 2, MFLAGS, 4, 4, DFLAGS, + RK3506_CLKGATE_CON(12), 11, GFLAGS), + GATE(PCLK_SPI1, "pclk_spi1", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 12, GFLAGS), + COMPOSITE(CLK_SPI1, "clk_spi1", xin24m_g_gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(34), 14, 2, MFLAGS, 10, 4, DFLAGS, + RK3506_CLKGATE_CON(12), 13, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(12), 14, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO2, "dbclk_gpio2", xin24m_400k_32k_parents_p, 0, + RK3506_CLKSEL_CON(35), 0, 2, MFLAGS, + RK3506_CLKGATE_CON(12), 15, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 0, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO3, "dbclk_gpio3", xin24m_400k_32k_parents_p, 0, + RK3506_CLKSEL_CON(35), 2, 2, MFLAGS, + RK3506_CLKGATE_CON(13), 1, GFLAGS), + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 2, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO4, "dbclk_gpio4", xin24m_400k_32k_parents_p, 0, + RK3506_CLKSEL_CON(35), 4, 2, MFLAGS, + RK3506_CLKGATE_CON(13), 3, GFLAGS), + GATE(HCLK_CAN0, "hclk_can0", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 4, GFLAGS), + COMPOSITE(CLK_CAN0, "clk_can0", clk_can_parents_p, 0, + RK3506_CLKSEL_CON(35), 11, 3, MFLAGS, 6, 5, DFLAGS, + RK3506_CLKGATE_CON(13), 5, GFLAGS), + GATE(HCLK_CAN1, "hclk_can1", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 6, GFLAGS), + COMPOSITE(CLK_CAN1, "clk_can1", clk_can_parents_p, 0, + RK3506_CLKSEL_CON(36), 5, 3, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(13), 7, GFLAGS), + GATE(HCLK_PDM, "hclk_pdm", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 8, GFLAGS), + COMPOSITE(MCLK_PDM, "mclk_pdm", clk_pdm_parents_p, 0, + RK3506_CLKSEL_CON(37), 5, 4, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(13), 9, GFLAGS), + COMPOSITE(CLKOUT_PDM, "clkout_pdm", clk_pdm_parents_p, 0, + RK3506_CLKSEL_CON(38), 10, 4, MFLAGS, 0, 10, DFLAGS, + RK3506_CLKGATE_CON(13), 10, GFLAGS), + COMPOSITE(MCLK_SPDIFTX, "mclk_spdiftx", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(39), 5, 4, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(13), 11, GFLAGS), + GATE(HCLK_SPDIFTX, "hclk_spdiftx", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 12, GFLAGS), + GATE(HCLK_SPDIFRX, "hclk_spdifrx", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(13), 13, GFLAGS), + COMPOSITE(MCLK_SPDIFRX, "mclk_spdifrx", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(39), 14, 2, MFLAGS, 9, 5, DFLAGS, + RK3506_CLKGATE_CON(13), 14, GFLAGS), + COMPOSITE(MCLK_SAI0, "mclk_sai0", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(40), 8, 4, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(13), 15, GFLAGS), + GATE(HCLK_SAI0, "hclk_sai0", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(14), 0, GFLAGS), + GATE(MCLK_OUT_SAI0, "mclk_out_sai0", "mclk_sai0", 0, + RK3506_CLKGATE_CON(14), 1, GFLAGS), + COMPOSITE(MCLK_SAI1, "mclk_sai1", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(41), 8, 4, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(14), 2, GFLAGS), + GATE(HCLK_SAI1, "hclk_sai1", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(14), 3, GFLAGS), + GATE(MCLK_OUT_SAI1, "mclk_out_sai1", "mclk_sai1", 0, + RK3506_CLKGATE_CON(14), 4, GFLAGS), + GATE(HCLK_ASRC0, "hclk_asrc0", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(14), 5, GFLAGS), + COMPOSITE(CLK_ASRC0, "clk_asrc0", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(42), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(14), 6, GFLAGS), + GATE(HCLK_ASRC1, "hclk_asrc1", "hclk_lsperi_root", 0, + RK3506_CLKGATE_CON(14), 7, GFLAGS), + COMPOSITE(CLK_ASRC1, "clk_asrc1", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(42), 12, 2, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_CRU, "pclk_cru", "pclk_lsperi_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(14), 9, GFLAGS), + GATE(PCLK_PMU_ROOT, "pclk_pmu_root", "pclk_lsperi_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(14), 10, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC0, "mclk_asrc0", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(46), 0, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 0, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC1, "mclk_asrc1", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(46), 4, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 1, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC2, "mclk_asrc2", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(46), 8, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 2, GFLAGS), + COMPOSITE_NODIV(MCLK_ASRC3, "mclk_asrc3", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(46), 12, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 3, GFLAGS), + COMPOSITE_NODIV(LRCK_ASRC0_SRC, "lrck_asrc0_src", lrck_asrc_parents_p, 0, + RK3506_CLKSEL_CON(47), 0, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 4, GFLAGS), + COMPOSITE_NODIV(LRCK_ASRC0_DST, "lrck_asrc0_dst", lrck_asrc_parents_p, 0, + RK3506_CLKSEL_CON(47), 4, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 5, GFLAGS), + COMPOSITE_NODIV(LRCK_ASRC1_SRC, "lrck_asrc1_src", lrck_asrc_parents_p, 0, + RK3506_CLKSEL_CON(47), 8, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 6, GFLAGS), + COMPOSITE_NODIV(LRCK_ASRC1_DST, "lrck_asrc1_dst", lrck_asrc_parents_p, 0, + RK3506_CLKSEL_CON(47), 12, 4, MFLAGS, + RK3506_CLKGATE_CON(16), 7, GFLAGS), + + /* hs peri */ + COMPOSITE(ACLK_HSPERI_ROOT, "aclk_hsperi_root", gpll_v0pll_v1pll_div_parents_p, CLK_IS_CRITICAL, + RK3506_CLKSEL_CON(49), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(17), 0, GFLAGS), + GATE(HCLK_HSPERI_ROOT, "hclk_hsperi_root", "aclk_hsperi_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(17), 1, GFLAGS), + GATE(PCLK_HSPERI_ROOT, "pclk_hsperi_root", "hclk_hsperi_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(17), 2, GFLAGS), + COMPOSITE(CCLK_SRC_SDMMC, "cclk_src_sdmmc", cclk_src_sdmmc_parents_p, 0, + RK3506_CLKSEL_CON(49), 13, 2, MFLAGS, 7, 6, DFLAGS, + RK3506_CLKGATE_CON(17), 6, GFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 7, GFLAGS), + GATE(HCLK_FSPI, "hclk_fspi", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 8, GFLAGS), + COMPOSITE(SCLK_FSPI, "sclk_fspi", xin24m_g_gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(50), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(17), 9, GFLAGS), + GATE(PCLK_SPI2, "pclk_spi2", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 10, GFLAGS), + GATE(ACLK_MAC0, "aclk_mac0", "aclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 11, GFLAGS), + GATE(ACLK_MAC1, "aclk_mac1", "aclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 12, GFLAGS), + GATE(PCLK_MAC0, "pclk_mac0", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 13, GFLAGS), + GATE(PCLK_MAC1, "pclk_mac1", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(17), 14, GFLAGS), + COMPOSITE_NOMUX(CLK_MAC_ROOT, "clk_mac_root", "gpll", 0, + RK3506_CLKSEL_CON(50), 7, 5, DFLAGS, + RK3506_CLKGATE_CON(17), 15, GFLAGS), + GATE(CLK_MAC0, "clk_mac0", "clk_mac_root", 0, + RK3506_CLKGATE_CON(18), 0, GFLAGS), + GATE(CLK_MAC1, "clk_mac1", "clk_mac_root", 0, + RK3506_CLKGATE_CON(18), 1, GFLAGS), + COMPOSITE(MCLK_SAI2, "mclk_sai2", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(51), 8, 4, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(18), 2, GFLAGS), + GATE(HCLK_SAI2, "hclk_sai2", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(18), 3, GFLAGS), + GATE(MCLK_OUT_SAI2, "mclk_out_sai2", "mclk_sai2", 0, + RK3506_CLKGATE_CON(18), 4, GFLAGS), + COMPOSITE(MCLK_SAI3_SRC, "mclk_sai3_src", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(52), 8, 4, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(18), 5, GFLAGS), + GATE(HCLK_SAI3, "hclk_sai3", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(18), 6, GFLAGS), + GATE(MCLK_SAI3, "mclk_sai3", "mclk_sai3_src", 0, + RK3506_CLKGATE_CON(18), 7, GFLAGS), + GATE(MCLK_OUT_SAI3, "mclk_out_sai3", "mclk_sai3_src", 0, + RK3506_CLKGATE_CON(18), 8, GFLAGS), + COMPOSITE(MCLK_SAI4_SRC, "mclk_sai4_src", mclk_sai_asrc_parents_p, 0, + RK3506_CLKSEL_CON(53), 8, 4, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(18), 9, GFLAGS), + GATE(HCLK_SAI4, "hclk_sai4", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(18), 10, GFLAGS), + GATE(MCLK_SAI4, "mclk_sai4", "mclk_sai4_src", 0, + RK3506_CLKGATE_CON(18), 11, GFLAGS), + GATE(HCLK_DSM, "hclk_dsm", "hclk_hsperi_root", 0, + RK3506_CLKGATE_CON(18), 12, GFLAGS), + GATE(MCLK_DSM, "mclk_dsm", "mclk_sai3_src", 0, + RK3506_CLKGATE_CON(18), 13, GFLAGS), + GATE(PCLK_AUDIO_ADC, "pclk_audio_adc", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(18), 14, GFLAGS), + GATE(MCLK_AUDIO_ADC, "mclk_audio_adc", "mclk_sai4_src", 0, + RK3506_CLKGATE_CON(18), 15, GFLAGS), + FACTOR(MCLK_AUDIO_ADC_DIV4, "mclk_audio_adc_div4", "mclk_audio_adc", 0, 1, 4), + GATE(PCLK_SARADC, "pclk_saradc", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(19), 0, GFLAGS), + COMPOSITE(CLK_SARADC, "clk_saradc", xin24m_400k_32k_parents_p, 0, + RK3506_CLKSEL_CON(54), 4, 2, MFLAGS, 0, 4, DFLAGS, + RK3506_CLKGATE_CON(19), 1, GFLAGS), + GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(19), 3, GFLAGS), + GATE(CLK_SBPI_OTPC_NS, "clk_sbpi_otpc_ns", "xin24m_gate", 0, + RK3506_CLKGATE_CON(19), 4, GFLAGS), + FACTOR(CLK_USER_OTPC_NS, "clk_user_otpc_ns", "clk_sbpi_otpc_ns", 0, 1, 2), + GATE(PCLK_UART5, "pclk_uart5", "pclk_hsperi_root", 0, + RK3506_CLKGATE_CON(19), 6, GFLAGS), + COMPOSITE(SCLK_UART5, "sclk_uart5", sclk_uart_parents_p, 0, + RK3506_CLKSEL_CON(54), 11, 3, MFLAGS, 6, 5, DFLAGS, + RK3506_CLKGATE_CON(19), 7, GFLAGS), + GATE(PCLK_GPIO234_IOC, "pclk_gpio234_ioc", "pclk_hsperi_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(19), 8, GFLAGS), + COMPOSITE(CLK_MAC_PTP_ROOT, "clk_mac_ptp_root", clk_mac_ptp_root_parents_p, 0, + RK3506_CLKSEL_CON(55), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(19), 9, GFLAGS), + GATE(CLK_MAC0_PTP, "clk_mac0_ptp", "clk_mac_ptp_root", 0, + RK3506_CLKGATE_CON(19), 10, GFLAGS), + GATE(CLK_MAC1_PTP, "clk_mac1_ptp", "clk_mac_ptp_root", 0, + RK3506_CLKGATE_CON(19), 11, GFLAGS), + COMPOSITE(ACLK_VIO_ROOT, "aclk_vio_root", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(58), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(21), 0, GFLAGS), + COMPOSITE(HCLK_VIO_ROOT, "hclk_vio_root", gpll_v0pll_v1pll_div_parents_p, 0, + RK3506_CLKSEL_CON(58), 12, 2, MFLAGS, 7, 5, DFLAGS, + RK3506_CLKGATE_CON(21), 1, GFLAGS), + GATE(PCLK_VIO_ROOT, "pclk_vio_root", "hclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 2, GFLAGS), + GATE(HCLK_RGA, "hclk_rga", "hclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 6, GFLAGS), + GATE(ACLK_RGA, "aclk_rga", "aclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 7, GFLAGS), + COMPOSITE(CLK_CORE_RGA, "clk_core_rga", gpll_v0pll_v1pll_g_parents_p, 0, + RK3506_CLKSEL_CON(59), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK3506_CLKGATE_CON(21), 8, GFLAGS), + GATE(ACLK_VOP, "aclk_vop", "aclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 9, GFLAGS), + GATE(HCLK_VOP, "hclk_vop", "hclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 10, GFLAGS), + COMPOSITE(DCLK_VOP, "dclk_vop", dclk_vop_parents_p, 0, + RK3506_CLKSEL_CON(60), 8, 3, MFLAGS, 0, 8, DFLAGS, + RK3506_CLKGATE_CON(21), 11, GFLAGS), + GATE(PCLK_DPHY, "pclk_dphy", "pclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 12, GFLAGS), + GATE(PCLK_DSI_HOST, "pclk_dsi_host", "pclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 13, GFLAGS), + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_vio_root", 0, + RK3506_CLKGATE_CON(21), 14, GFLAGS), + COMPOSITE_NOMUX(CLK_TSADC, "clk_tsadc", "xin24m_gate", 0, + RK3506_CLKSEL_CON(61), 0, 8, DFLAGS, + RK3506_CLKGATE_CON(21), 15, GFLAGS), + COMPOSITE_NOMUX(CLK_TSADC_TSEN, "clk_tsadc_tsen", "xin24m_gate", 0, + RK3506_CLKSEL_CON(61), 8, 3, DFLAGS, + RK3506_CLKGATE_CON(22), 0, GFLAGS), + GATE(PCLK_GPIO1_IOC, "pclk_gpio1_ioc", "pclk_vio_root", CLK_IS_CRITICAL, + RK3506_CLKGATE_CON(22), 1, GFLAGS), + + /* pmu */ + GATE(CLK_PMU, "clk_pmu", "xin24m", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 1, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_root", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 2, GFLAGS), + GATE(PCLK_PMU_CRU, "pclk_pmu_cru", "pclk_pmu_root", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 4, GFLAGS), + GATE(PCLK_PMU_GRF, "pclk_pmu_grf", "pclk_pmu_root", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 5, GFLAGS), + GATE(PCLK_GPIO0_IOC, "pclk_gpio0_ioc", "pclk_pmu_root", CLK_IS_CRITICAL, + RK3506_PMU_CLKGATE_CON(0), 7, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pmu_root", 0, + RK3506_PMU_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", dbclk_gpio0_parents_p, 0, + RK3506_PMU_CLKSEL_CON(0), 0, 2, MFLAGS, + RK3506_PMU_CLKGATE_CON(0), 9, GFLAGS), + GATE(PCLK_GPIO1_SHADOW, "pclk_gpio1_shadow", "pclk_pmu_root", 0, + RK3506_PMU_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO1_SHADOW, "dbclk_gpio1_shadow", dbclk_gpio0_parents_p, 0, + RK3506_PMU_CLKSEL_CON(0), 2, 2, MFLAGS, + RK3506_PMU_CLKGATE_CON(0), 11, GFLAGS), + GATE(PCLK_PMU_HP_TIMER, "pclk_pmu_hp_timer", "pclk_pmu_root", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 12, GFLAGS), + MUX(CLK_PMU_HP_TIMER, "clk_pmu_hp_timer", clk_pmu_hp_timer_parents_p, CLK_IGNORE_UNUSED, + RK3506_PMU_CLKSEL_CON(0), 4, 2, MFLAGS), + GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pmu_root", 0, + RK3506_PMU_CLKGATE_CON(0), 15, GFLAGS), + COMPOSITE_NOMUX(CLK_PWM0, "clk_pwm0", "clk_gpll_div_100m", 0, + RK3506_PMU_CLKSEL_CON(0), 6, 4, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 0, GFLAGS), + GATE(CLK_OSC_PWM0, "clk_osc_pwm0", "xin24m", 0, + RK3506_PMU_CLKGATE_CON(1), 1, GFLAGS), + GATE(CLK_RC_PWM0, "clk_rc_pwm0", "clk_rc", 0, + RK3506_PMU_CLKGATE_CON(1), 2, GFLAGS), + COMPOSITE_NOMUX(CLK_MAC_OUT, "clk_mac_out", "gpll", 0, + RK3506_PMU_CLKSEL_CON(0), 10, 6, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 3, GFLAGS), + COMPOSITE(CLK_REF_OUT0, "clk_ref_out0", clk_ref_out_parents_p, 0, + RK3506_PMU_CLKSEL_CON(1), 6, 2, MFLAGS, 0, 6, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 4, GFLAGS), + COMPOSITE(CLK_REF_OUT1, "clk_ref_out1", clk_ref_out_parents_p, 0, + RK3506_PMU_CLKSEL_CON(1), 14, 2, MFLAGS, 8, 6, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 5, GFLAGS), + MUX(CLK_32K_FRAC_MUX, "clk_32k_frac_mux", clk_32k_frac_parents_p, 0, + RK3506_PMU_CLKSEL_CON(3), 0, 2, MFLAGS), + COMPOSITE_FRAC(CLK_32K_FRAC, "clk_32k_frac", "clk_32k_frac_mux", 0, + RK3506_PMU_CLKSEL_CON(2), 0, + RK3506_PMU_CLKGATE_CON(1), 6, GFLAGS), + COMPOSITE_NOMUX(CLK_32K_RC, "clk_32k_rc", "clk_rc", CLK_IS_CRITICAL, + RK3506_PMU_CLKSEL_CON(3), 2, 5, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 7, GFLAGS), + COMPOSITE_NODIV(CLK_32K, "clk_32k", clk_32k_parents_p, CLK_IS_CRITICAL, + RK3506_PMU_CLKSEL_CON(3), 7, 2, MFLAGS, + RK3506_PMU_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_NODIV(CLK_32K_PMU, "clk_32k_pmu", clk_32k_parents_p, CLK_IS_CRITICAL, + RK3506_PMU_CLKSEL_CON(3), 9, 2, MFLAGS, + RK3506_PMU_CLKGATE_CON(1), 9, GFLAGS), + GATE(CLK_PMU_32K, "clk_pmu_32k", "clk_32k_pmu", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 3, GFLAGS), + GATE(CLK_PMU_HP_TIMER_32K, "clk_pmu_hp_timer_32k", "clk_32k_pmu", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(0), 14, GFLAGS), + GATE(PCLK_TOUCH_KEY, "pclk_touch_key", "pclk_pmu_root", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(1), 12, GFLAGS), + GATE(CLK_TOUCH_KEY, "clk_touch_key", "xin24m", CLK_IGNORE_UNUSED, + RK3506_PMU_CLKGATE_CON(1), 13, GFLAGS), + COMPOSITE(CLK_REF_PHY_PLL, "clk_ref_phy_pll", gpll_v0pll_v1pll_parents_p, 0, + RK3506_PMU_CLKSEL_CON(4), 13, 2, MFLAGS, 6, 7, DFLAGS, + RK3506_PMU_CLKGATE_CON(1), 14, GFLAGS), + MUX(CLK_REF_PHY_PMU_MUX, "clk_ref_phy_pmu_mux", clk_ref_phy_pmu_mux_parents_p, 0, + RK3506_PMU_CLKSEL_CON(4), 15, 1, MFLAGS), + GATE(CLK_WIFI_OUT, "clk_wifi_out", "xin24m", 0, + RK3506_PMU_CLKGATE_CON(2), 0, GFLAGS), + MUX(CLK_V0PLL_REF, "clk_v0pll_ref", clk_vpll_ref_parents_p, CLK_IGNORE_UNUSED, + RK3506_PMU_CLKSEL_CON(6), 0, 1, MFLAGS), + MUX(CLK_V1PLL_REF, "clk_v1pll_ref", clk_vpll_ref_parents_p, CLK_IGNORE_UNUSED, + RK3506_PMU_CLKSEL_CON(6), 1, 1, MFLAGS), + + /* secure ns */ + GATE(CLK_CORE_CRYPTO_NS, "clk_core_crypto_ns", "clk_core_crypto", 0, + RK3506_CLKGATE_CON(5), 12, GFLAGS), + GATE(CLK_PKA_CRYPTO_NS, "clk_pka_crypto_ns", "clk_pka_crypto", 0, + RK3506_CLKGATE_CON(5), 13, GFLAGS), + + /* io */ + GATE(CLK_SPI2, "clk_spi2", "clk_spi2_io", 0, + RK3506_CLKGATE_CON(20), 0, GFLAGS), +}; + +static void __init rk3506_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + unsigned long clk_nr_clks; + void __iomem *reg_base; + + clk_nr_clks = rockchip_clk_find_max_clk_id(rk3506_clk_branches, + ARRAY_SIZE(rk3506_clk_branches)) + 1; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, clk_nr_clks); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); + return; + } + + rockchip_clk_register_plls(ctx, rk3506_pll_clks, + ARRAY_SIZE(rk3506_pll_clks), + 0); + + rockchip_clk_register_armclk_multi_pll(ctx, &rk3506_armclk, + rk3506_cpuclk_rates, + ARRAY_SIZE(rk3506_cpuclk_rates)); + + rockchip_clk_register_branches(ctx, rk3506_clk_branches, + ARRAY_SIZE(rk3506_clk_branches)); + + rk3506_rst_init(np, reg_base); + + rockchip_register_restart_notifier(ctx, RK3506_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); + + /* pvtpll src init */ + writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RK3506_CLKSEL_CON(15)); +} + +CLK_OF_DECLARE(rk3506_cru, "rockchip,rk3506-cru", rk3506_clk_init); + +struct clk_rk3506_inits { + void (*inits)(struct device_node *np); +}; + +static const struct clk_rk3506_inits clk_rk3506_cru_init = { + .inits = rk3506_clk_init, +}; + +static const struct of_device_id clk_rk3506_match_table[] = { + { + .compatible = "rockchip,rk3506-cru", + .data = &clk_rk3506_cru_init, + }, + { } +}; + +static int clk_rk3506_probe(struct platform_device *pdev) +{ + const struct clk_rk3506_inits *init_data; + struct device *dev = &pdev->dev; + + init_data = device_get_match_data(dev); + if (!init_data) + return -EINVAL; + + if (init_data->inits) + init_data->inits(dev->of_node); + + return 0; +} + +static struct platform_driver clk_rk3506_driver = { + .probe = clk_rk3506_probe, + .driver = { + .name = "clk-rk3506", + .of_match_table = clk_rk3506_match_table, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver_probe(clk_rk3506_driver, clk_rk3506_probe); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 87f09320b942be..b2fff1d13a4aba 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -275,6 +275,18 @@ struct clk; #define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) #define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) +#define RK3506_PMU_CRU_BASE 0x10000 +#define RK3506_PLL_CON(x) ((x) * 0x4 + RK3506_PMU_CRU_BASE) +#define RK3506_CLKSEL_CON(x) ((x) * 0x4 + 0x300) +#define RK3506_CLKGATE_CON(x) ((x) * 0x4 + 0x800) +#define RK3506_SOFTRST_CON(x) ((x) * 0x4 + 0xa00) +#define RK3506_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3506_PMU_CRU_BASE) +#define RK3506_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RK3506_PMU_CRU_BASE) +#define RK3506_MODE_CON 0x280 +#define RK3506_GLB_CNT_TH 0xc00 +#define RK3506_GLB_SRST_FST 0xc08 +#define RK3506_GLB_SRST_SND 0xc0c + #define RK3528_PMU_CRU_BASE 0x10000 #define RK3528_PCIE_CRU_BASE 0x20000 #define RK3528_DDRPHY_CRU_BASE 0x28000 @@ -1329,6 +1341,7 @@ static inline void rockchip_register_softrst(struct device_node *np, } void rv1126b_rst_init(struct device_node *np, void __iomem *reg_base); +void rk3506_rst_init(struct device_node *np, void __iomem *reg_base); void rk3528_rst_init(struct device_node *np, void __iomem *reg_base); void rk3562_rst_init(struct device_node *np, void __iomem *reg_base); void rk3576_rst_init(struct device_node *np, void __iomem *reg_base); diff --git a/drivers/clk/rockchip/rst-rk3506.c b/drivers/clk/rockchip/rst-rk3506.c new file mode 100644 index 00000000000000..c3abde60f3c6b8 --- /dev/null +++ b/drivers/clk/rockchip/rst-rk3506.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * Author: Finley Xiao + */ + +#include +#include +#include +#include "clk.h" + +/* 0xFF9A0000 + 0x0A00 */ +#define RK3506_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + reg * 16 + bit) + +/* mapping table for reset ID to register offset */ +static const int rk3506_register_offset[] = { + /* CRU-->SOFTRST_CON00 */ + RK3506_CRU_RESET_OFFSET(SRST_NCOREPORESET0_AC, 0, 0), + RK3506_CRU_RESET_OFFSET(SRST_NCOREPORESET1_AC, 0, 1), + RK3506_CRU_RESET_OFFSET(SRST_NCOREPORESET2_AC, 0, 2), + RK3506_CRU_RESET_OFFSET(SRST_NCORESET0_AC, 0, 4), + RK3506_CRU_RESET_OFFSET(SRST_NCORESET1_AC, 0, 5), + RK3506_CRU_RESET_OFFSET(SRST_NCORESET2_AC, 0, 6), + RK3506_CRU_RESET_OFFSET(SRST_NL2RESET_AC, 0, 8), + RK3506_CRU_RESET_OFFSET(SRST_A_CORE_BIU_AC, 0, 9), + RK3506_CRU_RESET_OFFSET(SRST_H_M0_AC, 0, 10), + + /* CRU-->SOFTRST_CON02 */ + RK3506_CRU_RESET_OFFSET(SRST_NDBGRESET, 2, 10), + RK3506_CRU_RESET_OFFSET(SRST_P_CORE_BIU, 2, 14), + RK3506_CRU_RESET_OFFSET(SRST_PMU, 2, 15), + + /* CRU-->SOFTRST_CON03 */ + RK3506_CRU_RESET_OFFSET(SRST_P_DBG, 3, 1), + RK3506_CRU_RESET_OFFSET(SRST_POT_DBG, 3, 2), + RK3506_CRU_RESET_OFFSET(SRST_P_CORE_GRF, 3, 4), + RK3506_CRU_RESET_OFFSET(SRST_CORE_EMA_DETECT, 3, 6), + RK3506_CRU_RESET_OFFSET(SRST_REF_PVTPLL_CORE, 3, 7), + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO1, 3, 8), + RK3506_CRU_RESET_OFFSET(SRST_DB_GPIO1, 3, 9), + + /* CRU-->SOFTRST_CON04 */ + RK3506_CRU_RESET_OFFSET(SRST_A_CORE_PERI_BIU, 4, 3), + RK3506_CRU_RESET_OFFSET(SRST_A_DSMC, 4, 5), + RK3506_CRU_RESET_OFFSET(SRST_P_DSMC, 4, 6), + RK3506_CRU_RESET_OFFSET(SRST_FLEXBUS, 4, 7), + RK3506_CRU_RESET_OFFSET(SRST_A_FLEXBUS, 4, 9), + RK3506_CRU_RESET_OFFSET(SRST_H_FLEXBUS, 4, 10), + RK3506_CRU_RESET_OFFSET(SRST_A_DSMC_SLV, 4, 11), + RK3506_CRU_RESET_OFFSET(SRST_H_DSMC_SLV, 4, 12), + RK3506_CRU_RESET_OFFSET(SRST_DSMC_SLV, 4, 13), + + /* CRU-->SOFTRST_CON05 */ + RK3506_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 5, 3), + RK3506_CRU_RESET_OFFSET(SRST_H_BUS_BIU, 5, 4), + RK3506_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 5, 5), + RK3506_CRU_RESET_OFFSET(SRST_A_SYSRAM, 5, 6), + RK3506_CRU_RESET_OFFSET(SRST_H_SYSRAM, 5, 7), + RK3506_CRU_RESET_OFFSET(SRST_A_DMAC0, 5, 8), + RK3506_CRU_RESET_OFFSET(SRST_A_DMAC1, 5, 9), + RK3506_CRU_RESET_OFFSET(SRST_H_M0, 5, 10), + RK3506_CRU_RESET_OFFSET(SRST_M0_JTAG, 5, 11), + RK3506_CRU_RESET_OFFSET(SRST_H_CRYPTO, 5, 15), + + /* CRU-->SOFTRST_CON06 */ + RK3506_CRU_RESET_OFFSET(SRST_H_RNG, 6, 0), + RK3506_CRU_RESET_OFFSET(SRST_P_BUS_GRF, 6, 1), + RK3506_CRU_RESET_OFFSET(SRST_P_TIMER0, 6, 2), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH0, 6, 3), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH1, 6, 4), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH2, 6, 5), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH3, 6, 6), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH4, 6, 7), + RK3506_CRU_RESET_OFFSET(SRST_TIMER0_CH5, 6, 8), + RK3506_CRU_RESET_OFFSET(SRST_P_WDT0, 6, 9), + RK3506_CRU_RESET_OFFSET(SRST_T_WDT0, 6, 10), + RK3506_CRU_RESET_OFFSET(SRST_P_WDT1, 6, 11), + RK3506_CRU_RESET_OFFSET(SRST_T_WDT1, 6, 12), + RK3506_CRU_RESET_OFFSET(SRST_P_MAILBOX, 6, 13), + RK3506_CRU_RESET_OFFSET(SRST_P_INTMUX, 6, 14), + RK3506_CRU_RESET_OFFSET(SRST_P_SPINLOCK, 6, 15), + + /* CRU-->SOFTRST_CON07 */ + RK3506_CRU_RESET_OFFSET(SRST_P_DDRC, 7, 0), + RK3506_CRU_RESET_OFFSET(SRST_H_DDRPHY, 7, 1), + RK3506_CRU_RESET_OFFSET(SRST_P_DDRMON, 7, 2), + RK3506_CRU_RESET_OFFSET(SRST_DDRMON_OSC, 7, 3), + RK3506_CRU_RESET_OFFSET(SRST_P_DDR_LPC, 7, 4), + RK3506_CRU_RESET_OFFSET(SRST_H_USBOTG0, 7, 5), + RK3506_CRU_RESET_OFFSET(SRST_USBOTG0_ADP, 7, 7), + RK3506_CRU_RESET_OFFSET(SRST_H_USBOTG1, 7, 8), + RK3506_CRU_RESET_OFFSET(SRST_USBOTG1_ADP, 7, 10), + RK3506_CRU_RESET_OFFSET(SRST_P_USBPHY, 7, 11), + RK3506_CRU_RESET_OFFSET(SRST_USBPHY_POR, 7, 12), + RK3506_CRU_RESET_OFFSET(SRST_USBPHY_OTG0, 7, 13), + RK3506_CRU_RESET_OFFSET(SRST_USBPHY_OTG1, 7, 14), + + /* CRU-->SOFTRST_CON08 */ + RK3506_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 8, 0), + RK3506_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 8, 1), + + /* CRU-->SOFTRST_CON09 */ + RK3506_CRU_RESET_OFFSET(SRST_USBOTG0_UTMI, 9, 0), + RK3506_CRU_RESET_OFFSET(SRST_USBOTG1_UTMI, 9, 1), + + /* CRU-->SOFTRST_CON10 */ + RK3506_CRU_RESET_OFFSET(SRST_A_DDRC_0, 10, 0), + RK3506_CRU_RESET_OFFSET(SRST_A_DDRC_1, 10, 1), + RK3506_CRU_RESET_OFFSET(SRST_A_DDR_BIU, 10, 2), + RK3506_CRU_RESET_OFFSET(SRST_DDRC, 10, 3), + RK3506_CRU_RESET_OFFSET(SRST_DDRMON, 10, 4), + + /* CRU-->SOFTRST_CON11 */ + RK3506_CRU_RESET_OFFSET(SRST_H_LSPERI_BIU, 11, 2), + RK3506_CRU_RESET_OFFSET(SRST_P_UART0, 11, 4), + RK3506_CRU_RESET_OFFSET(SRST_P_UART1, 11, 5), + RK3506_CRU_RESET_OFFSET(SRST_P_UART2, 11, 6), + RK3506_CRU_RESET_OFFSET(SRST_P_UART3, 11, 7), + RK3506_CRU_RESET_OFFSET(SRST_P_UART4, 11, 8), + RK3506_CRU_RESET_OFFSET(SRST_UART0, 11, 9), + RK3506_CRU_RESET_OFFSET(SRST_UART1, 11, 10), + RK3506_CRU_RESET_OFFSET(SRST_UART2, 11, 11), + RK3506_CRU_RESET_OFFSET(SRST_UART3, 11, 12), + RK3506_CRU_RESET_OFFSET(SRST_UART4, 11, 13), + RK3506_CRU_RESET_OFFSET(SRST_P_I2C0, 11, 14), + RK3506_CRU_RESET_OFFSET(SRST_I2C0, 11, 15), + + /* CRU-->SOFTRST_CON12 */ + RK3506_CRU_RESET_OFFSET(SRST_P_I2C1, 12, 0), + RK3506_CRU_RESET_OFFSET(SRST_I2C1, 12, 1), + RK3506_CRU_RESET_OFFSET(SRST_P_I2C2, 12, 2), + RK3506_CRU_RESET_OFFSET(SRST_I2C2, 12, 3), + RK3506_CRU_RESET_OFFSET(SRST_P_PWM1, 12, 4), + RK3506_CRU_RESET_OFFSET(SRST_PWM1, 12, 5), + RK3506_CRU_RESET_OFFSET(SRST_P_SPI0, 12, 10), + RK3506_CRU_RESET_OFFSET(SRST_SPI0, 12, 11), + RK3506_CRU_RESET_OFFSET(SRST_P_SPI1, 12, 12), + RK3506_CRU_RESET_OFFSET(SRST_SPI1, 12, 13), + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO2, 12, 14), + RK3506_CRU_RESET_OFFSET(SRST_DB_GPIO2, 12, 15), + + /* CRU-->SOFTRST_CON13 */ + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO3, 13, 0), + RK3506_CRU_RESET_OFFSET(SRST_DB_GPIO3, 13, 1), + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO4, 13, 2), + RK3506_CRU_RESET_OFFSET(SRST_DB_GPIO4, 13, 3), + RK3506_CRU_RESET_OFFSET(SRST_H_CAN0, 13, 4), + RK3506_CRU_RESET_OFFSET(SRST_CAN0, 13, 5), + RK3506_CRU_RESET_OFFSET(SRST_H_CAN1, 13, 6), + RK3506_CRU_RESET_OFFSET(SRST_CAN1, 13, 7), + RK3506_CRU_RESET_OFFSET(SRST_H_PDM, 13, 8), + RK3506_CRU_RESET_OFFSET(SRST_M_PDM, 13, 9), + RK3506_CRU_RESET_OFFSET(SRST_PDM, 13, 10), + RK3506_CRU_RESET_OFFSET(SRST_SPDIFTX, 13, 11), + RK3506_CRU_RESET_OFFSET(SRST_H_SPDIFTX, 13, 12), + RK3506_CRU_RESET_OFFSET(SRST_H_SPDIFRX, 13, 13), + RK3506_CRU_RESET_OFFSET(SRST_SPDIFRX, 13, 14), + RK3506_CRU_RESET_OFFSET(SRST_M_SAI0, 13, 15), + + /* CRU-->SOFTRST_CON14 */ + RK3506_CRU_RESET_OFFSET(SRST_H_SAI0, 14, 0), + RK3506_CRU_RESET_OFFSET(SRST_M_SAI1, 14, 2), + RK3506_CRU_RESET_OFFSET(SRST_H_SAI1, 14, 3), + RK3506_CRU_RESET_OFFSET(SRST_H_ASRC0, 14, 5), + RK3506_CRU_RESET_OFFSET(SRST_ASRC0, 14, 6), + RK3506_CRU_RESET_OFFSET(SRST_H_ASRC1, 14, 7), + RK3506_CRU_RESET_OFFSET(SRST_ASRC1, 14, 8), + + /* CRU-->SOFTRST_CON17 */ + RK3506_CRU_RESET_OFFSET(SRST_H_HSPERI_BIU, 17, 4), + RK3506_CRU_RESET_OFFSET(SRST_H_SDMMC, 17, 7), + RK3506_CRU_RESET_OFFSET(SRST_H_FSPI, 17, 8), + RK3506_CRU_RESET_OFFSET(SRST_S_FSPI, 17, 9), + RK3506_CRU_RESET_OFFSET(SRST_P_SPI2, 17, 10), + RK3506_CRU_RESET_OFFSET(SRST_A_MAC0, 17, 11), + RK3506_CRU_RESET_OFFSET(SRST_A_MAC1, 17, 12), + + /* CRU-->SOFTRST_CON18 */ + RK3506_CRU_RESET_OFFSET(SRST_M_SAI2, 18, 2), + RK3506_CRU_RESET_OFFSET(SRST_H_SAI2, 18, 3), + RK3506_CRU_RESET_OFFSET(SRST_H_SAI3, 18, 6), + RK3506_CRU_RESET_OFFSET(SRST_M_SAI3, 18, 7), + RK3506_CRU_RESET_OFFSET(SRST_H_SAI4, 18, 10), + RK3506_CRU_RESET_OFFSET(SRST_M_SAI4, 18, 11), + RK3506_CRU_RESET_OFFSET(SRST_H_DSM, 18, 12), + RK3506_CRU_RESET_OFFSET(SRST_M_DSM, 18, 13), + RK3506_CRU_RESET_OFFSET(SRST_P_AUDIO_ADC, 18, 14), + RK3506_CRU_RESET_OFFSET(SRST_M_AUDIO_ADC, 18, 15), + + /* CRU-->SOFTRST_CON19 */ + RK3506_CRU_RESET_OFFSET(SRST_P_SARADC, 19, 0), + RK3506_CRU_RESET_OFFSET(SRST_SARADC, 19, 1), + RK3506_CRU_RESET_OFFSET(SRST_SARADC_PHY, 19, 2), + RK3506_CRU_RESET_OFFSET(SRST_P_OTPC_NS, 19, 3), + RK3506_CRU_RESET_OFFSET(SRST_SBPI_OTPC_NS, 19, 4), + RK3506_CRU_RESET_OFFSET(SRST_USER_OTPC_NS, 19, 5), + RK3506_CRU_RESET_OFFSET(SRST_P_UART5, 19, 6), + RK3506_CRU_RESET_OFFSET(SRST_UART5, 19, 7), + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO234_IOC, 19, 8), + + /* CRU-->SOFTRST_CON21 */ + RK3506_CRU_RESET_OFFSET(SRST_A_VIO_BIU, 21, 3), + RK3506_CRU_RESET_OFFSET(SRST_H_VIO_BIU, 21, 4), + RK3506_CRU_RESET_OFFSET(SRST_H_RGA, 21, 6), + RK3506_CRU_RESET_OFFSET(SRST_A_RGA, 21, 7), + RK3506_CRU_RESET_OFFSET(SRST_CORE_RGA, 21, 8), + RK3506_CRU_RESET_OFFSET(SRST_A_VOP, 21, 9), + RK3506_CRU_RESET_OFFSET(SRST_H_VOP, 21, 10), + RK3506_CRU_RESET_OFFSET(SRST_VOP, 21, 11), + RK3506_CRU_RESET_OFFSET(SRST_P_DPHY, 21, 12), + RK3506_CRU_RESET_OFFSET(SRST_P_DSI_HOST, 21, 13), + RK3506_CRU_RESET_OFFSET(SRST_P_TSADC, 21, 14), + RK3506_CRU_RESET_OFFSET(SRST_TSADC, 21, 15), + + /* CRU-->SOFTRST_CON22 */ + RK3506_CRU_RESET_OFFSET(SRST_P_GPIO1_IOC, 22, 1), +}; + +void rk3506_rst_init(struct device_node *np, void __iomem *reg_base) +{ + rockchip_register_softrst_lut(np, + rk3506_register_offset, + ARRAY_SIZE(rk3506_register_offset), + reg_base + RK3506_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); +} From 80cdf208117a36de82a30d210b3b8df0f193e75b Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 11 Nov 2025 11:37:57 +0000 Subject: [PATCH 483/684] tools headers UAPI: Sync linux/perf_event.h with the kernel sources To pickup config4 changes. Tested-by: Leo Yan Reviewed-by: Ian Rogers Signed-off-by: James Clark Acked-by: Peter Zijlstra (Intel) Signed-off-by: Namhyung Kim --- tools/include/uapi/linux/perf_event.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index 78a362b8002776..0d0ed85ad8cb34 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -382,6 +382,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER6 120 /* Add: aux_sample_size */ #define PERF_ATTR_SIZE_VER7 128 /* Add: sig_data */ #define PERF_ATTR_SIZE_VER8 136 /* Add: config3 */ +#define PERF_ATTR_SIZE_VER9 144 /* add: config4 */ /* * 'struct perf_event_attr' contains various attributes that define @@ -543,6 +544,7 @@ struct perf_event_attr { __u64 sig_data; __u64 config3; /* extension of config2 */ + __u64 config4; /* extension of config3 */ }; /* From 14a84c708efd75b3a2c107b1438354361c7dd75f Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 11 Nov 2025 11:37:58 +0000 Subject: [PATCH 484/684] perf tools: Add support for perf_event_attr::config4 perf_event_attr has gained a new field, config4, so add support for it extending the existing configN support. Reviewed-by: Leo Yan Reviewed-by: Ian Rogers Tested-by: Leo Yan Signed-off-by: James Clark Acked-by: Peter Zijlstra (Intel) Signed-off-by: Namhyung Kim --- tools/perf/tests/parse-events.c | 13 ++++++++++++- tools/perf/util/parse-events.c | 11 +++++++++++ tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 1 + tools/perf/util/pmu.c | 8 ++++++++ tools/perf/util/pmu.h | 1 + 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index e4cdb517c10e6f..128d21dc389f86 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -647,6 +647,7 @@ static int test__checkevent_pmu(struct evlist *evlist) TEST_ASSERT_EVSEL("wrong config1", 1 == evsel->core.attr.config1, evsel); TEST_ASSERT_EVSEL("wrong config2", 3 == evsel->core.attr.config2, evsel); TEST_ASSERT_EVSEL("wrong config3", 0 == evsel->core.attr.config3, evsel); + TEST_ASSERT_EVSEL("wrong config4", 0 == evsel->core.attr.config4, evsel); /* * The period value gets configured within evlist__config, * while this test executes only parse events method. @@ -669,6 +670,7 @@ static int test__checkevent_list(struct evlist *evlist) TEST_ASSERT_EVSEL("wrong config1", 0 == evsel->core.attr.config1, evsel); TEST_ASSERT_EVSEL("wrong config2", 0 == evsel->core.attr.config2, evsel); TEST_ASSERT_EVSEL("wrong config3", 0 == evsel->core.attr.config3, evsel); + TEST_ASSERT_EVSEL("wrong config4", 0 == evsel->core.attr.config4, evsel); TEST_ASSERT_EVSEL("wrong exclude_user", !evsel->core.attr.exclude_user, evsel); TEST_ASSERT_EVSEL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel, evsel); TEST_ASSERT_EVSEL("wrong exclude_hv", !evsel->core.attr.exclude_hv, evsel); @@ -849,6 +851,15 @@ static int test__checkterms_simple(struct parse_events_terms *terms) TEST_ASSERT_VAL("wrong val", term->val.num == 4); TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config3")); + /* config4=5 */ + term = list_entry(term->list.next, struct parse_events_term, list); + TEST_ASSERT_VAL("wrong type term", + term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG4); + TEST_ASSERT_VAL("wrong type val", + term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + TEST_ASSERT_VAL("wrong val", term->val.num == 5); + TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config4")); + /* umask=1*/ term = list_entry(term->list.next, struct parse_events_term, list); TEST_ASSERT_VAL("wrong type term", @@ -2516,7 +2527,7 @@ struct terms_test { static const struct terms_test test__terms[] = { [0] = { - .str = "config=10,config1,config2=3,config3=4,umask=1,read,r0xead", + .str = "config=10,config1,config2=3,config3=4,config4=5,umask=1,read,r0xead", .check = test__checkterms_simple, }, }; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5ffeb7b416d939..17c1c36a7bf9a3 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -216,6 +216,8 @@ __add_event(struct list_head *list, int *idx, PERF_PMU_FORMAT_VALUE_CONFIG2, "config2"); perf_pmu__warn_invalid_config(pmu, attr->config3, name, PERF_PMU_FORMAT_VALUE_CONFIG3, "config3"); + perf_pmu__warn_invalid_config(pmu, attr->config4, name, + PERF_PMU_FORMAT_VALUE_CONFIG4, "config4"); } } /* @@ -705,6 +707,7 @@ const char *parse_events__term_type_str(enum parse_events__term_type term_type) [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1", [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2", [PARSE_EVENTS__TERM_TYPE_CONFIG3] = "config3", + [PARSE_EVENTS__TERM_TYPE_CONFIG4] = "config4", [PARSE_EVENTS__TERM_TYPE_NAME] = "name", [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period", [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq", @@ -754,6 +757,7 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_CONFIG4: case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_METRIC_ID: case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: @@ -824,6 +828,10 @@ do { \ CHECK_TYPE_VAL(NUM); attr->config3 = term->val.num; break; + case PARSE_EVENTS__TERM_TYPE_CONFIG4: + CHECK_TYPE_VAL(NUM); + attr->config4 = term->val.num; + break; case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: CHECK_TYPE_VAL(NUM); break; @@ -1069,6 +1077,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr, case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_CONFIG4: case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: @@ -1212,6 +1221,7 @@ do { \ case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_CONFIG4: case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: @@ -1250,6 +1260,7 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head case PARSE_EVENTS__TERM_TYPE_CONFIG1: case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_CONFIG3: + case PARSE_EVENTS__TERM_TYPE_CONFIG4: case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: case PARSE_EVENTS__TERM_TYPE_NAME: diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 1012b441e9cd4d..3577ab2137304d 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -59,6 +59,7 @@ enum parse_events__term_type { PARSE_EVENTS__TERM_TYPE_CONFIG1, PARSE_EVENTS__TERM_TYPE_CONFIG2, PARSE_EVENTS__TERM_TYPE_CONFIG3, + PARSE_EVENTS__TERM_TYPE_CONFIG4, PARSE_EVENTS__TERM_TYPE_NAME, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 8e0ea441e57f12..251ce43218786d 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -287,6 +287,7 @@ config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } config3 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG3); } +config4 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG4); } name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index f14f2a12d06152..1b7c712d8f9902 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1574,6 +1574,10 @@ static int pmu_config_term(const struct perf_pmu *pmu, assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); pmu_format_value(bits, term->val.num, &attr->config3, zero); break; + case PARSE_EVENTS__TERM_TYPE_CONFIG4: + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + pmu_format_value(bits, term->val.num, &attr->config4, zero); + break; case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG: assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); assert(term->val.num < PERF_COUNT_HW_MAX); @@ -1649,6 +1653,9 @@ static int pmu_config_term(const struct perf_pmu *pmu, case PERF_PMU_FORMAT_VALUE_CONFIG3: vp = &attr->config3; break; + case PERF_PMU_FORMAT_VALUE_CONFIG4: + vp = &attr->config4; + break; default: return -EINVAL; } @@ -2008,6 +2015,7 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call "config1=0..0xffffffffffffffff", "config2=0..0xffffffffffffffff", "config3=0..0xffffffffffffffff", + "config4=0..0xffffffffffffffff", "legacy-hardware-config=0..9,", "legacy-cache-config=0..0xffffff,", "name=string", diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index cfcaba3e2e753b..5738e88fbb5487 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -23,6 +23,7 @@ enum { PERF_PMU_FORMAT_VALUE_CONFIG1, PERF_PMU_FORMAT_VALUE_CONFIG2, PERF_PMU_FORMAT_VALUE_CONFIG3, + PERF_PMU_FORMAT_VALUE_CONFIG4, PERF_PMU_FORMAT_VALUE_CONFIG_END, }; From 5accdaec526ed8708ec64cf027a5e75aa83eb504 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 11 Nov 2025 11:37:59 +0000 Subject: [PATCH 485/684] perf docs: arm-spe: Document new SPE filtering features FEAT_SPE_EFT and FEAT_SPE_FDS etc have new user facing format attributes so document them. Also document existing 'event_filter' bits that were missing from the doc and the fact that latency values are stored in the weight field. Reviewed-by: Leo Yan Tested-by: Leo Yan Reviewed-by: Ian Rogers Signed-off-by: James Clark Acked-by: Peter Zijlstra (Intel) Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-arm-spe.txt | 104 ++++++++++++++++++++-- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/tools/perf/Documentation/perf-arm-spe.txt b/tools/perf/Documentation/perf-arm-spe.txt index cda8dd47fc4dc9..8b02e5b983fa95 100644 --- a/tools/perf/Documentation/perf-arm-spe.txt +++ b/tools/perf/Documentation/perf-arm-spe.txt @@ -141,27 +141,65 @@ Config parameters These are placed between the // in the event and comma separated. For example '-e arm_spe/load_filter=1,min_latency=10/' - branch_filter=1 - collect branches only (PMSFCR.B) - event_filter= - filter on specific events (PMSEVFR) - see bitfield description below + event_filter= - logical AND filter on specific events (PMSEVFR) - see bitfield description below + inv_event_filter= - logical OR to filter out specific events (PMSNEVFR, FEAT_SPEv1p2) - see bitfield description below jitter=1 - use jitter to avoid resonance when sampling (PMSIRR.RND) - load_filter=1 - collect loads only (PMSFCR.LD) min_latency= - collect only samples with this latency or higher* (PMSLATFR) pa_enable=1 - collect physical address (as well as VA) of loads/stores (PMSCR.PA) - requires privilege pct_enable=1 - collect physical timestamp instead of virtual timestamp (PMSCR.PCT) - requires privilege - store_filter=1 - collect stores only (PMSFCR.ST) ts_enable=1 - enable timestamping with value of generic timer (PMSCR.TS) discard=1 - enable SPE PMU events but don't collect sample data - see 'Discard mode' (PMBLIMITR.FM = DISCARD) + inv_data_src_filter= - mask to filter from 0-63 possible data sources (PMSDSFR, FEAT_SPE_FDS) - See 'Data source filtering' +++*+++ Latency is the total latency from the point at which sampling started on that instruction, rather than only the execution latency. -Only some events can be filtered on; these include: - - bit 1 - instruction retired (i.e. omit speculative instructions) +Only some events can be filtered on using 'event_filter' bits. The overall +filter is the logical AND of these bits, for example if bits 3 and 5 are set +only samples that have both 'L1D cache refill' AND 'TLB walk' are recorded. When +FEAT_SPEv1p2 is implemented 'inv_event_filter' can also be used to exclude +events that have any (OR) of the filter's bits set. For example setting bits 3 +and 5 in 'inv_event_filter' will exclude any events that are either L1D cache +refill OR TLB walk. If the same bit is set in both filters it's UNPREDICTABLE +whether the sample is included or excluded. Filter bits for both event_filter +and inv_event_filter are: + + bit 1 - Instruction retired (i.e. omit speculative instructions) + bit 2 - L1D access (FEAT_SPEv1p4) bit 3 - L1D refill + bit 4 - TLB access (FEAT_SPEv1p4) bit 5 - TLB refill - bit 7 - mispredict - bit 11 - misaligned access + bit 6 - Not taken event (FEAT_SPEv1p2) + bit 7 - Mispredict + bit 8 - Last level cache access (FEAT_SPEv1p4) + bit 9 - Last level cache miss (FEAT_SPEv1p4) + bit 10 - Remote access (FEAT_SPEv1p4) + bit 11 - Misaligned access (FEAT_SPEv1p1) + bit 12-15 - IMPLEMENTATION DEFINED events (when implemented) + bit 16 - Transaction (FEAT_TME) + bit 17 - Partial or empty SME or SVE predicate (FEAT_SPEv1p1) + bit 18 - Empty SME or SVE predicate (FEAT_SPEv1p1) + bit 19 - L2D access (FEAT_SPEv1p4) + bit 20 - L2D miss (FEAT_SPEv1p4) + bit 21 - Cache data modified (FEAT_SPEv1p4) + bit 22 - Recently fetched (FEAT_SPEv1p4) + bit 23 - Data snooped (FEAT_SPEv1p4) + bit 24 - Streaming SVE mode event (when FEAT_SPE_SME is implemented), or + IMPLEMENTATION DEFINED event 24 (when implemented, only versions + less than FEAT_SPEv1p4) + bit 25 - SMCU or external coprocessor operation event when FEAT_SPE_SME is + implemented, or IMPLEMENTATION DEFINED event 25 (when implemented, + only versions less than FEAT_SPEv1p4) + bit 26-31 - IMPLEMENTATION DEFINED events (only versions less than FEAT_SPEv1p4) + bit 48-63 - IMPLEMENTATION DEFINED events (when implemented) + +For IMPLEMENTATION DEFINED bits, refer to the CPU TRM if these bits are +implemented. + +The driver will reject events if requested filter bits require unimplemented SPE +versions, but will not reject filter bits for unimplemented IMPDEF bits or when +their related feature is not present (e.g. SME). For example, if FEAT_SPEv1p2 is +not implemented, filtering on "Not taken event" (bit 6) will be rejected. So to sample just retired instructions: @@ -171,6 +209,31 @@ or just mispredicted branches: perf record -e arm_spe/event_filter=0x80/ -- ./mybench +When set, the following filters can be used to select samples that match any of +the operation types (OR filtering). If only one is set then only samples of that +type are collected: + + branch_filter=1 - Collect branches (PMSFCR.B) + load_filter=1 - Collect loads (PMSFCR.LD) + store_filter=1 - Collect stores (PMSFCR.ST) + +When extended filtering is supported (FEAT_SPE_EFT), SIMD and float +pointer operations can also be selected: + + simd_filter=1 - Collect SIMD loads, stores and operations (PMSFCR.SIMD) + float_filter=1 - Collect floating point loads, stores and operations (PMSFCR.FP) + +When extended filtering is supported (FEAT_SPE_EFT), operation type filters can +be changed to AND using _mask fields. For example samples could be selected if +they are store AND SIMD by setting 'store_filter=1,simd_filter=1, +store_filter_mask=1,simd_filter_mask=1'. The new masks are as follows: + + branch_filter_mask=1 - Change branch filter behavior from OR to AND (PMSFCR.Bm) + load_filter_mask=1 - Change load filter behavior from OR to AND (PMSFCR.LDm) + store_filter_mask=1 - Change store filter behavior from OR to AND (PMSFCR.STm) + simd_filter_mask=1 - Change SIMD filter behavior from OR to AND (PMSFCR.SIMDm) + float_filter_mask=1 - Change floating point filter behavior from OR to AND (PMSFCR.FPm) + Viewing the data ~~~~~~~~~~~~~~~~~ @@ -210,6 +273,10 @@ Memory access details are also stored on the samples and this can be viewed with perf report --mem-mode +The latency value from the SPE sample is stored in the 'weight' field of the +Perf samples and can be displayed in Perf script and report outputs by enabling +its display from the command line. + Common errors ~~~~~~~~~~~~~ @@ -253,6 +320,25 @@ to minimize output. Then run perf stat: perf record -e arm_spe/discard/ -a -N -B --no-bpf-event -o - > /dev/null & perf stat -e SAMPLE_FEED_LD +Data source filtering +~~~~~~~~~~~~~~~~~~~~~ + +When FEAT_SPE_FDS is present, 'inv_data_src_filter' can be used as a mask to +filter on a subset (0 - 63) of possible data source IDs. The full range of data +sources is 0 - 65535 although these are unlikely to be used in practice. Data +sources are IMPDEF so refer to the TRM for the mappings. Each bit N of the +filter maps to data source N. The filter is an OR of all the bits, and the value +provided inv_data_src_filter is inverted before writing to PMSDSFR_EL1 so that +set bits exclude that data source and cleared bits include that data source. +Therefore the default value of 0 is equivalent to no filtering (all data sources +included). + +For example, to include only data sources 0 and 3, clear bits 0 and 3 +(0xFFFFFFFFFFFFFFF6) + +When 'inv_data_src_filter' is set to 0xFFFFFFFFFFFFFFFF, any samples with any +data source set are excluded. + SEE ALSO -------- From ebd61482ffab499208f06b8d3fa183cbe2dd5fa7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 24 Nov 2025 15:35:16 +0100 Subject: [PATCH 486/684] pinctrl: cix: Fix obscure dependency When compile-testing for UM-Linux the build fails because we don't have IOMEM. Add an explicit dependency. Fixes: 920500c5fe66 ("pinctrl: cix: Add pin-controller support for sky1") Reviewed-by: Peter Chen Signed-off-by: Linus Walleij --- drivers/pinctrl/cix/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/cix/Kconfig b/drivers/pinctrl/cix/Kconfig index 455120dd731892..1529b1af63886b 100644 --- a/drivers/pinctrl/cix/Kconfig +++ b/drivers/pinctrl/cix/Kconfig @@ -9,6 +9,7 @@ config PINCTRL_SKY1_BASE config PINCTRL_SKY1 tristate "Cix Sky1 pinctrl driver" depends on ARCH_CIX || COMPILE_TEST + depends on HAS_IOMEM select PINCTRL_SKY1_BASE help Say Y here to enable the sky1 pinctrl driver From 87c75fa75559f5501b5a03caf442f18899e388be Mon Sep 17 00:00:00 2001 From: Anubhav Shelat Date: Tue, 25 Nov 2025 11:41:18 +0000 Subject: [PATCH 487/684] perf pmu: fix duplicate conditional statement Remove duplicate check for PERF_PMU_TYPE_DRM_END in perf_pmu__kind. Fixes: f0feb21e0a10 ("perf pmu: Add PMU kind to simplify differentiating") Signed-off-by: Anubhav Shelat Reviewed-by: Ian Rogers Closes: https://lore.kernel.org/linux-perf-users/CA+G8Dh+wLx+FvjjoEkypqvXhbzWEQVpykovzrsHi2_eQjHkzQA@mail.gmail.com/ Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 5738e88fbb5487..8f11bfe8ed6d86 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -332,8 +332,6 @@ static inline enum pmu_kind perf_pmu__kind(const struct perf_pmu *pmu) return PERF_PMU_KIND_PE; if (type <= PERF_PMU_TYPE_DRM_END) return PERF_PMU_KIND_DRM; - if (type <= PERF_PMU_TYPE_DRM_END) - return PERF_PMU_KIND_DRM; if (type <= PERF_PMU_TYPE_HWMON_END) return PERF_PMU_KIND_HWMON; if (type == PERF_PMU_TYPE_TOOL) From c9573287729bc5ed3d2adbc028fe33d265917ae5 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Tue, 14 Oct 2025 09:48:29 +0800 Subject: [PATCH 488/684] perf vendor events riscv: add T-HEAD C920V2 JSON support T-HEAD C920 has a V2 iteration, which supports Sscompmf. The V2 iteration supports the same perf events as V1. Reuse T-HEAD c900-legacy JSON file for T-HEAD C920V2. Signed-off-by: Inochi Amaoto Acked-by: Paul Walmsley Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/riscv/mapfile.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/pmu-events/arch/riscv/mapfile.csv b/tools/perf/pmu-events/arch/riscv/mapfile.csv index 0a7e7dcc81be49..d5eea7f9aa9a41 100644 --- a/tools/perf/pmu-events/arch/riscv/mapfile.csv +++ b/tools/perf/pmu-events/arch/riscv/mapfile.csv @@ -20,5 +20,6 @@ 0x489-0x8000000000000008-0x[[:xdigit:]]+,v1,sifive/p550,core 0x489-0x8000000000000[1-6]08-0x[9b][[:xdigit:]]+,v1,sifive/p650,core 0x5b7-0x0-0x0,v1,thead/c900-legacy,core +0x5b7-0x80000000090c0d00-0x2047000,v1,thead/c900-legacy,core 0x67e-0x80000000db0000[89]0-0x[[:xdigit:]]+,v1,starfive/dubhe-80,core 0x31e-0x8000000000008a45-0x[[:xdigit:]]+,v1,andes/ax45,core From 834ebb5678d75d844f5d4f44ede78724d8c96630 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 24 Nov 2025 10:59:08 +0000 Subject: [PATCH 489/684] perf tools: Don't read build-ids from non-regular files Simplify the build ID reading code by removing the non-blocking option. Having to pass the correct option to this function was fragile and a mistake would result in a hang, see the linked fix. Furthermore, compressed files are always opened blocking anyway, ignoring the non-blocking option. We also don't expect to read build IDs from non-regular files. The only hits to this function that are non-regular are devices that won't be elf files with build IDs, for example "/dev/dri/renderD129". Now instead of opening these as non-blocking and failing to read, we skip them. Even if something like a pipe or character device did have a build ID, I don't think it would have worked because you need to call read() in a loop, check for -EAGAIN and handle timeouts to make non-blocking reads work. Link: https://lore.kernel.org/linux-perf-users/20251022-james-perf-fix-dso-block-v1-1-c4faab150546@linaro.org/ Signed-off-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/bench/inject-buildid.c | 2 +- tools/perf/builtin-buildid-cache.c | 8 ++++---- tools/perf/builtin-inject.c | 4 ++-- tools/perf/tests/pe-file-parsing.c | 4 ++-- tools/perf/tests/sdt.c | 2 +- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/debuginfo.c | 2 +- tools/perf/util/dsos.c | 4 ++-- tools/perf/util/libbfd.c | 9 +++++++-- tools/perf/util/libbfd.h | 5 ++--- tools/perf/util/symbol-elf.c | 13 +++++++------ tools/perf/util/symbol-minimal.c | 11 ++++++++--- tools/perf/util/symbol.c | 5 ++--- tools/perf/util/symbol.h | 2 +- tools/perf/util/synthetic-events.c | 2 +- 15 files changed, 43 insertions(+), 34 deletions(-) diff --git a/tools/perf/bench/inject-buildid.c b/tools/perf/bench/inject-buildid.c index 12387ea88b9a9c..aad572a78d7fcf 100644 --- a/tools/perf/bench/inject-buildid.c +++ b/tools/perf/bench/inject-buildid.c @@ -85,7 +85,7 @@ static int add_dso(const char *fpath, const struct stat *sb __maybe_unused, if (typeflag == FTW_D || typeflag == FTW_SL) return 0; - if (filename__read_build_id(fpath, &bid, /*block=*/true) < 0) + if (filename__read_build_id(fpath, &bid) < 0) return 0; dso->name = realpath(fpath, NULL); diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 2e0f2004696ae9..c98104481c8a19 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c @@ -180,7 +180,7 @@ static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi) struct nscookie nsc; nsinfo__mountns_enter(nsi, &nsc); - err = filename__read_build_id(filename, &bid, /*block=*/true); + err = filename__read_build_id(filename, &bid); nsinfo__mountns_exit(&nsc); if (err < 0) { pr_debug("Couldn't read a build-id in %s\n", filename); @@ -204,7 +204,7 @@ static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi) int err; nsinfo__mountns_enter(nsi, &nsc); - err = filename__read_build_id(filename, &bid, /*block=*/true); + err = filename__read_build_id(filename, &bid); nsinfo__mountns_exit(&nsc); if (err < 0) { pr_debug("Couldn't read a build-id in %s\n", filename); @@ -280,7 +280,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) if (!dso__build_id_filename(dso, filename, sizeof(filename), false)) return true; - if (filename__read_build_id(filename, &bid, /*block=*/true) == -1) { + if (filename__read_build_id(filename, &bid) == -1) { if (errno == ENOENT) return false; @@ -309,7 +309,7 @@ static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi) int err; nsinfo__mountns_enter(nsi, &nsc); - err = filename__read_build_id(filename, &bid, /*block=*/true); + err = filename__read_build_id(filename, &bid); nsinfo__mountns_exit(&nsc); if (err < 0) { pr_debug("Couldn't read a build-id in %s\n", filename); diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index bd9245d2dd41aa..0e40f2a4bd18b9 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -668,12 +668,12 @@ static int dso__read_build_id(struct dso *dso) mutex_lock(dso__lock(dso)); nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); - if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) + if (filename__read_build_id(dso__long_name(dso), &bid) > 0) dso__set_build_id(dso, &bid); else if (dso__nsinfo(dso)) { char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); - if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) + if (new_name && filename__read_build_id(new_name, &bid) > 0) dso__set_build_id(dso, &bid); free(new_name); } diff --git a/tools/perf/tests/pe-file-parsing.c b/tools/perf/tests/pe-file-parsing.c index 8b31d1d05f905f..30c7da79e109b4 100644 --- a/tools/perf/tests/pe-file-parsing.c +++ b/tools/perf/tests/pe-file-parsing.c @@ -37,7 +37,7 @@ static int run_dir(const char *d) size_t idx; scnprintf(filename, PATH_MAX, "%s/pe-file.exe", d); - ret = filename__read_build_id(filename, &bid, /*block=*/true); + ret = filename__read_build_id(filename, &bid); TEST_ASSERT_VAL("Failed to read build_id", ret == sizeof(expect_build_id)); TEST_ASSERT_VAL("Wrong build_id", !memcmp(bid.data, expect_build_id, @@ -49,7 +49,7 @@ static int run_dir(const char *d) !strcmp(debuglink, expect_debuglink)); scnprintf(debugfile, PATH_MAX, "%s/%s", d, debuglink); - ret = filename__read_build_id(debugfile, &bid, /*block=*/true); + ret = filename__read_build_id(debugfile, &bid); TEST_ASSERT_VAL("Failed to read debug file build_id", ret == sizeof(expect_build_id)); TEST_ASSERT_VAL("Wrong build_id", !memcmp(bid.data, expect_build_id, diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c index 6132f1af3e22d3..93baee2eae42ab 100644 --- a/tools/perf/tests/sdt.c +++ b/tools/perf/tests/sdt.c @@ -31,7 +31,7 @@ static int build_id_cache__add_file(const char *filename) struct build_id bid = { .size = 0, }; int err; - err = filename__read_build_id(filename, &bid, /*block=*/true); + err = filename__read_build_id(filename, &bid); if (err < 0) { pr_debug("Failed to read build id of %s\n", filename); return err; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 35505a1ffd1117..fdb35133fde43a 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -122,7 +122,7 @@ int filename__snprintf_build_id(const char *pathname, char *sbuild_id, size_t sb struct build_id bid = { .size = 0, }; int ret; - ret = filename__read_build_id(pathname, &bid, /*block=*/true); + ret = filename__read_build_id(pathname, &bid); if (ret < 0) return ret; @@ -848,7 +848,7 @@ static int filename__read_build_id_ns(const char *filename, int ret; nsinfo__mountns_enter(nsi, &nsc); - ret = filename__read_build_id(filename, bid, /*block=*/true); + ret = filename__read_build_id(filename, bid); nsinfo__mountns_exit(&nsc); return ret; diff --git a/tools/perf/util/debuginfo.c b/tools/perf/util/debuginfo.c index bb9ebd84ec2d2a..4a559b3e8cdce6 100644 --- a/tools/perf/util/debuginfo.c +++ b/tools/perf/util/debuginfo.c @@ -115,7 +115,7 @@ struct debuginfo *debuginfo__new(const char *path) * incase the path isn't for a regular file. */ assert(!dso__has_build_id(dso)); - if (filename__read_build_id(path, &bid, /*block=*/false) > 0) + if (filename__read_build_id(path, &bid) > 0) dso__set_build_id(dso, &bid); for (type = distro_dwarf_types; diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c index 64c1d65b014961..0a7645c7fae7d3 100644 --- a/tools/perf/util/dsos.c +++ b/tools/perf/util/dsos.c @@ -81,13 +81,13 @@ static int dsos__read_build_ids_cb(struct dso *dso, void *data) return 0; } nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); - if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) { + if (filename__read_build_id(dso__long_name(dso), &bid) > 0) { dso__set_build_id(dso, &bid); args->have_build_id = true; } else if (errno == ENOENT && dso__nsinfo(dso)) { char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); - if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) { + if (new_name && filename__read_build_id(new_name, &bid) > 0) { dso__set_build_id(dso, &bid); args->have_build_id = true; } diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c index 01147fbf73b376..0099b415decca2 100644 --- a/tools/perf/util/libbfd.c +++ b/tools/perf/util/libbfd.c @@ -383,13 +383,18 @@ int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) return err; } -int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block) +int libbfd__read_build_id(const char *filename, struct build_id *bid) { size_t size = sizeof(bid->data); int err = -1, fd; bfd *abfd; - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); + if (!filename) + return -EFAULT; + if (!is_regular_file(filename)) + return -EWOULDBLOCK; + + fd = open(filename, O_RDONLY); if (fd < 0) return -1; diff --git a/tools/perf/util/libbfd.h b/tools/perf/util/libbfd.h index e300f171d1bd70..953886f3d62f37 100644 --- a/tools/perf/util/libbfd.h +++ b/tools/perf/util/libbfd.h @@ -25,7 +25,7 @@ void dso__free_a2l_libbfd(struct dso *dso); int symbol__disassemble_libbfd(const char *filename, struct symbol *sym, struct annotate_args *args); -int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block); +int libbfd__read_build_id(const char *filename, struct build_id *bid); int libbfd_filename__read_debuglink(const char *filename, char *debuglink, size_t size); @@ -59,8 +59,7 @@ static inline int symbol__disassemble_libbfd(const char *filename __always_unuse } static inline int libbfd__read_build_id(const char *filename __always_unused, - struct build_id *bid __always_unused, - bool block __always_unused) + struct build_id *bid __always_unused) { return -1; } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 9e820599bab388..c5c382c3409a73 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -860,20 +860,20 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) return err; } -static int read_build_id(const char *filename, struct build_id *bid, bool block) +static int read_build_id(const char *filename, struct build_id *bid) { size_t size = sizeof(bid->data); int fd, err; Elf *elf; - err = libbfd__read_build_id(filename, bid, block); + err = libbfd__read_build_id(filename, bid); if (err >= 0) goto out; if (size < BUILD_ID_SIZE) goto out; - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); + fd = open(filename, O_RDONLY); if (fd < 0) goto out; @@ -894,7 +894,7 @@ static int read_build_id(const char *filename, struct build_id *bid, bool block) return err; } -int filename__read_build_id(const char *filename, struct build_id *bid, bool block) +int filename__read_build_id(const char *filename, struct build_id *bid) { struct kmod_path m = { .name = NULL, }; char path[PATH_MAX]; @@ -902,6 +902,8 @@ int filename__read_build_id(const char *filename, struct build_id *bid, bool blo if (!filename) return -EFAULT; + if (!is_regular_file(filename)) + return -EWOULDBLOCK; err = kmod_path__parse(&m, filename); if (err) @@ -918,10 +920,9 @@ int filename__read_build_id(const char *filename, struct build_id *bid, bool blo } close(fd); filename = path; - block = true; } - err = read_build_id(filename, bid, block); + err = read_build_id(filename, bid); if (m.comp) unlink(filename); diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index aeb2532488953a..c6b17c14a2e994 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -85,7 +85,7 @@ int filename__read_debuglink(const char *filename __maybe_unused, /* * Just try PT_NOTE header otherwise fails */ -int filename__read_build_id(const char *filename, struct build_id *bid, bool block) +int filename__read_build_id(const char *filename, struct build_id *bid) { int fd, ret = -1; bool need_swap = false, elf32; @@ -102,7 +102,12 @@ int filename__read_build_id(const char *filename, struct build_id *bid, bool blo void *phdr, *buf = NULL; ssize_t phdr_size, ehdr_size, buf_size = 0; - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); + if (!filename) + return -EFAULT; + if (!is_regular_file(filename)) + return -EWOULDBLOCK; + + fd = open(filename, O_RDONLY); if (fd < 0) return -1; @@ -323,7 +328,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, if (ret >= 0) RC_CHK_ACCESS(dso)->is_64_bit = ret; - if (filename__read_build_id(ss->name, &bid, /*block=*/true) > 0) + if (filename__read_build_id(ss->name, &bid) > 0) dso__set_build_id(dso, &bid); return 0; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index cc26b7bf302b29..d8fc5ea77f8493 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1743,14 +1743,13 @@ int dso__load(struct dso *dso, struct map *map) /* * Read the build id if possible. This is required for - * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. Don't block in case path - * isn't for a regular file. + * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. */ if (!dso__has_build_id(dso)) { struct build_id bid = { .size = 0, }; __symbol__join_symfs(name, PATH_MAX, dso__long_name(dso)); - if (filename__read_build_id(name, &bid, /*block=*/false) > 0) + if (filename__read_build_id(name, &bid) > 0) dso__set_build_id(dso, &bid); } diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 3471062187992a..3fb5d146d9b15b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -140,7 +140,7 @@ struct symbol *dso__next_symbol(struct symbol *sym); enum dso_type dso__type_fd(int fd); -int filename__read_build_id(const char *filename, struct build_id *id, bool block); +int filename__read_build_id(const char *filename, struct build_id *id); int sysfs__read_build_id(const char *filename, struct build_id *bid); int modules__parse(const char *filename, void *arg, int (*process_module)(void *arg, const char *name, diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 5aa44c4aba6259..2ba9fa25e00a68 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -401,7 +401,7 @@ static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event, nsi = nsinfo__new(event->pid); nsinfo__mountns_enter(nsi, &nc); - rc = filename__read_build_id(event->filename, &bid, /*block=*/false) > 0 ? 0 : -1; + rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1; nsinfo__mountns_exit(&nc); nsinfo__put(nsi); From e35770610730af372659ef8d41199b556411c756 Mon Sep 17 00:00:00 2001 From: Xichao Zhao Date: Tue, 12 Aug 2025 10:10:07 +0800 Subject: [PATCH 490/684] ubifs: Remove unnecessary parameters '*c' Because the variable *c is not used within the function, remove it from the ubifs_crc_node function. Signed-off-by: Xichao Zhao Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- fs/ubifs/io.c | 4 ++-- fs/ubifs/ubifs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index a79f229df47548..e0dfe6827d65be 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -395,7 +395,7 @@ void ubifs_init_node(struct ubifs_info *c, void *node, int len, int pad) } } -void ubifs_crc_node(struct ubifs_info *c, void *node, int len) +void ubifs_crc_node(void *node, int len) { struct ubifs_ch *ch = node; uint32_t crc; @@ -432,7 +432,7 @@ int ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len, return err; } - ubifs_crc_node(c, node, len); + ubifs_crc_node(node, len); return 0; } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 49e50431741cd2..118392aa9f2a50 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1747,7 +1747,7 @@ int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum, int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len, int lnum, int offs, int quiet, int must_chk_crc); void ubifs_init_node(struct ubifs_info *c, void *buf, int len, int pad); -void ubifs_crc_node(struct ubifs_info *c, void *buf, int len); +void ubifs_crc_node(void *buf, int len); void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); int ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len, int hmac_offs, int pad); From 0288d5fe25a286641f0fc259d5de32d0e319db6d Mon Sep 17 00:00:00 2001 From: Xichao Zhao Date: Tue, 12 Aug 2025 10:10:08 +0800 Subject: [PATCH 491/684] ubifs: Simplify the code using ubifs_crc_node Replace part of the code using ubifs_crc_node. Signed-off-by: Xichao Zhao Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- fs/ubifs/io.c | 9 ++------- fs/ubifs/recovery.c | 4 +--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index e0dfe6827d65be..6c6d6824277930 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -327,8 +327,6 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len, */ void ubifs_pad(const struct ubifs_info *c, void *buf, int pad) { - uint32_t crc; - ubifs_assert(c, pad >= 0); if (pad >= UBIFS_PAD_NODE_SZ) { @@ -343,8 +341,7 @@ void ubifs_pad(const struct ubifs_info *c, void *buf, int pad) ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ); pad -= UBIFS_PAD_NODE_SZ; pad_node->pad_len = cpu_to_le32(pad); - crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8); - ch->crc = cpu_to_le32(crc); + ubifs_crc_node(buf, UBIFS_PAD_NODE_SZ); memset(buf + UBIFS_PAD_NODE_SZ, 0, pad); } else if (pad > 0) /* Too little space, padding node won't fit */ @@ -469,7 +466,6 @@ void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) */ void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last) { - uint32_t crc; struct ubifs_ch *ch = node; unsigned long long sqnum = next_sqnum(c); @@ -483,8 +479,7 @@ void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last) ch->group_type = UBIFS_IN_NODE_GROUP; ch->sqnum = cpu_to_le64(sqnum); ch->padding[0] = ch->padding[1] = 0; - crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); - ch->crc = cpu_to_le32(crc); + ubifs_crc_node(node, len); } /** diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index f0d51dd21c9e13..b36dc9b032f48d 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -1406,7 +1406,6 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) union ubifs_key key; int err, lnum, offs, len; loff_t i_size; - uint32_t crc; /* Locate the inode node LEB number and offset */ ino_key_init(c, &key, e->inum); @@ -1428,8 +1427,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) ino = c->sbuf + offs; ino->size = cpu_to_le64(e->d_size); len = le32_to_cpu(ino->ch.len); - crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8); - ino->ch.crc = cpu_to_le32(crc); + ubifs_crc_node((void *)ino, len); /* Work out where data in the LEB ends and free space begins */ p = c->sbuf; len = c->leb_size - 1; From c0d612b391b219f0119201d6a30514bf00f79066 Mon Sep 17 00:00:00 2001 From: Xichao Zhao Date: Mon, 11 Aug 2025 18:09:49 +0800 Subject: [PATCH 492/684] ubifs: Remove unnecessary variable assignments When an error occurs, ubifs_err is used to directly print the error, and different errors have different formats for printing. Therefore, it's not necessary to use 'err' to locate the error occurrence. Thus, remove the relevant assignments to 'err'. Signed-off-by: Xichao Zhao Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- fs/ubifs/tnc_misc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c index d3f8a6aa1f49da..10b222dc6a53b5 100644 --- a/fs/ubifs/tnc_misc.c +++ b/fs/ubifs/tnc_misc.c @@ -321,7 +321,6 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, c->fanout, znode->child_cnt); ubifs_err(c, "max levels %d, znode level %d", UBIFS_MAX_LEVELS, znode->level); - err = 1; goto out_dump; } @@ -342,7 +341,6 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, zbr->lnum >= c->leb_cnt || zbr->offs < 0 || zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) { ubifs_err(c, "bad branch %d", i); - err = 2; goto out_dump; } @@ -355,7 +353,6 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, default: ubifs_err(c, "bad key type at slot %d: %d", i, key_type(c, &zbr->key)); - err = 3; goto out_dump; } @@ -368,7 +365,6 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, ubifs_err(c, "bad target node (type %d) length (%d)", type, zbr->len); ubifs_err(c, "have to be %d", c->ranges[type].len); - err = 4; goto out_dump; } } else if (zbr->len < c->ranges[type].min_len || @@ -378,7 +374,6 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, ubifs_err(c, "have to be in range of %d-%d", c->ranges[type].min_len, c->ranges[type].max_len); - err = 5; goto out_dump; } } @@ -396,13 +391,11 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, cmp = keys_cmp(c, key1, key2); if (cmp > 0) { ubifs_err(c, "bad key order (keys %d and %d)", i, i + 1); - err = 6; goto out_dump; } else if (cmp == 0 && !is_hash_key(c, key1)) { /* These can only be keys with colliding hash */ ubifs_err(c, "keys %d and %d are not hashed but equivalent", i, i + 1); - err = 7; goto out_dump; } } @@ -411,7 +404,7 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, return 0; out_dump: - ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err); + ubifs_err(c, "bad indexing node at LEB %d:%d", lnum, offs); ubifs_dump_node(c, idx, c->max_idx_node_sz); kfree(idx); return -EINVAL; From 77530d1a78ca5c274e37d6494a965223672630b2 Mon Sep 17 00:00:00 2001 From: Cheng Ming Lin Date: Fri, 14 Nov 2025 10:44:52 +0800 Subject: [PATCH 493/684] mtd: ubi: skip programming unused bits in ubi headers This patch prevents unnecessary programming of bits in ec_hdr and vid_hdr that are not used or read during normal UBI operation. These unused bits are typcially already set to 1 in erased flash and do not need to be explicitly programmed to 0 if they are not used. Programming such unused areas offers no functional benefit and may result in unnecessary flash wear, reducing the overall lifetime of the device. By skipping these writes, we preserve the flash state as much as possible and minimize wear caused by redundant operations. This change ensures that only necessary fields are written when preparing UBI headers, improving flash efficiency without affecting functionality. Additionally, the Kioxia TC58NVG1S3HTA00 datasheet (page 63) also notes that continuous program/erase cycling with a high percentage of '0' bits in the data pattern can accelerate block endurance degradation. This further supports avoiding large 0x00 patterns. Link: https://europe.kioxia.com/content/dam/kioxia/newidr/productinfo/datasheet/201910/DST_TC58NVG1S3HTA00-TDE_EN_31442.pdf Signed-off-by: Cheng Ming Lin Reviewed-by: Miquel Raynal Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/io.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index a4999bce435f56..915eb64cb00113 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -868,6 +868,8 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, return -EROFS; } + memset((char *)ec_hdr + UBI_EC_HDR_SIZE, 0xFF, ubi->ec_hdr_alsize - UBI_EC_HDR_SIZE); + err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); return err; } @@ -1150,6 +1152,14 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, return -EROFS; } + if (ubi->vid_hdr_shift) { + memset((char *)p, 0xFF, ubi->vid_hdr_shift); + memset((char *)p + ubi->vid_hdr_shift + UBI_VID_HDR_SIZE, 0xFF, + ubi->vid_hdr_alsize - (ubi->vid_hdr_shift + UBI_VID_HDR_SIZE)); + } else { + memset((char *)p + UBI_VID_HDR_SIZE, 0xFF, ubi->vid_hdr_alsize - UBI_VID_HDR_SIZE); + } + err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); return err; From d133e30aabc7c8eb8206827f8fbe0f3679adb911 Mon Sep 17 00:00:00 2001 From: Liyuan Pang Date: Fri, 7 Nov 2025 18:00:57 +0800 Subject: [PATCH 494/684] ubi: fastmap: fix ubi->fm memory leak The problem is that scan_fast() allocate memory for ubi->fm and ubi->fm->e[x], but if the following attach process fails in ubi_wl_init or ubi_read_volume_table, the whole attach process will fail without executing ubi_wl_close to free the memory under ubi->fm. Fix this by add a new ubi_free_fastmap function in fastmap.c to free the memory allocated for fm. If SLUB_DEBUG and KUNIT are enabled, the following warning messages will show: ubi0: detaching mtd0 ubi0: mtd0 is detached ubi0: default fastmap pool size: 200 ubi0: default fastmap WL pool size: 100 ubi0: attaching mtd0 ubi0: attached by fastmap ubi0: fastmap pool size: 200 ubi0: fastmap WL pool size: 100 ubi0 error: ubi_wl_init [ubi]: no enough physical eraseblocks (4, need 203) ubi0 error: ubi_attach_mtd_dev [ubi]: failed to attach mtd0, error -28 UBI error: cannot attach mtd0 ================================================================= BUG ubi_wl_entry_slab (Tainted: G B O L ): Objects remaining in ubi_wl_entry_slab on __kmem_cache_shutdown() ----------------------------------------------------------------------------- Slab 0xffff2fd23a40cd00 objects=22 used=1 fp=0xffff2fd1d0334fd8 flags=0x883fffc010200(slab|head|section=34|node=0|zone=1|lastcpupid=0x7fff) CPU: 0 PID: 5884 Comm: insmod Tainted: G B O L 5.10.0 #1 Hardware name: LS1043A RDB Board (DT) Call trace: dump_backtrace+0x0/0x198 show_stack+0x18/0x28 dump_stack+0xe8/0x15c slab_err+0x94/0xc0 __kmem_cache_shutdown+0x1fc/0x39c kmem_cache_destroy+0x48/0x138 ubi_init+0x1d4/0xf34 [ubi] do_one_initcall+0xb4/0x24c do_init_module+0x4c/0x1dc load_module+0x212c/0x2260 __se_sys_finit_module+0xb4/0xd8 __arm64_sys_finit_module+0x18/0x28 el0_svc_common.constprop.0+0x78/0x1a0 do_el0_svc+0x78/0x90 el0_svc+0x20/0x38 el0_sync_handler+0xf0/0x140 normal+0x3d8/0x400 Object 0xffff2fd1d0334e68 @offset=3688 Allocated in ubi_scan_fastmap+0xf04/0xf40 [ubi] age=80 cpu=0 pid=5884 __slab_alloc.isra.21+0x6c/0xb4 kmem_cache_alloc+0x1e4/0x80c ubi_scan_fastmap+0xf04/0xf40 [ubi] ubi_attach+0x1f0/0x3a8 [ubi] ubi_attach_mtd_dev+0x810/0xbc8 [ubi] ubi_init+0x238/0xf34 [ubi] do_one_initcall+0xb4/0x24c do_init_module+0x4c/0x1dc load_module+0x212c/0x2260 __se_sys_finit_module+0xb4/0xd8 __arm64_sys_finit_module+0x18/0x28 el0_svc_common.constprop.0+0x78/0x1a0 do_el0_svc+0x78/0x90 el0_svc+0x20/0x38 el0_sync_handler+0xf0/0x140 normal+0x3d8/0x400 Link: https://bugzilla.kernel.org/show_bug.cgi?id=220744 Signed-off-by: Liyuan Pang Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 4 +++- drivers/mtd/ubi/fastmap-wl.c | 8 +------- drivers/mtd/ubi/ubi.h | 12 ++++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index adc47b87b38a5f..884171871d0e54 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1600,7 +1600,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) err = ubi_read_volume_table(ubi, ai); if (err) - goto out_ai; + goto out_fm; err = ubi_wl_init(ubi, ai); if (err) @@ -1642,6 +1642,8 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) out_vtbl: ubi_free_all_volumes(ubi); vfree(ubi->vtbl); +out_fm: + ubi_free_fastmap(ubi); out_ai: destroy_ai(ai); return err; diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index 9bdb6525f1281f..e2bc1122bfd319 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -530,8 +530,6 @@ int ubi_is_erase_work(struct ubi_work *wrk) static void ubi_fastmap_close(struct ubi_device *ubi) { - int i; - return_unused_pool_pebs(ubi, &ubi->fm_pool); return_unused_pool_pebs(ubi, &ubi->fm_wl_pool); @@ -540,11 +538,7 @@ static void ubi_fastmap_close(struct ubi_device *ubi) ubi->fm_anchor = NULL; } - if (ubi->fm) { - for (i = 0; i < ubi->fm->used_blocks; i++) - kfree(ubi->fm->e[i]); - } - kfree(ubi->fm); + ubi_free_fastmap(ubi); } /** diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index c792b9bcab9bce..44803d3329f424 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -969,10 +969,22 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, struct ubi_attach_info *scan_ai); int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count); void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol); +static inline void ubi_free_fastmap(struct ubi_device *ubi) +{ + if (ubi->fm) { + int i; + + for (i = 0; i < ubi->fm->used_blocks; i++) + kmem_cache_free(ubi_wl_entry_slab, ubi->fm->e[i]); + kfree(ubi->fm); + ubi->fm = NULL; + } +} #else static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } static inline int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; } static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} +static inline void ubi_free_fastmap(struct ubi_device *ubi) { } #endif /* block.c */ From 0695aef23d674815c352293c49d944a2375ee9c9 Mon Sep 17 00:00:00 2001 From: Qianfeng Rong Date: Sun, 17 Aug 2025 16:12:38 +0800 Subject: [PATCH 495/684] ubifs: vmalloc(array_size()) -> vmalloc_array() Remove array_size() calls and replace vmalloc() with vmalloc_array() in ubifs_create_dflt_lpt()/lpt_init_rd()/lpt_init_wr(). vmalloc_array() is optimized better, resulting in less instructions being used [1]. [1]: https://lore.kernel.org/lkml/abc66ec5-85a4-47e1-9759-2f60ab111971@vivo.com/ Signed-off-by: Qianfeng Rong Reviewed-by: Zhihao Cheng Signed-off-by: Richard Weinberger --- fs/ubifs/lpt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 441d0beca4cf3e..dde0aa3287f4b5 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -628,8 +628,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); buf = vmalloc(c->leb_size); - ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), - c->lpt_lebs)); + ltab = vmalloc_array(c->lpt_lebs, + sizeof(struct ubifs_lpt_lprops)); if (!pnode || !nnode || !buf || !ltab || !lsave) { err = -ENOMEM; goto out; @@ -1777,8 +1777,8 @@ static int lpt_init_rd(struct ubifs_info *c) { int err, i; - c->ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), - c->lpt_lebs)); + c->ltab = vmalloc_array(c->lpt_lebs, + sizeof(struct ubifs_lpt_lprops)); if (!c->ltab) return -ENOMEM; @@ -1846,8 +1846,8 @@ static int lpt_init_wr(struct ubifs_info *c) { int err, i; - c->ltab_cmt = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops), - c->lpt_lebs)); + c->ltab_cmt = vmalloc_array(c->lpt_lebs, + sizeof(struct ubifs_lpt_lprops)); if (!c->ltab_cmt) return -ENOMEM; From 8c0522993925b8843e3d3e3769d8ea09454a611a Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:27 +0200 Subject: [PATCH 496/684] i3c: mipi-i3c-hci-pci: Set 64-bit DMA mask for Intel controllers All Intel controllers support 64-bit DMA. Set the DMA mask accordingly. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-2-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index dd4484eff2f02b..3cd15ca7d391d7 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -36,6 +36,8 @@ static int mipi_i3c_hci_pci_intel_init(struct pci_dev *pci) if (!priv) return -ENOMEM; + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64)); + /* Assert reset, wait for completion and release reset */ writel(0, priv + INTEL_PRIV_RESETS); timeout = jiffies + msecs_to_jiffies(10); From f4fe6e7084952b919d3401745850a229cba0c8cf Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:28 +0200 Subject: [PATCH 497/684] i3c: mipi-i3c-hci-pci: Move all Intel-related definitions together Move all Intel-related definitions together, to tidy the code slightly. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-3-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 3cd15ca7d391d7..3d854cee05df3a 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -17,14 +17,14 @@ struct mipi_i3c_hci_pci_info { int (*init)(struct pci_dev *pci); }; +static DEFINE_IDA(mipi_i3c_hci_pci_ida); + #define INTEL_PRIV_OFFSET 0x2b0 #define INTEL_PRIV_SIZE 0x28 #define INTEL_PRIV_RESETS 0x04 #define INTEL_PRIV_RESETS_RESET BIT(0) #define INTEL_PRIV_RESETS_RESET_DONE BIT(1) -static DEFINE_IDA(mipi_i3c_hci_pci_ida); - static int mipi_i3c_hci_pci_intel_init(struct pci_dev *pci) { unsigned long timeout; From 58a9ae637112a66d385cf93e7125a2cb7ea8f143 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:29 +0200 Subject: [PATCH 498/684] i3c: mipi-i3c-hci-pci: Rename some Intel-related identifiers Rename some Intel-related identifiers to ensure Intel-related identifiers begin "intel_" or INTEL_, and for brevity removing purposeless "PRIV" in preparation to add more register definitions. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-4-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- .../i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 3d854cee05df3a..d434e296274005 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -21,11 +21,11 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida); #define INTEL_PRIV_OFFSET 0x2b0 #define INTEL_PRIV_SIZE 0x28 -#define INTEL_PRIV_RESETS 0x04 -#define INTEL_PRIV_RESETS_RESET BIT(0) -#define INTEL_PRIV_RESETS_RESET_DONE BIT(1) +#define INTEL_RESETS 0x04 +#define INTEL_RESETS_RESET BIT(0) +#define INTEL_RESETS_RESET_DONE BIT(1) -static int mipi_i3c_hci_pci_intel_init(struct pci_dev *pci) +static int intel_i3c_init(struct pci_dev *pci) { unsigned long timeout; void __iomem *priv; @@ -39,21 +39,21 @@ static int mipi_i3c_hci_pci_intel_init(struct pci_dev *pci) dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64)); /* Assert reset, wait for completion and release reset */ - writel(0, priv + INTEL_PRIV_RESETS); + writel(0, priv + INTEL_RESETS); timeout = jiffies + msecs_to_jiffies(10); - while (!(readl(priv + INTEL_PRIV_RESETS) & - INTEL_PRIV_RESETS_RESET_DONE)) { + while (!(readl(priv + INTEL_RESETS) & + INTEL_RESETS_RESET_DONE)) { if (time_after(jiffies, timeout)) break; cpu_relax(); } - writel(INTEL_PRIV_RESETS_RESET, priv + INTEL_PRIV_RESETS); + writel(INTEL_RESETS_RESET, priv + INTEL_RESETS); return 0; } static struct mipi_i3c_hci_pci_info intel_info = { - .init = mipi_i3c_hci_pci_intel_init, + .init = intel_i3c_init, }; static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, From 36f18ae15cfd1babf8b10c91468d084802d64a4c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:30 +0200 Subject: [PATCH 499/684] i3c: mipi-i3c-hci-pci: Use readl_poll_timeout() Use readl_poll_timeout() instead of open-coding the polling loop. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-5-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index d434e296274005..30915d78045ee1 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include @@ -24,11 +25,12 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida); #define INTEL_RESETS 0x04 #define INTEL_RESETS_RESET BIT(0) #define INTEL_RESETS_RESET_DONE BIT(1) +#define INTEL_RESETS_TIMEOUT_US (10 * USEC_PER_MSEC) static int intel_i3c_init(struct pci_dev *pci) { - unsigned long timeout; void __iomem *priv; + u32 reg; priv = devm_ioremap(&pci->dev, pci_resource_start(pci, 0) + INTEL_PRIV_OFFSET, @@ -40,13 +42,9 @@ static int intel_i3c_init(struct pci_dev *pci) /* Assert reset, wait for completion and release reset */ writel(0, priv + INTEL_RESETS); - timeout = jiffies + msecs_to_jiffies(10); - while (!(readl(priv + INTEL_RESETS) & - INTEL_RESETS_RESET_DONE)) { - if (time_after(jiffies, timeout)) - break; - cpu_relax(); - } + readl_poll_timeout(priv + INTEL_RESETS, reg, + reg & INTEL_RESETS_RESET_DONE, 0, + INTEL_RESETS_TIMEOUT_US); writel(INTEL_RESETS_RESET, priv + INTEL_RESETS); return 0; From fc6152dc777d16db61c5f3b279007ed9944a130f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:31 +0200 Subject: [PATCH 500/684] i3c: mipi-i3c-hci-pci: Constify driver data Add const qualifier to driver data because it is constant. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-6-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 30915d78045ee1..abc7bad5e069a6 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -50,14 +50,14 @@ static int intel_i3c_init(struct pci_dev *pci) return 0; } -static struct mipi_i3c_hci_pci_info intel_info = { +static const struct mipi_i3c_hci_pci_info intel_info = { .init = intel_i3c_init, }; static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { - struct mipi_i3c_hci_pci_info *info; + const struct mipi_i3c_hci_pci_info *info; struct platform_device *pdev; struct resource res[2]; int dev_id, ret; @@ -93,7 +93,7 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, if (ret) goto err; - info = (struct mipi_i3c_hci_pci_info *)id->driver_data; + info = (const struct mipi_i3c_hci_pci_info *)id->driver_data; if (info && info->init) { ret = info->init(pci); if (ret) From 9dfa23c41510570a6d7f405ab6bacdb215bf9d8f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:32 +0200 Subject: [PATCH 501/684] i3c: mipi-i3c-hci-pci: Factor out private registers ioremapping For neatness, factor out private registers ioremapping. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-7-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index abc7bad5e069a6..1e1f2c42bd7490 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -27,14 +27,18 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida); #define INTEL_RESETS_RESET_DONE BIT(1) #define INTEL_RESETS_TIMEOUT_US (10 * USEC_PER_MSEC) +static void __iomem *intel_priv(struct pci_dev *pci) +{ + resource_size_t base = pci_resource_start(pci, 0); + + return devm_ioremap(&pci->dev, base + INTEL_PRIV_OFFSET, INTEL_PRIV_SIZE); +} + static int intel_i3c_init(struct pci_dev *pci) { - void __iomem *priv; + void __iomem *priv = intel_priv(pci); u32 reg; - priv = devm_ioremap(&pci->dev, - pci_resource_start(pci, 0) + INTEL_PRIV_OFFSET, - INTEL_PRIV_SIZE); if (!priv) return -ENOMEM; From 6f6efdd15c67bd262a6e9c795fd54d47e4cb6857 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:33 +0200 Subject: [PATCH 502/684] i3c: mipi-i3c-hci-pci: Factor out intel_reset() For neatness, factor out intel_reset(). Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-8-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 1e1f2c42bd7490..b9794212b2fbe5 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -27,6 +27,18 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida); #define INTEL_RESETS_RESET_DONE BIT(1) #define INTEL_RESETS_TIMEOUT_US (10 * USEC_PER_MSEC) +static void intel_reset(void __iomem *priv) +{ + u32 reg; + + /* Assert reset, wait for completion and release reset */ + writel(0, priv + INTEL_RESETS); + readl_poll_timeout(priv + INTEL_RESETS, reg, + reg & INTEL_RESETS_RESET_DONE, 0, + INTEL_RESETS_TIMEOUT_US); + writel(INTEL_RESETS_RESET, priv + INTEL_RESETS); +} + static void __iomem *intel_priv(struct pci_dev *pci) { resource_size_t base = pci_resource_start(pci, 0); @@ -37,19 +49,13 @@ static void __iomem *intel_priv(struct pci_dev *pci) static int intel_i3c_init(struct pci_dev *pci) { void __iomem *priv = intel_priv(pci); - u32 reg; if (!priv) return -ENOMEM; dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64)); - /* Assert reset, wait for completion and release reset */ - writel(0, priv + INTEL_RESETS); - readl_poll_timeout(priv + INTEL_RESETS, reg, - reg & INTEL_RESETS_RESET_DONE, 0, - INTEL_RESETS_TIMEOUT_US); - writel(INTEL_RESETS_RESET, priv + INTEL_RESETS); + intel_reset(priv); return 0; } From da8116a9be9bdc0412ac3aa7931b16ab7335261e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:34 +0200 Subject: [PATCH 503/684] i3c: mipi-i3c-hci-pci: Allocate a structure for mipi_i3c_hci_pci device information Allocate a structure for mipi_i3c_hci_pci device information, in preparation for additional changes that need to store mipi_i3c_hci_pci device-specific information. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-9-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index b9794212b2fbe5..8936e50eddf783 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -14,6 +14,10 @@ #include #include +struct mipi_i3c_hci_pci { + struct platform_device *pdev; +}; + struct mipi_i3c_hci_pci_info { int (*init)(struct pci_dev *pci); }; @@ -68,10 +72,14 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { const struct mipi_i3c_hci_pci_info *info; - struct platform_device *pdev; + struct mipi_i3c_hci_pci *hci; struct resource res[2]; int dev_id, ret; + hci = devm_kzalloc(&pci->dev, sizeof(*hci), GFP_KERNEL); + if (!hci) + return -ENOMEM; + ret = pcim_enable_device(pci); if (ret) return ret; @@ -92,14 +100,14 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, if (dev_id < 0) return dev_id; - pdev = platform_device_alloc("mipi-i3c-hci", dev_id); - if (!pdev) + hci->pdev = platform_device_alloc("mipi-i3c-hci", dev_id); + if (!hci->pdev) return -ENOMEM; - pdev->dev.parent = &pci->dev; - device_set_node(&pdev->dev, dev_fwnode(&pci->dev)); + hci->pdev->dev.parent = &pci->dev; + device_set_node(&hci->pdev->dev, dev_fwnode(&pci->dev)); - ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); + ret = platform_device_add_resources(hci->pdev, res, ARRAY_SIZE(res)); if (ret) goto err; @@ -110,23 +118,24 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, goto err; } - ret = platform_device_add(pdev); + ret = platform_device_add(hci->pdev); if (ret) goto err; - pci_set_drvdata(pci, pdev); + pci_set_drvdata(pci, hci); return 0; err: - platform_device_put(pdev); + platform_device_put(hci->pdev); ida_free(&mipi_i3c_hci_pci_ida, dev_id); return ret; } static void mipi_i3c_hci_pci_remove(struct pci_dev *pci) { - struct platform_device *pdev = pci_get_drvdata(pci); + struct mipi_i3c_hci_pci *hci = pci_get_drvdata(pci); + struct platform_device *pdev = hci->pdev; int dev_id = pdev->id; platform_device_unregister(pdev); From 0f9ef14b3fb853815aa88f264f7924e1e0ee80c7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:35 +0200 Subject: [PATCH 504/684] i3c: mipi-i3c-hci-pci: Change callback parameter Prepare to add more callbacks in mipi_i3c_hci_pci_info. Change ->init() callback parameter from PCI device pointer to mipi_i3c_hci_pci_info device pointer. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-10-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 8936e50eddf783..7bfb9fe337b6f5 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -15,11 +15,12 @@ #include struct mipi_i3c_hci_pci { + struct pci_dev *pci; struct platform_device *pdev; }; struct mipi_i3c_hci_pci_info { - int (*init)(struct pci_dev *pci); + int (*init)(struct mipi_i3c_hci_pci *hci); }; static DEFINE_IDA(mipi_i3c_hci_pci_ida); @@ -50,14 +51,14 @@ static void __iomem *intel_priv(struct pci_dev *pci) return devm_ioremap(&pci->dev, base + INTEL_PRIV_OFFSET, INTEL_PRIV_SIZE); } -static int intel_i3c_init(struct pci_dev *pci) +static int intel_i3c_init(struct mipi_i3c_hci_pci *hci) { - void __iomem *priv = intel_priv(pci); + void __iomem *priv = intel_priv(hci->pci); if (!priv) return -ENOMEM; - dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64)); + dma_set_mask_and_coherent(&hci->pci->dev, DMA_BIT_MASK(64)); intel_reset(priv); @@ -80,6 +81,8 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, if (!hci) return -ENOMEM; + hci->pci = pci; + ret = pcim_enable_device(pci); if (ret) return ret; @@ -113,7 +116,7 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, info = (const struct mipi_i3c_hci_pci_info *)id->driver_data; if (info && info->init) { - ret = info->init(pci); + ret = info->init(hci); if (ret) goto err; } From 040dcd762d60ddc5307e5a9f0cf5d269a0af0814 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:36 +0200 Subject: [PATCH 505/684] i3c: mipi-i3c-hci-pci: Add exit callback Prepare to add device-specific features that require cleanup upon driver removal. Add ->exit() callback as a counterpart to ->init(). Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-11-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- .../i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 7bfb9fe337b6f5..7a91efbd3e5481 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -17,10 +17,12 @@ struct mipi_i3c_hci_pci { struct pci_dev *pci; struct platform_device *pdev; + const struct mipi_i3c_hci_pci_info *info; }; struct mipi_i3c_hci_pci_info { int (*init)(struct mipi_i3c_hci_pci *hci); + void (*exit)(struct mipi_i3c_hci_pci *hci); }; static DEFINE_IDA(mipi_i3c_hci_pci_ida); @@ -72,7 +74,6 @@ static const struct mipi_i3c_hci_pci_info intel_info = { static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { - const struct mipi_i3c_hci_pci_info *info; struct mipi_i3c_hci_pci *hci; struct resource res[2]; int dev_id, ret; @@ -114,21 +115,24 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, if (ret) goto err; - info = (const struct mipi_i3c_hci_pci_info *)id->driver_data; - if (info && info->init) { - ret = info->init(hci); + hci->info = (const struct mipi_i3c_hci_pci_info *)id->driver_data; + if (hci->info && hci->info->init) { + ret = hci->info->init(hci); if (ret) goto err; } ret = platform_device_add(hci->pdev); if (ret) - goto err; + goto err_exit; pci_set_drvdata(pci, hci); return 0; +err_exit: + if (hci->info && hci->info->exit) + hci->info->exit(hci); err: platform_device_put(hci->pdev); ida_free(&mipi_i3c_hci_pci_ida, dev_id); @@ -141,6 +145,9 @@ static void mipi_i3c_hci_pci_remove(struct pci_dev *pci) struct platform_device *pdev = hci->pdev; int dev_id = pdev->id; + if (hci->info && hci->info->exit) + hci->info->exit(hci); + platform_device_unregister(pdev); ida_free(&mipi_i3c_hci_pci_ida, dev_id); } From 884a33131f2a7c398daadcffae92384ed7f84b15 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:37 +0200 Subject: [PATCH 506/684] i3c: mipi-i3c-hci-pci: Add LTR support for Intel controllers Add support for Latency Tolerance Reporting (LTR) for Intel controllers. Implement PM ->set_latency_tolerance() callback to set LTR register values. Also expose LTR register values via debugfs. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-12-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 113 +++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 7a91efbd3e5481..25c129a856d6b2 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -7,17 +7,21 @@ * Author: Jarkko Nikula */ #include +#include +#include #include #include #include #include #include #include +#include struct mipi_i3c_hci_pci { struct pci_dev *pci; struct platform_device *pdev; const struct mipi_i3c_hci_pci_info *info; + void *private; }; struct mipi_i3c_hci_pci_info { @@ -34,6 +38,99 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida); #define INTEL_RESETS_RESET_DONE BIT(1) #define INTEL_RESETS_TIMEOUT_US (10 * USEC_PER_MSEC) +#define INTEL_ACTIVELTR 0x0c +#define INTEL_IDLELTR 0x10 + +#define INTEL_LTR_REQ BIT(15) +#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) +#define INTEL_LTR_SCALE_1US FIELD_PREP(INTEL_LTR_SCALE_MASK, 2) +#define INTEL_LTR_SCALE_32US FIELD_PREP(INTEL_LTR_SCALE_MASK, 3) +#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) + +struct intel_host { + void __iomem *priv; + u32 active_ltr; + u32 idle_ltr; + struct dentry *debugfs_root; +}; + +static void intel_cache_ltr(struct intel_host *host) +{ + host->active_ltr = readl(host->priv + INTEL_ACTIVELTR); + host->idle_ltr = readl(host->priv + INTEL_IDLELTR); +} + +static void intel_ltr_set(struct device *dev, s32 val) +{ + struct mipi_i3c_hci_pci *hci = dev_get_drvdata(dev); + struct intel_host *host = hci->private; + u32 ltr; + + /* + * Program latency tolerance (LTR) accordingly what has been asked + * by the PM QoS layer or disable it in case we were passed + * negative value or PM_QOS_LATENCY_ANY. + */ + ltr = readl(host->priv + INTEL_ACTIVELTR); + + if (val == PM_QOS_LATENCY_ANY || val < 0) { + ltr &= ~INTEL_LTR_REQ; + } else { + ltr |= INTEL_LTR_REQ; + ltr &= ~INTEL_LTR_SCALE_MASK; + ltr &= ~INTEL_LTR_VALUE_MASK; + + if (val > INTEL_LTR_VALUE_MASK) { + val >>= 5; + if (val > INTEL_LTR_VALUE_MASK) + val = INTEL_LTR_VALUE_MASK; + ltr |= INTEL_LTR_SCALE_32US | val; + } else { + ltr |= INTEL_LTR_SCALE_1US | val; + } + } + + if (ltr == host->active_ltr) + return; + + writel(ltr, host->priv + INTEL_ACTIVELTR); + writel(ltr, host->priv + INTEL_IDLELTR); + + /* Cache the values into intel_host structure */ + intel_cache_ltr(host); +} + +static void intel_ltr_expose(struct device *dev) +{ + dev->power.set_latency_tolerance = intel_ltr_set; + dev_pm_qos_expose_latency_tolerance(dev); +} + +static void intel_ltr_hide(struct device *dev) +{ + dev_pm_qos_hide_latency_tolerance(dev); + dev->power.set_latency_tolerance = NULL; +} + +static void intel_add_debugfs(struct mipi_i3c_hci_pci *hci) +{ + struct dentry *dir = debugfs_create_dir(dev_name(&hci->pci->dev), NULL); + struct intel_host *host = hci->private; + + intel_cache_ltr(host); + + host->debugfs_root = dir; + debugfs_create_x32("active_ltr", 0444, dir, &host->active_ltr); + debugfs_create_x32("idle_ltr", 0444, dir, &host->idle_ltr); +} + +static void intel_remove_debugfs(struct mipi_i3c_hci_pci *hci) +{ + struct intel_host *host = hci->private; + + debugfs_remove_recursive(host->debugfs_root); +} + static void intel_reset(void __iomem *priv) { u32 reg; @@ -55,20 +152,34 @@ static void __iomem *intel_priv(struct pci_dev *pci) static int intel_i3c_init(struct mipi_i3c_hci_pci *hci) { + struct intel_host *host = devm_kzalloc(&hci->pci->dev, sizeof(*host), GFP_KERNEL); void __iomem *priv = intel_priv(hci->pci); - if (!priv) + if (!host || !priv) return -ENOMEM; dma_set_mask_and_coherent(&hci->pci->dev, DMA_BIT_MASK(64)); + hci->private = host; + host->priv = priv; + intel_reset(priv); + intel_ltr_expose(&hci->pci->dev); + intel_add_debugfs(hci); + return 0; } +static void intel_i3c_exit(struct mipi_i3c_hci_pci *hci) +{ + intel_remove_debugfs(hci); + intel_ltr_hide(&hci->pci->dev); +} + static const struct mipi_i3c_hci_pci_info intel_info = { .init = intel_i3c_init, + .exit = intel_i3c_exit, }; static int mipi_i3c_hci_pci_probe(struct pci_dev *pci, From a54b1aeb61de63250ee608040a89bed8d1aa1e20 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Nov 2025 08:40:38 +0200 Subject: [PATCH 507/684] i3c: mipi-i3c-hci-pci: Set d3cold_delay to 0 for Intel controllers Set d3cold_delay to 0 for Intel controllers because a delay is not needed. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20251128064038.55158-13-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index 25c129a856d6b2..dc8ede0f8ad8df 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -160,6 +160,8 @@ static int intel_i3c_init(struct mipi_i3c_hci_pci *hci) dma_set_mask_and_coherent(&hci->pci->dev, DMA_BIT_MASK(64)); + hci->pci->d3cold_delay = 0; + hci->private = host; host->priv = priv; From 5b9481a4157198b93cd6a5e7ad2603682202149d Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 12 Nov 2025 22:30:00 +0100 Subject: [PATCH 508/684] i3c: master: Remove i3c_device_free_ibi from i3c_device_remove i3c_device_disable_ibi should be called before i3c_device_free_ibi, however, a driver using devm actions cannot yield the call before the bus_type.remove(), requiring to use a .remove method that is usually discouraged for drivers that uses resources already manage. Since the only consumer mctp-i3c.c of this method calls both i3c_device_disable_ibi then i3c_device_free_ibi, remove the call from the i3c_device_remove (bus_type.remove()). Signed-off-by: Jorge Marques Link: https://patch.msgid.link/20251112-ibi-unsafe-v1-1-d8454db22613@analog.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 66513a27e6e776..a0fe00e2487c89 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -334,8 +334,6 @@ static void i3c_device_remove(struct device *dev) if (driver->remove) driver->remove(i3cdev); - - i3c_device_free_ibi(i3cdev); } const struct bus_type i3c_bus_type = { From de53ad6ca49e5d73bba72d24b49ec5d40f33ee01 Mon Sep 17 00:00:00 2001 From: Marco Crivellari Date: Fri, 7 Nov 2025 14:29:49 +0100 Subject: [PATCH 509/684] i3c: master: add WQ_PERCPU to alloc_workqueue users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently if a user enqueues a work item using schedule_delayed_work() the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to schedule_work() that is using system_wq and queue_work(), that makes use again of WORK_CPU_UNBOUND. This lack of consistency cannot be addressed without refactoring the API. alloc_workqueue() treats all queues as per-CPU by default, while unbound workqueues must opt-in via WQ_UNBOUND. This default is suboptimal: most workloads benefit from unbound queues, allowing the scheduler to place worker threads where they’re needed and reducing noise when CPUs are isolated. This continues the effort to refactor workqueue APIs, which began with the introduction of new workqueues and a new alloc_workqueue flag in: commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") This change adds a new WQ_PERCPU flag to explicitly request alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified. With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND), any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND must now use WQ_PERCPU. Once migration is complete, WQ_UNBOUND can be removed and unbound will become the implicit default. Suggested-by: Tejun Heo Signed-off-by: Marco Crivellari Link: https://patch.msgid.link/20251107132949.184944-1-marco.crivellari@suse.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index a0fe00e2487c89..823661a81f5e70 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2923,7 +2923,7 @@ int i3c_master_register(struct i3c_master_controller *master, if (ret) goto err_put_dev; - master->wq = alloc_workqueue("%s", 0, 0, dev_name(parent)); + master->wq = alloc_workqueue("%s", WQ_PERCPU, 0, dev_name(parent)); if (!master->wq) { ret = -ENOMEM; goto err_put_dev; From 256a21743d911f94ce92fe28f793cd586f3860b2 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 6 Nov 2025 12:36:00 -0500 Subject: [PATCH 510/684] i3c: Add HDR API support Rename struct i3c_priv_xfer to struct i3c_xfer, since private xfer in the I3C spec refers only to SDR transfers. Ref: i3c spec ver1.2, section 3, Technical Overview. i3c_xfer will be used for both SDR and HDR. Rename enum i3c_hdr_mode to i3c_xfer_mode. Previous definition need match CCC GET_CAP1 bit position. Use 31 as SDR transfer mode. Add i3c_device_do_xfers() with an xfer mode argument, while keeping i3c_device_do_priv_xfers() as a wrapper that calls i3c_device_do_xfers() with I3C_SDR for backward compatibility. Introduce a 'cmd' field in struct i3c_xfer as an anonymous union with 'rnw', since HDR mode uses read/write commands instead of the SDR address bit. Add .i3c_xfers() callback for master controllers. If not implemented, fall back to SDR with .priv_xfers(). The .priv_xfers() API can be removed once all controllers switch to .i3c_xfers(). Add 'mode_mask' bitmask to advertise controller capability. Signed-off-by: Frank Li Link: https://patch.msgid.link/20251106-i3c_ddr-v11-1-33a6a66ed095@nxp.com Signed-off-by: Alexandre Belloni --- drivers/i3c/device.c | 27 ++++++++++++++++++------- drivers/i3c/internals.h | 6 +++--- drivers/i3c/master.c | 19 +++++++++++++----- include/linux/i3c/device.h | 40 +++++++++++++++++++++++++++----------- include/linux/i3c/master.h | 4 ++++ 5 files changed, 70 insertions(+), 26 deletions(-) diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c index 2396545763ff85..8a156f5ad69294 100644 --- a/drivers/i3c/device.c +++ b/drivers/i3c/device.c @@ -15,12 +15,12 @@ #include "internals.h" /** - * i3c_device_do_priv_xfers() - do I3C SDR private transfers directed to a - * specific device + * i3c_device_do_xfers() - do I3C transfers directed to a specific device * * @dev: device with which the transfers should be done * @xfers: array of transfers * @nxfers: number of transfers + * @mode: transfer mode * * Initiate one or several private SDR transfers with @dev. * @@ -33,9 +33,8 @@ * 'xfers' some time later. See I3C spec ver 1.1.1 09-Jun-2021. Section: * 5.1.2.2.3. */ -int i3c_device_do_priv_xfers(struct i3c_device *dev, - struct i3c_priv_xfer *xfers, - int nxfers) +int i3c_device_do_xfers(struct i3c_device *dev, struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode) { int ret, i; @@ -48,12 +47,12 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev, } i3c_bus_normaluse_lock(dev->bus); - ret = i3c_dev_do_priv_xfers_locked(dev->desc, xfers, nxfers); + ret = i3c_dev_do_xfers_locked(dev->desc, xfers, nxfers, mode); i3c_bus_normaluse_unlock(dev->bus); return ret; } -EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers); +EXPORT_SYMBOL_GPL(i3c_device_do_xfers); /** * i3c_device_do_setdasa() - do I3C dynamic address assignement with @@ -260,6 +259,20 @@ i3c_device_match_id(struct i3c_device *i3cdev, } EXPORT_SYMBOL_GPL(i3c_device_match_id); +/** + * i3c_device_get_supported_xfer_mode - Returns the supported transfer mode by + * connected master controller. + * @dev: I3C device + * + * Return: a bit mask, which supported transfer mode, bit position is defined at + * enum i3c_hdr_mode + */ +u32 i3c_device_get_supported_xfer_mode(struct i3c_device *dev) +{ + return i3c_dev_get_master(dev->desc)->this->info.hdr_cap | BIT(I3C_SDR); +} +EXPORT_SYMBOL_GPL(i3c_device_get_supported_xfer_mode); + /** * i3c_driver_register_with_owner() - register an I3C device driver * diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h index 79ceaa5f5afd6f..f609e5098137c1 100644 --- a/drivers/i3c/internals.h +++ b/drivers/i3c/internals.h @@ -15,9 +15,9 @@ void i3c_bus_normaluse_lock(struct i3c_bus *bus); void i3c_bus_normaluse_unlock(struct i3c_bus *bus); int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev); -int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, - struct i3c_priv_xfer *xfers, - int nxfers); +int i3c_dev_do_xfers_locked(struct i3c_dev_desc *dev, + struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode); int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev); int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev); int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev, diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 823661a81f5e70..f88f7e19203ae5 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2819,10 +2819,14 @@ EXPORT_SYMBOL_GPL(i3c_generic_ibi_recycle_slot); static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops) { - if (!ops || !ops->bus_init || !ops->priv_xfers || + if (!ops || !ops->bus_init || !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers) return -EINVAL; + /* Must provide one of priv_xfers (SDR only) or i3c_xfers (all modes) */ + if (!ops->priv_xfers && !ops->i3c_xfers) + return -EINVAL; + if (ops->request_ibi && (!ops->enable_ibi || !ops->disable_ibi || !ops->free_ibi || !ops->recycle_ibi_slot)) @@ -3012,9 +3016,8 @@ int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev) dev->boardinfo->init_dyn_addr); } -int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, - struct i3c_priv_xfer *xfers, - int nxfers) +int i3c_dev_do_xfers_locked(struct i3c_dev_desc *dev, struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode) { struct i3c_master_controller *master; @@ -3025,9 +3028,15 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, if (!master || !xfers) return -EINVAL; - if (!master->ops->priv_xfers) + if (mode != I3C_SDR && !(master->this->info.hdr_cap & BIT(mode))) return -EOPNOTSUPP; + if (master->ops->i3c_xfers) + return master->ops->i3c_xfers(dev, xfers, nxfers, mode); + + if (mode != I3C_SDR) + return -EINVAL; + return master->ops->priv_xfers(dev, xfers, nxfers); } diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 7f136de4b73ef8..7f7738041f3809 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -39,20 +39,25 @@ enum i3c_error_code { }; /** - * enum i3c_hdr_mode - HDR mode ids + * enum i3c_xfer_mode - I3C xfer mode ids * @I3C_HDR_DDR: DDR mode * @I3C_HDR_TSP: TSP mode * @I3C_HDR_TSL: TSL mode + * @I3C_SDR: SDR mode (NOT HDR mode) */ -enum i3c_hdr_mode { - I3C_HDR_DDR, - I3C_HDR_TSP, - I3C_HDR_TSL, +enum i3c_xfer_mode { + /* The below 3 value (I3C_HDR*) must match GETCAP1 Byte bit position */ + I3C_HDR_DDR = 0, + I3C_HDR_TSP = 1, + I3C_HDR_TSL = 2, + /* Use for default SDR transfer mode */ + I3C_SDR = 0x31, }; /** - * struct i3c_priv_xfer - I3C SDR private transfer + * struct i3c_xfer - I3C data transfer * @rnw: encodes the transfer direction. true for a read, false for a write + * @cmd: Read/Write command in HDR mode, read: 0x80 - 0xff, write: 0x00 - 0x7f * @len: transfer length in bytes of the transfer * @actual_len: actual length in bytes are transferred by the controller * @data: input/output buffer @@ -60,8 +65,11 @@ enum i3c_hdr_mode { * @data.out: output buffer. Must point to a DMA-able buffer * @err: I3C error code */ -struct i3c_priv_xfer { - u8 rnw; +struct i3c_xfer { + union { + u8 rnw; + u8 cmd; + }; u16 len; u16 actual_len; union { @@ -71,6 +79,9 @@ struct i3c_priv_xfer { enum i3c_error_code err; }; +/* keep back compatible */ +#define i3c_priv_xfer i3c_xfer + /** * enum i3c_dcr - I3C DCR values * @I3C_DCR_GENERIC_DEVICE: generic I3C device @@ -297,9 +308,15 @@ static __always_inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv, i3c_i2c_driver_unregister, \ __i2cdrv) -int i3c_device_do_priv_xfers(struct i3c_device *dev, - struct i3c_priv_xfer *xfers, - int nxfers); +int i3c_device_do_xfers(struct i3c_device *dev, struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode); + +static inline int i3c_device_do_priv_xfers(struct i3c_device *dev, + struct i3c_priv_xfer *xfers, + int nxfers) +{ + return i3c_device_do_xfers(dev, xfers, nxfers, I3C_SDR); +} int i3c_device_do_setdasa(struct i3c_device *dev); @@ -341,5 +358,6 @@ int i3c_device_request_ibi(struct i3c_device *dev, void i3c_device_free_ibi(struct i3c_device *dev); int i3c_device_enable_ibi(struct i3c_device *dev); int i3c_device_disable_ibi(struct i3c_device *dev); +u32 i3c_device_get_supported_xfer_mode(struct i3c_device *dev); #endif /* I3C_DEV_H */ diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index c52a82dd79a634..d0d5b3a9049f0b 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -474,9 +474,13 @@ struct i3c_master_controller_ops { const struct i3c_ccc_cmd *cmd); int (*send_ccc_cmd)(struct i3c_master_controller *master, struct i3c_ccc_cmd *cmd); + /* Deprecated, please use i3c_xfers() */ int (*priv_xfers)(struct i3c_dev_desc *dev, struct i3c_priv_xfer *xfers, int nxfers); + int (*i3c_xfers)(struct i3c_dev_desc *dev, + struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode); int (*attach_i2c_dev)(struct i2c_dev_desc *dev); void (*detach_i2c_dev)(struct i2c_dev_desc *dev); int (*i2c_xfers)(struct i2c_dev_desc *dev, From 9280b6ebbf08e53734d34f3bb325c37cddc1422d Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 6 Nov 2025 12:36:01 -0500 Subject: [PATCH 511/684] i3c: Switch to use new i3c_xfer from i3c_priv_xfer Switch to use i3c_xfer instead of i3c_priv_xfer because framework update to support HDR mode. i3c_priv_xfer is now an alias of i3c_xfer. Signed-off-by: Frank Li Link: https://patch.msgid.link/20251106-i3c_ddr-v11-2-33a6a66ed095@nxp.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 7f7738041f3809..ae0662d9d77eb3 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -27,7 +27,7 @@ * These are the standard error codes as defined by the I3C specification. * When -EIO is returned by the i3c_device_do_priv_xfers() or * i3c_device_send_hdr_cmds() one can check the error code in - * &struct_i3c_priv_xfer.err or &struct i3c_hdr_cmd.err to get a better idea of + * &struct_i3c_xfer.err or &struct i3c_hdr_cmd.err to get a better idea of * what went wrong. * */ @@ -312,7 +312,7 @@ int i3c_device_do_xfers(struct i3c_device *dev, struct i3c_xfer *xfers, int nxfers, enum i3c_xfer_mode mode); static inline int i3c_device_do_priv_xfers(struct i3c_device *dev, - struct i3c_priv_xfer *xfers, + struct i3c_xfer *xfers, int nxfers) { return i3c_device_do_xfers(dev, xfers, nxfers, I3C_SDR); From 108420fe2100b0c9cfb2d3598681eab3724247b9 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 6 Nov 2025 12:36:02 -0500 Subject: [PATCH 512/684] i3c: master: svc: Replace bool rnw with union for HDR support Replace the bool rnw field with a union in preparation for adding HDR support. HDR uses a cmd field instead of the rnw bit to indicate read or write direction. Add helper function svc_cmd_is_read() to check transfer direction. Add a local variable 'rnw' in svc_i3c_master_priv_xfers() to avoid repeatedly accessing xfers[i].rnw. No functional change. Signed-off-by: Frank Li Link: https://patch.msgid.link/20251106-i3c_ddr-v11-3-33a6a66ed095@nxp.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/svc-i3c-master.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index e70a64f2a32fa5..0543f06b9fba70 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -165,7 +165,11 @@ struct svc_i3c_cmd { u8 addr; - bool rnw; + union { + bool rnw; + u8 cmd; + u32 rnw_cmd; + }; u8 *in; const void *out; unsigned int len; @@ -383,6 +387,11 @@ svc_i3c_master_dev_from_addr(struct svc_i3c_master *master, return master->descs[i]; } +static bool svc_cmd_is_read(u32 rnw_cmd, u32 type) +{ + return rnw_cmd; +} + static void svc_i3c_master_emit_stop(struct svc_i3c_master *master) { writel(SVC_I3C_MCTRL_REQUEST_STOP, master->regs + SVC_I3C_MCTRL); @@ -1299,10 +1308,11 @@ static int svc_i3c_master_write(struct svc_i3c_master *master, } static int svc_i3c_master_xfer(struct svc_i3c_master *master, - bool rnw, unsigned int xfer_type, u8 addr, + u32 rnw_cmd, unsigned int xfer_type, u8 addr, u8 *in, const u8 *out, unsigned int xfer_len, unsigned int *actual_len, bool continued, bool repeat_start) { + bool rnw = svc_cmd_is_read(rnw_cmd, xfer_type); int retry = repeat_start ? 1 : 2; u32 reg; int ret; @@ -1490,7 +1500,7 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master) for (i = 0; i < xfer->ncmds; i++) { struct svc_i3c_cmd *cmd = &xfer->cmds[i]; - ret = svc_i3c_master_xfer(master, cmd->rnw, xfer->type, + ret = svc_i3c_master_xfer(master, cmd->rnw_cmd, xfer->type, cmd->addr, cmd->in, cmd->out, cmd->len, &cmd->actual_len, cmd->continued, i > 0); @@ -1683,14 +1693,15 @@ static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev, for (i = 0; i < nxfers; i++) { struct svc_i3c_cmd *cmd = &xfer->cmds[i]; + bool rnw = xfers[i].rnw; cmd->xfer = &xfers[i]; cmd->addr = master->addrs[data->index]; - cmd->rnw = xfers[i].rnw; - cmd->in = xfers[i].rnw ? xfers[i].data.in : NULL; - cmd->out = xfers[i].rnw ? NULL : xfers[i].data.out; + cmd->rnw = rnw; + cmd->in = rnw ? xfers[i].data.in : NULL; + cmd->out = rnw ? NULL : xfers[i].data.out; cmd->len = xfers[i].len; - cmd->actual_len = xfers[i].rnw ? xfers[i].len : 0; + cmd->actual_len = rnw ? xfers[i].len : 0; cmd->continued = (i + 1) < nxfers; } From 4e7263b87ca362825beeac669dcbe24aae2c6257 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 6 Nov 2025 12:36:03 -0500 Subject: [PATCH 513/684] i3c: master: svc: Add basic HDR mode support Add basic HDR mode support for the svs I3C master driver. Only support for private transfers and does not support sending CCC commands in HDR mode. Key differences: - HDR uses commands (0x00-0x7F for write, 0x80-0xFF for read) to distinguish transfer direction. - HDR read/write commands must be written to FIFO before issuing the I3C address command. The hardware automatically sends the standard CCC command to enter HDR mode. - HDR exit pattern must be sent instead of send a stop after transfer completion. - Read/write data size must be an even number. Co-developed-by: Carlos Song Signed-off-by: Carlos Song Signed-off-by: Frank Li Link: https://patch.msgid.link/20251106-i3c_ddr-v11-4-33a6a66ed095@nxp.com Signed-off-by: Alexandre Belloni --- drivers/i3c/master/svc-i3c-master.c | 96 +++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 0543f06b9fba70..a62f22ff8b5762 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -40,11 +40,13 @@ #define SVC_I3C_MCTRL_REQUEST_NONE 0 #define SVC_I3C_MCTRL_REQUEST_START_ADDR 1 #define SVC_I3C_MCTRL_REQUEST_STOP 2 +#define SVC_I3C_MCTRL_REQUEST_FORCE_EXIT 6 #define SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK 3 #define SVC_I3C_MCTRL_REQUEST_PROC_DAA 4 #define SVC_I3C_MCTRL_REQUEST_AUTO_IBI 7 #define SVC_I3C_MCTRL_TYPE_I3C 0 #define SVC_I3C_MCTRL_TYPE_I2C BIT(4) +#define SVC_I3C_MCTRL_TYPE_DDR BIT(5) #define SVC_I3C_MCTRL_IBIRESP_AUTO 0 #define SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE 0 #define SVC_I3C_MCTRL_IBIRESP_ACK_WITH_BYTE BIT(7) @@ -95,6 +97,7 @@ #define SVC_I3C_MINTMASKED 0x098 #define SVC_I3C_MERRWARN 0x09C #define SVC_I3C_MERRWARN_NACK BIT(2) +#define SVC_I3C_MERRWARN_CRC BIT(10) #define SVC_I3C_MERRWARN_TIMEOUT BIT(20) #define SVC_I3C_MDMACTRL 0x0A0 #define SVC_I3C_MDATACTRL 0x0AC @@ -174,7 +177,7 @@ struct svc_i3c_cmd { const void *out; unsigned int len; unsigned int actual_len; - struct i3c_priv_xfer *xfer; + struct i3c_xfer *xfer; bool continued; }; @@ -389,7 +392,32 @@ svc_i3c_master_dev_from_addr(struct svc_i3c_master *master, static bool svc_cmd_is_read(u32 rnw_cmd, u32 type) { - return rnw_cmd; + return (type == SVC_I3C_MCTRL_TYPE_DDR) ? (rnw_cmd & 0x80) : rnw_cmd; +} + +static void svc_i3c_master_emit_force_exit(struct svc_i3c_master *master) +{ + u32 reg; + + writel(SVC_I3C_MCTRL_REQUEST_FORCE_EXIT, master->regs + SVC_I3C_MCTRL); + + /* + * Not need check error here because it is never happen at hardware. + * IP just wait for few fclk cycle to complete DDR exit pattern. Even + * though fclk stop, timeout happen here, the whole data actually + * already finish transfer. The next command will be timeout because + * wrong hardware state. + */ + readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, + SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000); + + /* + * This delay is necessary after the emission of a stop, otherwise eg. + * repeating IBIs do not get detected. There is a note in the manual + * about it, stating that the stop condition might not be settled + * correctly if a start condition follows too rapidly. + */ + udelay(1); } static void svc_i3c_master_emit_stop(struct svc_i3c_master *master) @@ -527,7 +555,7 @@ static void svc_i3c_master_ibi_isr(struct svc_i3c_master *master) * cycle, leading to missed client IBI handlers. * * A typical scenario is when IBIWON occurs and bus arbitration is lost - * at svc_i3c_master_priv_xfers(). + * at svc_i3c_master_i3c_xfers(). * * Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI. */ @@ -807,6 +835,8 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m) info.dyn_addr = ret; + info.hdr_cap = I3C_CCC_HDR_MODE(I3C_HDR_DDR); + writel(SVC_MDYNADDR_VALID | SVC_MDYNADDR_ADDR(info.dyn_addr), master->regs + SVC_I3C_MDYNADDR); @@ -1320,6 +1350,16 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, /* clean SVC_I3C_MINT_IBIWON w1c bits */ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); + if (xfer_type == SVC_I3C_MCTRL_TYPE_DDR) { + /* DDR command need prefill into FIFO */ + writel(rnw_cmd, master->regs + SVC_I3C_MWDATAB); + if (!rnw) { + /* write data also need prefill into FIFO */ + ret = svc_i3c_master_write(master, out, xfer_len); + if (ret) + goto emit_stop; + } + } while (retry--) { writel(SVC_I3C_MCTRL_REQUEST_START_ADDR | @@ -1413,7 +1453,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, if (rnw) ret = svc_i3c_master_read(master, in, xfer_len); - else + else if (xfer_type != SVC_I3C_MCTRL_TYPE_DDR) ret = svc_i3c_master_write(master, out, xfer_len); if (ret < 0) goto emit_stop; @@ -1426,10 +1466,19 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, if (ret) goto emit_stop; + if (xfer_type == SVC_I3C_MCTRL_TYPE_DDR && + (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_CRC)) { + ret = -ENXIO; + goto emit_stop; + } + writel(SVC_I3C_MINT_COMPLETE, master->regs + SVC_I3C_MSTATUS); if (!continued) { - svc_i3c_master_emit_stop(master); + if (xfer_type != SVC_I3C_MCTRL_TYPE_DDR) + svc_i3c_master_emit_stop(master); + else + svc_i3c_master_emit_force_exit(master); /* Wait idle if stop is sent. */ readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg, @@ -1439,7 +1488,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, return 0; emit_stop: - svc_i3c_master_emit_stop(master); + if (xfer_type != SVC_I3C_MCTRL_TYPE_DDR) + svc_i3c_master_emit_stop(master); + else + svc_i3c_master_emit_force_exit(master); + svc_i3c_master_clear_merrwarn(master); svc_i3c_master_flush_fifo(master); @@ -1486,6 +1539,11 @@ static void svc_i3c_master_dequeue_xfer(struct svc_i3c_master *master, spin_unlock_irqrestore(&master->xferqueue.lock, flags); } +static int i3c_mode_to_svc_type(enum i3c_xfer_mode mode) +{ + return (mode == I3C_SDR) ? SVC_I3C_MCTRL_TYPE_I3C : SVC_I3C_MCTRL_TYPE_DDR; +} + static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master) { struct svc_i3c_xfer *xfer = master->xferqueue.cur; @@ -1675,9 +1733,8 @@ static int svc_i3c_master_send_ccc_cmd(struct i3c_master_controller *m, return ret; } -static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev, - struct i3c_priv_xfer *xfers, - int nxfers) +static int svc_i3c_master_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode) { struct i3c_master_controller *m = i3c_dev_get_master(dev); struct svc_i3c_master *master = to_svc_i3c_master(m); @@ -1685,19 +1742,32 @@ static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev, struct svc_i3c_xfer *xfer; int ret, i; + if (mode != I3C_SDR) { + /* + * Only support data size less than FIFO SIZE when using DDR + * mode. First entry is cmd in FIFO, so actual available FIFO + * for data is SVC_I3C_FIFO_SIZE - 2 since DDR only supports + * even length. + */ + for (i = 0; i < nxfers; i++) + if (xfers[i].len > SVC_I3C_FIFO_SIZE - 2) + return -EINVAL; + } + xfer = svc_i3c_master_alloc_xfer(master, nxfers); if (!xfer) return -ENOMEM; - xfer->type = SVC_I3C_MCTRL_TYPE_I3C; + xfer->type = i3c_mode_to_svc_type(mode); for (i = 0; i < nxfers; i++) { + u32 rnw_cmd = (mode == I3C_SDR) ? xfers[i].rnw : xfers[i].cmd; + bool rnw = svc_cmd_is_read(rnw_cmd, xfer->type); struct svc_i3c_cmd *cmd = &xfer->cmds[i]; - bool rnw = xfers[i].rnw; cmd->xfer = &xfers[i]; cmd->addr = master->addrs[data->index]; - cmd->rnw = rnw; + cmd->rnw_cmd = rnw_cmd; cmd->in = rnw ? xfers[i].data.in : NULL; cmd->out = rnw ? NULL : xfers[i].data.out; cmd->len = xfers[i].len; @@ -1896,7 +1966,7 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = { .do_daa = svc_i3c_master_do_daa, .supports_ccc_cmd = svc_i3c_master_supports_ccc_cmd, .send_ccc_cmd = svc_i3c_master_send_ccc_cmd, - .priv_xfers = svc_i3c_master_priv_xfers, + .i3c_xfers = svc_i3c_master_i3c_xfers, .i2c_xfers = svc_i3c_master_i2c_xfers, .request_ibi = svc_i3c_master_request_ibi, .free_ibi = svc_i3c_master_free_ibi, From 267c2e633af6e9461477bed91e428993f8b36ee8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 26 Nov 2025 20:44:18 -0800 Subject: [PATCH 514/684] perf trace: Skip internal syscall arguments Recent changes in the linux-next kernel will add new field for syscalls to have contents in the userspace like below. # cat /sys/kernel/tracing/events/syscalls/sys_enter_write/format name: sys_enter_write ID: 758 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:int __syscall_nr; offset:8; size:4; signed:1; field:unsigned int fd; offset:16; size:8; signed:0; field:const char * buf; offset:24; size:8; signed:0; field:size_t count; offset:32; size:8; signed:0; field:__data_loc char[] __buf_val; offset:40; size:4; signed:0; print fmt: "fd: 0x%08lx, buf: 0x%08lx (%s), count: 0x%08lx", ((unsigned long)(REC->fd)), ((unsigned long)(REC->buf)), __print_dynamic_array(__buf_val, 1), ((unsigned long)(REC->count)) We have a different way to handle those arguments and this change confuses perf trace then make some tests failing. Fix it by skipping the new fields that have "__data_loc char[]" type. Maybe we can switch to this instead of the BPF augmentation later. Reviewed-by: Howard Chu Tested-by: Thomas Richter Tested-by: Steven Rostedt (Google) Cc: Steven Rostedt Cc: Howard Chu Reported-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/builtin-trace.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a743bda294bd34..baee1f6956001d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2069,6 +2069,15 @@ static const struct syscall_arg_fmt *syscall_arg_fmt__find_by_name(const char *n return __syscall_arg_fmt__find_by_name(syscall_arg_fmts__by_name, nmemb, name); } +/* + * v6.19 kernel added new fields to read userspace memory for event tracing. + * But it's not used by perf and confuses the syscall parameters. + */ +static bool is_internal_field(struct tep_format_field *field) +{ + return !strcmp(field->type, "__data_loc char[]"); +} + static struct tep_format_field * syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field *field, bool *use_btf) @@ -2077,6 +2086,10 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field int len; for (; field; field = field->next, ++arg) { + /* assume it's the last argument */ + if (is_internal_field(field)) + continue; + last_field = field; if (arg->scnprintf) @@ -2145,6 +2158,7 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace) { char tp_name[128]; const char *name; + struct tep_format_field *field; int err; if (sc->nonexistent) @@ -2201,6 +2215,13 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace) --sc->nr_args; } + field = sc->args; + while (field) { + if (is_internal_field(field)) + --sc->nr_args; + field = field->next; + } + sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); sc->is_open = !strcmp(name, "open") || !strcmp(name, "openat"); From cf33f0b7df13685234ccea7be7bfe316b60db4db Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 24 Nov 2025 12:11:06 -0700 Subject: [PATCH 515/684] clk: samsung: exynos-clkout: Assign .num before accessing .hws Commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") annotated the hws member of 'struct clk_hw_onecell_data' with __counted_by, which informs the bounds sanitizer (UBSAN_BOUNDS) about the number of elements in .hws[], so that it can warn when .hws[] is accessed out of bounds. As noted in that change, the __counted_by member must be initialized with the number of elements before the first array access happens, otherwise there will be a warning from each access prior to the initialization because the number of elements is zero. This occurs in exynos_clkout_probe() due to .num being assigned after .hws[] has been accessed: UBSAN: array-index-out-of-bounds in drivers/clk/samsung/clk-exynos-clkout.c:178:18 index 0 is out of range for type 'clk_hw *[*]' Move the .num initialization to before the first access of .hws[], clearing up the warning. Cc: stable@vger.kernel.org Fixes: f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") Reported-by: Jochen Sprickerhof Closes: https://lore.kernel.org/aSIYDN5eyKFKoXKL@eldamar.lan/ Tested-by: Jochen Sprickerhof Signed-off-by: Nathan Chancellor Reviewed-by: Kees Cook Reviewed-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/samsung/clk-exynos-clkout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index 5f1a4f5e2e594f..5b21025338bd53 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -175,6 +175,7 @@ static int exynos_clkout_probe(struct platform_device *pdev) clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT; clkout->mux.lock = &clkout->slock; + clkout->data.num = EXYNOS_CLKOUT_NR_CLKS; clkout->data.hws[0] = clk_hw_register_composite(NULL, "clkout", parent_names, parent_count, &clkout->mux.hw, &clk_mux_ops, NULL, NULL, &clkout->gate.hw, @@ -185,7 +186,6 @@ static int exynos_clkout_probe(struct platform_device *pdev) goto err_unmap; } - clkout->data.num = EXYNOS_CLKOUT_NR_CLKS; ret = of_clk_add_hw_provider(clkout->np, of_clk_hw_onecell_get, &clkout->data); if (ret) goto err_clk_unreg; From 1413717ad0c6d3887192b0119ad6420dbf0c26ae Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 30 Nov 2025 12:02:31 -0800 Subject: [PATCH 516/684] clk: qcom: Mark camcc_sm7150_hws static This isn't used outside this file. Mark it static. Fixes: 9f0532da4226 ("clk: qcom: Add Camera Clock Controller driver for SM7150") Signed-off-by: Stephen Boyd --- drivers/clk/qcom/camcc-sm7150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/camcc-sm7150.c b/drivers/clk/qcom/camcc-sm7150.c index 8b06af8d15096c..ee963ed341c393 100644 --- a/drivers/clk/qcom/camcc-sm7150.c +++ b/drivers/clk/qcom/camcc-sm7150.c @@ -1895,7 +1895,7 @@ static struct gdsc camcc_titan_top_gdsc = { .pwrsts = PWRSTS_OFF_ON, }; -struct clk_hw *camcc_sm7150_hws[] = { +static struct clk_hw *camcc_sm7150_hws[] = { [CAMCC_PLL0_OUT_EVEN] = &camcc_pll0_out_even.hw, [CAMCC_PLL0_OUT_ODD] = &camcc_pll0_out_odd.hw, [CAMCC_PLL1_OUT_EVEN] = &camcc_pll1_out_even.hw, From 9c75986a298f121ed2c6599b05e51d9a34e77068 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 27 Nov 2025 14:42:43 +0100 Subject: [PATCH 517/684] clk: keystone: syscon-clk: fix regmap leak on probe failure The mmio regmap allocated during probe is never freed. Switch to using the device managed allocator so that the regmap is released on probe failures (e.g. probe deferral) and on driver unbind. Fixes: a250cd4c1901 ("clk: keystone: syscon-clk: Do not use syscon helper to build regmap") Cc: stable@vger.kernel.org # 6.15 Cc: Andrew Davis Signed-off-by: Johan Hovold Signed-off-by: Stephen Boyd --- drivers/clk/keystone/syscon-clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index c509929da85452..ecf180a7949c93 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -129,7 +129,7 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - regmap = regmap_init_mmio(dev, base, &ti_syscon_regmap_cfg); + regmap = devm_regmap_init_mmio(dev, base, &ti_syscon_regmap_cfg); if (IS_ERR(regmap)) return dev_err_probe(dev, PTR_ERR(regmap), "failed to get regmap\n"); From b276445e98fe28609688fb85b89a81b803910e63 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 27 Nov 2025 14:53:25 +0100 Subject: [PATCH 518/684] clk: keystone: fix compile testing Some keystone clock drivers can be selected when COMPILE_TEST is enabled but since commit b745c0794e2f ("clk: keystone: Add sci-clk driver support") they are never actually built. Enable compile testing by allowing the build system to process the keystone drivers. Fixes: b745c0794e2f ("clk: keystone: Add sci-clk driver support") Signed-off-by: Johan Hovold Signed-off-by: Stephen Boyd --- drivers/clk/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b74a1767ca2787..61ec08404442b4 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -125,8 +125,7 @@ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-y += imgtec/ obj-y += imx/ obj-y += ingenic/ -obj-$(CONFIG_ARCH_K3) += keystone/ -obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ +obj-y += keystone/ obj-y += mediatek/ obj-$(CONFIG_ARCH_MESON) += meson/ obj-y += microchip/ From 7448a8d6909a488304ff402c414b14606b8472c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 20 Nov 2025 18:55:38 +0100 Subject: [PATCH 519/684] MAINTAINERS: phy: Move Kishon Vijay Abraham I to credits There wasn't much of reviewing activity from Kishon of PHY subsystem during last few years [1] and last maintainer commit is from 2020, so move Kishon to Credits to indicate that PHY subsystem has only one active maintainer. Thank you Kishon for working on the PHY subsystem and for all the maintenance effort. Link: https://lore.kernel.org/all/?q=f%3A%22Kishon+Vijay+Abraham+I%22 [1] Cc: Kishon Vijay Abraham I Cc: Kishon Vijay Abraham I Cc: Vinod Koul Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20251120175537.171340-2-krzk@kernel.org Signed-off-by: Vinod Koul --- CREDITS | 4 ++++ MAINTAINERS | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CREDITS b/CREDITS index 903ea238e64f3c..c75115626c08e1 100644 --- a/CREDITS +++ b/CREDITS @@ -16,6 +16,10 @@ D: One of assisting postmasters for vger.kernel.org's lists S: (ask for current address) S: Finland +N: Kishon Vijay Abraham I +E: kishon@kernel.org +D: Generic Phy Framework + N: Thomas Abraham E: thomas.ab@samsung.com D: Samsung pin controller driver diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968e4..400523d03e14f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10439,7 +10439,6 @@ F: include/uapi/asm-generic/ GENERIC PHY FRAMEWORK M: Vinod Koul -M: Kishon Vijay Abraham I L: linux-phy@lists.infradead.org S: Supported Q: https://patchwork.kernel.org/project/linux-phy/list/ From 7fce856f1180c2db3c9f5a88b04bb7124a20cb21 Mon Sep 17 00:00:00 2001 From: Max Gurtovoy Date: Wed, 24 Sep 2025 23:35:44 +0300 Subject: [PATCH 520/684] nvmet: add sanity checks when freeing subsystem Add WARN_ON_ONCE checks in nvmet_subsys_free() to ensure that the ctrls and hosts lists are all empty during subsystem release. This helps catch resource leaks. Signed-off-by: Max Gurtovoy Signed-off-by: Keith Busch --- drivers/nvme/target/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 5d7d483bfbe372..9de429a3f0d893 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1903,6 +1903,8 @@ static void nvmet_subsys_free(struct kref *ref) struct nvmet_subsys *subsys = container_of(ref, struct nvmet_subsys, ref); + WARN_ON_ONCE(!list_empty(&subsys->ctrls)); + WARN_ON_ONCE(!list_empty(&subsys->hosts)); WARN_ON_ONCE(!xa_empty(&subsys->namespaces)); nvmet_debugfs_subsys_free(subsys); From edd17206e363aebc9595b2ffefa7e4d8aba096ef Mon Sep 17 00:00:00 2001 From: Max Gurtovoy Date: Wed, 24 Sep 2025 23:34:02 +0300 Subject: [PATCH 521/684] nvmet: remove redundant subsysnqn field from ctrl The subsysnqn field in the nvmet controller structure is redundant, since the subsystem NQN can always be accessed via the controller's subsystem reference. Remove this field to save memory and avoid unnecessary duplication. Signed-off-by: Max Gurtovoy Signed-off-by: Keith Busch --- drivers/nvme/target/auth.c | 18 ++++++++++-------- drivers/nvme/target/core.c | 1 - drivers/nvme/target/nvmet.h | 1 - drivers/nvme/target/passthru.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c index b340380f38922a..250d2d650ee9a6 100644 --- a/drivers/nvme/target/auth.c +++ b/drivers/nvme/target/auth.c @@ -380,8 +380,8 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response, ret = crypto_shash_update(shash, buf, 1); if (ret) goto out; - ret = crypto_shash_update(shash, ctrl->subsysnqn, - strlen(ctrl->subsysnqn)); + ret = crypto_shash_update(shash, ctrl->subsys->subsysnqn, + strlen(ctrl->subsys->subsysnqn)); if (ret) goto out; ret = crypto_shash_final(shash, response); @@ -428,7 +428,7 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response, } transformed_key = nvme_auth_transform_key(ctrl->ctrl_key, - ctrl->subsysnqn); + ctrl->subsys->subsysnqn); if (IS_ERR(transformed_key)) { ret = PTR_ERR(transformed_key); goto out_free_tfm; @@ -483,8 +483,8 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response, ret = crypto_shash_update(shash, "Controller", 10); if (ret) goto out; - ret = crypto_shash_update(shash, ctrl->subsysnqn, - strlen(ctrl->subsysnqn)); + ret = crypto_shash_update(shash, ctrl->subsys->subsysnqn, + strlen(ctrl->subsys->subsysnqn)); if (ret) goto out; ret = crypto_shash_update(shash, buf, 1); @@ -574,7 +574,7 @@ void nvmet_auth_insert_psk(struct nvmet_sq *sq) return; } ret = nvme_auth_generate_digest(sq->ctrl->shash_id, psk, psk_len, - sq->ctrl->subsysnqn, + sq->ctrl->subsys->subsysnqn, sq->ctrl->hostnqn, &digest); if (ret) { pr_warn("%s: ctrl %d qid %d failed to generate digest, error %d\n", @@ -589,8 +589,10 @@ void nvmet_auth_insert_psk(struct nvmet_sq *sq) goto out_free_digest; } #ifdef CONFIG_NVME_TARGET_TCP_TLS - tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, sq->ctrl->subsysnqn, - sq->ctrl->shash_id, tls_psk, psk_len, digest); + tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, + sq->ctrl->subsys->subsysnqn, + sq->ctrl->shash_id, tls_psk, psk_len, + digest); if (IS_ERR(tls_key)) { pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n", __func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key)); diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 9de429a3f0d893..da94d1c7699eba 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1628,7 +1628,6 @@ struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_alloc_ctrl_args *args) INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); INIT_DELAYED_WORK(&ctrl->ka_work, nvmet_keep_alive_timer); - memcpy(ctrl->subsysnqn, args->subsysnqn, NVMF_NQN_SIZE); memcpy(ctrl->hostnqn, args->hostnqn, NVMF_NQN_SIZE); kref_init(&ctrl->ref); diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 51df72f5e89b72..209f04adcde618 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -284,7 +284,6 @@ struct nvmet_ctrl { __le32 *changed_ns_list; u32 nr_changed_ns; - char subsysnqn[NVMF_NQN_FIELD_LEN]; char hostnqn[NVMF_NQN_FIELD_LEN]; struct device *p2p_client; diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index 0c361b1e356656..96648ec2fadb55 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -150,7 +150,7 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req) * code path with duplicate ctrl subsysnqn. In order to prevent that we * mask the passthru-ctrl subsysnqn with the target ctrl subsysnqn. */ - memcpy(id->subnqn, ctrl->subsysnqn, sizeof(id->subnqn)); + memcpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn)); /* use fabric id-ctrl values */ id->ioccsz = cpu_to_le32((sizeof(struct nvme_command) + From 511b3b644e28d9b66e32515a74c57ff599e89035 Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Tue, 9 Sep 2025 13:21:22 +0200 Subject: [PATCH 522/684] nvmet: pci-epf: move DMA initialization to EPC init callback For DMA initialization to work across all EPC drivers, the DMA initialization has to be done in the .init() callback. This is because not all EPC drivers will have a refclock (which is often needed to access registers of a DMA controller embedded in a PCIe controller) at the time the .bind() callback is called. However, all EPC drivers are guaranteed to have a refclock by the time the .init() callback is called. Thus, move the DMA initialization to the .init() callback. This change was already done for other EPF drivers in commit 60bd3e039aa2 ("PCI: endpoint: pci-epf-{mhi/test}: Move DMA initialization to EPC init callback"). Cc: stable@vger.kernel.org Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") Signed-off-by: Shin'ichiro Kawasaki Signed-off-by: Niklas Cassel Reviewed-by: Damien Le Moal Signed-off-by: Keith Busch --- drivers/nvme/target/pci-epf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c index 2e78397a7373a7..9c5b0f78ce8dfc 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c @@ -2325,6 +2325,8 @@ static int nvmet_pci_epf_epc_init(struct pci_epf *epf) return ret; } + nvmet_pci_epf_init_dma(nvme_epf); + /* Set device ID, class, etc. */ epf->header->vendorid = ctrl->tctrl->subsys->vendor_id; epf->header->subsys_vendor_id = ctrl->tctrl->subsys->subsys_vendor_id; @@ -2422,8 +2424,6 @@ static int nvmet_pci_epf_bind(struct pci_epf *epf) if (ret) return ret; - nvmet_pci_epf_init_dma(nvme_epf); - return 0; } From 3c1fb0ce60ef41eda52e8f847613b003e1ca35c9 Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Sat, 13 Sep 2025 15:53:50 +0900 Subject: [PATCH 523/684] nvmet: pci-epf: fix DMA channel debug print Currently, nvmet_pci_epf_init_dma() has two dev_dbg() calls intended to print debug information about the DMA channels for RX and TX. However, both calls mistakenly are made for the TX channel. Fix it by referreing to 'nvme_epf->rx_chan' and 'nvme_epf->tx_chan' and instead of the local variable 'chan'. Signed-off-by: Shin'ichiro Kawasaki Reviewed-by: Damien Le Moal Signed-off-by: Keith Busch --- drivers/nvme/target/pci-epf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c index 9c5b0f78ce8dfc..f858a6c9d7cb90 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c @@ -320,12 +320,14 @@ static void nvmet_pci_epf_init_dma(struct nvmet_pci_epf *nvme_epf) nvme_epf->dma_enabled = true; dev_dbg(dev, "Using DMA RX channel %s, maximum segment size %u B\n", - dma_chan_name(chan), - dma_get_max_seg_size(dmaengine_get_dma_device(chan))); + dma_chan_name(nvme_epf->dma_rx_chan), + dma_get_max_seg_size(dmaengine_get_dma_device(nvme_epf-> + dma_rx_chan))); dev_dbg(dev, "Using DMA TX channel %s, maximum segment size %u B\n", - dma_chan_name(chan), - dma_get_max_seg_size(dmaengine_get_dma_device(chan))); + dma_chan_name(nvme_epf->dma_tx_chan), + dma_get_max_seg_size(dmaengine_get_dma_device(nvme_epf-> + dma_tx_chan))); return; From c9adfb5b68cb623a37eea76432c09f478c593d0e Mon Sep 17 00:00:00 2001 From: Gerd Bayer Date: Fri, 24 Oct 2025 13:05:31 +0200 Subject: [PATCH 524/684] nvme-pci: print error message on failure in nvme_probe Add a new error message that makes failures to probe visible in the kernel log, like: nvme 0008:00:00.0: error -ENODEV: probe failed This highlights issues with a particular device right away instead of leaving users to search for missing drives. Reviewed-by: Christoph Hellwig Reviewed-by: Wilfred Mallawa Signed-off-by: Gerd Bayer Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 9085bed107fde4..9a7616aa6889be 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3602,6 +3602,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) nvme_uninit_ctrl(&dev->ctrl); out_put_ctrl: nvme_put_ctrl(&dev->ctrl); + dev_err_probe(&pdev->dev, result, "probe failed\n"); return result; } From 78723fe309f189ee4010d5b7a55f6a14644a40c2 Mon Sep 17 00:00:00 2001 From: Gerd Bayer Date: Fri, 24 Oct 2025 13:05:32 +0200 Subject: [PATCH 525/684] nvme-pci: add debug message on fail to read CSTS Add a debug log spelling out that reading the CSTS register failed - to distinguish this from other reasons for ENODEV. Reviewed-by: Wilfred Mallawa Reviewed-by: Chaitanya Kulkarni Reviewed-by: Christoph Hellwig Signed-off-by: Gerd Bayer Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 9a7616aa6889be..a9fc8ecdea4854 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2977,6 +2977,7 @@ static int nvme_pci_enable(struct nvme_dev *dev) pci_set_master(pdev); if (readl(dev->bar + NVME_REG_CSTS) == -1) { + dev_dbg(dev->ctrl.device, "reading CSTS register failed\n"); result = -ENODEV; goto disable; } From b71cbcf7d170e51148d5467820ae8a72febcb651 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Thu, 30 Oct 2025 11:05:45 +0100 Subject: [PATCH 526/684] nvme-fc: don't hold rport lock when putting ctrl nvme_fc_ctrl_put can acquire the rport lock when freeing the ctrl object: nvme_fc_ctrl_put nvme_fc_ctrl_free spin_lock_irqsave(rport->lock) Thus we can't hold the rport lock when calling nvme_fc_ctrl_put. Justin suggested use the safe list iterator variant because nvme_fc_ctrl_put will also modify the rport->list. Cc: Justin Tee Reviewed-by: Christoph Hellwig Signed-off-by: Daniel Wagner Signed-off-by: Keith Busch --- drivers/nvme/host/fc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 70c066c2e2d42d..31fca144086572 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -1468,14 +1468,14 @@ nvme_fc_match_disconn_ls(struct nvme_fc_rport *rport, { struct fcnvme_ls_disconnect_assoc_rqst *rqst = &lsop->rqstbuf->rq_dis_assoc; - struct nvme_fc_ctrl *ctrl, *ret = NULL; + struct nvme_fc_ctrl *ctrl, *tmp, *ret = NULL; struct nvmefc_ls_rcv_op *oldls = NULL; u64 association_id = be64_to_cpu(rqst->associd.association_id); unsigned long flags; spin_lock_irqsave(&rport->lock, flags); - list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list) { + list_for_each_entry_safe(ctrl, tmp, &rport->ctrl_list, ctrl_list) { if (!nvme_fc_ctrl_get(ctrl)) continue; spin_lock(&ctrl->lock); @@ -1488,7 +1488,9 @@ nvme_fc_match_disconn_ls(struct nvme_fc_rport *rport, if (ret) /* leave the ctrl get reference */ break; + spin_unlock_irqrestore(&rport->lock, flags); nvme_fc_ctrl_put(ctrl); + spin_lock_irqsave(&rport->lock, flags); } spin_unlock_irqrestore(&rport->lock, flags); From 716311dad200edf01a3776b62466571dfd217106 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 1 Dec 2025 14:16:50 +0530 Subject: [PATCH 527/684] MAINTAINERS: phy: Add Neil Armstrong as reviewers for phy subsystem Acked-by: Neil Armstrong Link: https://patch.msgid.link/20251201084652.422057-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 400523d03e14f0..233b6d56e45b1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10439,6 +10439,7 @@ F: include/uapi/asm-generic/ GENERIC PHY FRAMEWORK M: Vinod Koul +R: Neil Armstrong L: linux-phy@lists.infradead.org S: Supported Q: https://patchwork.kernel.org/project/linux-phy/list/ From 4b011b538f2b90d07580ff778e28954a4a6520eb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 2 Dec 2025 16:38:02 +0100 Subject: [PATCH 528/684] i3c: fix I3C_SDR bit number 0x31 is decimal 49 and doesn't fit in a 32 bit integer, switch to the intended decimal 31. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202512020956.Dnz8A2H0-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202512021613.97jVprvJ-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202512021644.lp8ZMSx5-lkp@intel.com/ Link: https://patch.msgid.link/20251202153804.2640623-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index ae0662d9d77eb3..9fcb6410a584f2 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -51,7 +51,7 @@ enum i3c_xfer_mode { I3C_HDR_TSP = 1, I3C_HDR_TSL = 2, /* Use for default SDR transfer mode */ - I3C_SDR = 0x31, + I3C_SDR = 31, }; /** From e01a8baf60af43f6f87a5850dee29cf31377ec25 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 2 Dec 2025 16:38:03 +0100 Subject: [PATCH 529/684] i3c: document i3c_xfers i3c_xfers was left undocumented, document it. Reported-by: Stephen Rothwell Link: https://patch.msgid.link/20251202153804.2640623-2-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index d0d5b3a9049f0b..2fd850f4678b22 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -418,7 +418,11 @@ struct i3c_bus { * @send_ccc_cmd: send a CCC command * This method is mandatory. * @priv_xfers: do one or several private I3C SDR transfers - * This method is mandatory. + * This method is mandatory when i3c_xfers is not implemented. It + * is deprecated. + * @i3c_xfers: do one or several I3C SDR or HDR transfers + * This method is mandatory when priv_xfers is not implemented but + * should be implemented instead of priv_xfers. * @attach_i2c_dev: called every time an I2C device is attached to the bus. * This is a good place to attach master controller specific * data to I2C devices. From 1f08a91cec5f405ee121c920933fbcf90487c9de Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 28 Oct 2025 10:57:52 -0400 Subject: [PATCH 530/684] hwmon: (lm75): switch to use i3c_xfer from i3c_priv_xfer Switch to use i3c_xfer instead of i3c_priv_xfer because framework will update to support HDR mode. i3c_priv_xfer is now an alias of i3c_xfer. Replace i3c_device_do_priv_xfers() with i3c_device_do_xfers(..., I3C_SDR) to align with the new API. Prepare for removal of i3c_priv_xfer and i3c_device_do_priv_xfers(). Signed-off-by: Frank Li Acked-by: Guenter Roeck Link: https://patch.msgid.link/20251028-lm75-v1-1-9bf88989c49c@nxp.com Signed-off-by: Alexandre Belloni --- drivers/hwmon/lm75.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 3c23b6e8e1bf5c..eda93a8c23c936 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -621,7 +621,7 @@ static int lm75_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) { struct i3c_device *i3cdev = context; struct lm75_data *data = i3cdev_get_drvdata(i3cdev); - struct i3c_priv_xfer xfers[] = { + struct i3c_xfer xfers[] = { { .rnw = false, .len = 1, @@ -640,7 +640,7 @@ static int lm75_i3c_reg_read(void *context, unsigned int reg, unsigned int *val) if (reg == LM75_REG_CONF && !data->params->config_reg_16bits) xfers[1].len--; - ret = i3c_device_do_priv_xfers(i3cdev, xfers, 2); + ret = i3c_device_do_xfers(i3cdev, xfers, 2, I3C_SDR); if (ret < 0) return ret; @@ -658,7 +658,7 @@ static int lm75_i3c_reg_write(void *context, unsigned int reg, unsigned int val) { struct i3c_device *i3cdev = context; struct lm75_data *data = i3cdev_get_drvdata(i3cdev); - struct i3c_priv_xfer xfers[] = { + struct i3c_xfer xfers[] = { { .rnw = false, .len = 3, @@ -680,7 +680,7 @@ static int lm75_i3c_reg_write(void *context, unsigned int reg, unsigned int val) data->val_buf[2] = val & 0xff; } - return i3c_device_do_priv_xfers(i3cdev, xfers, 1); + return i3c_device_do_xfers(i3cdev, xfers, 1, I3C_SDR); } static const struct regmap_bus lm75_i3c_regmap_bus = { From 57c4011d36374568b24d9e8cba892e81697ed9f4 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 28 Oct 2025 10:57:53 -0400 Subject: [PATCH 531/684] net: mctp i3c: switch to use i3c_xfer from i3c_priv_xfer Switch to use i3c_xfer instead of i3c_priv_xfer because framework will update to support HDR mode. i3c_priv_xfer is now an alias of i3c_xfer. Replace i3c_device_do_priv_xfers() with i3c_device_do_xfers(..., I3C_SDR) to align with the new API. Prepare for removal of i3c_priv_xfer and i3c_device_do_priv_xfers(). Signed-off-by: Frank Li Acked-by: Matt Johnston Link: https://patch.msgid.link/20251028-lm75-v1-2-9bf88989c49c@nxp.com Signed-off-by: Alexandre Belloni --- drivers/net/mctp/mctp-i3c.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c index c678f79aa35611..36c2405677c2c2 100644 --- a/drivers/net/mctp/mctp-i3c.c +++ b/drivers/net/mctp/mctp-i3c.c @@ -99,7 +99,7 @@ struct mctp_i3c_internal_hdr { static int mctp_i3c_read(struct mctp_i3c_device *mi) { - struct i3c_priv_xfer xfer = { .rnw = 1, .len = mi->mrl }; + struct i3c_xfer xfer = { .rnw = 1, .len = mi->mrl }; struct net_device_stats *stats = &mi->mbus->ndev->stats; struct mctp_i3c_internal_hdr *ihdr = NULL; struct sk_buff *skb = NULL; @@ -127,7 +127,7 @@ static int mctp_i3c_read(struct mctp_i3c_device *mi) /* Make sure netif_rx() is read in the same order as i3c. */ mutex_lock(&mi->lock); - rc = i3c_device_do_priv_xfers(mi->i3c, &xfer, 1); + rc = i3c_device_do_xfers(mi->i3c, &xfer, 1, I3C_SDR); if (rc < 0) goto err; @@ -360,7 +360,7 @@ mctp_i3c_lookup(struct mctp_i3c_bus *mbus, u64 pid) static void mctp_i3c_xmit(struct mctp_i3c_bus *mbus, struct sk_buff *skb) { struct net_device_stats *stats = &mbus->ndev->stats; - struct i3c_priv_xfer xfer = { .rnw = false }; + struct i3c_xfer xfer = { .rnw = false }; struct mctp_i3c_internal_hdr *ihdr = NULL; struct mctp_i3c_device *mi = NULL; unsigned int data_len; @@ -409,7 +409,7 @@ static void mctp_i3c_xmit(struct mctp_i3c_bus *mbus, struct sk_buff *skb) data[data_len] = pec; xfer.data.out = data; - rc = i3c_device_do_priv_xfers(mi->i3c, &xfer, 1); + rc = i3c_device_do_xfers(mi->i3c, &xfer, 1, I3C_SDR); if (rc == 0) { stats->tx_bytes += data_len; stats->tx_packets++; From 79c3ae7ada0548d5097bdb65dde5d24a7d660fae Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 28 Oct 2025 10:57:54 -0400 Subject: [PATCH 532/684] regmap: i3c: switch to use i3c_xfer from i3c_priv_xfer Switch to use i3c_xfer instead of i3c_priv_xfer because framework will update to support HDR mode. i3c_priv_xfer is now an alias of i3c_xfer. Replace i3c_device_do_priv_xfers() with i3c_device_do_xfers(..., I3C_SDR) to align with the new API. Prepare for removal of i3c_priv_xfer and i3c_device_do_priv_xfers(). Signed-off-by: Frank Li Acked-by: Mark Brown Link: https://patch.msgid.link/20251028-lm75-v1-3-9bf88989c49c@nxp.com Signed-off-by: Alexandre Belloni --- drivers/base/regmap/regmap-i3c.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/base/regmap/regmap-i3c.c b/drivers/base/regmap/regmap-i3c.c index b5300b7c477e45..4482e64f26eba9 100644 --- a/drivers/base/regmap/regmap-i3c.c +++ b/drivers/base/regmap/regmap-i3c.c @@ -10,7 +10,7 @@ static int regmap_i3c_write(void *context, const void *data, size_t count) { struct device *dev = context; struct i3c_device *i3c = dev_to_i3cdev(dev); - struct i3c_priv_xfer xfers[] = { + struct i3c_xfer xfers[] = { { .rnw = false, .len = count, @@ -18,7 +18,7 @@ static int regmap_i3c_write(void *context, const void *data, size_t count) }, }; - return i3c_device_do_priv_xfers(i3c, xfers, 1); + return i3c_device_do_xfers(i3c, xfers, 1, I3C_SDR); } static int regmap_i3c_read(void *context, @@ -27,7 +27,7 @@ static int regmap_i3c_read(void *context, { struct device *dev = context; struct i3c_device *i3c = dev_to_i3cdev(dev); - struct i3c_priv_xfer xfers[2]; + struct i3c_xfer xfers[2]; xfers[0].rnw = false; xfers[0].len = reg_size; @@ -37,7 +37,7 @@ static int regmap_i3c_read(void *context, xfers[1].len = val_size; xfers[1].data.in = val; - return i3c_device_do_priv_xfers(i3c, xfers, 2); + return i3c_device_do_xfers(i3c, xfers, 2, I3C_SDR); } static const struct regmap_bus regmap_i3c = { From ac52b4a98509de3760919fa33e03384a5e770d7a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 30 Nov 2025 17:14:45 +0100 Subject: [PATCH 533/684] MAINTAINERS: Change Linus Walleij mail address I will be using my kernel.org mail address going forward. There is no point in splitting this MAINTAINERS patch up per subsystem, I will just include it with the rest of my patches to pin control in the next merge window. Signed-off-by: Linus Walleij --- MAINTAINERS | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 181a58ec4a8d5c..13f61acdc8f7b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -195,7 +195,7 @@ F: drivers/pinctrl/pinctrl-upboard.c F: include/linux/mfd/upboard-fpga.h AB8500 BATTERY AND CHARGER DRIVERS -M: Linus Walleij +M: Linus Walleij F: Documentation/devicetree/bindings/power/supply/*ab8500* F: drivers/power/supply/*ab8500* @@ -2045,7 +2045,7 @@ F: Documentation/devicetree/bindings/display/arm,hdlcd.yaml F: drivers/gpu/drm/arm/hdlcd_* ARM INTEGRATOR, VERSATILE AND REALVIEW SUPPORT -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/arm,integrator.yaml @@ -2203,7 +2203,7 @@ F: Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml F: drivers/memory/pl353-smc.c ARM PRIMECELL SSP PL022 SPI DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/spi/spi-pl022.yaml @@ -2216,7 +2216,7 @@ F: drivers/tty/serial/amba-pl01*.c F: include/linux/amba/serial.h ARM PRIMECELL VIC PL190/PL192 DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/interrupt-controller/arm,vic.yaml @@ -2633,7 +2633,7 @@ F: tools/perf/util/cs-etm.* ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE M: Hans Ulli Kroll -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git https://github.com/ulli-kroll/linux.git @@ -3035,7 +3035,7 @@ F: include/dt-bindings/clock/mstar-* F: include/dt-bindings/gpio/msc313-gpio.h ARM/NOMADIK/Ux500 ARCHITECTURES -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git @@ -3732,7 +3732,7 @@ F: Documentation/devicetree/bindings/media/i2c/asahi-kasei,ak7375.yaml F: drivers/media/i2c/ak7375.c ASAHI KASEI AK8974 DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-iio@vger.kernel.org S: Supported W: http://www.akm.com/ @@ -6758,7 +6758,7 @@ S: Maintained F: drivers/pinctrl/pinctrl-cy8c95x0.c CYPRESS CY8CTMA140 TOUCHSCREEN DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-input@vger.kernel.org S: Maintained F: drivers/input/touchscreen/cy8ctma140.c @@ -6778,13 +6778,13 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ F: drivers/media/common/cypress_firmware* CYTTSP TOUCHSCREEN DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-input@vger.kernel.org S: Maintained F: drivers/input/touchscreen/cyttsp* D-LINK DIR-685 TOUCHKEYS DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-input@vger.kernel.org S: Supported F: drivers/input/keyboard/dlink-dir685-touchkeys.c @@ -7653,13 +7653,13 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: drivers/gpu/drm/tiny/appletbdrm.c DRM DRIVER FOR ARM PL111 CLCD -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: drivers/gpu/drm/pl111/ DRM DRIVER FOR ARM VERSATILE TFT PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml @@ -7709,7 +7709,7 @@ F: Documentation/devicetree/bindings/display/panel/ebbg,ft8719.yaml F: drivers/gpu/drm/panel/panel-ebbg-ft8719.c DRM DRIVER FOR FARADAY TVE200 TV ENCODER -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: drivers/gpu/drm/tve200/ @@ -7903,14 +7903,14 @@ F: include/dt-bindings/clock/qcom,dsi-phy-28nm.h F: include/uapi/drm/msm_drm.h DRM DRIVER FOR NOVATEK NT35510 PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml F: drivers/gpu/drm/panel/panel-novatek-nt35510.c DRM DRIVER FOR NOVATEK NT35560 PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml @@ -8028,7 +8028,7 @@ F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml F: drivers/gpu/drm/panel/panel-raydium-rm67191.c DRM DRIVER FOR SAMSUNG DB7430 PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml @@ -8112,7 +8112,7 @@ F: Documentation/devicetree/bindings/display/solomon,ssd13*.yaml F: drivers/gpu/drm/solomon/ssd130x* DRM DRIVER FOR ST-ERICSSON MCDE -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/ste,mcde.yaml @@ -8144,7 +8144,7 @@ F: Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml F: drivers/gpu/drm/bridge/ti-sn65dsi86.c DRM DRIVER FOR TPO TPG110 PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml @@ -8188,7 +8188,7 @@ F: drivers/gpu/drm/vmwgfx/ F: include/uapi/drm/vmwgfx_drm.h DRM DRIVER FOR WIDECHIPS WS2401 PANELS -M: Linus Walleij +M: Linus Walleij S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml @@ -9482,7 +9482,7 @@ F: include/linux/fanotify.h F: include/uapi/linux/fanotify.h FARADAY FOTG210 USB2 DUAL-ROLE CONTROLLER -M: Linus Walleij +M: Linus Walleij L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/fotg210/ @@ -10669,7 +10669,7 @@ F: drivers/gpio/gpio-sloppy-logic-analyzer.c F: tools/gpio/gpio-sloppy-logic-analyzer.sh GPIO SUBSYSTEM -M: Linus Walleij +M: Linus Walleij M: Bartosz Golaszewski L: linux-gpio@vger.kernel.org S: Maintained @@ -13033,7 +13033,7 @@ F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml F: drivers/iio/imu/inv_icm42600/ INVENSENSE MPU-3050 GYROSCOPE DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-iio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml @@ -13948,7 +13948,7 @@ F: drivers/auxdisplay/ks0108.c F: include/linux/ks0108.h KTD253 BACKLIGHT DRIVER -M: Linus Walleij +M: Linus Walleij S: Maintained F: Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml F: drivers/video/backlight/ktd253-backlight.c @@ -14159,7 +14159,7 @@ F: drivers/ata/pata_arasan_cf.c F: include/linux/pata_arasan_cf_data.h LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS -M: Linus Walleij +M: Linus Walleij L: linux-ide@vger.kernel.org S: Maintained F: drivers/ata/pata_ftide010.c @@ -19663,7 +19663,7 @@ F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml F: drivers/pci/controller/dwc/*imx6* PCI DRIVER FOR INTEL IXP4XX -M: Linus Walleij +M: Linus Walleij S: Maintained F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml F: drivers/pci/controller/pci-ixp4xx.c @@ -19774,7 +19774,7 @@ F: drivers/pci/controller/cadence/pci-j721e.c F: drivers/pci/controller/dwc/pci-dra7xx.c PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC -M: Linus Walleij +M: Linus Walleij L: linux-pci@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml @@ -20219,7 +20219,7 @@ K: (?i)clone3 K: \b(clone_args|kernel_clone_args)\b PIN CONTROL SUBSYSTEM -M: Linus Walleij +M: Linus Walleij L: linux-gpio@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git @@ -21631,7 +21631,7 @@ F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml F: drivers/watchdog/realtek_otto_wdt.c REALTEK RTL83xx SMI DSA ROUTER CHIPS -M: Linus Walleij +M: Linus Walleij M: Alvin Šipraga S: Maintained F: Documentation/devicetree/bindings/net/dsa/realtek.yaml @@ -23384,7 +23384,7 @@ S: Supported F: net/smc/ SHARP GP2AP002A00F/GP2AP002S00F SENSOR DRIVER -M: Linus Walleij +M: Linus Walleij L: linux-iio@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git From 441863ae3de61dd813049a120e5656df2e210a4b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:01:31 -0800 Subject: [PATCH 534/684] perf tools: Remove a trailing newline in the event terms So that it can show the correct encoding info in the JSON output. $ perf list -j hw [ { "Unit": "cpu", "Topic": "legacy hardware", "EventName": "branch-instructions", "EventType": "Kernel PMU event", "BriefDescription": "Retired branch instructions [This event is an alias of branches]", "Encoding": "cpu/event=0xc4/" }, ... Reviewed-by: Ian Rogers Suggested-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/pmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 1b7c712d8f9902..956ea273c2c780 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -645,6 +645,8 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, pr_err("Failed to read alias %s\n", name); return ret; } + if (line_len >= 1 && alias->terms[line_len - 1] == '\n') + alias->terms[line_len - 1] = '\0'; } alias->name = strdup(name); alias->desc = desc ? strdup(desc) : NULL; From 44f6b44027910eb9e6e6a67840f818038946e24f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 1 Dec 2025 15:11:36 -0800 Subject: [PATCH 535/684] perf test: Fix hybrid testing of event fallback test The mem-loads-aux event exists on hybrid systems but the "cpu" PMU does not. This causes an event parsing error which erroneously makes the test look like it is failing. Avoid naming the PMU to avoid this. Rather than cleaning up perf.data in the directory the test is run, explicitly send the 'perf record' output to /dev/null and avoid any cleanup scripts. Fixes: fc9c17b22352 ("perf test: Add a perf event fallback test") Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- .../tests/shell/test_event_open_fallback.sh | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/tools/perf/tests/shell/test_event_open_fallback.sh b/tools/perf/tests/shell/test_event_open_fallback.sh index 9c411153c01b68..9420a7557c1382 100755 --- a/tools/perf/tests/shell/test_event_open_fallback.sh +++ b/tools/perf/tests/shell/test_event_open_fallback.sh @@ -6,24 +6,9 @@ skip_cnt=0 ok_cnt=0 err_cnt=0 -cleanup() -{ - rm -f perf.data - rm -f perf.data.old - trap - EXIT TERM INT -} - -trap_cleanup() -{ - cleanup - exit 1 -} - -trap trap_cleanup EXIT TERM INT - perf_record() { - perf record "$@" -- true 1>/dev/null 2>&1 + perf record -o /dev/null "$@" -- true 1>/dev/null 2>&1 } test_decrease_precise_ip() @@ -49,7 +34,7 @@ test_decrease_precise_ip_complicated() perf list pmu | grep -q 'mem-loads-aux' || return 2 - if ! perf_record -e '{cpu/mem-loads-aux/S,cpu/mem-loads/PS}'; then + if ! perf_record -e '{mem-loads-aux:S,mem-loads:PS}'; then return 1 fi return 0 From 25d498e636d1f8d138d65246cfb5b1fc3069ca56 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 25 Nov 2025 00:07:46 -0800 Subject: [PATCH 536/684] perf jitdump: Add sym/str-tables to build-ID generation It was reported that python backtrace with JIT dump was broken after the change to built-in SHA-1 implementation. It seems python generates the same JIT code for each function. They will become separate DSOs but the contents are the same. Only difference is in the symbol name. But this caused a problem that every JIT'ed DSOs will have the same build-ID which makes perf confused. And it resulted in no python symbols (from JIT) in the output. Looking back at the original code before the conversion, it used the load_addr as well as the code section to distinguish each DSO. But it'd be better to use contents of symtab and strtab instead as it aligns with some linker behaviors. This patch adds a buffer to save all the contents in a single place for SHA-1 calculation. Probably we need to add sha1_update() or similar to update the existing hash value with different contents and use it here. But it's out of scope for this change and I'd like something that can be backported to the stable trees easily. Reviewed-by: Ian Rogers Cc: Eric Biggers Cc: Pablo Galindo Cc: Fangrui Song Link: https://github.com/python/cpython/issues/139544 Fixes: e3f612c1d8f3945b ("perf genelf: Remove libcrypto dependency and use built-in sha1()") Signed-off-by: Namhyung Kim --- tools/perf/util/genelf.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c index 591548b10e34ef..a1cd5196f4ec8f 100644 --- a/tools/perf/util/genelf.c +++ b/tools/perf/util/genelf.c @@ -173,6 +173,8 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, Elf_Shdr *shdr; uint64_t eh_frame_base_offset; char *strsym = NULL; + void *build_id_data = NULL, *tmp; + int build_id_data_len; int symlen; int retval = -1; @@ -251,6 +253,14 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; shdr->sh_entsize = 0; + build_id_data = malloc(csize); + if (build_id_data == NULL) { + warnx("cannot allocate build-id data"); + goto error; + } + memcpy(build_id_data, code, csize); + build_id_data_len = csize; + /* * Setup .eh_frame_hdr and .eh_frame */ @@ -334,6 +344,15 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, shdr->sh_entsize = sizeof(Elf_Sym); shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ + tmp = realloc(build_id_data, build_id_data_len + sizeof(symtab)); + if (tmp == NULL) { + warnx("cannot allocate build-id data"); + goto error; + } + memcpy(tmp + build_id_data_len, symtab, sizeof(symtab)); + build_id_data = tmp; + build_id_data_len += sizeof(symtab); + /* * setup symbols string table * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry @@ -376,6 +395,15 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, shdr->sh_flags = 0; shdr->sh_entsize = 0; + tmp = realloc(build_id_data, build_id_data_len + symlen); + if (tmp == NULL) { + warnx("cannot allocate build-id data"); + goto error; + } + memcpy(tmp + build_id_data_len, strsym, symlen); + build_id_data = tmp; + build_id_data_len += symlen; + /* * setup build-id section */ @@ -394,7 +422,7 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, /* * build-id generation */ - sha1(code, csize, bnote.build_id); + sha1(build_id_data, build_id_data_len, bnote.build_id); bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ bnote.desc.descsz = sizeof(bnote.build_id); bnote.desc.type = NT_GNU_BUILD_ID; @@ -439,7 +467,7 @@ jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, (void)elf_end(e); free(strsym); - + free(build_id_data); return retval; } From c9cd0c7e529e80e9be79867d2ebb874f67dbc35e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 25 Nov 2025 00:07:47 -0800 Subject: [PATCH 537/684] perf test: Add python JIT dump test Add a test case for the python interpreter like below so that we can make sure it won't break again. To validate the effect of build-ID generation, it adds and removes the JIT'ed DSOs to/from the build-ID cache for the test. $ perf test -vv jitdump 84: python profiling with jitdump: --- start --- test child forked, pid 214316 Run python with -Xperf_jit [ perf record: Woken up 5 times to write data ] [ perf record: Captured and wrote 1.180 MB /tmp/__perf_test.perf.data.XbqZNm (140 samples) ] Generate JIT-ed DSOs using perf inject Add JIT-ed DSOs to the build-ID cache Check the symbol containing the script name Found 108 matching lines Remove JIT-ed DSOs from the build-ID cache ---- end(0) ---- 84: python profiling with jitdump : Ok Cc: Pablo Galindo Link: https://docs.python.org/3/howto/perf_profiling.html#how-to-work-without-frame-pointers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/jitdump-python.sh | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 tools/perf/tests/shell/jitdump-python.sh diff --git a/tools/perf/tests/shell/jitdump-python.sh b/tools/perf/tests/shell/jitdump-python.sh new file mode 100755 index 00000000000000..ae86203b14a22b --- /dev/null +++ b/tools/perf/tests/shell/jitdump-python.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# python profiling with jitdump +# SPDX-License-Identifier: GPL-2.0 + +SHELLDIR=$(dirname $0) +# shellcheck source=lib/setup_python.sh +. "${SHELLDIR}"/lib/setup_python.sh + +OUTPUT=$(${PYTHON} -Xperf_jit -c 'import os, sys; print(os.getpid(), sys.is_stack_trampoline_active())' 2> /dev/null) +PID=${OUTPUT% *} +HAS_PERF_JIT=${OUTPUT#* } + +rm -f /tmp/jit-${PID}.dump 2> /dev/null +if [ "${HAS_PERF_JIT}" != "True" ]; then + echo "SKIP: python JIT dump is not available" + exit 2 +fi + +PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXXX) + +cleanup() { + echo "Cleaning up files..." + rm -f ${PERF_DATA} ${PERF_DATA}.jit /tmp/jit-${PID}.dump /tmp/jitted-${PID}-*.so 2> /dev/null + + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected termination" + cleanup + exit 1 +} + +trap trap_cleanup EXIT TERM INT + +echo "Run python with -Xperf_jit" +cat <') + +echo "Found ${NUM} matching lines" + +echo "Remove JIT-ed DSOs from the build-ID cache" +for F in /tmp/jitted-${PID}-*.so; do + perf buildid-cache -r "${F}" +done + +cleanup + +if [ "${NUM}" -eq 0 ]; then + exit 1 +fi From 6603c3c1fe8257e522496da7fd7b75ac52c2323f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:49:56 -0800 Subject: [PATCH 538/684] perf python: Correct copying of metric_leader in an evsel Ensure the metric_leader is copied and set up correctly. In compute_metric determine the correct metric_leader event to match the requested CPU. Fixes the handling of metrics particularly on hybrid machines. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 1 + tools/perf/util/python.c | 82 +++++++++++++++++++++++++++++----------- 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index aee42666e882da..5aae7f791bc270 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -538,6 +538,7 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig) #endif evsel->handler = orig->handler; evsel->core.leader = orig->core.leader; + evsel->metric_leader = orig->metric_leader; evsel->max_events = orig->max_events; zfree(&evsel->unit); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index fa5e4270d18251..cc1019d29a5d01 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1340,27 +1340,48 @@ static int prepare_metric(const struct metric_expr *mexp, struct metric_ref *metric_refs = mexp->metric_refs; for (int i = 0; metric_events[i]; i++) { - char *n = strdup(evsel__metric_id(metric_events[i])); + struct evsel *cur = metric_events[i]; double val, ena, run; - int source_count = evsel__source_count(metric_events[i]); - int ret; + int ret, source_count = 0; struct perf_counts_values *old_count, *new_count; + char *n = strdup(evsel__metric_id(cur)); if (!n) return -ENOMEM; + /* + * If there are multiple uncore PMUs and we're not reading the + * leader's stats, determine the stats for the appropriate + * uncore PMU. + */ + if (evsel && evsel->metric_leader && + evsel->pmu != evsel->metric_leader->pmu && + cur->pmu == evsel->metric_leader->pmu) { + struct evsel *pos; + + evlist__for_each_entry(evsel->evlist, pos) { + if (pos->pmu != evsel->pmu) + continue; + if (pos->metric_leader != cur) + continue; + cur = pos; + source_count = 1; + break; + } + } + if (source_count == 0) - source_count = 1; + source_count = evsel__source_count(cur); - ret = evsel__ensure_counts(metric_events[i]); + ret = evsel__ensure_counts(cur); if (ret) return ret; /* Set up pointers to the old and newly read counter values. */ - old_count = perf_counts(metric_events[i]->prev_raw_counts, cpu_idx, thread_idx); - new_count = perf_counts(metric_events[i]->counts, cpu_idx, thread_idx); - /* Update the value in metric_events[i]->counts. */ - evsel__read_counter(metric_events[i], cpu_idx, thread_idx); + old_count = perf_counts(cur->prev_raw_counts, cpu_idx, thread_idx); + new_count = perf_counts(cur->counts, cpu_idx, thread_idx); + /* Update the value in cur->counts. */ + evsel__read_counter(cur, cpu_idx, thread_idx); val = new_count->val - old_count->val; ena = new_count->ena - old_count->ena; @@ -1392,6 +1413,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, struct metric_expr *mexp = NULL; struct expr_parse_ctx *pctx; double result = 0; + struct evsel *metric_evsel = NULL; if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread)) return NULL; @@ -1404,6 +1426,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, list_for_each(pos, &me->head) { struct metric_expr *e = container_of(pos, struct metric_expr, nd); + struct evsel *pos2; if (strcmp(e->metric_name, metric)) continue; @@ -1411,20 +1434,24 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, if (e->metric_events[0] == NULL) continue; - cpu_idx = perf_cpu_map__idx(e->metric_events[0]->core.cpus, - (struct perf_cpu){.cpu = cpu}); - if (cpu_idx < 0) - continue; - - thread_idx = perf_thread_map__idx(e->metric_events[0]->core.threads, - thread); - if (thread_idx < 0) - continue; - - mexp = e; - break; + evlist__for_each_entry(&pevlist->evlist, pos2) { + if (pos2->metric_leader != e->metric_events[0]) + continue; + cpu_idx = perf_cpu_map__idx(pos2->core.cpus, + (struct perf_cpu){.cpu = cpu}); + if (cpu_idx < 0) + continue; + + thread_idx = perf_thread_map__idx(pos2->core.threads, thread); + if (thread_idx < 0) + continue; + metric_evsel = pos2; + mexp = e; + goto done; + } } } +done: if (!mexp) { PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'", metric, cpu, thread); @@ -1435,7 +1462,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, if (!pctx) return PyErr_NoMemory(); - ret = prepare_metric(mexp, mexp->metric_events[0], pctx, cpu_idx, thread_idx); + ret = prepare_metric(mexp, metric_evsel, pctx, cpu_idx, thread_idx); if (ret) { expr__ctx_free(pctx); errno = -ret; @@ -1996,6 +2023,17 @@ static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist) else if (leader == NULL) evsel__set_leader(pos, pos); } + + leader = pos->metric_leader; + + if (pos != leader) { + int idx = evlist__pos(evlist, leader); + + if (idx >= 0) + pos->metric_leader = evlist__at(&pevlist->evlist, idx); + else if (leader == NULL) + pos->metric_leader = pos; + } } metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL, &pevlist->evlist.metric_events, From 4b11c983f453689ac9d51d6528891ab4beb7393e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:49:57 -0800 Subject: [PATCH 539/684] perf ilist: Be tolerant of reading a metric on the wrong CPU This happens on hybrid machine metrics. Be tolerant and don't cause the ilist application to crash with an exception. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/python/ilist.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py index eb687ce9d5a6af..0d757ddb479598 100755 --- a/tools/perf/python/ilist.py +++ b/tools/perf/python/ilist.py @@ -77,8 +77,12 @@ def parse(self) -> perf.evlist: return perf.parse_metrics(self.metric_name, self.metric_pmu) def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) -> float: - val = evlist.compute_metric(self.metric_name, cpu, thread) - return 0 if math.isnan(val) else val + try: + val = evlist.compute_metric(self.metric_name, cpu, thread) + return 0 if math.isnan(val) else val + except: + # Be tolerant of failures to compute metrics on particular CPUs/threads. + return 0 @dataclass From 33c44bbcd48917275de7a43af9b2f25e03d3a52d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:49:58 -0800 Subject: [PATCH 540/684] perf jevents: Allow multiple metricgroups.json files Allow multiple metricgroups.json files by handling any file ending with metricgroups.json as a metricgroups file. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/jevents.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 3413ee5d022741..03f5ad262eb5ad 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -640,7 +640,7 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None: if not item.is_file() or not item.name.endswith('.json'): return - if item.name == 'metricgroups.json': + if item.name.endswith('metricgroups.json'): metricgroup_descriptions = json.load(open(item.path)) for mgroup in metricgroup_descriptions: assert len(mgroup) > 1, parents @@ -693,7 +693,7 @@ def is_leaf_dir_ignoring_sys(path: str) -> bool: # Ignore other directories. If the file name does not have a .json # extension, ignore it. It could be a readme.txt for instance. - if not item.is_file() or not item.name.endswith('.json') or item.name == 'metricgroups.json': + if not item.is_file() or not item.name.endswith('.json') or item.name.endswith('metricgroups.json'): return add_events_table_entries(item, get_topic(item.name)) From e7b9e750b3ce1b4105ecf7200d709113552ecd54 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:49:59 -0800 Subject: [PATCH 541/684] perf jevents: Update metric constraint support Previous metric constraints were binary, either none or don't group when the NMI watchdog is present. Update to match the definitions in 'enum metric_event_groups' in pmu-events.h. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 92acd89ed97aa9..8a718dd4b1fe58 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -4,8 +4,14 @@ import decimal import json import re +from enum import Enum from typing import Dict, List, Optional, Set, Tuple, Union +class MetricConstraint(Enum): + GROUPED_EVENTS = 0 + NO_GROUP_EVENTS = 1 + NO_GROUP_EVENTS_NMI = 2 + NO_GROUP_EVENTS_SMT = 3 class Expression: """Abstract base class of elements in a metric expression.""" @@ -423,14 +429,14 @@ class Metric: groups: Set[str] expr: Expression scale_unit: str - constraint: bool + constraint: MetricConstraint def __init__(self, name: str, description: str, expr: Expression, scale_unit: str, - constraint: bool = False): + constraint: MetricConstraint = MetricConstraint.GROUPED_EVENTS): self.name = name self.description = description self.expr = expr.Simplify() @@ -464,8 +470,8 @@ def ToPerfJson(self) -> Dict[str, str]: 'MetricExpr': self.expr.ToPerfJson(), 'ScaleUnit': self.scale_unit } - if self.constraint: - result['MetricConstraint'] = 'NO_NMI_WATCHDOG' + if self.constraint != MetricConstraint.GROUPED_EVENTS: + result['MetricConstraint'] = self.constraint.name return result From 38d9d511ed923f8fe9fa901d64c3c31bc812032c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:00 -0800 Subject: [PATCH 542/684] perf jevents: Add descriptions to metricgroup abstraction Add a function to recursively generate metric group descriptions. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 8a718dd4b1fe58..1de4fb72c75ed5 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -475,6 +475,8 @@ def ToPerfJson(self) -> Dict[str, str]: return result + def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]: + return {} class _MetricJsonEncoder(json.JSONEncoder): """Special handling for Metric objects.""" @@ -493,10 +495,12 @@ class MetricGroup: which can facilitate arrangements similar to trees. """ - def __init__(self, name: str, metric_list: List[Union[Metric, - 'MetricGroup']]): + def __init__(self, name: str, + metric_list: List[Union[Metric, 'MetricGroup']], + description: Optional[str] = None): self.name = name self.metric_list = metric_list + self.description = description for metric in metric_list: metric.AddToMetricGroup(self) @@ -516,6 +520,12 @@ def Flatten(self) -> Set[Metric]: def ToPerfJson(self) -> str: return json.dumps(sorted(self.Flatten()), indent=2, cls=_MetricJsonEncoder) + def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]: + result = {self.name: self.description} if self.description else {} + for x in self.metric_list: + result.update(x.ToMetricGroupDescriptions(False)) + return result + def __str__(self) -> str: return self.ToPerfJson() From e90c66c37c646962d5a7e525f5e04c75ea31f167 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:01 -0800 Subject: [PATCH 543/684] perf jevents: Allow metric groups not to be named It can be convenient to have unnamed metric groups for the sake of organizing other metrics and metric groups. An unspecified name shouldn't contribute to the MetricGroup json value, so don't record it. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 1de4fb72c75ed5..847b614d40d5f3 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -455,7 +455,8 @@ def __lt__(self, other): def AddToMetricGroup(self, group): """Callback used when being added to a MetricGroup.""" - self.groups.add(group.name) + if group.name: + self.groups.add(group.name) def Flatten(self) -> Set['Metric']: """Return a leaf metric.""" From 826650f76e6a634ae6e92f5f7341087b12bda4d0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:02 -0800 Subject: [PATCH 544/684] perf jevents: Support parsing negative exponents Support negative exponents when parsing from a json metric string by making the numbers after the 'e' optional in the 'Event' insertion fix up. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 2 +- tools/perf/pmu-events/metric_test.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 847b614d40d5f3..31eea2f45152d1 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -573,7 +573,7 @@ def ParsePerfJson(orig: str) -> Expression: # a double by the Bison parser py = re.sub(r'0Event\(r"[xX]([0-9a-fA-F]*)"\)', r'Event("0x\1")', py) # Convert accidentally converted scientific notation constants back - py = re.sub(r'([0-9]+)Event\(r"(e[0-9]+)"\)', r'\1\2', py) + py = re.sub(r'([0-9]+)Event\(r"(e[0-9]*)"\)', r'\1\2', py) # Convert all the known keywords back from events to just the keyword keywords = ['if', 'else', 'min', 'max', 'd_ratio', 'source_count', 'has_event', 'strcmp_cpuid_str'] for kw in keywords: diff --git a/tools/perf/pmu-events/metric_test.py b/tools/perf/pmu-events/metric_test.py index ee22ff43ddd7e9..8acfe4652b5550 100755 --- a/tools/perf/pmu-events/metric_test.py +++ b/tools/perf/pmu-events/metric_test.py @@ -61,6 +61,10 @@ def test_ParsePerfJson(self): after = before self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + before = r'a + 3e-12 + b' + after = before + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + def test_IfElseTests(self): # if-else needs rewriting to Select and back. before = r'Event1 if #smt_on else Event2' From 7d5b4061a86ac1bafe9e34dcb8b79aaad42a99b7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:03 -0800 Subject: [PATCH 545/684] perf jevents: Term list fix in event parsing Fix events seemingly broken apart at a comma. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 31eea2f45152d1..0f4e67e5cfea2c 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -568,6 +568,12 @@ def ParsePerfJson(orig: str) -> Expression: r'Event(r"\1")', py) # If it started with a # it should have been a literal, rather than an event name py = re.sub(r'#Event\(r"([^"]*)"\)', r'Literal("#\1")', py) + # Fix events wrongly broken at a ',' + while True: + prev_py = py + py = re.sub(r'Event\(r"([^"]*)"\),Event\(r"([^"]*)"\)', r'Event(r"\1,\2")', py) + if py == prev_py: + break # Convert accidentally converted hex constants ("0Event(r"xDEADBEEF)"") back to a constant, # but keep it wrapped in Event(), otherwise Python drops the 0x prefix and it gets interpreted as # a double by the Bison parser @@ -586,7 +592,6 @@ def ParsePerfJson(orig: str) -> Expression: parsed = ast.fix_missing_locations(parsed) return _Constify(eval(compile(parsed, orig, 'eval'))) - def RewriteMetricsInTermsOfOthers(metrics: List[Tuple[str, str, Expression]] )-> Dict[Tuple[str, str], Expression]: """Shorten metrics by rewriting in terms of others. From b90e94aed9080a2cfb0142e99ca4eba3e341c45e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:04 -0800 Subject: [PATCH 546/684] perf jevents: Add threshold expressions to Metric Allow threshold expressions for metrics to be generated. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 0f4e67e5cfea2c..e81fed2e29b5f7 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -430,13 +430,15 @@ class Metric: expr: Expression scale_unit: str constraint: MetricConstraint + threshold: Optional[Expression] def __init__(self, name: str, description: str, expr: Expression, scale_unit: str, - constraint: MetricConstraint = MetricConstraint.GROUPED_EVENTS): + constraint: MetricConstraint = MetricConstraint.GROUPED_EVENTS, + threshold: Optional[Expression] = None): self.name = name self.description = description self.expr = expr.Simplify() @@ -447,6 +449,7 @@ def __init__(self, else: self.scale_unit = f'1{scale_unit}' self.constraint = constraint + self.threshold = threshold self.groups = set() def __lt__(self, other): @@ -473,6 +476,8 @@ def ToPerfJson(self) -> Dict[str, str]: } if self.constraint != MetricConstraint.GROUPED_EVENTS: result['MetricConstraint'] = self.constraint.name + if self.threshold: + result['MetricThreshold'] = self.threshold.ToPerfJson() return result From 3f31651a06f3e42cd96b04e9e822e662a9517583 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:05 -0800 Subject: [PATCH 547/684] perf jevents: Move json encoding to its own functions Have dedicated encode functions rather than having them embedded in MetricGroup. This is to provide some uniformity in the Metric ToXXX routines. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index e81fed2e29b5f7..b391891826085c 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -484,15 +484,6 @@ def ToPerfJson(self) -> Dict[str, str]: def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]: return {} -class _MetricJsonEncoder(json.JSONEncoder): - """Special handling for Metric objects.""" - - def default(self, o): - if isinstance(o, Metric): - return o.ToPerfJson() - return json.JSONEncoder.default(self, o) - - class MetricGroup: """A group of metrics. @@ -523,8 +514,11 @@ def Flatten(self) -> Set[Metric]: return result - def ToPerfJson(self) -> str: - return json.dumps(sorted(self.Flatten()), indent=2, cls=_MetricJsonEncoder) + def ToPerfJson(self) -> List[Dict[str, str]]: + result = [] + for x in sorted(self.Flatten()): + result.append(x.ToPerfJson()) + return result def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]: result = {self.name: self.description} if self.description else {} @@ -533,7 +527,23 @@ def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]: return result def __str__(self) -> str: - return self.ToPerfJson() + return str(self.ToPerfJson()) + + +def JsonEncodeMetric(x: MetricGroup): + class MetricJsonEncoder(json.JSONEncoder): + """Special handling for Metric objects.""" + + def default(self, o): + if isinstance(o, Metric) or isinstance(o, MetricGroup): + return o.ToPerfJson() + return json.JSONEncoder.default(self, o) + + return json.dumps(x, indent=2, cls=MetricJsonEncoder) + + +def JsonEncodeMetricGroupDescriptions(x: MetricGroup): + return json.dumps(x.ToMetricGroupDescriptions(), indent=2) class _RewriteIfExpToSelect(ast.NodeTransformer): From a1d9bb1a047286b36a06a5353a266e8baac4b93d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:06 -0800 Subject: [PATCH 548/684] perf jevents: Drop duplicate pending metrics Drop adding a pending metric if there is an existing one. Ensure the PMUs differ for hybrid systems. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/jevents.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 03f5ad262eb5ad..3a1bcdcdc685f1 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -501,7 +501,8 @@ def add_events_table_entries(item: os.DirEntry, topic: str) -> None: for e in read_json_events(item.path, topic): if e.name: _pending_events.append(e) - if e.metric_name: + if e.metric_name and not any(e.metric_name == x.metric_name and + e.pmu == x.pmu for x in _pending_metrics): _pending_metrics.append(e) From d9f2ce394c91c28728481564168a59aa5bac376f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 09:50:07 -0800 Subject: [PATCH 549/684] perf jevents: Skip optional metrics in metric group list For metric groups, skip metrics in the list that are None. This allows functions to better optionally return metrics. Signed-off-by: Ian Rogers Tested-by: Thomas Falcon Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/metric.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index b391891826085c..dd8fd06940e634 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -493,13 +493,15 @@ class MetricGroup: """ def __init__(self, name: str, - metric_list: List[Union[Metric, 'MetricGroup']], + metric_list: List[Union[Optional[Metric], Optional['MetricGroup']]], description: Optional[str] = None): self.name = name - self.metric_list = metric_list + self.metric_list = [] self.description = description for metric in metric_list: - metric.AddToMetricGroup(self) + if metric: + self.metric_list.append(metric) + metric.AddToMetricGroup(self) def AddToMetricGroup(self, group): """Callback used when a MetricGroup is added into another.""" From 22b0ceee1c48178ed3a69a17ea36150ab1f1eb9a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:47:59 -0800 Subject: [PATCH 550/684] tools headers UAPI: Sync linux/perf_event.h for deferred callchains It needs to sync with the kernel to support user space changes for the deferred callchains. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/include/uapi/linux/perf_event.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index 0d0ed85ad8cb34..c44a8fb3e4181c 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -464,7 +464,9 @@ struct perf_event_attr { inherit_thread : 1, /* children only inherit if cloned with CLONE_THREAD */ remove_on_exec : 1, /* event is removed from task on exec */ sigtrap : 1, /* send synchronous SIGTRAP on event */ - __reserved_1 : 26; + defer_callchain: 1, /* request PERF_RECORD_CALLCHAIN_DEFERRED records */ + defer_output : 1, /* output PERF_RECORD_CALLCHAIN_DEFERRED records */ + __reserved_1 : 24; union { __u32 wakeup_events; /* wake up every n events */ @@ -1241,6 +1243,22 @@ enum perf_event_type { */ PERF_RECORD_AUX_OUTPUT_HW_ID = 21, + /* + * This user callchain capture was deferred until shortly before + * returning to user space. Previous samples would have kernel + * callchains only and they need to be stitched with this to make full + * callchains. + * + * struct { + * struct perf_event_header header; + * u64 cookie; + * u64 nr; + * u64 ips[nr]; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_CALLCHAIN_DEFERRED = 22, + PERF_RECORD_MAX, /* non-ABI */ }; @@ -1271,6 +1289,7 @@ enum perf_callchain_context { PERF_CONTEXT_HV = (__u64)-32, PERF_CONTEXT_KERNEL = (__u64)-128, PERF_CONTEXT_USER = (__u64)-512, + PERF_CONTEXT_USER_DEFERRED = (__u64)-640, PERF_CONTEXT_GUEST = (__u64)-2048, PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176, From f4e3381648be205365cb475512ee536e108e060e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:48:00 -0800 Subject: [PATCH 551/684] perf tools: Minimal DEFERRED_CALLCHAIN support Add a new event type for deferred callchains and a new callback for the struct perf_tool. For now it doesn't actually handle the deferred callchains but it just marks the sample if it has the PERF_CONTEXT_ USER_DEFFERED in the callchain array. At least, perf report can dump the raw data with this change. Actually this requires the next commit to enable attr.defer_callchain, but if you already have a data file, it'll show the following result. $ perf report -D ... 0x2158@perf.data [0x40]: event: 22 . . ... raw event: size 64 bytes . 0000: 16 00 00 00 02 00 40 00 06 00 00 00 0b 00 00 00 ......@......... . 0010: 03 00 00 00 00 00 00 00 a7 7f 33 fe 18 7f 00 00 ..........3..... . 0020: 0f 0e 33 fe 18 7f 00 00 48 14 33 fe 18 7f 00 00 ..3.....H.3..... . 0030: 08 09 00 00 08 09 00 00 e6 7a e7 35 1c 00 00 00 .........z.5.... 121163447014 0x2158 [0x40]: PERF_RECORD_CALLCHAIN_DEFERRED(IP, 0x2): 2312/2312: 0xb00000006 ... FP chain: nr:3 ..... 0: 00007f18fe337fa7 ..... 1: 00007f18fe330e0f ..... 2: 00007f18fe331448 : unhandled! Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/lib/perf/include/perf/event.h | 13 ++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/evsel.c | 31 +++++++++++++++++++++-- tools/perf/util/machine.c | 1 + tools/perf/util/perf_event_attr_fprintf.c | 2 ++ tools/perf/util/sample.h | 2 ++ tools/perf/util/session.c | 20 +++++++++++++++ tools/perf/util/tool.c | 3 +++ tools/perf/util/tool.h | 3 ++- 9 files changed, 73 insertions(+), 3 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index aa1e91c97a226e..43a8cb04994fa0 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -151,6 +151,18 @@ struct perf_record_switch { __u32 next_prev_tid; }; +struct perf_record_callchain_deferred { + struct perf_event_header header; + /* + * This is to match kernel and (deferred) user stacks together. + * The kernel part will be in the sample callchain array after + * the PERF_CONTEXT_USER_DEFERRED entry. + */ + __u64 cookie; + __u64 nr; + __u64 ips[]; +}; + struct perf_record_header_attr { struct perf_event_header header; struct perf_event_attr attr; @@ -523,6 +535,7 @@ union perf_event { struct perf_record_read read; struct perf_record_throttle throttle; struct perf_record_sample sample; + struct perf_record_callchain_deferred callchain_deferred; struct perf_record_bpf_event bpf; struct perf_record_ksymbol ksymbol; struct perf_record_text_poke_event text_poke; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index fcf44149feb20c..4c92cc1a952c1d 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -61,6 +61,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_CGROUP] = "CGROUP", [PERF_RECORD_TEXT_POKE] = "TEXT_POKE", [PERF_RECORD_AUX_OUTPUT_HW_ID] = "AUX_OUTPUT_HW_ID", + [PERF_RECORD_CALLCHAIN_DEFERRED] = "CALLCHAIN_DEFERRED", [PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5aae7f791bc270..df5351fde33987 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3090,6 +3090,20 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, data->data_src = PERF_MEM_DATA_SRC_NONE; data->vcpu = -1; + if (event->header.type == PERF_RECORD_CALLCHAIN_DEFERRED) { + const u64 max_callchain_nr = UINT64_MAX / sizeof(u64); + + data->callchain = (struct ip_callchain *)&event->callchain_deferred.nr; + if (data->callchain->nr > max_callchain_nr) + return -EFAULT; + + data->deferred_cookie = event->callchain_deferred.cookie; + + if (evsel->core.attr.sample_id_all) + perf_evsel__parse_id_sample(evsel, event, data); + return 0; + } + if (event->header.type != PERF_RECORD_SAMPLE) { if (!evsel->core.attr.sample_id_all) return 0; @@ -3214,12 +3228,25 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, if (type & PERF_SAMPLE_CALLCHAIN) { const u64 max_callchain_nr = UINT64_MAX / sizeof(u64); + u64 callchain_nr; OVERFLOW_CHECK_u64(array); data->callchain = (struct ip_callchain *)array++; - if (data->callchain->nr > max_callchain_nr) + callchain_nr = data->callchain->nr; + if (callchain_nr > max_callchain_nr) return -EFAULT; - sz = data->callchain->nr * sizeof(u64); + sz = callchain_nr * sizeof(u64); + /* + * Save the cookie for the deferred user callchain. The last 2 + * entries in the callchain should be the context marker and the + * cookie. The cookie will be used to match PERF_RECORD_ + * CALLCHAIN_DEFERRED later. + */ + if (evsel->core.attr.defer_callchain && callchain_nr >= 2 && + data->callchain->ips[callchain_nr - 2] == PERF_CONTEXT_USER_DEFERRED) { + data->deferred_cookie = data->callchain->ips[callchain_nr - 1]; + data->deferred_callchain = true; + } OVERFLOW_CHECK(array, sz, max_size); array = (void *)array + sz; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index b5dd42588c916d..841b711d970e94 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2124,6 +2124,7 @@ static int add_callchain_ip(struct thread *thread, *cpumode = PERF_RECORD_MISC_KERNEL; break; case PERF_CONTEXT_USER: + case PERF_CONTEXT_USER_DEFERRED: *cpumode = PERF_RECORD_MISC_USER; break; default: diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c index 66b666d9ce649d..741c3d657a8b6a 100644 --- a/tools/perf/util/perf_event_attr_fprintf.c +++ b/tools/perf/util/perf_event_attr_fprintf.c @@ -343,6 +343,8 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, PRINT_ATTRf(inherit_thread, p_unsigned); PRINT_ATTRf(remove_on_exec, p_unsigned); PRINT_ATTRf(sigtrap, p_unsigned); + PRINT_ATTRf(defer_callchain, p_unsigned); + PRINT_ATTRf(defer_output, p_unsigned); PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned, false); PRINT_ATTRf(bp_type, p_unsigned); diff --git a/tools/perf/util/sample.h b/tools/perf/util/sample.h index fae834144ef421..a8307b20a9ea80 100644 --- a/tools/perf/util/sample.h +++ b/tools/perf/util/sample.h @@ -107,6 +107,8 @@ struct perf_sample { /** @weight3: On x86 holds retire_lat, on powerpc holds p_stage_cyc. */ u16 weight3; bool no_hw_idx; /* No hw_idx collected in branch_stack */ + bool deferred_callchain; /* Has deferred user callchains */ + u64 deferred_cookie; char insn[MAX_INSN]; void *raw_data; struct ip_callchain *callchain; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4b0236b2df2913..361e15c1f26a96 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -720,6 +720,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_CGROUP] = perf_event__cgroup_swap, [PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap, [PERF_RECORD_AUX_OUTPUT_HW_ID] = perf_event__all64_swap, + [PERF_RECORD_CALLCHAIN_DEFERRED] = perf_event__all64_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, @@ -854,6 +855,9 @@ static void callchain__printf(struct evsel *evsel, for (i = 0; i < callchain->nr; i++) printf("..... %2d: %016" PRIx64 "\n", i, callchain->ips[i]); + + if (sample->deferred_callchain) + printf("...... (deferred)\n"); } static void branch_stack__printf(struct perf_sample *sample, @@ -1123,6 +1127,19 @@ static void dump_sample(struct evsel *evsel, union perf_event *event, sample_read__printf(sample, evsel->core.attr.read_format); } +static void dump_deferred_callchain(struct evsel *evsel, union perf_event *event, + struct perf_sample *sample) +{ + if (!dump_trace) + return; + + printf("(IP, 0x%x): %d/%d: %#" PRIx64 "\n", + event->header.misc, sample->pid, sample->tid, sample->deferred_cookie); + + if (evsel__has_callchain(evsel)) + callchain__printf(evsel, sample); +} + static void dump_read(struct evsel *evsel, union perf_event *event) { struct perf_record_read *read_event = &event->read; @@ -1353,6 +1370,9 @@ static int machines__deliver_event(struct machines *machines, return tool->text_poke(tool, event, sample, machine); case PERF_RECORD_AUX_OUTPUT_HW_ID: return tool->aux_output_hw_id(tool, event, sample, machine); + case PERF_RECORD_CALLCHAIN_DEFERRED: + dump_deferred_callchain(evsel, event, sample); + return tool->callchain_deferred(tool, event, sample, evsel, machine); default: ++evlist->stats.nr_unknown_events; return -1; diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index 22a8a4ffe05f77..e77f0e2ecc1f79 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -287,6 +287,7 @@ void perf_tool__init(struct perf_tool *tool, bool ordered_events) tool->read = process_event_sample_stub; tool->throttle = process_event_stub; tool->unthrottle = process_event_stub; + tool->callchain_deferred = process_event_sample_stub; tool->attr = process_event_synth_attr_stub; tool->event_update = process_event_synth_event_update_stub; tool->tracing_data = process_event_synth_tracing_data_stub; @@ -335,6 +336,7 @@ bool perf_tool__compressed_is_stub(const struct perf_tool *tool) } CREATE_DELEGATE_SAMPLE(read); CREATE_DELEGATE_SAMPLE(sample); +CREATE_DELEGATE_SAMPLE(callchain_deferred); #define CREATE_DELEGATE_ATTR(name) \ static int delegate_ ## name(const struct perf_tool *tool, \ @@ -468,6 +470,7 @@ void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate) tool->tool.ksymbol = delegate_ksymbol; tool->tool.bpf = delegate_bpf; tool->tool.text_poke = delegate_text_poke; + tool->tool.callchain_deferred = delegate_callchain_deferred; tool->tool.attr = delegate_attr; tool->tool.event_update = delegate_event_update; diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 88337cee1e3e2b..9b9f0a8cbf3de4 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -44,7 +44,8 @@ enum show_feature_header { struct perf_tool { event_sample sample, - read; + read, + callchain_deferred; event_op mmap, mmap2, comm, From 27ddc1d7a6b79ae76f5c07af293fde966da8221b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:48:01 -0800 Subject: [PATCH 552/684] perf record: Add --call-graph fp,defer option for deferred callchains Add a new callchain record mode option for deferred callchains. For now it only works with FP (frame-pointer) mode. And add the missing feature detection logic to clear the flag on old kernels. $ perf record --call-graph fp,defer -vv true ... ------------------------------------------------------------ perf_event_attr: type 0 (PERF_TYPE_HARDWARE) size 136 config 0 (PERF_COUNT_HW_CPU_CYCLES) { sample_period, sample_freq } 4000 sample_type IP|TID|TIME|CALLCHAIN|PERIOD read_format ID|LOST disabled 1 inherit 1 mmap 1 comm 1 freq 1 enable_on_exec 1 task 1 sample_id_all 1 mmap2 1 comm_exec 1 ksymbol 1 bpf_event 1 defer_callchain 1 defer_output 1 ------------------------------------------------------------ sys_perf_event_open: pid 162755 cpu 0 group_fd -1 flags 0x8 sys_perf_event_open failed, error -22 switching off deferred callchain support Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-config.txt | 3 +++ tools/perf/Documentation/perf-record.txt | 4 ++++ tools/perf/util/callchain.c | 16 +++++++++++++--- tools/perf/util/callchain.h | 1 + tools/perf/util/evsel.c | 19 +++++++++++++++++++ tools/perf/util/evsel.h | 1 + 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index c6f33565966735..642d1c490d9e3b 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -452,6 +452,9 @@ call-graph.*:: kernel space is controlled not by this option but by the kernel config (CONFIG_UNWINDER_*). + The 'defer' mode can be used with 'fp' mode to enable deferred + user callchains (like 'fp,defer'). + call-graph.dump-size:: The size of stack to dump in order to do post-unwinding. Default is 8192 (byte). When using dwarf into record-mode, the default size will be used if omitted. diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 067891bd7da6ed..e8b9aadbbfa505 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -325,6 +325,10 @@ OPTIONS by default. User can change the number by passing it after comma like "--call-graph fp,32". + Also "defer" can be used with "fp" (like "--call-graph fp,defer") to + enable deferred user callchain which will collect user-space callchains + when the thread returns to the user space. + -q:: --quiet:: Don't print any warnings or messages, useful for scripting. diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index d7b7eef740b9d6..2884187ccbbecf 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -275,9 +275,13 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) if (tok) { unsigned long size; - size = strtoul(tok, &name, 0); - if (size < (unsigned) sysctl__max_stack()) - param->max_stack = size; + if (!strncmp(tok, "defer", sizeof("defer"))) { + param->defer = true; + } else { + size = strtoul(tok, &name, 0); + if (size < (unsigned) sysctl__max_stack()) + param->max_stack = size; + } } break; @@ -314,6 +318,12 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) } while (0); free(buf); + + if (param->defer && param->record_mode != CALLCHAIN_FP) { + pr_err("callchain: deferred callchain only works with FP\n"); + return -EINVAL; + } + return ret; } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 86ed9e4d04f9ee..d5ae4fbb7ce5fa 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -98,6 +98,7 @@ extern bool dwarf_callchain_users; struct callchain_param { bool enabled; + bool defer; enum perf_call_graph_mode record_mode; u32 dump_size; enum chain_mode mode; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index df5351fde33987..9cd706f6279313 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1066,6 +1066,9 @@ static void __evsel__config_callchain(struct evsel *evsel, struct record_opts *o pr_info("Disabling user space callchains for function trace event.\n"); attr->exclude_callchain_user = 1; } + + if (param->defer && !attr->exclude_callchain_user) + attr->defer_callchain = 1; } void evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, @@ -1512,6 +1515,7 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts, attr->mmap2 = track && !perf_missing_features.mmap2; attr->comm = track; attr->build_id = track && opts->build_id; + attr->defer_output = track && callchain && callchain->defer; /* * ksymbol is tracked separately with text poke because it needs to be @@ -2200,6 +2204,10 @@ static int __evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus, static void evsel__disable_missing_features(struct evsel *evsel) { + if (perf_missing_features.defer_callchain && evsel->core.attr.defer_callchain) + evsel->core.attr.defer_callchain = 0; + if (perf_missing_features.defer_callchain && evsel->core.attr.defer_output) + evsel->core.attr.defer_output = 0; if (perf_missing_features.inherit_sample_read && evsel->core.attr.inherit && (evsel->core.attr.sample_type & PERF_SAMPLE_READ)) evsel->core.attr.inherit = 0; @@ -2474,6 +2482,13 @@ static bool evsel__detect_missing_features(struct evsel *evsel, struct perf_cpu /* Please add new feature detection here. */ + attr.defer_callchain = true; + if (has_attr_feature(&attr, /*flags=*/0)) + goto found; + perf_missing_features.defer_callchain = true; + pr_debug2("switching off deferred callchain support\n"); + attr.defer_callchain = false; + attr.inherit = true; attr.sample_type = PERF_SAMPLE_READ | PERF_SAMPLE_TID; if (has_attr_feature(&attr, /*flags=*/0)) @@ -2585,6 +2600,10 @@ static bool evsel__detect_missing_features(struct evsel *evsel, struct perf_cpu errno = old_errno; check: + if ((evsel->core.attr.defer_callchain || evsel->core.attr.defer_output) && + perf_missing_features.defer_callchain) + return true; + if (evsel->core.attr.inherit && (evsel->core.attr.sample_type & PERF_SAMPLE_READ) && perf_missing_features.inherit_sample_read) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3ae4ac8f9a37e0..a08130ff2e47a8 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -221,6 +221,7 @@ struct perf_missing_features { bool branch_counters; bool aux_action; bool inherit_sample_read; + bool defer_callchain; }; extern struct perf_missing_features perf_missing_features; From 25a9dd56cf84300f0e08609aeef1418bcf0f097d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:48:02 -0800 Subject: [PATCH 553/684] perf script: Display PERF_RECORD_CALLCHAIN_DEFERRED Handle the deferred callchains in the script output. $ perf script ... pwd 2312 121.163435: 249113 cpu/cycles/P: ffffffff845b78d8 __build_id_parse.isra.0+0x218 ([kernel.kallsyms]) ffffffff83bb5bf6 perf_event_mmap+0x2e6 ([kernel.kallsyms]) ffffffff83c31959 mprotect_fixup+0x1e9 ([kernel.kallsyms]) ffffffff83c31dc5 do_mprotect_pkey+0x2b5 ([kernel.kallsyms]) ffffffff83c3206f __x64_sys_mprotect+0x1f ([kernel.kallsyms]) ffffffff845e6692 do_syscall_64+0x62 ([kernel.kallsyms]) ffffffff8360012f entry_SYSCALL_64_after_hwframe+0x76 ([kernel.kallsyms]) b00000006 (cookie) ([unknown]) pwd 2312 121.163447: DEFERRED CALLCHAIN [cookie: b00000006] 7f18fe337fa7 mprotect+0x7 (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) 7f18fe330e0f _dl_sysdep_start+0x7f (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) 7f18fe331448 _dl_start_user+0x0 (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-script.c | 89 +++++++++++++++++++++++++++++++++ tools/perf/util/evsel_fprintf.c | 5 +- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 011962e1ee0f68..85b42205a71b39 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2706,6 +2706,94 @@ static int process_sample_event(const struct perf_tool *tool, return ret; } +static int process_deferred_sample_event(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct evsel *evsel, + struct machine *machine) +{ + struct perf_script *scr = container_of(tool, struct perf_script, tool); + struct perf_event_attr *attr = &evsel->core.attr; + struct evsel_script *es = evsel->priv; + unsigned int type = output_type(attr->type); + struct addr_location al; + FILE *fp = es->fp; + int ret = 0; + + if (output[type].fields == 0) + return 0; + + /* Set thread to NULL to indicate addr_al and al are not initialized */ + addr_location__init(&al); + + if (perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num, + sample->time)) { + goto out_put; + } + + if (debug_mode) { + if (sample->time < last_timestamp) { + pr_err("Samples misordered, previous: %" PRIu64 + " this: %" PRIu64 "\n", last_timestamp, + sample->time); + nr_unordered++; + } + last_timestamp = sample->time; + goto out_put; + } + + if (filter_cpu(sample)) + goto out_put; + + if (machine__resolve(machine, &al, sample) < 0) { + pr_err("problem processing %d event, skipping it.\n", + event->header.type); + ret = -1; + goto out_put; + } + + if (al.filtered) + goto out_put; + + if (!show_event(sample, evsel, al.thread, &al, NULL)) + goto out_put; + + if (evswitch__discard(&scr->evswitch, evsel)) + goto out_put; + + perf_sample__fprintf_start(scr, sample, al.thread, evsel, + PERF_RECORD_CALLCHAIN_DEFERRED, fp); + fprintf(fp, "DEFERRED CALLCHAIN [cookie: %llx]", + (unsigned long long)event->callchain_deferred.cookie); + + if (PRINT_FIELD(IP)) { + struct callchain_cursor *cursor = NULL; + + if (symbol_conf.use_callchain && sample->callchain) { + cursor = get_tls_callchain_cursor(); + if (thread__resolve_callchain(al.thread, cursor, evsel, + sample, NULL, NULL, + scripting_max_stack)) { + pr_info("cannot resolve deferred callchains\n"); + cursor = NULL; + } + } + + fputc(cursor ? '\n' : ' ', fp); + sample__fprintf_sym(sample, &al, 0, output[type].print_ip_opts, + cursor, symbol_conf.bt_stop_list, fp); + } + + fprintf(fp, "\n"); + + if (verbose > 0) + fflush(fp); + +out_put: + addr_location__exit(&al); + return ret; +} + // Used when scr->per_event_dump is not set static struct evsel_script es_stdout; @@ -4303,6 +4391,7 @@ int cmd_script(int argc, const char **argv) perf_tool__init(&script.tool, !unsorted_dump); script.tool.sample = process_sample_event; + script.tool.callchain_deferred = process_deferred_sample_event; script.tool.mmap = perf_event__process_mmap; script.tool.mmap2 = perf_event__process_mmap2; script.tool.comm = perf_event__process_comm; diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 103984b29b1e10..10f1a03c28601e 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -168,7 +168,10 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, node_al.addr = addr; node_al.map = map__get(map); - if (print_symoffset) { + if (sample->deferred_callchain && + sample->deferred_cookie == node->ip) { + printed += fprintf(fp, "(cookie)"); + } else if (print_symoffset) { printed += __symbol__fprintf_symname_offs(sym, &node_al, print_unknown_as_addr, true, fp); From 9b4525fd089decf3557eff4a3ef348cdc2b68353 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:48:03 -0800 Subject: [PATCH 554/684] perf tools: Merge deferred user callchains Save samples with deferred callchains in a separate list and deliver them after merging the user callchains. If users don't want to merge they can set tool->merge_deferred_callchains to false to prevent the behavior. With previous result, now perf script will show the merged callchains. $ perf script ... pwd 2312 121.163435: 249113 cpu/cycles/P: ffffffff845b78d8 __build_id_parse.isra.0+0x218 ([kernel.kallsyms]) ffffffff83bb5bf6 perf_event_mmap+0x2e6 ([kernel.kallsyms]) ffffffff83c31959 mprotect_fixup+0x1e9 ([kernel.kallsyms]) ffffffff83c31dc5 do_mprotect_pkey+0x2b5 ([kernel.kallsyms]) ffffffff83c3206f __x64_sys_mprotect+0x1f ([kernel.kallsyms]) ffffffff845e6692 do_syscall_64+0x62 ([kernel.kallsyms]) ffffffff8360012f entry_SYSCALL_64_after_hwframe+0x76 ([kernel.kallsyms]) 7f18fe337fa7 mprotect+0x7 (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) 7f18fe330e0f _dl_sysdep_start+0x7f (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) 7f18fe331448 _dl_start_user+0x0 (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) ... The old output can be get using --no-merge-callchain option. Also perf report can get the user callchain entry at the end. $ perf report --no-children --stdio -q -S __build_id_parse.isra.0 # symbol: __build_id_parse.isra.0 8.40% pwd [kernel.kallsyms] | ---__build_id_parse.isra.0 perf_event_mmap mprotect_fixup do_mprotect_pkey __x64_sys_mprotect do_syscall_64 entry_SYSCALL_64_after_hwframe mprotect _dl_sysdep_start _dl_start_user Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-script.txt | 5 ++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-report.c | 1 + tools/perf/builtin-script.c | 4 ++ tools/perf/util/callchain.c | 35 +++++++++++ tools/perf/util/callchain.h | 3 + tools/perf/util/evlist.c | 1 + tools/perf/util/evlist.h | 2 + tools/perf/util/session.c | 79 +++++++++++++++++++++++- tools/perf/util/tool.c | 2 + tools/perf/util/tool.h | 1 + 11 files changed, 133 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 28bec7e78bc858..03d1129606328d 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -527,6 +527,11 @@ include::itrace.txt[] The known limitations include exception handing such as setjmp/longjmp will have calls/returns not match. +--merge-callchains:: + Enable merging deferred user callchains if available. This is the + default behavior. If you want to see separate CALLCHAIN_DEFERRED + records for some reason, use --no-merge-callchains explicitly. + :GMEXAMPLECMD: script :GMEXAMPLESUBCMD: include::guest-files.txt[] diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 0e40f2a4bd18b9..aa7be4fb5838fb 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -2527,6 +2527,7 @@ int cmd_inject(int argc, const char **argv) inject.tool.auxtrace = perf_event__repipe_auxtrace; inject.tool.bpf_metadata = perf_event__repipe_op2_synth; inject.tool.dont_split_sample_group = true; + inject.tool.merge_deferred_callchains = false; inject.session = __perf_session__new(&data, &inject.tool, /*trace_event_repipe=*/inject.output.is_pipe, /*host_env=*/NULL); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 2bc269f5fcef80..add6b1c2aaf042 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1614,6 +1614,7 @@ int cmd_report(int argc, const char **argv) report.tool.event_update = perf_event__process_event_update; report.tool.feature = process_feature_event; report.tool.ordering_requires_timestamps = true; + report.tool.merge_deferred_callchains = !dump_trace; session = perf_session__new(&data, &report.tool); if (IS_ERR(session)) { diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 85b42205a71b39..62e43d3c5ad731 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -4009,6 +4009,7 @@ int cmd_script(int argc, const char **argv) bool header_only = false; bool script_started = false; bool unsorted_dump = false; + bool merge_deferred_callchains = true; char *rec_script_path = NULL; char *rep_script_path = NULL; struct perf_session *session; @@ -4162,6 +4163,8 @@ int cmd_script(int argc, const char **argv) "Guest code can be found in hypervisor process"), OPT_BOOLEAN('\0', "stitch-lbr", &script.stitch_lbr, "Enable LBR callgraph stitching approach"), + OPT_BOOLEAN('\0', "merge-callchains", &merge_deferred_callchains, + "Enable merge deferred user callchains"), OPTS_EVSWITCH(&script.evswitch), OPT_END() }; @@ -4418,6 +4421,7 @@ int cmd_script(int argc, const char **argv) script.tool.throttle = process_throttle_event; script.tool.unthrottle = process_throttle_event; script.tool.ordering_requires_timestamps = true; + script.tool.merge_deferred_callchains = merge_deferred_callchains; session = perf_session__new(&data, &script.tool); if (IS_ERR(session)) return PTR_ERR(session); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 2884187ccbbecf..428e5350d7a2c5 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1838,3 +1838,38 @@ int sample__for_each_callchain_node(struct thread *thread, struct evsel *evsel, } return 0; } + +/* + * This function merges earlier samples (@sample_orig) waiting for deferred + * user callchains with the matching callchain record (@sample_callchain) + * which is delivered now. The @sample_orig->callchain should be released + * after use if ->deferred_callchain is set. + */ +int sample__merge_deferred_callchain(struct perf_sample *sample_orig, + struct perf_sample *sample_callchain) +{ + u64 nr_orig = sample_orig->callchain->nr - 1; + u64 nr_deferred = sample_callchain->callchain->nr; + struct ip_callchain *callchain; + + if (sample_orig->callchain->nr < 2) { + sample_orig->deferred_callchain = false; + return -EINVAL; + } + + callchain = calloc(1 + nr_orig + nr_deferred, sizeof(u64)); + if (callchain == NULL) { + sample_orig->deferred_callchain = false; + return -ENOMEM; + } + + callchain->nr = nr_orig + nr_deferred; + /* copy original including PERF_CONTEXT_USER_DEFERRED (but the cookie) */ + memcpy(callchain->ips, sample_orig->callchain->ips, nr_orig * sizeof(u64)); + /* copy deferred user callchains */ + memcpy(&callchain->ips[nr_orig], sample_callchain->callchain->ips, + nr_deferred * sizeof(u64)); + + sample_orig->callchain = callchain; + return 0; +} diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index d5ae4fbb7ce5fa..2a52af8c80ace3 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -318,4 +318,7 @@ int sample__for_each_callchain_node(struct thread *thread, struct evsel *evsel, struct perf_sample *sample, int max_stack, bool symbols, callchain_iter_fn cb, void *data); +int sample__merge_deferred_callchain(struct perf_sample *sample_orig, + struct perf_sample *sample_callchain); + #endif /* __PERF_CALLCHAIN_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e8217efdda5323..03674d2cbd015e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -85,6 +85,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, evlist->ctl_fd.pos = -1; evlist->nr_br_cntr = -1; metricgroup__rblist_init(&evlist->metric_events); + INIT_LIST_HEAD(&evlist->deferred_samples); } struct evlist *evlist__new(void) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 5e71e3dc604230..911834ae7c2a6f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -92,6 +92,8 @@ struct evlist { * of struct metric_expr. */ struct rblist metric_events; + /* samples with deferred_callchain would wait here. */ + struct list_head deferred_samples; }; struct evsel_str_handler { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 361e15c1f26a96..dc570ad47ccc2c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1285,6 +1285,66 @@ static int evlist__deliver_sample(struct evlist *evlist, const struct perf_tool per_thread); } +/* + * Samples with deferred callchains should wait for the next matching + * PERF_RECORD_CALLCHAIN_RECORD entries. Keep the events in a list and + * deliver them once it finds the callchains. + */ +struct deferred_event { + struct list_head list; + union perf_event *event; +}; + +static int evlist__deliver_deferred_callchain(struct evlist *evlist, + const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct deferred_event *de, *tmp; + struct evsel *evsel; + int ret = 0; + + if (!tool->merge_deferred_callchains) { + evsel = evlist__id2evsel(evlist, sample->id); + return tool->callchain_deferred(tool, event, sample, + evsel, machine); + } + + list_for_each_entry_safe(de, tmp, &evlist->deferred_samples, list) { + struct perf_sample orig_sample; + + ret = evlist__parse_sample(evlist, de->event, &orig_sample); + if (ret < 0) { + pr_err("failed to parse original sample\n"); + break; + } + + if (sample->tid != orig_sample.tid) + continue; + + if (event->callchain_deferred.cookie == orig_sample.deferred_cookie) + sample__merge_deferred_callchain(&orig_sample, sample); + else + orig_sample.deferred_callchain = false; + + evsel = evlist__id2evsel(evlist, orig_sample.id); + ret = evlist__deliver_sample(evlist, tool, de->event, + &orig_sample, evsel, machine); + + if (orig_sample.deferred_callchain) + free(orig_sample.callchain); + + list_del(&de->list); + free(de->event); + free(de); + + if (ret) + break; + } + return ret; +} + static int machines__deliver_event(struct machines *machines, struct evlist *evlist, union perf_event *event, @@ -1313,6 +1373,22 @@ static int machines__deliver_event(struct machines *machines, return 0; } dump_sample(evsel, event, sample, perf_env__arch(machine->env)); + if (sample->deferred_callchain && tool->merge_deferred_callchains) { + struct deferred_event *de = malloc(sizeof(*de)); + size_t sz = event->header.size; + + if (de == NULL) + return -ENOMEM; + + de->event = malloc(sz); + if (de->event == NULL) { + free(de); + return -ENOMEM; + } + memcpy(de->event, event, sz); + list_add_tail(&de->list, &evlist->deferred_samples); + return 0; + } return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); case PERF_RECORD_MMAP: return tool->mmap(tool, event, sample, machine); @@ -1372,7 +1448,8 @@ static int machines__deliver_event(struct machines *machines, return tool->aux_output_hw_id(tool, event, sample, machine); case PERF_RECORD_CALLCHAIN_DEFERRED: dump_deferred_callchain(evsel, event, sample); - return tool->callchain_deferred(tool, event, sample, evsel, machine); + return evlist__deliver_deferred_callchain(evlist, tool, event, + sample, machine); default: ++evlist->stats.nr_unknown_events; return -1; diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index e77f0e2ecc1f79..27ba5849c74a2e 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -266,6 +266,7 @@ void perf_tool__init(struct perf_tool *tool, bool ordered_events) tool->cgroup_events = false; tool->no_warn = false; tool->show_feat_hdr = SHOW_FEAT_NO_HEADER; + tool->merge_deferred_callchains = true; tool->sample = process_event_sample_stub; tool->mmap = process_event_stub; @@ -448,6 +449,7 @@ void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate) tool->tool.cgroup_events = delegate->cgroup_events; tool->tool.no_warn = delegate->no_warn; tool->tool.show_feat_hdr = delegate->show_feat_hdr; + tool->tool.merge_deferred_callchains = delegate->merge_deferred_callchains; tool->tool.sample = delegate_sample; tool->tool.read = delegate_read; diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 9b9f0a8cbf3de4..e96b69d25a5b73 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -90,6 +90,7 @@ struct perf_tool { bool cgroup_events; bool no_warn; bool dont_split_sample_group; + bool merge_deferred_callchains; enum show_feature_header show_feat_hdr; }; From 405f5756bbd231e6b70949909a526bdaf538e2fc Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Nov 2025 15:48:04 -0800 Subject: [PATCH 555/684] perf tools: Flush remaining samples w/o deferred callchains It's possible that some kernel samples don't have matching deferred callchain records when the profiling session was ended before the threads came back to userspace. Let's flush the samples before finish the session. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/session.c | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dc570ad47ccc2c..4236503c8f6c13 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1295,6 +1295,10 @@ struct deferred_event { union perf_event *event; }; +/* + * This is called when a deferred callchain record comes up. Find all matching + * samples, merge the callchains and process them. + */ static int evlist__deliver_deferred_callchain(struct evlist *evlist, const struct perf_tool *tool, union perf_event *event, @@ -1345,6 +1349,42 @@ static int evlist__deliver_deferred_callchain(struct evlist *evlist, return ret; } +/* + * This is called at the end of the data processing for the session. Flush the + * remaining samples as there's no hope for matching deferred callchains. + */ +static int session__flush_deferred_samples(struct perf_session *session, + const struct perf_tool *tool) +{ + struct evlist *evlist = session->evlist; + struct machine *machine = &session->machines.host; + struct deferred_event *de, *tmp; + struct evsel *evsel; + int ret = 0; + + list_for_each_entry_safe(de, tmp, &evlist->deferred_samples, list) { + struct perf_sample sample; + + ret = evlist__parse_sample(evlist, de->event, &sample); + if (ret < 0) { + pr_err("failed to parse original sample\n"); + break; + } + + evsel = evlist__id2evsel(evlist, sample.id); + ret = evlist__deliver_sample(evlist, tool, de->event, + &sample, evsel, machine); + + list_del(&de->list); + free(de->event); + free(de); + + if (ret) + break; + } + return ret; +} + static int machines__deliver_event(struct machines *machines, struct evlist *evlist, union perf_event *event, @@ -2038,6 +2078,9 @@ static int __perf_session__process_pipe_events(struct perf_session *session) done: /* do the final flush for ordered samples */ err = ordered_events__flush(oe, OE_FLUSH__FINAL); + if (err) + goto out_err; + err = session__flush_deferred_samples(session, tool); if (err) goto out_err; err = auxtrace__flush_events(session, tool); @@ -2384,6 +2427,9 @@ static int __perf_session__process_events(struct perf_session *session) if (err) goto out_err; err = auxtrace__flush_events(session, tool); + if (err) + goto out_err; + err = session__flush_deferred_samples(session, tool); if (err) goto out_err; err = perf_session__flush_thread_stacks(session); @@ -2506,6 +2552,10 @@ static int __perf_session__process_dir_events(struct perf_session *session) if (ret) goto out_err; + ret = session__flush_deferred_samples(session, tool); + if (ret) + goto out_err; + ret = perf_session__flush_thread_stacks(session); out_err: ui_progress__finish(); From 7da4d60db33cccd8f4c445ab20bba71531435ee5 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:57:14 -0800 Subject: [PATCH 556/684] perf tools: Mark split kallsyms DSOs as loaded The maps__split_kallsyms() will split symbols to module DSOs if it comes from a module. It also handled some unusual kernel symbols after modules by creating new kernel maps like "[kernel].0". But they are pseudo DSOs to have those unexpected symbols. They should not be considered as unloaded kernel DSOs. Otherwise the dso__load() for them will end up calling dso__load_kallsyms() and then maps__split_kallsyms() again and again. Reviewed-by: Ian Rogers Fixes: 2e538c4a1847291cf ("perf tools: Improve kernel/modules symbol lookup") Signed-off-by: Namhyung Kim --- tools/perf/util/symbol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index d8fc5ea77f8493..5a38435d90c960 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -972,6 +972,7 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, return -1; dso__set_kernel(ndso, dso__kernel(dso)); + dso__set_loaded(ndso); curr_map = map__new2(pos->start, ndso); if (curr_map == NULL) { From ad0b9c4865b98dc37f4d606d26b1c19808796805 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:57:15 -0800 Subject: [PATCH 557/684] perf tools: Fix split kallsyms DSO counting It's counted twice as it's increased after calling maps__insert(). I guess we want to increase it only after it's added properly. Reviewed-by: Ian Rogers Fixes: 2e538c4a1847291cf ("perf tools: Improve kernel/modules symbol lookup") Signed-off-by: Namhyung Kim --- tools/perf/util/symbol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 5a38435d90c960..8eea49c50453d1 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -960,11 +960,11 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, if (dso__kernel(dso) == DSO_SPACE__KERNEL_GUEST) snprintf(dso_name, sizeof(dso_name), "[guest.kernel].%d", - kernel_range++); + kernel_range); else snprintf(dso_name, sizeof(dso_name), "[kernel].%d", - kernel_range++); + kernel_range); ndso = dso__new(dso_name); map__zput(curr_map); From 295d8a03ca04858d956efdaf4ac2a3be3fc05108 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:57:16 -0800 Subject: [PATCH 558/684] perf tools: Fallback to initial kernel map properly In maps__split_kallsyms(), it assumes new kernel map when it finds a symbol without module after any module and the initial kernel map has some symbols. Because it expects modules are out of the kernel map so modules should not have symbols in the kernel map. For example, the following memory map shows symbols and maps. Any symbols in the module 1 area will go to the module 1. The main kernel map starts at 0xffffffffbc200000. But if any symbol has a module between the symbols in that area, next symbols after 0xffffffffbd008000 will generate new kernel maps like [kernel].1. kernel address | | | | 0xffffffffc0000000 |---------------------| | (symbols) | | ... | <--- [kernel].N 0xffffffffbc400000 |---------------------| | (symbols) | | module 2 | <--- bad? 0xffffffffbc380000 |---------------------| | ... | | (symbols) | | [kernel.kallsyms] | <--- initial map 0xffffffffbc200000 |---------------------| | | | | 0xffffffffabcde000 |---------------------| | (symbols) | | module 1 | 0xffffffffabcd0000 |---------------------| This is very fragile when the module has a symbol that falls into the main kernel map for some reason. My system has a livepatch module with such symbols. And it created a lot of new kernel maps after those symbols. But the symbol may have broken addresses and the later symbols can still be found in the initial kernel map. Let's check the symbol address in the initial map and use it if found. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/symbol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 8eea49c50453d1..b533fbf17a8b19 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -951,7 +951,8 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, pos->end -= delta; } - if (count == 0) { + if (map__start(initial_map) <= (pos->start + delta) && + (pos->start + delta) < map__end(initial_map)) { map__zput(curr_map); curr_map = map__get(initial_map); goto add_symbol; From 4fba95fc383f9231ba486512ee1c9d60b8f4a9a4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:57:17 -0800 Subject: [PATCH 559/684] perf tools: Use machine->root_dir to find /proc/kallsyms This is for test functions to find the kallsyms correctly. It can find the machine from the kernel maps and use its root_dir. This is helpful to setup fake /proc directory for testing. Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/symbol.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b533fbf17a8b19..6ddbf4427c60da 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2002,6 +2002,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) char sbuild_id[SBUILD_ID_SIZE]; bool is_host = false; char path[PATH_MAX]; + struct maps *kmaps = map__kmaps(map); if (!dso__has_build_id(dso)) { /* @@ -2038,8 +2039,13 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) return strdup(path); /* Use current /proc/kallsyms if possible */ - if (is_host) { proc_kallsyms: + if (kmaps) { + struct machine *machine = maps__machine(kmaps); + + scnprintf(path, sizeof(path), "%s/proc/kallsyms", machine->root_dir); + return strdup(path); + } else if (is_host) { return strdup("/proc/kallsyms"); } From 34e271ae55382fbdb04f3e13e856457d8e0dee45 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 2 Dec 2025 15:57:18 -0800 Subject: [PATCH 560/684] perf test: Add kallsyms split test Create a fake root directory for /proc/{version,modules,kallsyms} in /tmp for testing. The kallsyms has a bad symbol in the module and it causes the main map splitted. The test ensures it only has two maps - kernel and the module and it finds the initial map after the module without creating the split maps like [kernel].0 and so on. $ perf test -vv "split kallsyms" 69: split kallsyms: --- start --- test child forked, pid 1016196 try to create fake root directory create kernel maps from the fake root directory maps__set_modules_path_dir: cannot open /tmp/perf-test.Zrv6Sy/lib/modules/X.Y.Z dir Problems setting modules path maps, continuing anyway... Failed to open /tmp/perf-test.Zrv6Sy/proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO capability to access. Using /tmp/perf-test.Zrv6Sy/proc/kallsyms for symbols kernel map loaded - check symbol and map ---- end(0) ---- 69: split kallsyms : Ok Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/kallsyms-split.c | 156 ++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 159 insertions(+) create mode 100644 tools/perf/tests/kallsyms-split.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index af67f8ef74b49c..c2a67ce459417e 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -69,6 +69,7 @@ perf-test-y += util.o perf-test-y += hwmon_pmu.o perf-test-y += tool_pmu.o perf-test-y += subcmd-help.o +perf-test-y += kallsyms-split.o ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc)) perf-test-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 9090e8238a4478..bd6ffa8e457843 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -140,6 +140,7 @@ static struct test_suite *generic_tests[] = { &suite__symbols, &suite__util, &suite__subcmd_help, + &suite__kallsyms_split, NULL, }; diff --git a/tools/perf/tests/kallsyms-split.c b/tools/perf/tests/kallsyms-split.c new file mode 100644 index 00000000000000..bbbc66957e5d04 --- /dev/null +++ b/tools/perf/tests/kallsyms-split.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include "util/dso.h" +#include "util/map.h" +#include "util/symbol.h" +#include "util/debug.h" +#include "util/machine.h" +#include "tests.h" + +/* + * This test is to check whether a bad symbol in a module won't split kallsyms maps. + * The main_symbol[1-3] should belong to the main [kernel.kallsyms] map even if the + * bad_symbol from the module is found in the middle. + */ +static char root_template[] = "/tmp/perf-test.XXXXXX"; +static char *root_dir; + +static const char proc_version[] = "Linux version X.Y.Z (just for perf test)\n"; +static const char proc_modules[] = "module 4096 1 - Live 0xffffffffcd000000\n"; +static const char proc_kallsyms[] = + "ffffffffab200000 T _stext\n" + "ffffffffab200010 T good_symbol\n" + "ffffffffab200020 t bad_symbol\n" + "ffffffffab200030 t main_symbol1\n" + "ffffffffab200040 t main_symbol2\n" + "ffffffffab200050 t main_symbol3\n" + "ffffffffab200060 T _etext\n" + "ffffffffcd000000 T start_module\t[module]\n" + "ffffffffab200020 u bad_symbol\t[module]\n" + "ffffffffcd000040 T end_module\t[module]\n"; + +static struct { + const char *name; + const char *contents; + long len; +} proc_files[] = { + { "version", proc_version, sizeof(proc_version) - 1 }, + { "modules", proc_modules, sizeof(proc_modules) - 1 }, + { "kallsyms", proc_kallsyms, sizeof(proc_kallsyms) - 1 }, +}; + +static void remove_proc_dir(int sig __maybe_unused) +{ + char buf[128]; + + if (root_dir == NULL) + return; + + for (unsigned i = 0; i < ARRAY_SIZE(proc_files); i++) { + scnprintf(buf, sizeof(buf), "%s/proc/%s", root_dir, proc_files[i].name); + remove(buf); + } + + scnprintf(buf, sizeof(buf), "%s/proc", root_dir); + rmdir(buf); + + rmdir(root_dir); + root_dir = NULL; +} + +static int create_proc_dir(void) +{ + char buf[128]; + + root_dir = mkdtemp(root_template); + if (root_dir == NULL) + return -1; + + scnprintf(buf, sizeof(buf), "%s/proc", root_dir); + if (mkdir(buf, 0700) < 0) + goto err; + + for (unsigned i = 0; i < ARRAY_SIZE(proc_files); i++) { + int fd, len; + + scnprintf(buf, sizeof(buf), "%s/proc/%s", root_dir, proc_files[i].name); + fd = open(buf, O_RDWR | O_CREAT, 0600); + if (fd < 0) + goto err; + + len = write(fd, proc_files[i].contents, proc_files[i].len); + close(fd); + if (len != proc_files[i].len) + goto err; + } + return 0; + +err: + remove_proc_dir(0); + return -1; +} + +static int test__kallsyms_split(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + struct machine m; + struct map *map = NULL; + int ret = TEST_FAIL; + + pr_debug("try to create fake root directory\n"); + if (create_proc_dir() < 0) { + pr_debug("SKIP: cannot create a fake root directory\n"); + return TEST_SKIP; + } + + signal(SIGINT, remove_proc_dir); + signal(SIGPIPE, remove_proc_dir); + signal(SIGSEGV, remove_proc_dir); + signal(SIGTERM, remove_proc_dir); + + pr_debug("create kernel maps from the fake root directory\n"); + machine__init(&m, root_dir, HOST_KERNEL_ID); + if (machine__create_kernel_maps(&m) < 0) { + pr_debug("FAIL: failed to create kernel maps\n"); + goto out; + } + + /* force to use /proc/kallsyms */ + symbol_conf.ignore_vmlinux = true; + symbol_conf.ignore_vmlinux_buildid = true; + symbol_conf.allow_aliases = true; + + if (map__load(machine__kernel_map(&m)) < 0) { + pr_debug("FAIL: failed to load kallsyms\n"); + goto out; + } + + pr_debug("kernel map loaded - check symbol and map\n"); + if (maps__nr_maps(machine__kernel_maps(&m)) != 2) { + pr_debug("FAIL: it should have the kernel and a module, but has %u maps\n", + maps__nr_maps(machine__kernel_maps(&m))); + goto out; + } + + if (machine__find_kernel_symbol_by_name(&m, "main_symbol3", &map) == NULL) { + pr_debug("FAIL: failed to find a symbol\n"); + goto out; + } + + if (!RC_CHK_EQUAL(map, machine__kernel_map(&m))) { + pr_debug("FAIL: the symbol is not in the kernel map\n"); + goto out; + } + ret = TEST_OK; + +out: + remove_proc_dir(0); + machine__exit(&m); + return ret; +} + +DEFINE_SUITE("split kallsyms", kallsyms_split); diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index f5fba95b6f3ffb..cb67ddbd037535 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -178,6 +178,7 @@ DECLARE_SUITE(event_groups); DECLARE_SUITE(symbols); DECLARE_SUITE(util); DECLARE_SUITE(subcmd_help); +DECLARE_SUITE(kallsyms_split); /* * PowerPC and S390 do not support creation of instruction breakpoints using the From e28f834f57131be2cfd60a1c9c580f0a71995dc9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Dec 2025 11:50:03 -0300 Subject: [PATCH 561/684] perf auxtrace: Include sys/types.h for pid_t In 754187ad73b73bcb ("perf build: Remove NO_AUXTRACE build option") sys/types.h was removed, which broke the build in all Alpine Linux releases, as musl libc has pid_t defined via sys/types.h, add it back. Fixes: 754187ad73b73bcb ("perf build: Remove NO_AUXTRACE build option") Signed-off-by: Arnaldo Carvalho de Melo Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/auxtrace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index eee2c11f766683..6947f3f284c029 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -7,6 +7,7 @@ #ifndef __PERF_AUXTRACE_H #define __PERF_AUXTRACE_H +#include #include // FILE #include #include From c4fe074b61556536d515ccf2737fb1c185f55ee4 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 13 Nov 2025 10:57:39 +0000 Subject: [PATCH 562/684] perf arm_spe: Add CPU variants supporting common data source packet Add the following CPU variants to the list for data source decoding: - Cortex-A715 [1] - Cortex-A78C [2] - Cortex-X1 [3] - Cortex-X4 [4] - Neoverse V3 [5] [1] https://developer.arm.com/documentation/101590/0103/Statistical-Profiling-Extension-Support/Statistical-Profiling-Extension-data-source-packet [2] https://developer.arm.com/documentation/102226/0002/Debug-descriptions/Statistical-Profiling-Extension/implementation-defined-features-of-SPE [3] https://developer.arm.com/documentation/101433/0102/Debug-descriptions/Statistical-Profiling-Extension/implementation-defined-features-of-SPE [4] https://developer.arm.com/documentation/102484/0003/Statistical-Profiling-Extension-support/Statistical-Profiling-Extension-data-source-packet [5] https://developer.arm.com/documentation/107734/0002/Statistical-Profiling-Extension-support/Statistical-Profiling-Extension-data-source-packet Signed-off-by: Leo Yan Reviewed-by: James Clark Signed-off-by: Namhyung Kim --- tools/perf/util/arm-spe.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 6a9c61d4aeeb22..dc19e72258f30d 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -572,16 +572,21 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, } static const struct midr_range common_ds_encoding_cpus[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A715), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720AE), MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X4), MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), {}, }; From c914d68371b0defc7dbc06a404eb0ef03180014b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:32 -0800 Subject: [PATCH 563/684] perf vendor events intel: Update alderlake events from 1.34 to 1.35 The updated events were published in: https://github.com/intel/perfmon/commit/c74f1cefa94d224cb3338507961b59d8a2a1c4e9 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- .../pmu-events/arch/x86/alderlake/cache.json | 16 ++++++++-------- .../pmu-events/arch/x86/alderlake/pipeline.json | 6 ++++-- .../pmu-events/arch/x86/alderlaken/cache.json | 16 ++++++++-------- .../pmu-events/arch/x86/alderlaken/pipeline.json | 6 ++++-- tools/perf/pmu-events/arch/x86/mapfile.csv | 4 ++-- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/alderlake/cache.json b/tools/perf/pmu-events/arch/x86/alderlake/cache.json index 4cd535baf7034b..be15a7f837171e 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/cache.json @@ -877,7 +877,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 128 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -890,7 +890,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 16 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -903,7 +903,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 256 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -916,7 +916,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 32 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -929,7 +929,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 4 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -942,7 +942,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 512 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -955,7 +955,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 64 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -968,7 +968,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 8 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json index 33d1f39e441fd0..57a8c78cdc490e 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json @@ -32,8 +32,9 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Counts the number of active floating point and integer dividers per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_OCCUPANCY", "SampleAfterValue": "1000003", @@ -41,8 +42,9 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of floating point and integer divider uops executed per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_UOPS", "SampleAfterValue": "1000003", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/cache.json b/tools/perf/pmu-events/arch/x86/alderlaken/cache.json index 669f4979b65118..76a841675337f8 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/cache.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/cache.json @@ -247,7 +247,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 128 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -259,7 +259,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 16 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -271,7 +271,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 256 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -283,7 +283,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 32 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -295,7 +295,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 4 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -307,7 +307,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 512 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -319,7 +319,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 64 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -331,7 +331,7 @@ }, { "BriefDescription": "Counts the number of tagged loads with an instruction latency that exceeds or equals the threshold of 8 cycles as defined in MEC_CR_PEBS_LD_LAT_THRESHOLD (3F6H). Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json index 1dd61baec1a9fa..d650cbd48c1fb9 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json @@ -9,16 +9,18 @@ "UMask": "0x3" }, { - "BriefDescription": "Counts the number of active floating point and integer dividers per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_OCCUPANCY", "SampleAfterValue": "1000003", "UMask": "0x3" }, { - "BriefDescription": "Counts the number of floating point and integer divider uops executed per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_UOPS", "SampleAfterValue": "1000003", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 32093bded9491f..d640acb8a3c7ca 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,6 +1,6 @@ Family-model,Version,Filename,EventType -GenuineIntel-6-(97|9A|B7|BA|BF),v1.34,alderlake,core -GenuineIntel-6-BE,v1.34,alderlaken,core +GenuineIntel-6-(97|9A|B7|BA|BF),v1.35,alderlake,core +GenuineIntel-6-BE,v1.35,alderlaken,core GenuineIntel-6-C[56],v1.13,arrowlake,core GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core GenuineIntel-6-(3D|47),v30,broadwell,core From 99eb7146cd6d04bb4bf1b1193cd17e8c04761ed9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:33 -0800 Subject: [PATCH 564/684] perf vendor events intel: Update arrowlake events from 1.13 to 1.14 The updated events were published in: https://github.com/intel/perfmon/commit/588dd77675039e1aaacee27a414cbcf3625c58a3 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- .../pmu-events/arch/x86/arrowlake/cache.json | 337 ++++++++++++++++- .../arch/x86/arrowlake/floating-point.json | 73 ++++ .../arch/x86/arrowlake/frontend.json | 72 ++++ .../pmu-events/arch/x86/arrowlake/memory.json | 64 ++++ .../pmu-events/arch/x86/arrowlake/other.json | 119 ++++++ .../arch/x86/arrowlake/pipeline.json | 350 ++++++++++++++++++ .../arch/x86/arrowlake/virtual-memory.json | 113 ++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 8 files changed, 1111 insertions(+), 19 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/cache.json b/tools/perf/pmu-events/arch/x86/arrowlake/cache.json index 30dd56b487ba55..fba4a0672f6c8e 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/cache.json @@ -8,6 +8,16 @@ "SampleAfterValue": "1000003", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L1D cacheline (dirty) evictions caused by load misses, stores, and prefetches.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x51", + "EventName": "DL1.DIRTY_EVICTION", + "PublicDescription": "Counts the number of L1D cacheline (dirty) evictions caused by load misses, stores, and prefetches. Does not count evictions or dirty writebacks caused by snoops. Does not count a replacement unless a (dirty) line was written back.", + "SampleAfterValue": "200003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L1D cacheline (dirty) evictions caused by load misses, stores, and prefetches.", "Counter": "0,1,2,3,4,5,6,7", @@ -109,6 +119,15 @@ "UMask": "0x1f", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Exclusive state", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.E", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Exclusive state", "Counter": "0,1,2,3,4,5,6,7", @@ -119,6 +138,15 @@ "UMask": "0x4", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Forward state", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.F", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Forward state", "Counter": "0,1,2,3,4,5,6,7", @@ -129,6 +157,25 @@ "UMask": "0x10", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Invalid state", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.I", + "PublicDescription": "Counts the number of cache lines filled into the L2 cache that are in Invalid state, does not count lines that go Invalid due to an eviction", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Modified state", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.M", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Modified state", "Counter": "0,1,2,3,4,5,6,7", @@ -139,6 +186,15 @@ "UMask": "0x8", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Shared state", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.S", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cache lines filled into the L2 cache that are in Shared state", "Counter": "0,1,2,3,4,5,6,7", @@ -189,6 +245,16 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of L2 cache lines that have been L2 hardware prefetched but not used by demand accesses", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x26", + "EventName": "L2_LINES_OUT.USELESS_HWPF", + "PublicDescription": "Counts the number of L2 cache lines that have been L2 hardware prefetched but not used by demand accesses. Increments on the core that brought the line in originally.", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cache lines that have been L2 hardware prefetched but not used by demand accesses", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -199,6 +265,42 @@ "UMask": "0x4", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of L2 prefetches initiated by either the L2 Stream or AMP that were throttled due to Dynamic Prefetch Throttling. The throttle requestor/source could be from the uncore/SOC or the Dead Block Predictor. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x28", + "EventName": "L2_PREFETCHES_THROTTLED.DPT", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of L2 prefetches initiated by the L2 Stream that were throttled due to Demand Throttle Prefetcher. DTP Global Triggered with no Local Override. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x28", + "EventName": "L2_PREFETCHES_THROTTLED.DTP", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of L2 prefetches initiated by the L2 Stream and not throttled by DTP due to local override. These prefetches may still be throttled due to another throttler mechanism besides DTP. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x28", + "EventName": "L2_PREFETCHES_THROTTLED.DTP_OVERRIDE", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of L2 prefetches initiated by either the L2 Stream or AMP that were throttled due to exceeding the XQ threshold set by either XQ_THRESHOLD_DTP or XQ_THRESHOLD. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x28", + "EventName": "L2_PREFETCHES_THROTTLED.XQ_THRESH", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.", "Counter": "0,1,2,3,4,5,6,7", @@ -208,6 +310,16 @@ "SampleAfterValue": "1000003", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L2 Cache Accesses Counts the total number of L2 Cache Accesses - sum of hits, misses, rejects front door requests for CRd/DRd/RFO/ItoM/L2 Prefetches only, per core event", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.ALL", + "PublicDescription": "Counts the number of L2 Cache Accesses Counts the total number of L2 Cache Accesses - sum of hits, misses, rejects front door requests for CRd/DRd/RFO/ItoM/L2 Prefetches only.", + "SampleAfterValue": "1000003", + "UMask": "0x7", + "Unit": "cpu_atom" + }, { "BriefDescription": "All accesses to L2 cache [This event is alias to L2_RQSTS.REFERENCES, L2_RQSTS.ANY]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -218,6 +330,15 @@ "UMask": "0xff", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of L2 Cache Accesses that resulted in a Hit from a front door request only (does not include rejects or recycles), per core event", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 Cache Accesses that resulted in a Hit from a front door request only (does not include rejects or recycles), per core event", "Counter": "0,1,2,3,4,5,6,7", @@ -227,6 +348,15 @@ "UMask": "0x2", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of total L2 Cache Accesses that resulted in a Miss from a front door request only (does not include rejects or recycles), per core event", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Read requests with true-miss in L2 cache [This event is alias to L2_RQSTS.MISS]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -246,6 +376,15 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of L2 Cache Accesses that miss the L2 and get BBL reject short and long rejects (includes those counted in L2_reject_XQ.any), per core event", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.REJECTS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 Cache Accesses that miss the L2 and get BBL reject short and long rejects, per core event", "Counter": "0,1,2,3,4,5,6,7", @@ -365,6 +504,51 @@ "UMask": "0x22", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of LLC prefetches that were throttled due to Dynamic Prefetch Throttling. The throttle requestor/source could be from the uncore/SOC or the Dead Block Predictor. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x29", + "EventName": "LLC_PREFETCHES_THROTTLED.DPT", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of LLC prefetches throttled due to Demand Throttle Prefetcher. DTP Global Triggered with no Local Override. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x29", + "EventName": "LLC_PREFETCHES_THROTTLED.DTP", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of LLC prefetches not throttled by DTP due to local override. These prefetches may still be throttled due to another throttler mechanism. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x29", + "EventName": "LLC_PREFETCHES_THROTTLED.DTP_OVERRIDE", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of LLC prefetches throttled due to LLC hit rate in . Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x29", + "EventName": "LLC_PREFETCHES_THROTTLED.HIT_RATE", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of LLC prefetches throttled due to exceeding the XQ threshold set by either XQ_THRESHOLD_DTP or LLC_XQ_THRESHOLD. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x29", + "EventName": "LLC_PREFETCHES_THROTTLED.XQ_THRESH", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles when L1D is locked", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -375,6 +559,16 @@ "UMask": "0x2", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PublicDescription": "Counts the number of cacheable memory requests that miss in the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the core has access to an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.", + "SampleAfterValue": "200003", + "UMask": "0x41", + "Unit": "cpu_atom" + }, { "BriefDescription": "Core-originated cacheable requests that missed L3 (Except hardware prefetches to the L3)", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -385,6 +579,26 @@ "UMask": "0x41", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PublicDescription": "Counts the number of cacheable memory requests that miss in the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the core has access to an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.", + "SampleAfterValue": "200003", + "UMask": "0x41", + "Unit": "cpu_lowpower" + }, + { + "BriefDescription": "Counts the number of cacheable memory requests that access the LLC. Counts on a per core basis.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.REFERENCE", + "PublicDescription": "Counts the number of cacheable memory requests that access the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the core has access to an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.", + "SampleAfterValue": "200003", + "UMask": "0x4f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Core-originated cacheable requests that refer to L3 (Except hardware prefetches to the L3)", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -535,6 +749,15 @@ "UMask": "0x78", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled to a store buffer full condition", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.SBFULL", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled to a store buffer full condition", "Counter": "0,1,2,3,4,5,6,7", @@ -858,6 +1081,15 @@ "UMask": "0x20", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.LOCAL_DRAM", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the number of load ops retired that hit the L1 data cache", "Counter": "0,1,2,3,4,5,6,7", @@ -940,6 +1172,15 @@ "UMask": "0x1c", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT", + "SampleAfterValue": "200003", + "UMask": "0x1c", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the number of loads that hit in a write combining buffer (WCB), excluding the first load that caused the WCB to allocate.", "Counter": "0,1,2,3,4,5,6,7", @@ -1039,6 +1280,16 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "SampleAfterValue": "200003", + "UMask": "0x83", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load uops retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -1081,7 +1332,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", @@ -1093,7 +1344,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -1105,7 +1356,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -1117,7 +1368,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -1129,7 +1380,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -1141,7 +1392,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", @@ -1153,7 +1404,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -1165,7 +1416,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -1177,7 +1428,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -1189,7 +1440,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -1201,7 +1452,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -1213,7 +1464,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -1225,7 +1476,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -1237,7 +1488,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -1249,7 +1500,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -1261,7 +1512,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -1273,7 +1524,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", @@ -1285,7 +1536,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", @@ -1315,6 +1566,26 @@ "UMask": "0x21", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of memory renamed load uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_LOADS", + "SampleAfterValue": "200003", + "UMask": "0x9", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of memory renamed store uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_STORES", + "SampleAfterValue": "200003", + "UMask": "0xa", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of memory uops retired that were splits.", "Counter": "0,1,2,3,4,5,6,7", @@ -1375,6 +1646,16 @@ "UMask": "0x42", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of memory uops retired that missed in the second level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS", + "SampleAfterValue": "200003", + "UMask": "0x13", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of memory uops retired that missed in the second level TLB.", "Counter": "0,1,2,3,4,5,6,7", @@ -1385,6 +1666,16 @@ "UMask": "0x13", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of load ops retired that filled the STLB - includes those in DTLB_LOAD_MISSES submasks", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS", + "SampleAfterValue": "200003", + "UMask": "0x11", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load uops retired that miss in the second Level TLB.", "Counter": "0,1,2,3,4,5,6,7", @@ -1395,6 +1686,16 @@ "UMask": "0x11", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of store ops retired (store STLB miss)", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES", + "SampleAfterValue": "200003", + "UMask": "0x12", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of store uops retired that miss in the second level TLB.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json b/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json index 23a80c526aa15a..3e68c2468f1157 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json @@ -1,4 +1,14 @@ [ + { + "BriefDescription": "Counts the number of cycles when any of the floating point dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles when floating-point divide unit is busy executing divide or square root operations.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -20,6 +30,24 @@ "UMask": "0x2", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of active floating point dividers per cycle in the loop stage.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of floating point divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts all microcode FP assists.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -473,6 +501,51 @@ "UMask": "0x3f", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on all floating point ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x1f", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2, 3.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/frontend.json b/tools/perf/pmu-events/arch/x86/arrowlake/frontend.json index db2ef84ca04152..a15de050a76cf5 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/frontend.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/frontend.json @@ -29,6 +29,42 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of BACLEARS due to a conditional jump.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.COND", + "SampleAfterValue": "200003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to an indirect branch.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.INDIRECT", + "SampleAfterValue": "200003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to a return branch.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.RETURN", + "SampleAfterValue": "200003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to a direct, unconditional jump.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.UNCOND", + "SampleAfterValue": "200003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Stalls caused by changing prefix length of the instruction.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -48,6 +84,15 @@ "UMask": "0x2", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of times a decode restriction reduces the decode throughput due to wrong instruction length prediction.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe9", + "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG", + "SampleAfterValue": "200003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "DSB-to-MITE switch true penalty cycles.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -733,6 +778,15 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles that the micro-sequencer is busy.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe7", + "EventName": "MS_DECODED.MS_BUSY", + "SampleAfterValue": "200003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the micro-sequencer is busy.", "Counter": "0,1,2,3,4,5,6,7", @@ -741,5 +795,23 @@ "SampleAfterValue": "1000003", "UMask": "0x4", "Unit": "cpu_lowpower" + }, + { + "BriefDescription": "Counts the number of times entered into a ucode flow in the FEC. Includes inserted flows due to front-end detected faults or assists.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe7", + "EventName": "MS_DECODED.MS_ENTRY", + "SampleAfterValue": "200003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of times nanocode flow is executed.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe7", + "EventName": "MS_DECODED.NANO_CODE", + "SampleAfterValue": "200003", + "UMask": "0x2", + "Unit": "cpu_atom" } ] diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/memory.json b/tools/perf/pmu-events/arch/x86/arrowlake/memory.json index aba1e27e5e3716..05cc46518232e0 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/memory.json @@ -1,4 +1,13 @@ [ + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ANY", + "SampleAfterValue": "1000003", + "UMask": "0x7f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.", "Counter": "0,1,2,3,4,5,6,7", @@ -62,6 +71,16 @@ "UMask": "0x81", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", "Counter": "0,1,2,3,4,5,6,7", @@ -82,6 +101,15 @@ "UMask": "0xc0", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.PGWALK", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.", "Counter": "0,1,2,3,4,5,6,7", @@ -100,6 +128,15 @@ "UMask": "0xa0", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store address match.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_ADDR", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.", "Counter": "0,1,2,3,4,5,6,7", @@ -118,6 +155,24 @@ "UMask": "0x84", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to store data forward block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_DATA", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", "Counter": "0,1,2,3,4,5,6,7", @@ -155,6 +210,15 @@ "UMask": "0x2", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING_FAST", + "SampleAfterValue": "20003", + "UMask": "0x82", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 1024 cycles.", "Counter": "2,3,4,5,6,7,8,9", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/other.json b/tools/perf/pmu-events/arch/x86/arrowlake/other.json index ab7aac14e69786..c8feed3a99a6ab 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/other.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/other.json @@ -18,6 +18,89 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of unhalted cycles a Core is blocked due to a lock In Progress issued by another core", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x63", + "EventName": "BUS_LOCK.BLOCKED_CYCLES", + "PublicDescription": "Counts the number of unhalted cycles a Core is blocked due to a lock In Progress issued by another core. Counts on a per core basis.", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of unhalted cycles a Core is blocked due to an Accepted lock it issued, includes both split and non-split lock cycles.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x63", + "EventName": "BUS_LOCK.LOCK_CYCLES", + "PublicDescription": "Counts the number of unhalted cycles a Core is blocked due to an Accepted lock it issued, includes both split and non-split lock cycles. Counts on a per core basis.", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of non-split locks such as UC locks issued by a Core (does not include cache locks)", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x63", + "EventName": "BUS_LOCK.NON_SPLIT_LOCKS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of split locks issued by a Core", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x63", + "EventName": "BUS_LOCK.SPLIT_LOCKS", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles the L2 Prefetchers are at throttle level 0", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x32", + "EventName": "DYNAMIC_PREFETCH_THROTTLER.LEVEL0_SOC", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles the L2 Prefetcher throttle level is at 1", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x32", + "EventName": "DYNAMIC_PREFETCH_THROTTLER.LEVEL1_SOC", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles the L2 Prefetcher throttle level is at 2", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x32", + "EventName": "DYNAMIC_PREFETCH_THROTTLER.LEVEL2_SOC", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles the L2 Prefetcher throttle level is at 3", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x32", + "EventName": "DYNAMIC_PREFETCH_THROTTLER.LEVEL3_SOC", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles the L2 Prefetcher throttle level is at 4", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x32", + "EventName": "DYNAMIC_PREFETCH_THROTTLER.LEVEL4_SOC", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event is deprecated. [This event is alias to MISC_RETIRED.LBR_INSERTS]", "Counter": "0,1,2,3,4,5,6,7", @@ -86,5 +169,41 @@ "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of prefetch requests that were promoted in the XQ to a demand request.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xf4", + "EventName": "XQ_PROMOTION.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x7", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of prefetch requests that were promoted in the XQ to a demand code read.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xf4", + "EventName": "XQ_PROMOTION.CRDS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of prefetch requests that were promoted in the XQ to a demand read.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xf4", + "EventName": "XQ_PROMOTION.DRDS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of prefetch requests that were promoted in the XQ to a demand RFO.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xf4", + "EventName": "XQ_PROMOTION.RFOS", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" } ] diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json b/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json index 0651e2c4561e46..80561605292555 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json @@ -30,6 +30,16 @@ "UMask": "0x3", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of cycles when any of the integer dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles when integer divide unit is busy executing divide or square root operations.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -41,6 +51,24 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of active integer dividers per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of integer divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -117,6 +145,15 @@ "UMask": "0x7e", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of not taken JCC branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_NTAKEN", + "SampleAfterValue": "200003", + "UMask": "0x7f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Not taken branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -252,6 +289,15 @@ "UMask": "0xfb", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of near indirect JMP branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.INDIRECT_JMP", + "SampleAfterValue": "200003", + "UMask": "0xef", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of near indirect JMP branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -261,6 +307,17 @@ "UMask": "0xef", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.INDIRECT_CALL", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "Errata": "ARL011", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.IND_CALL", + "SampleAfterValue": "200003", + "UMask": "0xfb", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the number of near CALL branch instructions retired", "Counter": "0,1,2,3,4,5,6,7", @@ -318,6 +375,15 @@ "UMask": "0xf7", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "SampleAfterValue": "200003", + "UMask": "0xc0", + "Unit": "cpu_atom" + }, { "BriefDescription": "Taken branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -440,6 +506,15 @@ "UMask": "0x151", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of mispredicted not taken JCC branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_NTAKEN", + "SampleAfterValue": "200003", + "UMask": "0x7f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Mispredicted non-taken conditional branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -613,6 +688,15 @@ "UMask": "0xc0", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of mispredicted near indirect JMP branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.INDIRECT_JMP", + "SampleAfterValue": "200003", + "UMask": "0xef", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of mispredicted near indirect JMP branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -622,6 +706,15 @@ "UMask": "0xef", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of mispredicted near taken branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -689,6 +782,15 @@ "UMask": "0x48", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the total number of BTCLEARS.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe8", + "EventName": "BTCLEAR.ANY", + "PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Core clocks when the thread is in the C0.1 light-weight slower wakeup time but more power saving optimized state.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1187,6 +1289,15 @@ "UMask": "0x80", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on all Integer ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on a load port.", "Counter": "0,1,2,3,4,5,6,7", @@ -1197,6 +1308,42 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on integer port 0,1, 2, 3.", "Counter": "0,1,2,3,4,5,6,7", @@ -1327,6 +1474,15 @@ "UMask": "0x4", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of occurrences a retired load was blocked for any of the following reasons: utlb_miss, 4k_alias, unknown_sta/bad_fwd, unready_fwd (includes md blocks and esp consuming load blocks)", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x1f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of occurrences a retired load gets blocked because its address exactly matches an older store whose data is not ready (a.k.a. unknown). unready_fwd", "Counter": "0,1,2,3,4,5,6,7", @@ -1392,6 +1548,25 @@ "UMask": "0x2", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of demand loads that match on a wcb (request buffer) allocated by an L1 hardware prefetch [This event is alias to LOAD_HIT_PREFETCH.HW_PF]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x4c", + "EventName": "LOAD_HIT_PREFETCH.HWPF", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to LOAD_HIT_PREFETCH.HWPF]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0x4c", + "EventName": "LOAD_HIT_PREFETCH.HW_PF", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1432,6 +1607,15 @@ "SampleAfterValue": "20003", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY_FAST", + "SampleAfterValue": "20003", + "UMask": "0xff", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of machine clears (nukes) of any type.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1462,6 +1646,15 @@ "UMask": "0x8", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.DISAMBIGUATION_FAST", + "SampleAfterValue": "20003", + "UMask": "0x88", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of nukes due to memory renaming", "Counter": "0,1,2,3,4,5,6,7", @@ -1471,6 +1664,15 @@ "UMask": "0x10", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE_FAST", + "SampleAfterValue": "20003", + "UMask": "0x90", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of times that the machine clears due to a page fault. Covers both I-Side and D-Side (Loads/Stores) page faults. A page fault occurs when either the page is not present, or an access violation.", "Counter": "0,1,2,3,4,5,6,7", @@ -1574,6 +1776,15 @@ "UMask": "0x20", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe4", + "EventName": "MISC_RETIRED.LBR_INSERTS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "LBR record is inserted", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1593,6 +1804,86 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of CLFLUSH, CLWB, and CLDEMOTE instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.CL_INST", + "SampleAfterValue": "1000003", + "UMask": "0xff", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of LFENCE instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.LFENCE", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of RDPMC, RDTSC, and RDTSCP instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.RDPMC_RDTSC_P", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Count the number of WRMSR instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.WRMSR", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of faults and software interrupts with vector < 32.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.FAULT_ALL", + "PublicDescription": "Counts the number of faults and software interrupts with vector < 32, including VOE cases.", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of PSB+ nuke events and ToPA trap events.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.INTEL_PT_CLEARS", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of user interrupts delivered.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.ULI_DELIVERY", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of SENDUIPI instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.ULI_SENDUIPI", + "SampleAfterValue": "1000003", + "UMask": "0x9", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of VM exits.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.VM_EXIT", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1643,6 +1934,15 @@ "UMask": "0x4", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots where no uop could issue due to an IQ scoreboard that stalls allocation until a specified older uop retires or (in the case of jump scoreboard) executes. Commonly executed instructions with IQ scoreboards include LFENCE and MFENCE.", "Counter": "0,1,2,3,4,5,6,7", @@ -1720,6 +2020,15 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Fixed Counter: Counts the number of issue slots not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.", + "Counter": "Fixed counter 4", + "EventName": "TOPDOWN_BAD_SPECULATION.ALL", + "PublicDescription": "Fixed Counter: Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Counts all issue slots blocked during this recovery window including relevant microcode flows and while uops are not yet available in the IQ. Also, includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.", "Counter": "0,1,2,3,4,5,6,7", @@ -1836,6 +2145,14 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.ALL_NON_ARCH", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls [This event is alias to TOPDOWN_BE_BOUND.ALL]", "Counter": "0,1,2,3,4,5,6,7", @@ -1951,6 +2268,14 @@ "UMask": "0x6", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of retirement slots not consumed due to front end stalls", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.ALL_NON_ARCH", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to front end stalls", "Counter": "0,1,2,3,4,5,6,7", @@ -2148,6 +2473,14 @@ "UMask": "0x7", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of consumed retirement slots.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x72", + "EventName": "TOPDOWN_RETIRING.ALL_NON_ARCH", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of consumed retirement slots.", "Counter": "0,1,2,3,4,5,6,7", @@ -2367,6 +2700,14 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of uops retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.ALL", + "SampleAfterValue": "2000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the total number of uops retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -2414,6 +2755,15 @@ "UMask": "0x10", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of uops retired that were delivered by the loop stream detector (LSD).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.LSD", + "SampleAfterValue": "2000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS). This includes uops from flows due to complex instructions, faults, assists, and inserted flows.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/arrowlake/virtual-memory.json index a3e4a4f3ab458a..602e2ad5de6e04 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/virtual-memory.json @@ -8,6 +8,15 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts walks that miss the PDE_CACHE", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.PDE_CACHE_MISS", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of first level TLB misses but second level hits due to a demand load that did not start a page walk. Accounts for all page sizes. Will result in a DTLB write from STLB.", "Counter": "0,1,2,3,4,5,6,7", @@ -47,6 +56,16 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to any page size.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", + "SampleAfterValue": "200003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, { "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -175,6 +194,15 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts walks that miss the PDE_CACHE", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.PDE_CACHE_MISS", + "SampleAfterValue": "2000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of first level TLB misses but second level hits due to stores that did not start a page walk. Accounts for all page sizes. Will result in a DTLB write from STLB.", "Counter": "0,1,2,3,4,5,6,7", @@ -215,6 +243,16 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to any page size.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", + "SampleAfterValue": "2000003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, { "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -244,6 +282,16 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to a 2M or 4M page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", + "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 2M or 4M pages. Includes page walks that page fault.", + "SampleAfterValue": "2000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Page walks completed due to a demand data store to a 2M/4M page.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -324,6 +372,16 @@ "UMask": "0x10", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of times there was an ITLB miss and a new translation was filled into the ITLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x81", + "EventName": "ITLB.FILLS", + "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) and a new translation was filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.", + "SampleAfterValue": "200003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of page walks initiated by a instruction fetch that missed the first and second level TLBs.", "Counter": "0,1,2,3,4,5,6,7", @@ -342,6 +400,15 @@ "UMask": "0x1", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts walks that miss the PDE_CACHE", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.PDE_CACHE_MISS", + "SampleAfterValue": "2000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of first level TLB misses but second level hits due to an instruction fetch that did not start a page walk. Account for all pages sizes. Will result in an ITLB write from STLB.", "Counter": "0,1,2,3,4,5,6,7", @@ -501,6 +568,24 @@ "UMask": "0x10", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of occurrences a load gets blocked because of a micro TLB miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -518,5 +603,33 @@ "SampleAfterValue": "1000003", "UMask": "0x90", "Unit": "cpu_lowpower" + }, + { + "BriefDescription": "Counts the number of PMH walks that hit in the L1 or WCBs", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xbc", + "EventName": "PAGE_WALKER_LOADS.DTLB_L1_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of PMH walks that hit in the L2", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xbc", + "EventName": "PAGE_WALKER_LOADS.DTLB_L2_HIT", + "PublicDescription": "Counts the number of PMH walks that hit in the L2. Includes L2 Hit resulting from and L1D eviction of another core in the same module which is longer latency than a typical L2 hit.", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Count number of any STLB flush attempts (Entire, PCID, InvPage, CR3 write, etc)", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xbd", + "EventName": "TLB_FLUSHES.STLB_ANY", + "SampleAfterValue": "20003", + "UMask": "0x20", + "Unit": "cpu_atom" } ] diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index d640acb8a3c7ca..c25f718cfd54b3 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,7 +1,7 @@ Family-model,Version,Filename,EventType GenuineIntel-6-(97|9A|B7|BA|BF),v1.35,alderlake,core GenuineIntel-6-BE,v1.35,alderlaken,core -GenuineIntel-6-C[56],v1.13,arrowlake,core +GenuineIntel-6-C[56],v1.14,arrowlake,core GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core GenuineIntel-6-(3D|47),v30,broadwell,core GenuineIntel-6-56,v12,broadwellde,core From 5a341ccbdda901b5b492101bc98e443540f5598d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:34 -0800 Subject: [PATCH 565/684] perf vendor events intel: Update cascadelakex metric units The updated metrics were published in: https://github.com/intel/perfmon/pull/348/commits/2dce436130ddfb8b442fc373d103f970de26cb78 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- .../arch/x86/cascadelakex/uncore-cache.json | 2 +- .../arch/x86/cascadelakex/uncore-memory.json | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-cache.json b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-cache.json index c9596e18ec0901..30390d734051d7 100644 --- a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-cache.json @@ -22,7 +22,7 @@ "Unit": "CHA" }, { - "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_cha_tor_inserts.ia_miss", + "BriefDescription": "LLC misses - Uncacheable reads (from cpu). Derived from unc_cha_tor_inserts.ia_miss", "Counter": "0,1,2,3", "EventCode": "0x35", "EventName": "LLC_MISSES.UNCACHEABLE", diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json index 265cdf334f6ab2..aafa7af46e69a8 100644 --- a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json +++ b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json @@ -316,32 +316,32 @@ "Unit": "iMC" }, { - "BriefDescription": "Intel Optane DC persistent memory bandwidth read (MB/sec). Derived from unc_m_pmm_rpq_inserts", + "BriefDescription": "Intel Optane DC persistent memory bandwidth read (MiB/sec). Derived from unc_m_pmm_rpq_inserts", "Counter": "0,1,2,3", "EventCode": "0xE3", "EventName": "UNC_M_PMM_BANDWIDTH.READ", "PerPkg": "1", - "ScaleUnit": "6.103515625E-5MB/sec", + "ScaleUnit": "6.103515625E-5MiB/sec", "Unit": "iMC" }, { - "BriefDescription": "Intel Optane DC persistent memory bandwidth total (MB/sec). Derived from unc_m_pmm_rpq_inserts", + "BriefDescription": "Intel Optane DC persistent memory bandwidth total (MiB/sec). Derived from unc_m_pmm_rpq_inserts", "Counter": "0,1,2,3", "EventCode": "0xE3", "EventName": "UNC_M_PMM_BANDWIDTH.TOTAL", "MetricExpr": "UNC_M_PMM_RPQ_INSERTS + UNC_M_PMM_WPQ_INSERTS", "MetricName": "UNC_M_PMM_BANDWIDTH.TOTAL", "PerPkg": "1", - "ScaleUnit": "6.103515625E-5MB/sec", + "ScaleUnit": "6.103515625E-5MiB/sec", "Unit": "iMC" }, { - "BriefDescription": "Intel Optane DC persistent memory bandwidth write (MB/sec). Derived from unc_m_pmm_wpq_inserts", + "BriefDescription": "Intel Optane DC persistent memory bandwidth write (MiB/sec). Derived from unc_m_pmm_wpq_inserts", "Counter": "0,1,2,3", "EventCode": "0xE7", "EventName": "UNC_M_PMM_BANDWIDTH.WRITE", "PerPkg": "1", - "ScaleUnit": "6.103515625E-5MB/sec", + "ScaleUnit": "6.103515625E-5MiB/sec", "Unit": "iMC" }, { From 1d341e543f1cdbca4fbf00f55f005e937762f7a3 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:35 -0800 Subject: [PATCH 566/684] perf vendor events intel: Update graniterapids events from 1.15 to 1.16 The updated events were published in: https://github.com/intel/perfmon/commit/b4acc3fd520eb098db41083010b65b75ae906c96 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/x86/graniterapids/cache.json | 4 ++-- .../pmu-events/arch/x86/graniterapids/uncore-cache.json | 9 +++++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/graniterapids/cache.json b/tools/perf/pmu-events/arch/x86/graniterapids/cache.json index 7edb73583b07ac..db28866444b6a1 100644 --- a/tools/perf/pmu-events/arch/x86/graniterapids/cache.json +++ b/tools/perf/pmu-events/arch/x86/graniterapids/cache.json @@ -488,12 +488,12 @@ "UMask": "0x2" }, { - "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram", + "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from dram homed in the local socket", "Counter": "0,1,2,3", "Data_LA": "1", "EventCode": "0xd3", "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM", - "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM. Available PDIST counters: 0", + "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from DRAM homed in the local socket. Available PDIST counters: 0", "RetirementLatencyMax": 4146, "RetirementLatencyMean": 115.83, "RetirementLatencyMin": 0, diff --git a/tools/perf/pmu-events/arch/x86/graniterapids/uncore-cache.json b/tools/perf/pmu-events/arch/x86/graniterapids/uncore-cache.json index b782f6d54fc2b7..721fc42797b10c 100644 --- a/tools/perf/pmu-events/arch/x86/graniterapids/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/graniterapids/uncore-cache.json @@ -9,6 +9,15 @@ "PublicDescription": "UNC_CHACMS_CLOCKTICKS", "Unit": "CHACMS" }, + { + "BriefDescription": "UNC_CHACMS_DISTRESS_ASSERTED", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHACMS_DISTRESS_ASSERTED", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "CHACMS" + }, { "BriefDescription": "Counts the number of cycles FAST trigger is received from the global FAST distress wire.", "Counter": "0,1,2,3", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index c25f718cfd54b3..521718b0d4e00e 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -13,7 +13,7 @@ GenuineIntel-6-CF,v1.20,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core GenuineIntel-6-7A,v1.01,goldmontplus,core GenuineIntel-6-B6,v1.10,grandridge,core -GenuineIntel-6-A[DE],v1.15,graniterapids,core +GenuineIntel-6-A[DE],v1.16,graniterapids,core GenuineIntel-6-(3C|45|46),v36,haswell,core GenuineIntel-6-3F,v29,haswellx,core GenuineIntel-6-7[DE],v1.24,icelake,core From cf99cdf53e30101c0e6dfef845e06c22a866f573 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:36 -0800 Subject: [PATCH 567/684] perf vendor events intel: Update icelakex events from 1.28 to 1.30 The updated events were published in: https://github.com/intel/perfmon/commit/dc6ffee20c74bfd21d7a7e338345578d4b7ca9ca Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/x86/icelakex/uncore-cache.json | 4 ++-- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/icelakex/uncore-cache.json b/tools/perf/pmu-events/arch/x86/icelakex/uncore-cache.json index 6f84ad47276d5a..1c225192ba34de 100644 --- a/tools/perf/pmu-events/arch/x86/icelakex/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/icelakex/uncore-cache.json @@ -6050,7 +6050,7 @@ "EventName": "UNC_CHA_SNOOP_RESP.RSPIFWD", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "Counts when a a transaction with the opcode type RspIFwd Snoop Response was received which indicates a remote caching agent forwarded the data and the requesting agent is able to acquire the data in E (Exclusive) or M (modified) states. This is commonly returned with RFO (the Read for Ownership issued before a write) transactions. The snoop could have either been to a cacheline in the M,E,F (Modified, Exclusive or Forward) states.", + "PublicDescription": "Counts when a transaction with the opcode type RspIFwd Snoop Response was received which indicates a remote caching agent forwarded the data and the requesting agent is able to acquire the data in E (Exclusive) or M (modified) states. This is commonly returned with RFO (the Read for Ownership issued before a write) transactions. The snoop could have either been to a cacheline in the M,E,F (Modified, Exclusive or Forward) states.", "UMask": "0x4", "Unit": "CHA" }, @@ -6072,7 +6072,7 @@ "EventName": "UNC_CHA_SNOOP_RESP.RSPSFWD", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "Counts when a a transaction with the opcode type RspSFwd Snoop Response was received which indicates a remote caching agent forwarded the data but held on to its current copy. This is common for data and code reads that hit in a remote socket in E (Exclusive) or F (Forward) state.", + "PublicDescription": "Counts when a transaction with the opcode type RspSFwd Snoop Response was received which indicates a remote caching agent forwarded the data but held on to its current copy. This is common for data and code reads that hit in a remote socket in E (Exclusive) or F (Forward) state.", "UMask": "0x8", "Unit": "CHA" }, diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 521718b0d4e00e..946471c4d4b7f2 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -17,7 +17,7 @@ GenuineIntel-6-A[DE],v1.16,graniterapids,core GenuineIntel-6-(3C|45|46),v36,haswell,core GenuineIntel-6-3F,v29,haswellx,core GenuineIntel-6-7[DE],v1.24,icelake,core -GenuineIntel-6-6[AC],v1.28,icelakex,core +GenuineIntel-6-6[AC],v1.30,icelakex,core GenuineIntel-6-3A,v24,ivybridge,core GenuineIntel-6-3E,v24,ivytown,core GenuineIntel-6-2D,v24,jaketown,core From 60688cfd84d748cb582581dc47e33294037ce485 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:37 -0800 Subject: [PATCH 568/684] perf vendor events intel: Update lunarlake events from 1.18 to 1.19 The updated events were published in: https://github.com/intel/perfmon/commit/09a0c74b23b5d20adf1f97e5022856568d05494c Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- .../pmu-events/arch/x86/lunarlake/cache.json | 20 +++++++------- .../pmu-events/arch/x86/lunarlake/other.json | 1 + .../arch/x86/lunarlake/pipeline.json | 26 ++++++++++++++++--- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/cache.json b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json index 402ca8fc50b60a..3d2616be8ec10a 100644 --- a/tools/perf/pmu-events/arch/x86/lunarlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json @@ -243,7 +243,7 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of L2 prefetches initiated by either the L2 Stream or AMP that were throttled due to exceeding the XQ threshold set by either XQ_THRESOLD_DTP or XQ_THRESHOLD. Counts on a per core basis.", + "BriefDescription": "Counts the number of L2 prefetches initiated by either the L2 Stream or AMP that were throttled due to exceeding the XQ threshold set by either XQ_THRESHOLD_DTP or XQ_THRESHOLD. Counts on a per core basis.", "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0x28", "EventName": "L2_PREFETCHES_THROTTLED.XQ_THRESH", @@ -464,7 +464,7 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of LLC prefetches throttled due to exceeding the XQ threshold set by either XQ_THRESOLD_DTP or LLC_XQ_THRESHOLD. Counts on a per core basis.", + "BriefDescription": "Counts the number of LLC prefetches throttled due to exceeding the XQ threshold set by either XQ_THRESHOLD_DTP or LLC_XQ_THRESHOLD. Counts on a per core basis.", "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0x29", "EventName": "LLC_PREFETCHES_THROTTLED.XQ_THRESH", @@ -1089,7 +1089,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -1101,7 +1101,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -1113,7 +1113,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -1125,7 +1125,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -1137,7 +1137,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -1149,7 +1149,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -1161,7 +1161,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -1173,7 +1173,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/other.json b/tools/perf/pmu-events/arch/x86/lunarlake/other.json index 1df716442549a2..164374edf293b8 100644 --- a/tools/perf/pmu-events/arch/x86/lunarlake/other.json +++ b/tools/perf/pmu-events/arch/x86/lunarlake/other.json @@ -178,6 +178,7 @@ "EventCode": "0xf4", "EventName": "XQ_PROMOTION.ALL", "SampleAfterValue": "1000003", + "UMask": "0x7", "Unit": "cpu_atom" }, { diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json index cdaa01e9a57d05..97797f7b072eea 100644 --- a/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json @@ -21,8 +21,9 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Counts the number of active floating point and integer dividers per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_OCCUPANCY", "SampleAfterValue": "1000003", @@ -30,8 +31,9 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of floating point and integer divider uops executed per cycle.", + "BriefDescription": "This event is deprecated.", "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", "EventCode": "0xcd", "EventName": "ARITH.DIV_UOPS", "SampleAfterValue": "1000003", @@ -1023,6 +1025,15 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of uops executed on secondary integer ports 0,1,2,3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.2ND", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on all Integer ports.", "Counter": "0,1,2,3,4,5,6,7", @@ -1205,7 +1216,7 @@ "EventCode": "0x03", "EventName": "LD_BLOCKS.ALL", "SampleAfterValue": "1000003", - "UMask": "0x10", + "UMask": "0x1f", "Unit": "cpu_atom" }, { @@ -1613,6 +1624,15 @@ "UMask": "0x8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots where no uop could issue due to an IQ scoreboard that stalls allocation until a specified older uop retires or (in the case of jump scoreboard) executes. Commonly executed instructions with IQ scoreboards include LFENCE and MFENCE.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.IQ_JEU_SCB", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 946471c4d4b7f2..3bed131e242d72 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -22,7 +22,7 @@ GenuineIntel-6-3A,v24,ivybridge,core GenuineIntel-6-3E,v24,ivytown,core GenuineIntel-6-2D,v24,jaketown,core GenuineIntel-6-(57|85),v16,knightslanding,core -GenuineIntel-6-BD,v1.18,lunarlake,core +GenuineIntel-6-BD,v1.19,lunarlake,core GenuineIntel-6-(AA|AC|B5),v1.17,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core From aa2f558bf6e145ccc248f3b8c4f02b8f2a3bd380 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:38 -0800 Subject: [PATCH 569/684] perf vendor events intel: Update meteorlake events from 1.17 to 1.18 The updated events were published in: https://github.com/intel/perfmon/commit/348f33fae477f281812c32e1c07812b7e35614dd Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../pmu-events/arch/x86/meteorlake/cache.json | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 3bed131e242d72..558e4f8a1419a2 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -23,7 +23,7 @@ GenuineIntel-6-3E,v24,ivytown,core GenuineIntel-6-2D,v24,jaketown,core GenuineIntel-6-(57|85),v16,knightslanding,core GenuineIntel-6-BD,v1.19,lunarlake,core -GenuineIntel-6-(AA|AC|B5),v1.17,meteorlake,core +GenuineIntel-6-(AA|AC|B5),v1.18,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core GenuineIntel-6-CC,v1.00,pantherlake,core diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json index d4731e300d6d20..d3fc04b2ffbd12 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json @@ -970,7 +970,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", @@ -982,7 +982,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -994,7 +994,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -1006,7 +1006,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", @@ -1018,7 +1018,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -1030,7 +1030,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -1042,7 +1042,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -1054,7 +1054,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -1066,7 +1066,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -1078,7 +1078,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", From 77621ef2d649f5698da0877af6ff940ba9cad1a1 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:39 -0800 Subject: [PATCH 570/684] perf vendor events intel: Update pantherlake events from 1.00 to 1.02 The updated events were published in: https://github.com/intel/perfmon/commit/6edacf434dffa046435de2f6a182c00df3cf4edc Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../arch/x86/pantherlake/cache.json | 38 +++ .../arch/x86/pantherlake/floating-point.json | 73 +++++ .../arch/x86/pantherlake/memory.json | 9 + .../arch/x86/pantherlake/pipeline.json | 305 +++++++++++++++++- 5 files changed, 425 insertions(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 558e4f8a1419a2..77a5ec666a51ba 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -26,7 +26,7 @@ GenuineIntel-6-BD,v1.19,lunarlake,core GenuineIntel-6-(AA|AC|B5),v1.18,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core -GenuineIntel-6-CC,v1.00,pantherlake,core +GenuineIntel-6-CC,v1.02,pantherlake,core GenuineIntel-6-A7,v1.04,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core GenuineIntel-6-8F,v1.35,sapphirerapids,core diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/cache.json b/tools/perf/pmu-events/arch/x86/pantherlake/cache.json index 7098ea1d6d16a9..91f5ab908926fd 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/cache.json @@ -383,6 +383,15 @@ "UMask": "0x10", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches, a snoop was required, and hits in other core or module on same die. Another core provides the data with a fwd, no fwd, or hitM.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_OTHERMOD", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts all retired load instructions.", "Counter": "0,1,2,3", @@ -727,6 +736,16 @@ "UMask": "0x40", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load ops retired that hit the L1 data cache.", "Counter": "0,1,2,3,4,5,6,7", @@ -830,6 +849,16 @@ "SampleAfterValue": "100021", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x83", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load ops retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -1371,5 +1400,14 @@ "SampleAfterValue": "100003", "UMask": "0x4", "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to an icache miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.ICACHE", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" } ] diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/floating-point.json b/tools/perf/pmu-events/arch/x86/pantherlake/floating-point.json index 57c26866bc796e..e306a45b22eeb5 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/floating-point.json @@ -273,6 +273,69 @@ "UMask": "0x3f", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on all floating point ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x1f", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2, 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0x1e", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.STD", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of floating point operations retired that required microcode assist.", "Counter": "0,1,2,3,4,5,6,7", @@ -282,5 +345,15 @@ "SampleAfterValue": "1000003", "UMask": "0x4", "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.FPDIV", + "PublicDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" } ] diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/memory.json b/tools/perf/pmu-events/arch/x86/pantherlake/memory.json index 397a15dbb9647d..3d31e620383d33 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/memory.json @@ -8,6 +8,15 @@ "UMask": "0xf4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json b/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json index 2d805ac98c5b53..fb87d30c403dd8 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json @@ -329,6 +329,17 @@ "SampleAfterValue": "400009", "Unit": "cpu_core" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_MISP_RETIRED.NEAR_INDIRECT]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.ALL_NEAR_IND", + "PublicDescription": "This event is deprecated. [This event is alias to BR_MISP_RETIRED.NEAR_INDIRECT] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50", + "Unit": "cpu_atom" + }, { "BriefDescription": "Mispredicted conditional branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -570,6 +581,16 @@ "UMask": "0x8040", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_MISP_RETIRED.ALL_NEAR_IND]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_INDIRECT", + "PublicDescription": "Counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_MISP_RETIRED.ALL_NEAR_IND] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50", + "Unit": "cpu_atom" + }, { "BriefDescription": "Miss-predicted near indirect branch instructions retired (excluding returns) [This event is alias to BR_MISP_RETIRED.INDIRECT]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1126,6 +1147,70 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of uops executed on secondary integer ports 0,1,2,3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.2ND", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on all Integer ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on a load port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.LD", + "PublicDescription": "Counts the number of uops executed on a load port. This event counts for integer uops even if the destination is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on integer port 0,1, 2, 3.", "Counter": "0,1,2,3,4,5,6,7", @@ -1135,6 +1220,25 @@ "UMask": "0x78", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on a Store address port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STA", + "PublicDescription": "Counts the number of uops executed on a Store address port. This event counts integer uops even if the data source is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on an integer store data and jump port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STD_JMP", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of vector integer instructions retired of 128-bit vector-width.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1236,7 +1340,7 @@ "EventName": "LD_BLOCKS.ALL", "PublicDescription": "Counts the number of retired loads that are blocked for any of the following reasons: DTLB miss, address alias, store forward or data unknown (includes memory disambiguation blocks and ESP consuming load blocks). Available PDIST counters: 0,1", "SampleAfterValue": "1000003", - "UMask": "0x10", + "UMask": "0x1f", "Unit": "cpu_atom" }, { @@ -1360,6 +1464,15 @@ "UMask": "0x20", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears due to program modifying data (self modifying code) within 1K of a recently fetched code page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.SMC", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Self-modifying code (SMC) detected.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1507,6 +1620,25 @@ "UMask": "0x4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots where no uop could issue due to an IQ scoreboard that stalls allocation until a specified older uop retires or (in the case of jump scoreboard) executes. Commonly executed instructions with IQ scoreboards include LFENCE and MFENCE.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.IQ_JEU_SCB", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.NON_C01_MS_SCB", + "PublicDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires. The most commonly executed instruction with an MS scoreboard is PAUSE.", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event counts a subset of the Topdown Slots event that were not consumed by the back-end pipeline due to lack of back-end resources, as a result of memory subsystem delays, execution units limitations, or other conditions.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1582,6 +1714,42 @@ "SampleAfterValue": "1000003", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to Fast Nukes such as Memory Ordering Machine clears and MRN nukes", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.FASTNUKE", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to a branch mispredict that resulted in LSD exit.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.LSD_MISPREDICT", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to Branch Mispredict", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.MISPREDICT", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to a machine clear (nuke).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls. [This event is alias to TOPDOWN_BE_BOUND.ALL_P]", "Counter": "0,1,2,3,4,5,6,7", @@ -1591,6 +1759,15 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to due to certain allocation restrictions.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.ALLOC_RESTRICTIONS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls. [This event is alias to TOPDOWN_BE_BOUND.ALL]", "Counter": "0,1,2,3,4,5,6,7", @@ -1600,6 +1777,33 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to LSD entry.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.LSD", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to memory reservation stall (scheduler not being able to accept another uop). This could be caused by RSV full or load/store buffer block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to iq/jeu scoreboards or ms scb", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.SERIALIZATION", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Fixed Counter: Counts the number of retirement slots not consumed due to front end stalls.", "Counter": "Fixed counter 5", @@ -1617,6 +1821,78 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BAClear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.BRANCH_DETECT", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BTClear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.BRANCH_RESTEER", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to ms", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.CISC", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to decode stall", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.DECODE", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to latency related stalls including BACLEARs, BTCLEARs, ITLB misses, and ICache misses.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.FRONTEND_LATENCY", + "SampleAfterValue": "1000003", + "UMask": "0x72", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to itlb miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.ITLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend that do not categorize into any other common frontend stall", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.OTHER", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to predecode wrong", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.PREDECODE", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Fixed Counter: Counts the number of consumed retirement slots.", "Counter": "Fixed counter 6", @@ -1841,6 +2117,25 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of integer divide uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.IDIV", + "PublicDescription": "Counts the number of integer divide uops retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS). This includes uops from flows due to complex instructions, faults, assists, and inserted flows.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.MS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "UOPS_RETIRED.MS", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1887,5 +2182,13 @@ "SampleAfterValue": "1000003", "UMask": "0x2", "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of x87 uops retired, includes those in ms flows.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.X87", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" } ] From 492689ba72d0391e2c263b159a17beeea7b130a8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Dec 2025 08:53:40 -0800 Subject: [PATCH 571/684] perf vendor events intel: Update sierraforest events from 1.12 to 1.13 The updated events were published in: https://github.com/intel/perfmon/commit/445e38f5128592f8b5c38da30267fff025e37613 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Signed-off-by: Namhyung Kim --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../arch/x86/sierraforest/cache.json | 20 +++++++++---------- .../arch/x86/sierraforest/uncore-cache.json | 9 +++++++++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 77a5ec666a51ba..3d0c571980569a 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -30,7 +30,7 @@ GenuineIntel-6-CC,v1.02,pantherlake,core GenuineIntel-6-A7,v1.04,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core GenuineIntel-6-8F,v1.35,sapphirerapids,core -GenuineIntel-6-AF,v1.12,sierraforest,core +GenuineIntel-6-AF,v1.13,sierraforest,core GenuineIntel-6-(37|4A|4C|4D|5A),v15,silvermont,core GenuineIntel-6-(4E|5E|8E|9E|A5|A6),v59,skylake,core GenuineIntel-6-55-[01234],v1.37,skylakex,core diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/cache.json b/tools/perf/pmu-events/arch/x86/sierraforest/cache.json index b2650e8ae2528c..de0e7661a52d9c 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/cache.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/cache.json @@ -327,7 +327,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", @@ -338,7 +338,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", @@ -349,7 +349,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", @@ -360,7 +360,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", @@ -371,7 +371,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", @@ -382,7 +382,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", @@ -393,7 +393,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", @@ -404,7 +404,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", @@ -415,7 +415,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", @@ -426,7 +426,7 @@ }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1,2,3,4,5,6,7", + "Counter": "0,1", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/uncore-cache.json b/tools/perf/pmu-events/arch/x86/sierraforest/uncore-cache.json index 3d1fb5f0417ecc..35b1763b002089 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/uncore-cache.json @@ -9,6 +9,15 @@ "PublicDescription": "UNC_CHACMS_CLOCKTICKS", "Unit": "CHACMS" }, + { + "BriefDescription": "UNC_CHACMS_DISTRESS_ASSERTED", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHACMS_DISTRESS_ASSERTED", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "CHACMS" + }, { "BriefDescription": "Counts the number of cycles FAST trigger is received from the global FAST distress wire.", "Counter": "0,1,2,3", From 27e711257902475097dea3f79cbdf241fe37ec00 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:13 -0800 Subject: [PATCH 572/684] perf kvm: Fix debug assertion There are 2 slots left for kvm_add_default_arch_event, fix the assertion so that debug builds don't fail the assert and to agree with the comment. Fixes: 45ff39f6e70aa55d0 ("perf tools kvm: Fix the potential out of range memory access issue") Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f0f285763f190a..c61369d54dd9d0 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -2014,7 +2014,7 @@ static int __cmd_record(const char *file_name, int argc, const char **argv) for (j = 1; j < argc; j++, i++) rec_argv[i] = STRDUP_FAIL_EXIT(argv[j]); - BUG_ON(i != rec_argc); + BUG_ON(i + 2 != rec_argc); ret = kvm_add_default_arch_event(&i, rec_argv); if (ret) From 830f1854c4a02d70d2d7d7e2e8f71cb3b928c0d6 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:14 -0800 Subject: [PATCH 573/684] perf timechart: Add record support for output perf.data path The '-o' option exists for the SVG creation but not for `perf timechart record`. Add to better allow testing. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-timechart.txt | 3 +++ tools/perf/builtin-timechart.c | 15 +++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt index ef0c7565bd5c61..ef2281c56743ea 100644 --- a/tools/perf/Documentation/perf-timechart.txt +++ b/tools/perf/Documentation/perf-timechart.txt @@ -94,6 +94,9 @@ RECORD OPTIONS -g:: --callchain:: Do call-graph (stack chain/backtrace) recording +-o:: +--output=:: + Select the output file (default: perf.data) EXAMPLES -------- diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 22050c640dfa7d..f8b49d69e9a52a 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -1651,7 +1651,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) return ret; } -static int timechart__io_record(int argc, const char **argv) +static int timechart__io_record(int argc, const char **argv, const char *output_data) { unsigned int rec_argc, i; const char **rec_argv; @@ -1659,7 +1659,7 @@ static int timechart__io_record(int argc, const char **argv) char *filter = NULL; const char * const common_args[] = { - "record", "-a", "-R", "-c", "1", + "record", "-a", "-R", "-c", "1", "-o", output_data, }; unsigned int common_args_nr = ARRAY_SIZE(common_args); @@ -1786,7 +1786,8 @@ static int timechart__io_record(int argc, const char **argv) } -static int timechart__record(struct timechart *tchart, int argc, const char **argv) +static int timechart__record(struct timechart *tchart, int argc, const char **argv, + const char *output_data) { unsigned int rec_argc, i, j; const char **rec_argv; @@ -1794,7 +1795,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar unsigned int record_elems; const char * const common_args[] = { - "record", "-a", "-R", "-c", "1", + "record", "-a", "-R", "-c", "1", "-o", output_data, }; unsigned int common_args_nr = ARRAY_SIZE(common_args); @@ -1934,6 +1935,7 @@ int cmd_timechart(int argc, const char **argv) .merge_dist = 1000, }; const char *output_name = "output.svg"; + const char *output_record_data = "perf.data"; const struct option timechart_common_options[] = { OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, "output processes data only"), @@ -1976,6 +1978,7 @@ int cmd_timechart(int argc, const char **argv) OPT_BOOLEAN('I', "io-only", &tchart.io_only, "record only IO data"), OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), + OPT_STRING('o', "output", &output_record_data, "file", "output data file name"), OPT_PARENT(timechart_common_options), }; const char * const timechart_record_usage[] = { @@ -2024,9 +2027,9 @@ int cmd_timechart(int argc, const char **argv) } if (tchart.io_only) - ret = timechart__io_record(argc, argv); + ret = timechart__io_record(argc, argv, output_record_data); else - ret = timechart__record(&tchart, argc, argv); + ret = timechart__record(&tchart, argc, argv, output_record_data); goto out; } else if (argc) usage_with_options(timechart_usage, timechart_options); From b3ea721b804f9b7ae1de2a651aa4aca9bf5ff04b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:15 -0800 Subject: [PATCH 574/684] perf symbol-elf: Add missing puts on error path In dso__process_kernel_symbol if inserting a map fails, probably ENOMEM, then the reference count puts were missing on the dso and map. Signed-off-by: Ian Rogers Reviewed-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index c5c382c3409a73..957143fbf8a07c 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1447,8 +1447,11 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map, map__set_mapping_type(curr_map, MAPPING_TYPE__IDENTITY); } dso__set_symtab_type(curr_dso, dso__symtab_type(dso)); - if (maps__insert(kmaps, curr_map)) + if (maps__insert(kmaps, curr_map)) { + dso__put(curr_dso); + map__put(curr_map); return -1; + } dsos__add(&maps__machine(kmaps)->dsos, curr_dso); dso__set_loaded(curr_dso); dso__put(*curr_dsop); From b4e44399eb2ebe21d3b00ae14e8ebaab1a3aa094 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:16 -0800 Subject: [PATCH 575/684] perf symbol: Add missed dso__put Add missing dso__put for the dso created in maps__split_kallsyms. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/symbol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 6ddbf4427c60da..21d3e328899b7b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -987,6 +987,7 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, dso__put(ndso); return -1; } + dso__put(ndso); ++kernel_range; } else if (delta) { /* Kernel was relocated at boot time */ From dc4d16543e60c22cd342135f321e99f2ecad3d54 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:17 -0800 Subject: [PATCH 576/684] perf probe-event: Ensure probe event nsinfo is always cleared Move nsinfo__zput from cleanup_perf_probe_events to clear_perf_probe_event so it is always executed. Clean up clear_perf_probe_events to not call nsinfo__zput and use the pev variable to avoid repeated array accesses. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/util/probe-event.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 6ab2eb551b6cdf..710e4620923ea8 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2419,6 +2419,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev) } pev->nargs = 0; zfree(&pev->args); + nsinfo__zput(pev->nsi); } #define strdup_or_goto(str, label) \ @@ -3767,12 +3768,11 @@ void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs) /* Loop 3: cleanup and free trace events */ for (i = 0; i < npevs; i++) { pev = &pevs[i]; - for (j = 0; j < pevs[i].ntevs; j++) - clear_probe_trace_event(&pevs[i].tevs[j]); - zfree(&pevs[i].tevs); - pevs[i].ntevs = 0; - nsinfo__zput(pev->nsi); - clear_perf_probe_event(&pevs[i]); + for (j = 0; j < pev->ntevs; j++) + clear_probe_trace_event(&pev->tevs[j]); + zfree(&pev->tevs); + pev->ntevs = 0; + clear_perf_probe_event(pev); } } From f60efb4454b24cc944ff3eac164bb9dce9169f71 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:18 -0800 Subject: [PATCH 577/684] perf hist: In init, ensure mem_info is put on error paths Rather than exit the internal map_symbols directly, put the mem-info that does this and also lowers the reference count on the mem-info itself otherwise the mem-info is being leaked. Fixes: 56e144fe98260a0f ("perf mem_info: Add and use map_symbol__exit and addr_map_symbol__exit") Signed-off-by: Ian Rogers Reviewed-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/util/hist.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 64ff427040c341..ef4b569f7df463 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -608,10 +608,8 @@ static int hist_entry__init(struct hist_entry *he, map_symbol__exit(&he->branch_info->to.ms); zfree(&he->branch_info); } - if (he->mem_info) { - map_symbol__exit(&mem_info__iaddr(he->mem_info)->ms); - map_symbol__exit(&mem_info__daddr(he->mem_info)->ms); - } + if (he->mem_info) + mem_info__zput(he->mem_info); err: map_symbol__exit(&he->ms); zfree(&he->stat_acc); From 69d247295a51db53294efc14dc7e73b3c57df0f8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:19 -0800 Subject: [PATCH 578/684] perf mem-events: Don't leak online CPU map Reference count checking found the online CPU map was being gotten but not put. Add in the missing put. Signed-off-by: Ian Rogers Reviewed-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/util/mem-events.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 80b3069427bc4b..0b49fce251fcc1 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -303,12 +303,15 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, char **eve } if (cpu_map) { - if (!perf_cpu_map__equal(cpu_map, cpu_map__online())) { + struct perf_cpu_map *online = cpu_map__online(); + + if (!perf_cpu_map__equal(cpu_map, online)) { char buf[200]; cpu_map__snprint(cpu_map, buf, sizeof(buf)); pr_warning("Memory events are enabled on a subset of CPUs: %s\n", buf); } + perf_cpu_map__put(online); perf_cpu_map__put(cpu_map); } From 1da7c10b2e36541a9c74bc6cf04992f089fa7e00 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:20 -0800 Subject: [PATCH 579/684] perf jitdump: Fix missed dso__put Reference count checking caught a missing dso__put following a machine__findnew_dso_id. Signed-off-by: Ian Rogers Reviewed-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/util/jitdump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 496ca2d2bfdb82..f00814e37de966 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -547,6 +547,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) if (dso) dso__set_hit(dso); + + dso__put(dso); } out: perf_sample__exit(&sample); From 3118d14349cdbef112aa8b60c22b74c12478c4b1 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:21 -0800 Subject: [PATCH 580/684] perf c2c: Clean up some defensive gets and make asan clean To deal with histogram code that had missing gets the c2c code had some defensive gets. Those other issues were cleaned up by the reference count checker, clean them up for the c2c command here. Signed-off-by: Ian Rogers Reviewed-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/perf/builtin-c2c.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 14c3823f8fed5b..d390ae4e3ec819 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -322,7 +322,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, struct c2c_stats stats = { .nr_entries = 0, }; struct hist_entry *he; struct addr_location al; - struct mem_info *mi, *mi_dup; + struct mem_info *mi = NULL; struct callchain_cursor *cursor; int ret; @@ -349,20 +349,15 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, goto out; } - /* - * The mi object is released in hists__add_entry_ops, - * if it gets sorted out into existing data, so we need - * to take the copy now. - */ - mi_dup = mem_info__get(mi); - c2c_decode_stats(&stats, mi); he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, &al, NULL, NULL, mi, NULL, sample, true); - if (he == NULL) - goto free_mi; + if (he == NULL) { + ret = -ENOMEM; + goto out; + } c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_add_stats(&c2c_he->stats, &stats); @@ -393,17 +388,19 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu; int node = c2c.cpu2node[cpu]; - mi = mi_dup; - c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2, machine->env); - if (!c2c_hists) - goto free_mi; + if (!c2c_hists) { + ret = -ENOMEM; + goto out; + } he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, &al, NULL, NULL, mi, NULL, sample, true); - if (he == NULL) - goto free_mi; + if (he == NULL) { + ret = -ENOMEM; + goto out; + } c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_add_stats(&c2c_he->stats, &stats); @@ -421,14 +418,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, } out: + mem_info__put(mi); addr_location__exit(&al); return ret; - -free_mi: - mem_info__put(mi_dup); - mem_info__put(mi); - ret = -ENOMEM; - goto out; } static const char * const c2c_usage[] = { From ac881007c4bf7be4dae713c36b7f0309f2843611 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:22 -0800 Subject: [PATCH 581/684] perf tests c2c: Add a basic c2c Add basic c2c record and report testing to gain some coverage. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/c2c.sh | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 tools/perf/tests/shell/c2c.sh diff --git a/tools/perf/tests/shell/c2c.sh b/tools/perf/tests/shell/c2c.sh new file mode 100755 index 00000000000000..2471d44595c35c --- /dev/null +++ b/tools/perf/tests/shell/c2c.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# perf c2c tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_c2c_test.perf.data.XXXXX) + +cleanup() { + rm -f "${perfdata}" + rm -f "${perfdata}".old + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +check_c2c_support() { + # Check if perf c2c record works. + if ! perf c2c record -o "${perfdata}" -- true > /dev/null 2>&1 ; then + return 1 + fi + return 0 +} + +test_c2c_record_report() { + echo "c2c record and report test" + if ! check_c2c_support ; then + echo "c2c record and report test [Skipped: perf c2c record failed (possibly missing hardware support)]" + err=2 + return + fi + + # Run a workload that does some memory operations. + if ! perf c2c record -o "${perfdata}" -- perf test -w datasym 1 > /dev/null 2>&1 ; then + echo "c2c record and report test [Skipped: perf c2c record failed during workload]" + return + fi + + if ! perf c2c report -i "${perfdata}" --stdio > /dev/null 2>&1 ; then + echo "c2c record and report test [Failed: report failed]" + err=1 + return + fi + + if ! perf c2c report -i "${perfdata}" -N > /dev/null 2>&1 ; then + echo "c2c record and report test [Failed: report -N failed]" + err=1 + return + fi + + echo "c2c record and report test [Success]" +} + +test_c2c_record_report +cleanup +exit $err From 0eb307d954c10ef2dbf8d4597954e013dfe263ed Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:23 -0800 Subject: [PATCH 582/684] perf tests buildid: Add purge and remove testing Add testing for the purge and remove commands. Use the noploop workload rather than just a return to avoid missing samples in the workload in perf record. Tidy up the cleanup code to cleanup when signals happen. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/buildid.sh | 203 ++++++++++++++++++++++++++---- 1 file changed, 177 insertions(+), 26 deletions(-) diff --git a/tools/perf/tests/shell/buildid.sh b/tools/perf/tests/shell/buildid.sh index d2eb213da01d8d..102808cca9db33 100755 --- a/tools/perf/tests/shell/buildid.sh +++ b/tools/perf/tests/shell/buildid.sh @@ -36,16 +36,69 @@ if [ ${run_pe} -eq 1 ]; then unset WAYLAND_DISPLAY fi -ex_md5=$(mktemp /tmp/perf.ex.MD5.XXX) -ex_sha1=$(mktemp /tmp/perf.ex.SHA1.XXX) +build_id_dir= +ex_source=$(mktemp /tmp/perf_buildid_test.ex.XXX.c) +ex_md5=$(mktemp /tmp/perf_buildid_test.ex.MD5.XXX) +ex_sha1=$(mktemp /tmp/perf_buildid_test.ex.SHA1.XXX) ex_pe=$(dirname $0)/../pe-file.exe +data=$(mktemp /tmp/perf_buildid_test.data.XXX) +log_out=$(mktemp /tmp/perf_buildid_test.log.out.XXX) +log_err=$(mktemp /tmp/perf_buildid_test.log.err.XXX) -echo 'int main(void) { return 0; }' | cc -Wl,--build-id=sha1 -o ${ex_sha1} -x c - -echo 'int main(void) { return 0; }' | cc -Wl,--build-id=md5 -o ${ex_md5} -x c - +cleanup() { + rm -f ${ex_source} ${ex_md5} ${ex_sha1} ${data} ${log_out} ${log_err} + if [ ${run_pe} -eq 1 ]; then + rm -r ${wineprefix} + fi + if [ -d ${build_id_dir} ]; then + rm -rf ${build_id_dir} + fi + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +# Test program based on the noploop workload. +cat < ${ex_source} +#include +#include +#include +static volatile sig_atomic_t done; + +static void sighandler(int sig) +{ + (void)sig; + done = 1; +} + +int main(int argc, const char **argv) +{ + int sec = 1; + + if (argc > 1) + sec = atoi(argv[1]); + + signal(SIGINT, sighandler); + signal(SIGALRM, sighandler); + alarm(sec); + + while (!done) + continue; + + return 0; +} +EOF +cc -Wl,--build-id=sha1 ${ex_source} -o ${ex_sha1} -x c - +cc -Wl,--build-id=md5 ${ex_source} -o ${ex_md5} -x c - echo "test binaries: ${ex_sha1} ${ex_md5} ${ex_pe}" -check() +get_build_id() { case $1 in *.exe) @@ -64,6 +117,15 @@ check() id=`readelf -n ${1} 2>/dev/null | grep 'Build ID' | awk '{print $3}'` ;; esac + echo ${id} +} + +check() +{ + file=$1 + perf_data=$2 + + id=$(get_build_id $file) echo "build id: ${id}" id_file=${id#??} @@ -76,45 +138,53 @@ check() exit 1 fi - file=${build_id_dir}/.build-id/$id_dir/`readlink ${link}`/elf - echo "file: ${file}" + cached_file=${build_id_dir}/.build-id/$id_dir/`readlink ${link}`/elf + echo "file: ${cached_file}" # Check for file permission of original file # in case of pe-file.exe file echo $1 | grep ".exe" if [ $? -eq 0 ]; then - if [ -x $1 ] && [ ! -x $file ]; then - echo "failed: file ${file} executable does not exist" + if [ -x $1 ] && [ ! -x $cached_file ]; then + echo "failed: file ${cached_file} executable does not exist" exit 1 fi - if [ ! -x $file ] && [ ! -e $file ]; then - echo "failed: file ${file} does not exist" + if [ ! -x $cached_file ] && [ ! -e $cached_file ]; then + echo "failed: file ${cached_file} does not exist" exit 1 fi - elif [ ! -x $file ]; then - echo "failed: file ${file} does not exist" + elif [ ! -x $cached_file ]; then + echo "failed: file ${cached_file} does not exist" exit 1 fi - diff ${file} ${1} + diff ${cached_file} ${1} if [ $? -ne 0 ]; then - echo "failed: ${file} do not match" + echo "failed: ${cached_file} do not match" exit 1 fi - ${perf} buildid-cache -l | grep ${id} + ${perf} buildid-cache -l | grep -q ${id} if [ $? -ne 0 ]; then echo "failed: ${id} is not reported by \"perf buildid-cache -l\"" exit 1 fi + if [ -n "${perf_data}" ]; then + ${perf} buildid-list -i ${perf_data} | grep -q ${id} + if [ $? -ne 0 ]; then + echo "failed: ${id} is not reported by \"perf buildid-list -i ${perf_data}\"" + exit 1 + fi + fi + echo "OK for ${1}" } test_add() { - build_id_dir=$(mktemp -d /tmp/perf.debug.XXX) + build_id_dir=$(mktemp -d /tmp/perf_buildid_test.debug.XXX) perf="perf --buildid-dir ${build_id_dir}" ${perf} buildid-cache -v -a ${1} @@ -128,12 +198,88 @@ test_add() rm -rf ${build_id_dir} } +test_remove() +{ + build_id_dir=$(mktemp -d /tmp/perf_buildid_test.debug.XXX) + perf="perf --buildid-dir ${build_id_dir}" + + ${perf} buildid-cache -v -a ${1} + if [ $? -ne 0 ]; then + echo "failed: add ${1} to build id cache" + exit 1 + fi + + id=$(get_build_id ${1}) + if ! ${perf} buildid-cache -l | grep -q ${id}; then + echo "failed: ${id} not in cache" + exit 1 + fi + + ${perf} buildid-cache -v -r ${1} + if [ $? -ne 0 ]; then + echo "failed: remove ${id} from build id cache" + exit 1 + fi + + if ${perf} buildid-cache -l | grep -q ${id}; then + echo "failed: ${id} still in cache after remove" + exit 1 + fi + + echo "remove: OK" + rm -rf ${build_id_dir} +} + +test_purge() +{ + build_id_dir=$(mktemp -d /tmp/perf_buildid_test.debug.XXX) + perf="perf --buildid-dir ${build_id_dir}" + + id1=$(get_build_id ${ex_sha1}) + ${perf} buildid-cache -v -a ${ex_sha1} + if ! ${perf} buildid-cache -l | grep -q ${id1}; then + echo "failed: ${id1} not in cache" + exit 1 + fi + + id2=$(get_build_id ${ex_md5}) + ${perf} buildid-cache -v -a ${ex_md5} + if ! ${perf} buildid-cache -l | grep -q ${id2}; then + echo "failed: ${id2} not in cache" + exit 1 + fi + + # Purge by path + ${perf} buildid-cache -v -p ${ex_sha1} + if [ $? -ne 0 ]; then + echo "failed: purge build id cache of ${ex_sha1}" + exit 1 + fi + + ${perf} buildid-cache -v -p ${ex_md5} + if [ $? -ne 0 ]; then + echo "failed: purge build id cache of ${ex_md5}" + exit 1 + fi + + # Verify both are gone + if ${perf} buildid-cache -l | grep -q ${id1}; then + echo "failed: ${id1} still in cache after purge" + exit 1 + fi + + if ${perf} buildid-cache -l | grep -q ${id2}; then + echo "failed: ${id2} still in cache after purge" + exit 1 + fi + + echo "purge: OK" + rm -rf ${build_id_dir} +} + test_record() { - data=$(mktemp /tmp/perf.data.XXX) - build_id_dir=$(mktemp -d /tmp/perf.debug.XXX) - log_out=$(mktemp /tmp/perf.log.out.XXX) - log_err=$(mktemp /tmp/perf.log.err.XXX) + build_id_dir=$(mktemp -d /tmp/perf_buildid_test.debug.XXX) perf="perf --buildid-dir ${build_id_dir}" echo "running: perf record $*" @@ -145,7 +291,7 @@ test_record() fi args="$*" - check ${args##* } + check ${args##* } ${data} rm -f ${log_out} ${log_err} rm -rf ${build_id_dir} @@ -166,10 +312,15 @@ if [ ${run_pe} -eq 1 ]; then test_record wine ${ex_pe} fi -# cleanup -rm ${ex_sha1} ${ex_md5} -if [ ${run_pe} -eq 1 ]; then - rm -r ${wineprefix} +# remove binaries manually via perf buildid-cache -r +test_remove ${ex_sha1} +test_remove ${ex_md5} +if [ ${add_pe} -eq 1 ]; then + test_remove ${ex_pe} fi +# purge binaries manually via perf buildid-cache -p +test_purge + +cleanup exit 0 From 75e961730b9e8506aa9b5cb670bdd674ce80e46a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:24 -0800 Subject: [PATCH 583/684] perf tests top: Add basic perf top coverage test The test starts a backgroup thloop workload and monitors it using cpu-clock ensuring test_loop appears in the output. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/top.sh | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 tools/perf/tests/shell/top.sh diff --git a/tools/perf/tests/shell/top.sh b/tools/perf/tests/shell/top.sh new file mode 100755 index 00000000000000..768ebcf7a89cbf --- /dev/null +++ b/tools/perf/tests/shell/top.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# perf top tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +log_file=$(mktemp /tmp/perf.top.log.XXXXX) + +cleanup() { + rm -f "${log_file}" + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +test_basic_perf_top() { + echo "Basic perf top test" + + # Start a workload that spins to generate samples + # thloop runs for the specified number of seconds + perf test -w thloop 20 & + PID=$! + + # Allow it to start + sleep 0.1 + + # Run perf top for 5 seconds, monitoring that PID + # Use --stdio to avoid TUI and redirect output + # Use -d 1 to avoid flooding output + # Use -e cpu-clock to ensure we get samples + # Use sleep to keep stdin open but silent, preventing EOF loop or interactive spam + if ! sleep 10 | timeout 5s perf top --stdio -d 1 -e cpu-clock -p $PID > "${log_file}" 2>&1; then + retval=$? + if [ $retval -ne 124 ] && [ $retval -ne 0 ]; then + echo "Basic perf top test [Failed: perf top failed to start or run (ret=$retval)]" + head -n 50 "${log_file}" + kill $PID + wait $PID 2>/dev/null || true + err=1 + return + fi + fi + + kill $PID + wait $PID 2>/dev/null || true + + # Check for some sample data (percentage) + if ! grep -E -q "[0-9]+\.[0-9]+%" "${log_file}"; then + echo "Basic perf top test [Failed: no sample percentage found]" + head -n 50 "${log_file}" + err=1 + return + fi + + # Check for the symbol + if ! grep -q "test_loop" "${log_file}"; then + echo "Basic perf top test [Failed: test_loop symbol not found]" + head -n 50 "${log_file}" + err=1 + return + fi + + echo "Basic perf top test [Success]" +} + +test_basic_perf_top +cleanup +exit $err From 279385cf634b50ad25aabc10dd334fdd78b09e7c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:25 -0800 Subject: [PATCH 584/684] perf tests timechart: Add a perf timechart test Basic coverage for `perf timechart` doing a record and then a basic sanity test of the generated SVG file. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/timechart.sh | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 tools/perf/tests/shell/timechart.sh diff --git a/tools/perf/tests/shell/timechart.sh b/tools/perf/tests/shell/timechart.sh new file mode 100755 index 00000000000000..b14b3472c2846b --- /dev/null +++ b/tools/perf/tests/shell/timechart.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# perf timechart tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_timechart_test.perf.data.XXXXX) +output=$(mktemp /tmp/__perf_timechart_test.output.XXXXX.svg) + +cleanup() { + rm -f "${perfdata}" + rm -f "${output}" + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +test_timechart() { + echo "Basic perf timechart test" + + # Try to record timechart data. + # perf timechart record uses system-wide recording and specific tracepoints. + # If it fails (e.g. permissions, missing tracepoints), skip the test. + if ! perf timechart record -o "${perfdata}" true > /dev/null 2>&1; then + echo "Basic perf timechart test [Skipped: perf timechart record failed (permissions/events?)]" + return + fi + + # Generate the timechart + if ! perf timechart -i "${perfdata}" -o "${output}" > /dev/null 2>&1; then + echo "Basic perf timechart test [Failed: perf timechart command failed]" + err=1 + return + fi + + # Check if output file exists and is not empty + if [ ! -s "${output}" ]; then + echo "Basic perf timechart test [Failed: output file is empty or missing]" + err=1 + return + fi + + # Check if it looks like an SVG + if ! grep -q "svg" "${output}"; then + echo "Basic perf timechart test [Failed: output doesn't look like SVG]" + err=1 + return + fi + + echo "Basic perf timechart test [Success]" +} + +if ! perf check feature -q libtraceevent ; then + echo "perf timechart is not supported. Skip." + cleanup + exit 2 +fi + +test_timechart +cleanup +exit $err From 526ed2f8a7fb6017df74d87ded0d32c86deb5803 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:26 -0800 Subject: [PATCH 585/684] perf tests kallsyms: Add basic kallsyms test Add test that kallsyms finds a well known symbol and fails for another. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/kallsyms.sh | 56 ++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 tools/perf/tests/shell/kallsyms.sh diff --git a/tools/perf/tests/shell/kallsyms.sh b/tools/perf/tests/shell/kallsyms.sh new file mode 100755 index 00000000000000..d0eb99753f477f --- /dev/null +++ b/tools/perf/tests/shell/kallsyms.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# perf kallsyms tests +# SPDX-License-Identifier: GPL-2.0 + +err=0 + +test_kallsyms() { + echo "Basic perf kallsyms test" + + # Check if /proc/kallsyms is readable + if [ ! -r /proc/kallsyms ]; then + echo "Basic perf kallsyms test [Skipped: /proc/kallsyms not readable]" + err=2 + return + fi + + # Use a symbol that is definitely a function and present in all kernels, e.g. schedule + symbol="schedule" + + # Run perf kallsyms + # It prints "address symbol_name" + output=$(perf kallsyms $symbol 2>&1) + ret=$? + + if [ $ret -ne 0 ] || [ -z "$output" ]; then + # If empty or failed, it might be due to permissions (kptr_restrict) + # Check if we can grep the symbol from /proc/kallsyms directly + if grep -q "$symbol" /proc/kallsyms 2>/dev/null; then + # If it's in /proc/kallsyms but perf kallsyms returned empty/error, + # it likely means perf couldn't parse it or access it correctly (e.g. kptr_restrict=2). + echo "Basic perf kallsyms test [Skipped: $symbol found in /proc/kallsyms but perf kallsyms failed (output: '$output')]" + err=2 + return + else + echo "Basic perf kallsyms test [Skipped: $symbol not found in /proc/kallsyms]" + err=2 + return + fi + fi + + if echo "$output" | grep -q "not found"; then + echo "Basic perf kallsyms test [Failed: output '$output' does not contain $symbol]" + err=1 + return + fi + + if perf kallsyms ErlingHaaland | grep -vq "not found"; then + echo "Basic perf kallsyms test [Failed: ErlingHaaland found in the output]" + err=1 + return + fi + echo "Basic perf kallsyms test [Success]" +} + +test_kallsyms +exit $err From 199d5e872a9ce73728ec0669bb5e31be6f9cf261 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:27 -0800 Subject: [PATCH 586/684] perf tests script dlfilter: Add a dlfilter test Compile a simple dlfilter and make sure it remove samples from everything other than a test_loop. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/script_dlfilter.sh | 107 ++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100755 tools/perf/tests/shell/script_dlfilter.sh diff --git a/tools/perf/tests/shell/script_dlfilter.sh b/tools/perf/tests/shell/script_dlfilter.sh new file mode 100755 index 00000000000000..45c97d4a7d5f90 --- /dev/null +++ b/tools/perf/tests/shell/script_dlfilter.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# perf script --dlfilter tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +shelldir=$(dirname "$0") +# shellcheck source=lib/setup_python.sh +. "${shelldir}"/lib/setup_python.sh + +# skip if there's no compiler +if ! [ -x "$(command -v cc)" ]; then + echo "failed: no compiler, install gcc" + exit 2 +fi + +err=0 +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) +dlfilter_c=$(mktemp /tmp/__perf_test.dlfilter.test.c.XXXXX) +dlfilter_so=$(mktemp /tmp/__perf_test.dlfilter.so.XXXXX) + +cleanup() { + rm -f "${perfdata}" + rm -f "${dlfilter_c}" + rm -f "${dlfilter_so}" + rm -f "${dlfilter_so}.o" + + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +cat < "${dlfilter_c}" +#include +#include +#include + +struct perf_dlfilter_fns perf_dlfilter_fns; + +int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx) +{ + const struct perf_dlfilter_al *al; + + if (!sample->ip) + return 0; + + al = perf_dlfilter_fns.resolve_ip(ctx); + if (!al || !al->sym || strcmp(al->sym, "test_loop")) + return 1; + + return 0; +} +EOF + +test_dlfilter() { + echo "Basic --dlfilter test" + # Generate perf.data file + if ! perf record -o "${perfdata}" perf test -w thloop 1 2> /dev/null + then + echo "Basic --dlfilter test [Failed record]" + err=1 + return + fi + + # Build the dlfilter + if ! cc -c -I tools/perf/include -fpic -x c "${dlfilter_c}" -o "${dlfilter_so}.o" + then + echo "Basic --dlfilter test [Failed to build dlfilter object]" + err=1 + return + fi + + if ! cc -shared -o "${dlfilter_so}" "${dlfilter_so}.o" + then + echo "Basic --dlfilter test [Failed to link dlfilter shared object]" + err=1 + return + fi + + # Check that the output contains "test_loop" and nothing else + if ! perf script -i "${perfdata}" --dlfilter "${dlfilter_so}" | grep -q "test_loop" + then + echo "Basic --dlfilter test [Failed missing output]" + err=1 + return + fi + + # The filter should filter out everything except test_loop, so ensure no other symbols are present + # This is a simple check; we could be more rigorous + if perf script -i "${perfdata}" --dlfilter "${dlfilter_so}" | grep -v "test_loop" | grep -q "perf" + then + echo "Basic --dlfilter test [Failed filtering]" + err=1 + return + fi + + echo "Basic --dlfilter test [Success]" +} + +test_dlfilter +cleanup +exit $err From db452961de9392258a3de60960919c17b5e39a50 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:28 -0800 Subject: [PATCH 587/684] perf tests evlist: Add basic evlist test Add test that evlist reports expected events from perf record. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/evlist.sh | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 tools/perf/tests/shell/evlist.sh diff --git a/tools/perf/tests/shell/evlist.sh b/tools/perf/tests/shell/evlist.sh new file mode 100755 index 00000000000000..140f099e75c1ea --- /dev/null +++ b/tools/perf/tests/shell/evlist.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# perf evlist tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) + +cleanup() { + rm -f "${perfdata}" + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +test_evlist_simple() { + echo "Simple evlist test" + if ! perf record -e cycles -o "${perfdata}" true 2> /dev/null + then + echo "Simple evlist [Failed record]" + err=1 + return + fi + if ! perf evlist -i "${perfdata}" | grep -q "cycles" + then + echo "Simple evlist [Failed to list event]" + err=1 + return + fi + echo "Simple evlist test [Success]" +} + +test_evlist_group() { + echo "Group evlist test" + if ! perf record -e "{cycles,instructions}" -o "${perfdata}" true 2> /dev/null + then + echo "Group evlist [Skipped event group recording failed]" + return + fi + + if ! perf evlist -i "${perfdata}" -g | grep -q "{.*cycles.*,.*instructions.*}" + then + echo "Group evlist [Failed to list event group]" + err=1 + return + fi + echo "Group evlist test [Success]" +} + +test_evlist_verbose() { + echo "Event configuration evlist test" + if ! perf record -e cycles -o "${perfdata}" true 2> /dev/null + then + echo "Event configuration evlist [Failed record]" + err=1 + return + fi + + if ! perf evlist -i "${perfdata}" -v | grep -q "config:" + then + echo "Event configuration evlist [Failed to list verbose info]" + err=1 + return + fi + echo "Event configuration evlist test [Success]" +} + +test_evlist_simple +test_evlist_group +test_evlist_verbose + +cleanup +exit $err From b58261584d2f6b5241ac1693026242ef2f2148b4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 22 Nov 2025 00:19:29 -0800 Subject: [PATCH 588/684] perf test kvm: Add some basic perf kvm test coverage Setup qemu with KVM then run kvm stat and some host recording/reporting/build-id tests. Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/kvm.sh | 154 ++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100755 tools/perf/tests/shell/kvm.sh diff --git a/tools/perf/tests/shell/kvm.sh b/tools/perf/tests/shell/kvm.sh new file mode 100755 index 00000000000000..2fafde1a29cca0 --- /dev/null +++ b/tools/perf/tests/shell/kvm.sh @@ -0,0 +1,154 @@ +#!/bin/bash +# perf kvm tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_kvm_test.perf.data.XXXXX) +qemu_pid_file=$(mktemp /tmp/__perf_kvm_test.qemu.pid.XXXXX) + +cleanup() { + rm -f "${perfdata}" + if [ -f "${qemu_pid_file}" ]; then + if [ -s "${qemu_pid_file}" ]; then + qemu_pid=$(cat "${qemu_pid_file}") + if [ -n "${qemu_pid}" ]; then + kill "${qemu_pid}" 2>/dev/null || true + fi + fi + rm -f "${qemu_pid_file}" + fi + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +skip() { + echo "Skip: $1" + cleanup + exit 2 +} + +test_kvm_stat() { + echo "Testing perf kvm stat" + + echo "Recording kvm events for pid ${qemu_pid}..." + if ! perf kvm stat record -p "${qemu_pid}" -o "${perfdata}" sleep 1; then + echo "Failed to record kvm events" + err=1 + return + fi + + echo "Reporting kvm events..." + if ! perf kvm -i "${perfdata}" stat report 2>&1 | grep -q "VM-EXIT"; then + echo "Failed to find VM-EXIT in report" + perf kvm -i "${perfdata}" stat report 2>&1 + err=1 + return + fi + + echo "perf kvm stat test [Success]" +} + +test_kvm_record_report() { + echo "Testing perf kvm record/report" + + echo "Recording kvm profile for pid ${qemu_pid}..." + # Use --host to avoid needing guest symbols/mounts for this simple test + # We just want to verify the command runs and produces data + # We run in background and kill it because 'perf kvm record' appends options + # after the command, which breaks 'sleep' (e.g. it gets '-e cycles'). + perf kvm --host record -p "${qemu_pid}" -o "${perfdata}" & + rec_pid=$! + sleep 1 + kill -INT "${rec_pid}" + wait "${rec_pid}" || true + + echo "Reporting kvm profile..." + # Check for some standard output from report + if ! perf kvm -i "${perfdata}" report --stdio 2>&1 | grep -q "Event count"; then + echo "Failed to report kvm profile" + perf kvm -i "${perfdata}" report --stdio 2>&1 + err=1 + return + fi + + echo "perf kvm record/report test [Success]" +} + +test_kvm_buildid_list() { + echo "Testing perf kvm buildid-list" + + # We reuse the perf.data from the previous record test + if ! perf kvm --host -i "${perfdata}" buildid-list 2>&1 | grep -q "."; then + echo "Failed to list buildids" + perf kvm --host -i "${perfdata}" buildid-list 2>&1 + err=1 + return + fi + + echo "perf kvm buildid-list test [Success]" +} + +setup_qemu() { + # Find qemu + if [ "$(uname -m)" = "x86_64" ]; then + qemu="qemu-system-x86_64" + elif [ "$(uname -m)" = "aarch64" ]; then + qemu="qemu-system-aarch64" + elif [ "$(uname -m)" = "s390x" ]; then + qemu="qemu-system-s390x" + elif [ "$(uname -m)" = "ppc64le" ]; then + qemu="qemu-system-ppc64" + else + qemu="qemu-system-$(uname -m)" + fi + + if ! which -s "$qemu"; then + skip "$qemu not found" + fi + + if [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then + skip "/dev/kvm not accessible" + fi + + if ! perf kvm stat record -a sleep 0.01 >/dev/null 2>&1; then + skip "No permission to record kvm events" + fi + + echo "Starting $qemu..." + # Start qemu in background, detached, with pidfile + # We use -display none -daemonize and a monitor to keep it alive/controllable if needed + # We don't need a real kernel, just KVM active. + if ! $qemu -enable-kvm -display none -daemonize -pidfile "${qemu_pid_file}" -monitor none; then + echo "Failed to start qemu" + err=1 + return + fi + + # Wait a bit for qemu to start + sleep 1 + qemu_pid=$(cat "${qemu_pid_file}") + + if ! kill -0 "${qemu_pid}" 2>/dev/null; then + echo "Qemu process failed to stay alive" + err=1 + return + fi +} + +setup_qemu +if [ $err -eq 0 ]; then + test_kvm_stat + test_kvm_record_report + test_kvm_buildid_list +fi + +cleanup +exit $err From 61d1bb53547d42c6bdaec9da4496beb3a1a05264 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Wed, 3 Dec 2025 14:13:47 +0800 Subject: [PATCH 589/684] pinctrl: single: Fix incorrect type for error return variable pcs_pinconf_get() and pcs_pinconf_set() declare ret as unsigned int, but assign it the return values of pcs_get_function() that may return negative error codes. This causes negative error codes to be converted to large positive values. Change ret from unsigned int to int in both functions. Fixes: 9dddb4df90d1 ("pinctrl: single: support generic pinconf") Signed-off-by: Haotian Zhang Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 6d580aa282ec98..998f23d6c3179e 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -485,7 +485,8 @@ static int pcs_pinconf_get(struct pinctrl_dev *pctldev, struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); struct pcs_function *func; enum pin_config_param param; - unsigned offset = 0, data = 0, i, j, ret; + unsigned offset = 0, data = 0, i, j; + int ret; ret = pcs_get_function(pctldev, pin, &func); if (ret) @@ -549,9 +550,9 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev, { struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); struct pcs_function *func; - unsigned offset = 0, shift = 0, i, data, ret; + unsigned offset = 0, shift = 0, i, data; u32 arg; - int j; + int j, ret; enum pin_config_param param; ret = pcs_get_function(pctldev, pin, &func); From 9dc966799ac9a2573d970080334a801fcc283a1b Mon Sep 17 00:00:00 2001 From: Ali Tariq Date: Sun, 26 Oct 2025 11:42:40 +0000 Subject: [PATCH 590/684] pinctrl: starfive: use dynamic GPIO base allocation The JH7110 pinctrl driver currently sets a static GPIO base number from platform data: sfp->gc.base = info->gc_base; Static base assignment is deprecated and results in the following warning: gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation. Set `sfp->gc.base = -1` to let the GPIO core dynamically allocate the base number. This removes the warning and aligns the driver with current GPIO guidelines. Since the GPIO base is now allocated dynamically, remove `gc_base` field in `struct jh7110_pinctrl_soc_info` and the associated `JH7110_SYS_GC_BASE` and `JH7110_AON_GC_BASE` constants as they are no longer used anywhere in the driver. Tested on VisionFive 2 (JH7110 SoC). Signed-off-by: Ali Tariq Reviewed-by: Emil Renner Berthing Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c | 2 -- drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c | 2 -- drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c | 2 +- drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c index cf42e204cbf01b..3433b3c916923c 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c @@ -29,7 +29,6 @@ #include "pinctrl-starfive-jh7110.h" #define JH7110_AON_NGPIO 4 -#define JH7110_AON_GC_BASE 64 #define JH7110_AON_REGS_NUM 37 @@ -138,7 +137,6 @@ static const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = { .pins = jh7110_aon_pins, .npins = ARRAY_SIZE(jh7110_aon_pins), .ngpios = JH7110_AON_NGPIO, - .gc_base = JH7110_AON_GC_BASE, .dout_reg_base = JH7110_AON_DOUT, .dout_mask = GENMASK(3, 0), .doen_reg_base = JH7110_AON_DOEN, diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c index 03c2ad808d61c6..9b67063a0b0b60 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c @@ -29,7 +29,6 @@ #include "pinctrl-starfive-jh7110.h" #define JH7110_SYS_NGPIO 64 -#define JH7110_SYS_GC_BASE 0 #define JH7110_SYS_REGS_NUM 174 @@ -410,7 +409,6 @@ static const struct jh7110_pinctrl_soc_info jh7110_sys_pinctrl_info = { .pins = jh7110_sys_pins, .npins = ARRAY_SIZE(jh7110_sys_pins), .ngpios = JH7110_SYS_NGPIO, - .gc_base = JH7110_SYS_GC_BASE, .dout_reg_base = JH7110_SYS_DOUT, .dout_mask = GENMASK(6, 0), .doen_reg_base = JH7110_SYS_DOEN, diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c index 05e3af75b09f5b..eb5cf8c067d1e4 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c @@ -938,7 +938,7 @@ int jh7110_pinctrl_probe(struct platform_device *pdev) sfp->gc.set = jh7110_gpio_set; sfp->gc.set_config = jh7110_gpio_set_config; sfp->gc.add_pin_ranges = jh7110_gpio_add_pin_ranges; - sfp->gc.base = info->gc_base; + sfp->gc.base = -1; sfp->gc.ngpio = info->ngpios; jh7110_irq_chip.name = sfp->gc.label; diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h index a33d0d4e13820d..2da2d6858008cc 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h @@ -38,7 +38,6 @@ struct jh7110_pinctrl_soc_info { const struct pinctrl_pin_desc *pins; unsigned int npins; unsigned int ngpios; - unsigned int gc_base; /* gpio dout/doen/din/gpioinput register */ unsigned int dout_reg_base; From 28b68b2a3b2fae3789717ca9e306ae8f01269849 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 14 Oct 2025 14:27:01 +0800 Subject: [PATCH 591/684] f2fs: clean up w/ bio_add_folio_nofail() In add_bio_entry(), adding a page to newly allocated bio should never fail, let's use bio_add_folio_nofail() instead of bio_add_page() & unnecessary error handling for cleanup. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 16a71301342747..d8a9f8f8cb5dbf 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -752,7 +752,7 @@ static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, } static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, - struct page *page, enum temp_type temp) + struct folio *folio, enum temp_type temp) { struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; struct bio_entry *be; @@ -761,8 +761,7 @@ static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, be->bio = bio; bio_get(bio); - if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) - f2fs_bug_on(sbi, 1); + bio_add_folio_nofail(bio, folio, folio_size(folio), 0); f2fs_down_write(&io->bio_list_lock); list_add_tail(&be->list, &io->bio_list); @@ -904,7 +903,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) f2fs_set_bio_crypt_ctx(bio, folio->mapping->host, folio->index, fio, GFP_NOIO); - add_bio_entry(fio->sbi, bio, &data_folio->page, fio->temp); + add_bio_entry(fio->sbi, bio, data_folio, fio->temp); } else { if (add_ipu_page(fio, &bio, &data_folio->page)) goto alloc_new; From 3b7e73ddc07f77eeb67474354b44ec7fed8e8b56 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 14 Oct 2025 14:27:02 +0800 Subject: [PATCH 592/684] f2fs: convert add_ipu_page() to use folio No logic changes. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d8a9f8f8cb5dbf..68151617d313be 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -775,7 +775,7 @@ static void del_bio_entry(struct bio_entry *be) } static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, - struct page *page) + struct folio *folio) { struct folio *fio_folio = fio->folio; struct f2fs_sb_info *sbi = fio->sbi; @@ -801,8 +801,7 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, if (f2fs_crypt_mergeable_bio(*bio, fio_folio->mapping->host, fio_folio->index, fio) && - bio_add_page(*bio, page, PAGE_SIZE, 0) == - PAGE_SIZE) { + bio_add_folio(*bio, folio, folio_size(folio), 0)) { ret = 0; break; } @@ -905,7 +904,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) add_bio_entry(fio->sbi, bio, data_folio, fio->temp); } else { - if (add_ipu_page(fio, &bio, &data_folio->page)) + if (add_ipu_page(fio, &bio, data_folio)) goto alloc_new; } From e0b89d00ea9f846da42fc92f200c96254d0e2fef Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 14 Oct 2025 14:27:03 +0800 Subject: [PATCH 593/684] f2fs: use f2fs_filemap_get_folio() instead of f2fs_pagecache_get_page() Let's use f2fs_filemap_get_folio() instead of f2fs_pagecache_get_page() in ra_data_block() and move_data_block(), then remove f2fs_pagecache_get_page() since it has no user. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 10 ---------- fs/f2fs/gc.c | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b6e35fdd5fd3d4..9cc3b83b8d10c4 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2961,16 +2961,6 @@ static inline struct folio *f2fs_filemap_get_folio( return __filemap_get_folio(mapping, index, fgp_flags, gfp_mask); } -static inline struct page *f2fs_pagecache_get_page( - struct address_space *mapping, pgoff_t index, - fgf_t fgp_flags, gfp_t gfp_mask) -{ - if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_GET)) - return NULL; - - return pagecache_get_page(mapping, index, fgp_flags, gfp_mask); -} - static inline void f2fs_folio_put(struct folio *folio, bool unlock) { if (IS_ERR_OR_NULL(folio)) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 8abf521530ff3f..22fe6e2c6d5cda 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1211,7 +1211,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index) struct address_space *mapping = f2fs_is_cow_file(inode) ? F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping; struct dnode_of_data dn; - struct folio *folio; + struct folio *folio, *efolio; struct f2fs_io_info fio = { .sbi = sbi, .ino = inode->i_ino, @@ -1266,14 +1266,15 @@ static int ra_data_block(struct inode *inode, pgoff_t index) f2fs_wait_on_block_writeback(inode, dn.data_blkaddr); - fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(sbi), - dn.data_blkaddr, + efolio = f2fs_filemap_get_folio(META_MAPPING(sbi), dn.data_blkaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS); - if (!fio.encrypted_page) { - err = -ENOMEM; + if (IS_ERR(efolio)) { + err = PTR_ERR(efolio); goto put_folio; } + fio.encrypted_page = &efolio->page; + err = f2fs_submit_page_bio(&fio); if (err) goto put_encrypted_page; @@ -1313,7 +1314,7 @@ static int move_data_block(struct inode *inode, block_t bidx, struct dnode_of_data dn; struct f2fs_summary sum; struct node_info ni; - struct folio *folio, *mfolio; + struct folio *folio, *mfolio, *efolio; block_t newaddr; int err = 0; bool lfs_mode = f2fs_lfs_mode(fio.sbi); @@ -1407,14 +1408,16 @@ static int move_data_block(struct inode *inode, block_t bidx, goto up_out; } - fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi), - newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS); - if (!fio.encrypted_page) { - err = -ENOMEM; + efolio = f2fs_filemap_get_folio(META_MAPPING(fio.sbi), newaddr, + FGP_LOCK | FGP_CREAT, GFP_NOFS); + if (IS_ERR(efolio)) { + err = PTR_ERR(efolio); f2fs_folio_put(mfolio, true); goto recover_block; } + fio.encrypted_page = &efolio->page; + /* write target block */ f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true); memcpy(page_address(fio.encrypted_page), From c1cdb0048832e84549cd24964ba6bdd71d44a4ae Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 14 Oct 2025 14:27:04 +0800 Subject: [PATCH 594/684] f2fs: use f2fs_filemap_get_folio() to support fault injection Use f2fs_filemap_get_folio() instead of __filemap_get_folio() in: - f2fs_find_data_folio - f2fs_write_begin - f2fs_read_merkle_tree_page So that, we can trigger fault injection in those places. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 4 ++-- fs/f2fs/verity.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 68151617d313be..eec691262fece6 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1273,7 +1273,7 @@ struct folio *f2fs_find_data_folio(struct inode *inode, pgoff_t index, struct address_space *mapping = inode->i_mapping; struct folio *folio; - folio = __filemap_get_folio(mapping, index, FGP_ACCESSED, 0); + folio = f2fs_filemap_get_folio(mapping, index, FGP_ACCESSED, 0); if (IS_ERR(folio)) goto read; if (folio_test_uptodate(folio)) @@ -3567,7 +3567,7 @@ static int f2fs_write_begin(const struct kiocb *iocb, * Do not use FGP_STABLE to avoid deadlock. * Will wait that below with our IO control. */ - folio = __filemap_get_folio(mapping, index, + folio = f2fs_filemap_get_folio(mapping, index, FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_NOFS, mapping_gfp_mask(mapping)); if (IS_ERR(folio)) { diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index f0ab9a3c7a82b3..05b935b552164c 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -263,7 +263,7 @@ static struct page *f2fs_read_merkle_tree_page(struct inode *inode, index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT; - folio = __filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0); + folio = f2fs_filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0); if (IS_ERR(folio) || !folio_test_uptodate(folio)) { DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index); From ca8b201f28547e28343a6f00a6e91fa8c09572fe Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 14 Oct 2025 19:47:35 +0800 Subject: [PATCH 595/684] f2fs: fix to avoid potential deadlock As Jiaming Zhang and syzbot reported, there is potential deadlock in f2fs as below: Chain exists of: &sbi->cp_rwsem --> fs_reclaim --> sb_internal#2 Possible unsafe locking scenario: CPU0 CPU1 ---- ---- rlock(sb_internal#2); lock(fs_reclaim); lock(sb_internal#2); rlock(&sbi->cp_rwsem); *** DEADLOCK *** 3 locks held by kswapd0/73: #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat mm/vmscan.c:7015 [inline] #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: kswapd+0x951/0x2800 mm/vmscan.c:7389 #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_trylock_shared fs/super.c:562 [inline] #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_cache_scan+0x91/0x4b0 fs/super.c:197 #2: ffff888011840610 (sb_internal#2){.+.+}-{0:0}, at: f2fs_evict_inode+0x8d9/0x1b60 fs/f2fs/inode.c:890 stack backtrace: CPU: 0 UID: 0 PID: 73 Comm: kswapd0 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_circular_bug+0x2ee/0x310 kernel/locking/lockdep.c:2043 check_noncircular+0x134/0x160 kernel/locking/lockdep.c:2175 check_prev_add kernel/locking/lockdep.c:3165 [inline] check_prevs_add kernel/locking/lockdep.c:3284 [inline] validate_chain+0xb9b/0x2140 kernel/locking/lockdep.c:3908 __lock_acquire+0xab9/0xd20 kernel/locking/lockdep.c:5237 lock_acquire+0x120/0x360 kernel/locking/lockdep.c:5868 down_read+0x46/0x2e0 kernel/locking/rwsem.c:1537 f2fs_down_read fs/f2fs/f2fs.h:2278 [inline] f2fs_lock_op fs/f2fs/f2fs.h:2357 [inline] f2fs_do_truncate_blocks+0x21c/0x10c0 fs/f2fs/file.c:791 f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:867 f2fs_truncate+0x489/0x7c0 fs/f2fs/file.c:925 f2fs_evict_inode+0x9f2/0x1b60 fs/f2fs/inode.c:897 evict+0x504/0x9c0 fs/inode.c:810 f2fs_evict_inode+0x1dc/0x1b60 fs/f2fs/inode.c:853 evict+0x504/0x9c0 fs/inode.c:810 dispose_list fs/inode.c:852 [inline] prune_icache_sb+0x21b/0x2c0 fs/inode.c:1000 super_cache_scan+0x39b/0x4b0 fs/super.c:224 do_shrink_slab+0x6ef/0x1110 mm/shrinker.c:437 shrink_slab_memcg mm/shrinker.c:550 [inline] shrink_slab+0x7ef/0x10d0 mm/shrinker.c:628 shrink_one+0x28a/0x7c0 mm/vmscan.c:4955 shrink_many mm/vmscan.c:5016 [inline] lru_gen_shrink_node mm/vmscan.c:5094 [inline] shrink_node+0x315d/0x3780 mm/vmscan.c:6081 kswapd_shrink_node mm/vmscan.c:6941 [inline] balance_pgdat mm/vmscan.c:7124 [inline] kswapd+0x147c/0x2800 mm/vmscan.c:7389 kthread+0x70e/0x8a0 kernel/kthread.c:463 ret_from_fork+0x4bc/0x870 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 The root cause is deadlock among four locks as below: kswapd - fs_reclaim --- Lock A - shrink_one - evict - f2fs_evict_inode - sb_start_intwrite --- Lock B - iput - evict - f2fs_evict_inode - sb_start_intwrite --- Lock B - f2fs_truncate - f2fs_truncate_blocks - f2fs_do_truncate_blocks - f2fs_lock_op --- Lock C ioctl - f2fs_ioc_commit_atomic_write - f2fs_lock_op --- Lock C - __f2fs_commit_atomic_write - __replace_atomic_write_block - f2fs_get_dnode_of_data - __get_node_folio - f2fs_check_nid_range - f2fs_handle_error - f2fs_record_errors - f2fs_down_write --- Lock D open - do_open - do_truncate - security_inode_need_killpriv - f2fs_getxattr - lookup_all_xattrs - f2fs_handle_error - f2fs_record_errors - f2fs_down_write --- Lock D - f2fs_commit_super - read_mapping_folio - filemap_alloc_folio_noprof - prepare_alloc_pages - fs_reclaim_acquire --- Lock A In order to avoid such deadlock, we need to avoid grabbing sb_lock in f2fs_handle_error(), so, let's use asynchronous method instead: - remove f2fs_handle_error() implementation - rename f2fs_handle_error_async() to f2fs_handle_error() - spread f2fs_handle_error() Fixes: 95fa90c9e5a7 ("f2fs: support recording errors into superblock") Cc: stable@kernel.org Reported-by: syzbot+14b90e1156b9f6fc1266@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-f2fs-devel/68eae49b.050a0220.ac43.0001.GAE@google.com Reported-by: Jiaming Zhang Closes: https://lore.kernel.org/lkml/CANypQFa-Gy9sD-N35o3PC+FystOWkNuN8pv6S75HLT0ga-Tzgw@mail.gmail.com Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 5 +---- fs/f2fs/f2fs.h | 1 - fs/f2fs/super.c | 41 ----------------------------------------- 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 6ad8d3bc6df7a8..811bfe38e5c09a 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -759,10 +759,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task) ret = -EFSCORRUPTED; /* Avoid f2fs_commit_super in irq context */ - if (!in_task) - f2fs_handle_error_async(sbi, ERROR_FAIL_DECOMPRESSION); - else - f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); + f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); goto out_release; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9cc3b83b8d10c4..575f9666c3b752 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3800,7 +3800,6 @@ void f2fs_quota_off_umount(struct super_block *sb); void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason); void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); -void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error); int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); int f2fs_sync_fs(struct super_block *sb, int sync); int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index db7afb8064115c..cb65ca90f9f69c 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4544,48 +4544,7 @@ void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag) spin_unlock_irqrestore(&sbi->error_lock, flags); } -static bool f2fs_update_errors(struct f2fs_sb_info *sbi) -{ - unsigned long flags; - bool need_update = false; - - spin_lock_irqsave(&sbi->error_lock, flags); - if (sbi->error_dirty) { - memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors, - MAX_F2FS_ERRORS); - sbi->error_dirty = false; - need_update = true; - } - spin_unlock_irqrestore(&sbi->error_lock, flags); - - return need_update; -} - -static void f2fs_record_errors(struct f2fs_sb_info *sbi, unsigned char error) -{ - int err; - - f2fs_down_write(&sbi->sb_lock); - - if (!f2fs_update_errors(sbi)) - goto out_unlock; - - err = f2fs_commit_super(sbi, false); - if (err) - f2fs_err_ratelimited(sbi, - "f2fs_commit_super fails to record errors:%u, err:%d", - error, err); -out_unlock: - f2fs_up_write(&sbi->sb_lock); -} - void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error) -{ - f2fs_save_errors(sbi, error); - f2fs_record_errors(sbi, error); -} - -void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error) { f2fs_save_errors(sbi, error); From 7c37c79510329cd951a4dedf3f7bf7e2b18dccec Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 20 Oct 2025 10:42:12 +0800 Subject: [PATCH 596/684] f2fs: fix to avoid updating zero-sized extent in extent cache As syzbot reported: F2FS-fs (loop0): __update_extent_tree_range: extent len is zero, type: 0, extent [0, 0, 0], age [0, 0] ------------[ cut here ]------------ kernel BUG at fs/f2fs/extent_cache.c:678! Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI CPU: 0 UID: 0 PID: 5336 Comm: syz.0.0 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:__update_extent_tree_range+0x13bc/0x1500 fs/f2fs/extent_cache.c:678 Call Trace: f2fs_update_read_extent_cache_range+0x192/0x3e0 fs/f2fs/extent_cache.c:1085 f2fs_do_zero_range fs/f2fs/file.c:1657 [inline] f2fs_zero_range+0x10c1/0x1580 fs/f2fs/file.c:1737 f2fs_fallocate+0x583/0x990 fs/f2fs/file.c:2030 vfs_fallocate+0x669/0x7e0 fs/open.c:342 ioctl_preallocate fs/ioctl.c:289 [inline] file_ioctl+0x611/0x780 fs/ioctl.c:-1 do_vfs_ioctl+0xb33/0x1430 fs/ioctl.c:576 __do_sys_ioctl fs/ioctl.c:595 [inline] __se_sys_ioctl+0x82/0x170 fs/ioctl.c:583 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f07bc58eec9 In error path of f2fs_zero_range(), it may add a zero-sized extent into extent cache, it should be avoided. Fixes: 6e9619499f53 ("f2fs: support in batch fzero in dnode page") Cc: stable@kernel.org Reported-by: syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-f2fs-devel/68e5d698.050a0220.256323.0032.GAE@google.com Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index ffa045b39c01de..c045e38e60ee83 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1654,8 +1654,11 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start, f2fs_set_data_blkaddr(dn, NEW_ADDR); } - f2fs_update_read_extent_cache_range(dn, start, 0, index - start); - f2fs_update_age_extent_cache_range(dn, start, index - start); + if (index > start) { + f2fs_update_read_extent_cache_range(dn, start, 0, + index - start); + f2fs_update_age_extent_cache_range(dn, start, index - start); + } return ret; } From 10b591e7fb7cdc8c1e53e9c000dc0ef7069aaa76 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 22 Oct 2025 11:06:36 +0800 Subject: [PATCH 597/684] f2fs: fix to avoid updating compression context during writeback Bai, Shuangpeng reported a bug as below: Oops: divide error: 0000 [#1] SMP KASAN PTI CPU: 0 UID: 0 PID: 11441 Comm: syz.0.46 Not tainted 6.17.0 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:f2fs_all_cluster_page_ready+0x106/0x550 fs/f2fs/compress.c:857 Call Trace: f2fs_write_cache_pages fs/f2fs/data.c:3078 [inline] __f2fs_write_data_pages fs/f2fs/data.c:3290 [inline] f2fs_write_data_pages+0x1c19/0x3600 fs/f2fs/data.c:3317 do_writepages+0x38e/0x640 mm/page-writeback.c:2634 filemap_fdatawrite_wbc mm/filemap.c:386 [inline] __filemap_fdatawrite_range mm/filemap.c:419 [inline] file_write_and_wait_range+0x2ba/0x3e0 mm/filemap.c:794 f2fs_do_sync_file+0x6e6/0x1b00 fs/f2fs/file.c:294 generic_write_sync include/linux/fs.h:3043 [inline] f2fs_file_write_iter+0x76e/0x2700 fs/f2fs/file.c:5259 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x7e9/0xe00 fs/read_write.c:686 ksys_write+0x19d/0x2d0 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xf7/0x470 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f The bug was triggered w/ below race condition: fsync setattr ioctl - f2fs_do_sync_file - file_write_and_wait_range - f2fs_write_cache_pages : inode is non-compressed : cc.cluster_size = F2FS_I(inode)->i_cluster_size = 0 - tag_pages_for_writeback - f2fs_setattr - truncate_setsize - f2fs_truncate - f2fs_fileattr_set - f2fs_setflags_common - set_compress_context : F2FS_I(inode)->i_cluster_size = 4 : set_inode_flag(inode, FI_COMPRESSED_FILE) - f2fs_compressed_file : return true - f2fs_all_cluster_page_ready : "pgidx % cc->cluster_size" trigger dividing 0 issue Let's change as below to fix this issue: - introduce a new atomic type variable .writeback in structure f2fs_inode_info to track the number of threads which calling f2fs_write_cache_pages(). - use .i_sem lock to protect .writeback update. - check .writeback before update compression context in f2fs_setflags_common() to avoid race w/ ->writepages. Fixes: 4c8ff7095bef ("f2fs: support data compression") Cc: stable@kernel.org Reported-by: Bai, Shuangpeng Tested-by: Bai, Shuangpeng Closes: https://lore.kernel.org/lkml/44D8F7B3-68AD-425F-9915-65D27591F93F@psu.edu Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 17 +++++++++++++++++ fs/f2fs/f2fs.h | 3 ++- fs/f2fs/file.c | 5 +++-- fs/f2fs/super.c | 1 + 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index eec691262fece6..b92d362a02d6a0 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3222,6 +3222,19 @@ static inline bool __should_serialize_io(struct inode *inode, return false; } +static inline void account_writeback(struct inode *inode, bool inc) +{ + if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) + return; + + f2fs_down_read(&F2FS_I(inode)->i_sem); + if (inc) + atomic_inc(&F2FS_I(inode)->writeback); + else + atomic_dec(&F2FS_I(inode)->writeback); + f2fs_up_read(&F2FS_I(inode)->i_sem); +} + static int __f2fs_write_data_pages(struct address_space *mapping, struct writeback_control *wbc, enum iostat_type io_type) @@ -3267,10 +3280,14 @@ static int __f2fs_write_data_pages(struct address_space *mapping, locked = true; } + account_writeback(inode, true); + blk_start_plug(&plug); ret = f2fs_write_cache_pages(mapping, wbc, io_type); blk_finish_plug(&plug); + account_writeback(inode, false); + if (locked) mutex_unlock(&sbi->writepages); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 575f9666c3b752..e69b01c1173ad9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -947,6 +947,7 @@ struct f2fs_inode_info { unsigned char i_compress_level; /* compress level (lz4hc,zstd) */ unsigned char i_compress_flag; /* compress flag */ unsigned int i_cluster_size; /* cluster size */ + atomic_t writeback; /* count # of writeback thread */ unsigned int atomic_write_cnt; loff_t original_i_size; /* original i_size before atomic write */ @@ -4663,7 +4664,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode) f2fs_up_write(&fi->i_sem); return true; } - if (f2fs_is_mmap_file(inode) || + if (f2fs_is_mmap_file(inode) || atomic_read(&fi->writeback) || (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))) { f2fs_up_write(&fi->i_sem); return false; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index c045e38e60ee83..6d42e2d28861ce 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2128,8 +2128,9 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) f2fs_down_write(&fi->i_sem); if (!f2fs_may_compress(inode) || - (S_ISREG(inode->i_mode) && - F2FS_HAS_BLOCKS(inode))) { + atomic_read(&fi->writeback) || + (S_ISREG(inode->i_mode) && + F2FS_HAS_BLOCKS(inode))) { f2fs_up_write(&fi->i_sem); return -EINVAL; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index cb65ca90f9f69c..d0b5791a1f8cba 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1759,6 +1759,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) atomic_set(&fi->dirty_pages, 0); atomic_set(&fi->i_compr_blocks, 0); atomic_set(&fi->open_count, 0); + atomic_set(&fi->writeback, 0); init_f2fs_rwsem(&fi->i_sem); spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); From 1f27ef42bb0b7c0740c5616ec577ec188b8a1d05 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 21 Oct 2025 11:48:56 +0800 Subject: [PATCH 598/684] f2fs: use global inline_xattr_slab instead of per-sb slab cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Hong Yun reported in mailing list: loop7: detected capacity change from 0 to 131072 ------------[ cut here ]------------ kmem_cache of name 'f2fs_xattr_entry-7:7' already exists WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 kmem_cache_sanity_check mm/slab_common.c:109 [inline] WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 __kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 CPU: 0 UID: 0 PID: 24426 Comm: syz.7.1370 Not tainted 6.17.0-rc4 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:kmem_cache_sanity_check mm/slab_common.c:109 [inline] RIP: 0010:__kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 Call Trace:  __kmem_cache_create include/linux/slab.h:353 [inline]  f2fs_kmem_cache_create fs/f2fs/f2fs.h:2943 [inline]  f2fs_init_xattr_caches+0xa5/0xe0 fs/f2fs/xattr.c:843  f2fs_fill_super+0x1645/0x2620 fs/f2fs/super.c:4918  get_tree_bdev_flags+0x1fb/0x260 fs/super.c:1692  vfs_get_tree+0x43/0x140 fs/super.c:1815  do_new_mount+0x201/0x550 fs/namespace.c:3808  do_mount fs/namespace.c:4136 [inline]  __do_sys_mount fs/namespace.c:4347 [inline]  __se_sys_mount+0x298/0x2f0 fs/namespace.c:4324  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]  do_syscall_64+0x8e/0x3a0 arch/x86/entry/syscall_64.c:94  entry_SYSCALL_64_after_hwframe+0x76/0x7e The bug can be reproduced w/ below scripts: - mount /dev/vdb /mnt1 - mount /dev/vdc /mnt2 - umount /mnt1 - mounnt /dev/vdb /mnt1 The reason is if we created two slab caches, named f2fs_xattr_entry-7:3 and f2fs_xattr_entry-7:7, and they have the same slab size. Actually, slab system will only create one slab cache core structure which has slab name of "f2fs_xattr_entry-7:3", and two slab caches share the same structure and cache address. So, if we destroy f2fs_xattr_entry-7:3 cache w/ cache address, it will decrease reference count of slab cache, rather than release slab cache entirely, since there is one more user has referenced the cache. Then, if we try to create slab cache w/ name "f2fs_xattr_entry-7:3" again, slab system will find that there is existed cache which has the same name and trigger the warning. Let's changes to use global inline_xattr_slab instead of per-sb slab cache for fixing. Fixes: a999150f4fe3 ("f2fs: use kmem_cache pool during inline xattr lookups") Cc: stable@kernel.org Reported-by: Hong Yun Tested-by: Hong Yun Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 3 --- fs/f2fs/super.c | 17 ++++++++--------- fs/f2fs/xattr.c | 32 +++++++++++--------------------- fs/f2fs/xattr.h | 10 ++++++---- 4 files changed, 25 insertions(+), 37 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e69b01c1173ad9..9ca2124aac84d0 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1885,9 +1885,6 @@ struct f2fs_sb_info { spinlock_t error_lock; /* protect errors/stop_reason array */ bool error_dirty; /* errors of sb is dirty */ - struct kmem_cache *inline_xattr_slab; /* inline xattr entry */ - unsigned int inline_xattr_slab_size; /* default inline xattr slab size */ - /* For reclaimed segs statistics per each GC mode */ unsigned int gc_segment_mode; /* GC state for reclaimed segments */ unsigned int gc_reclaimed_segs[MAX_GC_MODE]; /* Reclaimed segs for each mode */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index d0b5791a1f8cba..f76ba2b08be02d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2027,7 +2027,6 @@ static void f2fs_put_super(struct super_block *sb) kfree(sbi->raw_super); f2fs_destroy_page_array_cache(sbi); - f2fs_destroy_xattr_caches(sbi); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) kfree(F2FS_OPTION(sbi).s_qf_names[i]); @@ -4975,13 +4974,9 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) if (err) goto free_iostat; - /* init per sbi slab cache */ - err = f2fs_init_xattr_caches(sbi); - if (err) - goto free_percpu; err = f2fs_init_page_array_cache(sbi); if (err) - goto free_xattr_cache; + goto free_percpu; /* get an inode for meta space */ sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); @@ -5310,8 +5305,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) sbi->meta_inode = NULL; free_page_array_cache: f2fs_destroy_page_array_cache(sbi); -free_xattr_cache: - f2fs_destroy_xattr_caches(sbi); free_percpu: destroy_percpu_info(sbi); free_iostat: @@ -5514,10 +5507,15 @@ static int __init init_f2fs_fs(void) err = f2fs_create_casefold_cache(); if (err) goto free_compress_cache; - err = register_filesystem(&f2fs_fs_type); + err = f2fs_init_xattr_cache(); if (err) goto free_casefold_cache; + err = register_filesystem(&f2fs_fs_type); + if (err) + goto free_xattr_cache; return 0; +free_xattr_cache: + f2fs_destroy_xattr_cache(); free_casefold_cache: f2fs_destroy_casefold_cache(); free_compress_cache: @@ -5558,6 +5556,7 @@ static int __init init_f2fs_fs(void) static void __exit exit_f2fs_fs(void) { unregister_filesystem(&f2fs_fs_type); + f2fs_destroy_xattr_cache(); f2fs_destroy_casefold_cache(); f2fs_destroy_compress_cache(); f2fs_destroy_compress_mempool(); diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 58632a2b66136c..b4e5c406632f81 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -23,11 +23,12 @@ #include "xattr.h" #include "segment.h" +static struct kmem_cache *inline_xattr_slab; static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline) { - if (likely(size == sbi->inline_xattr_slab_size)) { + if (likely(size == DEFAULT_XATTR_SLAB_SIZE)) { *is_inline = true; - return f2fs_kmem_cache_alloc(sbi->inline_xattr_slab, + return f2fs_kmem_cache_alloc(inline_xattr_slab, GFP_F2FS_ZERO, false, sbi); } *is_inline = false; @@ -38,7 +39,7 @@ static void xattr_free(struct f2fs_sb_info *sbi, void *xattr_addr, bool is_inline) { if (is_inline) - kmem_cache_free(sbi->inline_xattr_slab, xattr_addr); + kmem_cache_free(inline_xattr_slab, xattr_addr); else kfree(xattr_addr); } @@ -830,25 +831,14 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, return err; } -int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) +int __init f2fs_init_xattr_cache(void) { - dev_t dev = sbi->sb->s_bdev->bd_dev; - char slab_name[32]; - - sprintf(slab_name, "f2fs_xattr_entry-%u:%u", MAJOR(dev), MINOR(dev)); - - sbi->inline_xattr_slab_size = F2FS_OPTION(sbi).inline_xattr_size * - sizeof(__le32) + XATTR_PADDING_SIZE; - - sbi->inline_xattr_slab = f2fs_kmem_cache_create(slab_name, - sbi->inline_xattr_slab_size); - if (!sbi->inline_xattr_slab) - return -ENOMEM; - - return 0; + inline_xattr_slab = f2fs_kmem_cache_create("f2fs_xattr_entry", + DEFAULT_XATTR_SLAB_SIZE); + return inline_xattr_slab ? 0 : -ENOMEM; } -void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) +void f2fs_destroy_xattr_cache(void) { - kmem_cache_destroy(sbi->inline_xattr_slab); -} + kmem_cache_destroy(inline_xattr_slab); +} \ No newline at end of file diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 4fc0b2305fbd80..bce3d93e4755b5 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -89,6 +89,8 @@ struct f2fs_xattr_entry { F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \ DEF_INLINE_RESERVED_SIZE - \ MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) +#define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \ + sizeof(__le32) + XATTR_PADDING_SIZE) /* * On-disk structure of f2fs_xattr @@ -132,8 +134,8 @@ int f2fs_setxattr(struct inode *, int, const char *, const void *, int f2fs_getxattr(struct inode *, int, const char *, void *, size_t, struct folio *); ssize_t f2fs_listxattr(struct dentry *, char *, size_t); -int f2fs_init_xattr_caches(struct f2fs_sb_info *); -void f2fs_destroy_xattr_caches(struct f2fs_sb_info *); +int __init f2fs_init_xattr_cache(void); +void f2fs_destroy_xattr_cache(void); #else #define f2fs_xattr_handlers NULL @@ -150,8 +152,8 @@ static inline int f2fs_getxattr(struct inode *inode, int index, { return -EOPNOTSUPP; } -static inline int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) { return 0; } -static inline void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { } +static inline int __init f2fs_init_xattr_cache(void) { return 0; } +static inline void f2fs_destroy_xattr_cache(void) { } #endif #ifdef CONFIG_F2FS_FS_SECURITY From d33f89b34aa313f50f9a512d58dd288999f246b0 Mon Sep 17 00:00:00 2001 From: Deepanshu Kartikey Date: Mon, 27 Oct 2025 18:36:34 +0530 Subject: [PATCH 599/684] f2fs: invalidate dentry cache on failed whiteout creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit F2FS can mount filesystems with corrupted directory depth values that get runtime-clamped to MAX_DIR_HASH_DEPTH. When RENAME_WHITEOUT operations are performed on such directories, f2fs_rename performs directory modifications (updating target entry and deleting source entry) before attempting to add the whiteout entry via f2fs_add_link. If f2fs_add_link fails due to the corrupted directory structure, the function returns an error to VFS, but the partial directory modifications have already been committed to disk. VFS assumes the entire rename operation failed and does not update the dentry cache, leaving stale mappings. In the error path, VFS does not call d_move() to update the dentry cache. This results in new_dentry still pointing to the old inode (new_inode) which has already had its i_nlink decremented to zero. The stale cache causes subsequent operations to incorrectly reference the freed inode. This causes subsequent operations to use cached dentry information that no longer matches the on-disk state. When a second rename targets the same entry, VFS attempts to decrement i_nlink on the stale inode, which may already have i_nlink=0, triggering a WARNING in drop_nlink(). Example sequence: 1. First rename (RENAME_WHITEOUT): file2 → file1 - f2fs updates file1 entry on disk (points to inode 8) - f2fs deletes file2 entry on disk - f2fs_add_link(whiteout) fails (corrupted directory) - Returns error to VFS - VFS does not call d_move() due to error - VFS cache still has: file1 → inode 7 (stale!) - inode 7 has i_nlink=0 (already decremented) 2. Second rename: file3 → file1 - VFS uses stale cache: file1 → inode 7 - Tries to drop_nlink on inode 7 (i_nlink already 0) - WARNING in drop_nlink() Fix this by explicitly invalidating old_dentry and new_dentry when f2fs_add_link fails during whiteout creation. This forces VFS to refresh from disk on subsequent operations, ensuring cache consistency even when the rename partially succeeds. Reproducer: 1. Mount F2FS image with corrupted i_current_depth 2. renameat2(file2, file1, RENAME_WHITEOUT) 3. renameat2(file3, file1, 0) 4. System triggers WARNING in drop_nlink() Fixes: 7e01e7ad746b ("f2fs: support RENAME_WHITEOUT") Reported-by: syzbot+632cf32276a9a564188d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=632cf32276a9a564188d Suggested-by: Chao Yu Link: https://lore.kernel.org/all/20251022233349.102728-1-kartikey406@gmail.com/ [v1] Cc: stable@vger.kernel.org Signed-off-by: Deepanshu Kartikey Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/namei.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index b882771e469971..712479b7b93d78 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -1053,9 +1053,11 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir, if (whiteout) { set_inode_flag(whiteout, FI_INC_LINK); err = f2fs_add_link(old_dentry, whiteout); - if (err) + if (err) { + d_invalidate(old_dentry); + d_invalidate(new_dentry); goto put_out_dir; - + } spin_lock(&whiteout->i_lock); whiteout->i_state &= ~I_LINKABLE; spin_unlock(&whiteout->i_lock); From 89c16629e3136f0972dfa270d9318f07fa1c4053 Mon Sep 17 00:00:00 2001 From: Yongpeng Yang Date: Mon, 27 Oct 2025 20:55:43 +0800 Subject: [PATCH 600/684] f2fs: change the unlock parameter of f2fs_put_page to bool Change the type of the unlock parameter of f2fs_put_page to bool. All callers should consistently pass true or false. No logical change. Signed-off-by: Yongpeng Yang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 8 ++++---- fs/f2fs/data.c | 6 ++---- fs/f2fs/f2fs.h | 2 +- fs/f2fs/gc.c | 6 +++--- fs/f2fs/inline.c | 4 ++-- fs/f2fs/namei.c | 4 ++-- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 811bfe38e5c09a..716004ba44dc1e 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -120,7 +120,7 @@ static void f2fs_unlock_rpages(struct compress_ctx *cc, int len) } static void f2fs_put_rpages_wbc(struct compress_ctx *cc, - struct writeback_control *wbc, bool redirty, int unlock) + struct writeback_control *wbc, bool redirty, bool unlock) { unsigned int i; @@ -1202,7 +1202,7 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata, if (copied) set_cluster_dirty(&cc); - f2fs_put_rpages_wbc(&cc, NULL, false, 1); + f2fs_put_rpages_wbc(&cc, NULL, false, true); f2fs_destroy_compress_ctx(&cc, false); return first_index; @@ -1605,7 +1605,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, add_compr_block_stat(cc->inode, cc->cluster_size); goto write; } else if (err) { - f2fs_put_rpages_wbc(cc, wbc, true, 1); + f2fs_put_rpages_wbc(cc, wbc, true, true); goto destroy_out; } @@ -1619,7 +1619,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, f2fs_bug_on(F2FS_I_SB(cc->inode), *submitted); err = f2fs_write_raw_pages(cc, submitted, wbc, io_type); - f2fs_put_rpages_wbc(cc, wbc, false, 0); + f2fs_put_rpages_wbc(cc, wbc, false, false); destroy_out: f2fs_destroy_compress_ctx(cc, false); return err; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b92d362a02d6a0..ee519de1aa1a42 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3656,8 +3656,7 @@ static int f2fs_write_begin(const struct kiocb *iocb, return 0; put_folio: - folio_unlock(folio); - folio_put(folio); + f2fs_folio_put(folio, true); fail: f2fs_write_failed(inode, pos + len); return err; @@ -3713,8 +3712,7 @@ static int f2fs_write_end(const struct kiocb *iocb, pos + copied); } unlock_out: - folio_unlock(folio); - folio_put(folio); + f2fs_folio_put(folio, true); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); return copied; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9ca2124aac84d0..d4f5648477de6a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2971,7 +2971,7 @@ static inline void f2fs_folio_put(struct folio *folio, bool unlock) folio_put(folio); } -static inline void f2fs_put_page(struct page *page, int unlock) +static inline void f2fs_put_page(struct page *page, bool unlock) { if (!page) return; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 22fe6e2c6d5cda..fd8bb0424bf380 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1278,7 +1278,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index) err = f2fs_submit_page_bio(&fio); if (err) goto put_encrypted_page; - f2fs_put_page(fio.encrypted_page, 0); + f2fs_put_page(fio.encrypted_page, false); f2fs_folio_put(folio, true); f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE); @@ -1286,7 +1286,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index) return 0; put_encrypted_page: - f2fs_put_page(fio.encrypted_page, 1); + f2fs_put_page(fio.encrypted_page, true); put_folio: f2fs_folio_put(folio, true); return err; @@ -1442,7 +1442,7 @@ static int move_data_block(struct inode *inode, block_t bidx, f2fs_update_data_blkaddr(&dn, newaddr); set_inode_flag(inode, FI_APPEND_WRITE); - f2fs_put_page(fio.encrypted_page, 1); + f2fs_put_page(fio.encrypted_page, true); recover_block: if (err) f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr, diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 58ac831ef704ea..e5c6a08b7e4f3f 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -287,7 +287,7 @@ int f2fs_write_inline_data(struct inode *inode, struct folio *folio) set_inode_flag(inode, FI_DATA_EXIST); folio_clear_f2fs_inline(ifolio); - f2fs_folio_put(ifolio, 1); + f2fs_folio_put(ifolio, true); return 0; } @@ -577,7 +577,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct folio *ifolio, f2fs_i_depth_write(dir, 0); f2fs_i_size_write(dir, MAX_INLINE_DATA(dir)); folio_mark_dirty(ifolio); - f2fs_folio_put(ifolio, 1); + f2fs_folio_put(ifolio, true); kfree(backup_dentry); return err; diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 712479b7b93d78..85e2d13841dab0 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -1249,11 +1249,11 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, return 0; out_new_dir: if (new_dir_entry) { - f2fs_folio_put(new_dir_folio, 0); + f2fs_folio_put(new_dir_folio, false); } out_old_dir: if (old_dir_entry) { - f2fs_folio_put(old_dir_folio, 0); + f2fs_folio_put(old_dir_folio, false); } out_new: f2fs_folio_put(new_folio, false); From be112e7449a6e1b54aa9feac618825d154b3a5c7 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 27 Oct 2025 14:35:33 +0800 Subject: [PATCH 601/684] f2fs: fix to propagate error from f2fs_enable_checkpoint() In order to let userspace detect such error rather than suffering silent failure. Fixes: 4354994f097d ("f2fs: checkpoint disabling") Cc: stable@kernel.org Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index f76ba2b08be02d..60382c9b5293d0 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2632,10 +2632,11 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) return err; } -static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) +static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) { unsigned int nr_pages = get_pages(sbi, F2FS_DIRTY_DATA) / 16; long long start, writeback, end; + int ret; f2fs_info(sbi, "f2fs_enable_checkpoint() starts, meta: %lld, node: %lld, data: %lld", get_pages(sbi, F2FS_DIRTY_META), @@ -2669,7 +2670,9 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) set_sbi_flag(sbi, SBI_IS_DIRTY); f2fs_up_write(&sbi->gc_lock); - f2fs_sync_fs(sbi->sb, 1); + ret = f2fs_sync_fs(sbi->sb, 1); + if (ret) + f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret); /* Let's ensure there's no pending checkpoint anymore */ f2fs_flush_ckpt_thread(sbi); @@ -2679,6 +2682,7 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) f2fs_info(sbi, "f2fs_enable_checkpoint() finishes, writeback:%llu, sync:%llu", ktime_ms_delta(writeback, start), ktime_ms_delta(end, writeback)); + return ret; } static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) @@ -2892,7 +2896,9 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) goto restore_discard; need_enable_checkpoint = true; } else { - f2fs_enable_checkpoint(sbi); + err = f2fs_enable_checkpoint(sbi); + if (err) + goto restore_discard; need_disable_checkpoint = true; } } @@ -2935,7 +2941,8 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) return 0; restore_checkpoint: if (need_enable_checkpoint) { - f2fs_enable_checkpoint(sbi); + if (f2fs_enable_checkpoint(sbi)) + f2fs_warn(sbi, "checkpoint has not been enabled"); } else if (need_disable_checkpoint) { if (f2fs_disable_checkpoint(sbi)) f2fs_warn(sbi, "checkpoint has not been disabled"); @@ -5212,13 +5219,12 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) if (err) goto sync_free_meta; - if (test_opt(sbi, DISABLE_CHECKPOINT)) { + if (test_opt(sbi, DISABLE_CHECKPOINT)) err = f2fs_disable_checkpoint(sbi); - if (err) - goto sync_free_meta; - } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) { - f2fs_enable_checkpoint(sbi); - } + else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) + err = f2fs_enable_checkpoint(sbi); + if (err) + goto sync_free_meta; /* * If filesystem is not mounted as read-only then From 196c81fdd438f7ac429d5639090a9816abb9760a Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 27 Oct 2025 14:35:34 +0800 Subject: [PATCH 602/684] f2fs: block cache/dio write during f2fs_enable_checkpoint() If there are too many background IOs during f2fs_enable_checkpoint(), sync_inodes_sb() may be blocked for long time due to it will loop to write dirty datas which are generated by in parallel write() continuously. Let's change as below to resolve this issue: - hold cp_enable_rwsem write lock to block any cache/dio write - decrease DEF_ENABLE_INTERVAL from 16 to 5 In addition, dump more logs during f2fs_enable_checkpoint(). Testcase: 1. fill data into filesystem until 90% usage. 2. mount -o remount,checkpoint=disable:10% /data 3. fio --rw=randwrite --bs=4kb --size=1GB --numjobs=10 \ --iodepth=64 --ioengine=psync --time_based --runtime=600 \ --directory=/data/fio_dir/ & 4. mount -o remount,checkpoint=enable /data Before: F2FS-fs (dm-51): f2fs_enable_checkpoint() finishes, writeback:7232, sync:39793, cp:457 After: F2FS-fs (dm-51): f2fs_enable_checkpoint end, writeback:5032, lock:0, sync_inode:5552, sync_fs:84 Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 2 ++ fs/f2fs/f2fs.h | 3 ++- fs/f2fs/super.c | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index ee519de1aa1a42..7be0837a945661 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1418,6 +1418,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) static void f2fs_map_lock(struct f2fs_sb_info *sbi, int flag) { + f2fs_down_read(&sbi->cp_enable_rwsem); if (flag == F2FS_GET_BLOCK_PRE_AIO) f2fs_down_read(&sbi->node_change); else @@ -1430,6 +1431,7 @@ static void f2fs_map_unlock(struct f2fs_sb_info *sbi, int flag) f2fs_up_read(&sbi->node_change); else f2fs_unlock_op(sbi); + f2fs_up_read(&sbi->cp_enable_rwsem); } int f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d4f5648477de6a..0e2c5e86a6a16b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -281,7 +281,7 @@ enum { #define DEF_CP_INTERVAL 60 /* 60 secs */ #define DEF_IDLE_INTERVAL 5 /* 5 secs */ #define DEF_DISABLE_INTERVAL 5 /* 5 secs */ -#define DEF_ENABLE_INTERVAL 16 /* 16 secs */ +#define DEF_ENABLE_INTERVAL 5 /* 5 secs */ #define DEF_DISABLE_QUICK_INTERVAL 1 /* 1 secs */ #define DEF_UMOUNT_DISCARD_TIMEOUT 5 /* 5 secs */ @@ -1695,6 +1695,7 @@ struct f2fs_sb_info { long interval_time[MAX_TIME]; /* to store thresholds */ struct ckpt_req_control cprc_info; /* for checkpoint request control */ struct cp_stats cp_stats; /* for time stat of checkpoint */ + struct f2fs_rwsem cp_enable_rwsem; /* block cache/dio write */ struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 60382c9b5293d0..bdb5ddb4f9662e 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2635,10 +2635,11 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) { unsigned int nr_pages = get_pages(sbi, F2FS_DIRTY_DATA) / 16; - long long start, writeback, end; + long long start, writeback, lock, sync_inode, end; int ret; - f2fs_info(sbi, "f2fs_enable_checkpoint() starts, meta: %lld, node: %lld, data: %lld", + f2fs_info(sbi, "%s start, meta: %lld, node: %lld, data: %lld", + __func__, get_pages(sbi, F2FS_DIRTY_META), get_pages(sbi, F2FS_DIRTY_NODES), get_pages(sbi, F2FS_DIRTY_DATA)); @@ -2657,11 +2658,18 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) } writeback = ktime_get(); - sync_inodes_sb(sbi->sb); + f2fs_down_write(&sbi->cp_enable_rwsem); + + lock = ktime_get(); + + if (get_pages(sbi, F2FS_DIRTY_DATA)) + sync_inodes_sb(sbi->sb); if (unlikely(get_pages(sbi, F2FS_DIRTY_DATA))) - f2fs_warn(sbi, "checkpoint=enable has some unwritten data: %lld", - get_pages(sbi, F2FS_DIRTY_DATA)); + f2fs_warn(sbi, "%s: has some unwritten data: %lld", + __func__, get_pages(sbi, F2FS_DIRTY_DATA)); + + sync_inode = ktime_get(); f2fs_down_write(&sbi->gc_lock); f2fs_dirty_to_prefree(sbi); @@ -2670,6 +2678,13 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) set_sbi_flag(sbi, SBI_IS_DIRTY); f2fs_up_write(&sbi->gc_lock); + f2fs_info(sbi, "%s sync_fs, meta: %lld, imeta: %lld, node: %lld, dents: %lld, qdata: %lld", + __func__, + get_pages(sbi, F2FS_DIRTY_META), + get_pages(sbi, F2FS_DIRTY_IMETA), + get_pages(sbi, F2FS_DIRTY_NODES), + get_pages(sbi, F2FS_DIRTY_DENTS), + get_pages(sbi, F2FS_DIRTY_QDATA)); ret = f2fs_sync_fs(sbi->sb, 1); if (ret) f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret); @@ -2677,11 +2692,17 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) /* Let's ensure there's no pending checkpoint anymore */ f2fs_flush_ckpt_thread(sbi); + f2fs_up_write(&sbi->cp_enable_rwsem); + end = ktime_get(); - f2fs_info(sbi, "f2fs_enable_checkpoint() finishes, writeback:%llu, sync:%llu", - ktime_ms_delta(writeback, start), - ktime_ms_delta(end, writeback)); + f2fs_info(sbi, "%s end, writeback:%llu, " + "lock:%llu, sync_inode:%llu, sync_fs:%llu", + __func__, + ktime_ms_delta(writeback, start), + ktime_ms_delta(lock, writeback), + ktime_ms_delta(sync_inode, lock), + ktime_ms_delta(end, sync_inode)); return ret; } @@ -4870,6 +4891,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) init_f2fs_rwsem(&sbi->node_change); spin_lock_init(&sbi->stat_lock); init_f2fs_rwsem(&sbi->cp_rwsem); + init_f2fs_rwsem(&sbi->cp_enable_rwsem); init_f2fs_rwsem(&sbi->quota_sem); init_waitqueue_head(&sbi->cp_wait); spin_lock_init(&sbi->error_lock); From 297baa4aa263ff8f5b3d246ee16a660d76aa82c4 Mon Sep 17 00:00:00 2001 From: Jan Prusakowski Date: Mon, 6 Oct 2025 10:46:15 +0200 Subject: [PATCH 603/684] f2fs: ensure node page reads complete before f2fs_put_super() finishes Xfstests generic/335, generic/336 sometimes crash with the following message: F2FS-fs (dm-0): detect filesystem reference count leak during umount, type: 9, count: 1 ------------[ cut here ]------------ kernel BUG at fs/f2fs/super.c:1939! Oops: invalid opcode: 0000 [#1] SMP NOPTI CPU: 1 UID: 0 PID: 609351 Comm: umount Tainted: G W 6.17.0-rc5-xfstests-g9dd1835ecda5 #1 PREEMPT(none) Tainted: [W]=WARN Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:f2fs_put_super+0x3b3/0x3c0 Call Trace: generic_shutdown_super+0x7e/0x190 kill_block_super+0x1a/0x40 kill_f2fs_super+0x9d/0x190 deactivate_locked_super+0x30/0xb0 cleanup_mnt+0xba/0x150 task_work_run+0x5c/0xa0 exit_to_user_mode_loop+0xb7/0xc0 do_syscall_64+0x1ae/0x1c0 entry_SYSCALL_64_after_hwframe+0x76/0x7e ---[ end trace 0000000000000000 ]--- It appears that sometimes it is possible that f2fs_put_super() is called before all node page reads are completed. Adding a call to f2fs_wait_on_all_pages() for F2FS_RD_NODE fixes the problem. Cc: stable@kernel.org Fixes: 20872584b8c0b ("f2fs: fix to drop all dirty meta/node pages during umount()") Signed-off-by: Jan Prusakowski Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index bdb5ddb4f9662e..0b0ef8ba243b33 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1989,14 +1989,6 @@ static void f2fs_put_super(struct super_block *sb) truncate_inode_pages_final(META_MAPPING(sbi)); } - for (i = 0; i < NR_COUNT_TYPE; i++) { - if (!get_pages(sbi, i)) - continue; - f2fs_err(sbi, "detect filesystem reference count leak during " - "umount, type: %d, count: %lld", i, get_pages(sbi, i)); - f2fs_bug_on(sbi, 1); - } - f2fs_bug_on(sbi, sbi->fsync_node_num); f2fs_destroy_compress_inode(sbi); @@ -2007,6 +1999,15 @@ static void f2fs_put_super(struct super_block *sb) iput(sbi->meta_inode); sbi->meta_inode = NULL; + /* Should check the page counts after dropping all node/meta pages */ + for (i = 0; i < NR_COUNT_TYPE; i++) { + if (!get_pages(sbi, i)) + continue; + f2fs_err(sbi, "detect filesystem reference count leak during " + "umount, type: %d, count: %lld", i, get_pages(sbi, i)); + f2fs_bug_on(sbi, 1); + } + /* * iput() can update stat information, if f2fs_write_checkpoint() * above failed with error. From 5b5578c3b06eba4c256bc3a2788f5a65cd9f31ea Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 29 Oct 2025 14:31:04 +0800 Subject: [PATCH 604/684] f2fs: fix to access i_size w/ i_size_read() It recommends to use i_size_{read,write}() to access and update i_size, otherwise, we may get wrong tearing value due to high 32-bits value and low 32-bits value of i_size field are not updated atomically in 32-bits archicture machine. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- include/trace/events/f2fs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index edbbd869078f06..e1fae78d64a585 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -204,7 +204,7 @@ DECLARE_EVENT_CLASS(f2fs__inode, __entry->pino = F2FS_I(inode)->i_pino; __entry->mode = inode->i_mode; __entry->nlink = inode->i_nlink; - __entry->size = inode->i_size; + __entry->size = i_size_read(inode); __entry->blocks = inode->i_blocks; __entry->advise = F2FS_I(inode)->i_advise; ), @@ -353,7 +353,7 @@ TRACE_EVENT(f2fs_unlink_enter, TP_fast_assign( __entry->dev = dir->i_sb->s_dev; __entry->ino = dir->i_ino; - __entry->size = dir->i_size; + __entry->size = i_size_read(dir); __entry->blocks = dir->i_blocks; __assign_str(name); ), @@ -433,7 +433,7 @@ DECLARE_EVENT_CLASS(f2fs__truncate_op, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; __entry->ino = inode->i_ino; - __entry->size = inode->i_size; + __entry->size = i_size_read(inode); __entry->blocks = inode->i_blocks; __entry->from = from; ), @@ -1006,7 +1006,7 @@ TRACE_EVENT(f2fs_fallocate, __entry->mode = mode; __entry->offset = offset; __entry->len = len; - __entry->size = inode->i_size; + __entry->size = i_size_read(inode); __entry->blocks = inode->i_blocks; __entry->ret = ret; ), From 392711ef18bff524a873b9c239a73148c5432262 Mon Sep 17 00:00:00 2001 From: Xiaole He Date: Wed, 29 Oct 2025 13:18:07 +0800 Subject: [PATCH 605/684] f2fs: fix uninitialized one_time_gc in victim_sel_policy The one_time_gc field in struct victim_sel_policy is conditionally initialized but unconditionally read, leading to undefined behavior that triggers UBSAN warnings. In f2fs_get_victim() at fs/f2fs/gc.c:774, the victim_sel_policy structure is declared without initialization: struct victim_sel_policy p; The field p.one_time_gc is only assigned when the 'one_time' parameter is true (line 789): if (one_time) { p.one_time_gc = one_time; ... } However, this field is unconditionally read in subsequent get_gc_cost() at line 395: if (p->one_time_gc && (valid_thresh_ratio < 100) && ...) When one_time is false, p.one_time_gc contains uninitialized stack memory. Hence p.one_time_gc is an invalid bool value. UBSAN detects this invalid bool value: UBSAN: invalid-load in fs/f2fs/gc.c:395:7 load of value 77 is not a valid value for type '_Bool' CPU: 3 UID: 0 PID: 1297 Comm: f2fs_gc-252:16 Not tainted 6.18.0-rc3 #5 PREEMPT(voluntary) Hardware name: OpenStack Foundation OpenStack Nova, BIOS 1.13.0-1ubuntu1.1 04/01/2014 Call Trace: dump_stack_lvl+0x70/0x90 dump_stack+0x14/0x20 __ubsan_handle_load_invalid_value+0xb3/0xf0 ? dl_server_update+0x2e/0x40 ? update_curr+0x147/0x170 f2fs_get_victim.cold+0x66/0x134 [f2fs] ? sched_balance_newidle+0x2ca/0x470 ? finish_task_switch.isra.0+0x8d/0x2a0 f2fs_gc+0x2ba/0x8e0 [f2fs] ? _raw_spin_unlock_irqrestore+0x12/0x40 ? __timer_delete_sync+0x80/0xe0 ? timer_delete_sync+0x14/0x20 ? schedule_timeout+0x82/0x100 gc_thread_func+0x38b/0x860 [f2fs] ? gc_thread_func+0x38b/0x860 [f2fs] ? __pfx_autoremove_wake_function+0x10/0x10 kthread+0x10b/0x220 ? __pfx_gc_thread_func+0x10/0x10 [f2fs] ? _raw_spin_unlock_irq+0x12/0x40 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x11a/0x160 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 This issue is reliably reproducible with the following steps on a 100GB SSD /dev/vdb: mkfs.f2fs -f /dev/vdb mount /dev/vdb /mnt/f2fs_test fio --name=gc --directory=/mnt/f2fs_test --rw=randwrite \ --bs=4k --size=8G --numjobs=12 --fsync=4 --runtime=10 \ --time_based echo 1 > /sys/fs/f2fs/vdb/gc_urgent The uninitialized value causes incorrect GC victim selection, leading to unpredictable garbage collection behavior. Fix by zero-initializing the entire victim_sel_policy structure to ensure all fields have defined values. Fixes: e791d00bd06c ("f2fs: add valid block ratio not to do excessive GC for one time GC") Cc: stable@kernel.org Signed-off-by: Xiaole He Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index fd8bb0424bf380..e04aafee1f2c87 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -774,7 +774,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct sit_info *sm = SIT_I(sbi); - struct victim_sel_policy p; + struct victim_sel_policy p = {0}; unsigned int secno, last_victim; unsigned int last_segment; unsigned int nsearched; From d8bdf7856e17b31263bcd37d60903ee36bd2f857 Mon Sep 17 00:00:00 2001 From: Yongpeng Yang Date: Fri, 24 Oct 2025 22:37:46 +0800 Subject: [PATCH 606/684] f2fs: ensure minimum trim granularity accounts for all devices When F2FS uses multiple block devices, each device may have a different discard granularity. The minimum trim granularity must be at least the maximum discard granularity of all devices, excluding zoned devices. Use max_t instead of the max() macro to compute the maximum value. Signed-off-by: Yongpeng Yang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 12 ++++++++++++ fs/f2fs/file.c | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 0e2c5e86a6a16b..c85384e8cf4208 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4752,6 +4752,18 @@ static inline bool f2fs_hw_support_discard(struct f2fs_sb_info *sbi) return false; } +static inline unsigned int f2fs_hw_discard_granularity(struct f2fs_sb_info *sbi) +{ + int i = 1; + unsigned int discard_granularity = bdev_discard_granularity(sbi->sb->s_bdev); + + if (f2fs_is_multi_device(sbi)) + for (; i < sbi->s_ndevs && !bdev_is_zoned(FDEV(i).bdev); i++) + discard_granularity = max_t(unsigned int, discard_granularity, + bdev_discard_granularity(FDEV(i).bdev)); + return discard_granularity; +} + static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi) { return (test_opt(sbi, DISCARD) && f2fs_hw_support_discard(sbi)) || diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 6d42e2d28861ce..7b966f6d40d23f 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2588,14 +2588,14 @@ static int f2fs_keep_noreuse_range(struct inode *inode, static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); - struct super_block *sb = inode->i_sb; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct fstrim_range range; int ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!f2fs_hw_support_discard(F2FS_SB(sb))) + if (!f2fs_hw_support_discard(sbi)) return -EOPNOTSUPP; if (copy_from_user(&range, (struct fstrim_range __user *)arg, @@ -2606,9 +2606,9 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) if (ret) return ret; - range.minlen = max((unsigned int)range.minlen, - bdev_discard_granularity(sb->s_bdev)); - ret = f2fs_trim_fs(F2FS_SB(sb), &range); + range.minlen = max_t(unsigned int, range.minlen, + f2fs_hw_discard_granularity(sbi)); + ret = f2fs_trim_fs(sbi, &range); mnt_drop_write_file(filp); if (ret < 0) return ret; @@ -2616,7 +2616,7 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range))) return -EFAULT; - f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); + f2fs_update_time(sbi, REQ_TIME); return 0; } From 9b3c8336c633ca11778a1ff42b7c37b0563e6430 Mon Sep 17 00:00:00 2001 From: "Nikola Z. Ivanov" Date: Wed, 5 Nov 2025 13:09:42 +0200 Subject: [PATCH 607/684] f2fs: Rename f2fs_unlink exit label Rename "fail" label to "out" as it's used as a default exit path out of f2fs_unlink as well as error path. Signed-off-by: Nikola Z. Ivanov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/namei.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 85e2d13841dab0..0245a2800170a1 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -552,21 +552,21 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (unlikely(f2fs_cp_error(sbi))) { err = -EIO; - goto fail; + goto out; } err = f2fs_dquot_initialize(dir); if (err) - goto fail; + goto out; err = f2fs_dquot_initialize(inode); if (err) - goto fail; + goto out; de = f2fs_find_entry(dir, &dentry->d_name, &folio); if (!de) { if (IS_ERR(folio)) err = PTR_ERR(folio); - goto fail; + goto out; } if (unlikely(inode->i_nlink == 0)) { @@ -575,7 +575,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) err = -EFSCORRUPTED; set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); f2fs_folio_put(folio, false); - goto fail; + goto out; } f2fs_balance_fs(sbi, true); @@ -585,7 +585,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (err) { f2fs_unlock_op(sbi); f2fs_folio_put(folio, false); - goto fail; + goto out; } f2fs_delete_entry(de, folio, dir, inode); f2fs_unlock_op(sbi); @@ -601,7 +601,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); -fail: +out: trace_f2fs_unlink_exit(inode, err); return err; } From f37981edcd06cd552c15c153c3202a6b2fa450e4 Mon Sep 17 00:00:00 2001 From: "Nikola Z. Ivanov" Date: Wed, 5 Nov 2025 13:09:43 +0200 Subject: [PATCH 608/684] f2fs: Add sanity checks before unlinking and loading inodes Add check for inode->i_nlink == 1 for directories during unlink, as their value is decremented twice, which can trigger a warning in drop_nlink. In such case mark the filesystem as corrupted and return from the function call with the relevant failure return value. Additionally add the check for i_nlink == 1 in sanity_check_inode in order to detect on-disk corruption early. Reported-by: syzbot+c07d47c7bc68f47b9083@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c07d47c7bc68f47b9083 Tested-by: syzbot+c07d47c7bc68f47b9083@syzkaller.appspotmail.com Signed-off-by: Nikola Z. Ivanov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 6 ++++++ fs/f2fs/namei.c | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 8c4eafe9ffac04..e2405b79b3cc20 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -294,6 +294,12 @@ static bool sanity_check_inode(struct inode *inode, struct folio *node_folio) return false; } + if (S_ISDIR(inode->i_mode) && unlikely(inode->i_nlink == 1)) { + f2fs_warn(sbi, "%s: directory inode (ino=%lx) has a single i_nlink", + __func__, inode->i_ino); + return false; + } + if (f2fs_has_extra_attr(inode)) { if (!f2fs_sb_has_extra_attr(sbi)) { f2fs_warn(sbi, "%s: inode (ino=%lx) is with extra_attr, but extra_attr feature is off", diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 0245a2800170a1..1530314e8b923c 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -570,12 +570,13 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) } if (unlikely(inode->i_nlink == 0)) { - f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink", + f2fs_warn(sbi, "%s: inode (ino=%lx) has zero i_nlink", __func__, inode->i_ino); - err = -EFSCORRUPTED; - set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); - f2fs_folio_put(folio, false); - goto out; + goto corrupted; + } else if (S_ISDIR(inode->i_mode) && unlikely(inode->i_nlink == 1)) { + f2fs_warn(sbi, "%s: directory inode (ino=%lx) has a single i_nlink", + __func__, inode->i_ino); + goto corrupted; } f2fs_balance_fs(sbi, true); @@ -601,6 +602,12 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); + + goto out; +corrupted: + err = -EFSCORRUPTED; + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_folio_put(folio, false); out: trace_f2fs_unlink_exit(inode, err); return err; From 27bf6a637b7613fc85fa6af468b7d612d78cd5c0 Mon Sep 17 00:00:00 2001 From: Xiaole He Date: Mon, 27 Oct 2025 17:23:41 +0800 Subject: [PATCH 609/684] f2fs: fix age extent cache insertion skip on counter overflow The age extent cache uses last_blocks (derived from allocated_data_blocks) to determine data age. However, there's a conflict between the deletion marker (last_blocks=0) and legitimate last_blocks=0 cases when allocated_data_blocks overflows to 0 after reaching ULLONG_MAX. In this case, valid extents are incorrectly skipped due to the "if (!tei->last_blocks)" check in __update_extent_tree_range(). This patch fixes the issue by: 1. Reserving ULLONG_MAX as an invalid/deletion marker 2. Limiting allocated_data_blocks to range [0, ULLONG_MAX-1] 3. Using F2FS_EXTENT_AGE_INVALID for deletion scenarios 4. Adjusting overflow age calculation from ULLONG_MAX to (ULLONG_MAX-1) Reproducer (using a patched kernel with allocated_data_blocks initialized to ULLONG_MAX - 3 for quick testing): Step 1: Mount and check initial state # dd if=/dev/zero of=/tmp/test.img bs=1M count=100 # mkfs.f2fs -f /tmp/test.img # mkdir -p /mnt/f2fs_test # mount -t f2fs -o loop,age_extent_cache /tmp/test.img /mnt/f2fs_test # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 18446744073709551612 # ULLONG_MAX - 3 Inner Struct Count: tree: 1(0), node: 0 Step 2: Create files and write data to trigger overflow # touch /mnt/f2fs_test/{1,2,3,4}.txt; sync # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 18446744073709551613 # ULLONG_MAX - 2 Inner Struct Count: tree: 5(0), node: 1 # dd if=/dev/urandom of=/mnt/f2fs_test/1.txt bs=4K count=1; sync # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 18446744073709551614 # ULLONG_MAX - 1 Inner Struct Count: tree: 5(0), node: 2 # dd if=/dev/urandom of=/mnt/f2fs_test/2.txt bs=4K count=1; sync # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 18446744073709551615 # ULLONG_MAX Inner Struct Count: tree: 5(0), node: 3 # dd if=/dev/urandom of=/mnt/f2fs_test/3.txt bs=4K count=1; sync # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 0 # Counter overflowed! Inner Struct Count: tree: 5(0), node: 4 Step 3: Trigger the bug - next write should create node but gets skipped # dd if=/dev/urandom of=/mnt/f2fs_test/4.txt bs=4K count=1; sync # cat /sys/kernel/debug/f2fs/status | grep -A 4 "Block Age" Allocated Data Blocks: 1 Inner Struct Count: tree: 5(0), node: 4 Expected: node: 5 (new extent node for 4.txt) Actual: node: 4 (extent insertion was incorrectly skipped due to last_blocks = allocated_data_blocks = 0 in __get_new_block_age) After this fix, the extent node is correctly inserted and node count becomes 5 as expected. Fixes: 71644dff4811 ("f2fs: add block_age-based extent cache") Cc: stable@kernel.org Signed-off-by: Xiaole He Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/extent_cache.c | 5 +++-- fs/f2fs/f2fs.h | 6 ++++++ fs/f2fs/segment.c | 9 +++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 33e09c453c7033..0ed84cc065a7ed 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -808,7 +808,7 @@ static void __update_extent_tree_range(struct inode *inode, } goto out_read_extent_cache; update_age_extent_cache: - if (!tei->last_blocks) + if (tei->last_blocks == F2FS_EXTENT_AGE_INVALID) goto out_read_extent_cache; __set_extent_info(&ei, fofs, len, 0, false, @@ -912,7 +912,7 @@ static int __get_new_block_age(struct inode *inode, struct extent_info *ei, cur_age = cur_blocks - tei.last_blocks; else /* allocated_data_blocks overflow */ - cur_age = ULLONG_MAX - tei.last_blocks + cur_blocks; + cur_age = (ULLONG_MAX - 1) - tei.last_blocks + cur_blocks; if (tei.age) ei->age = __calculate_block_age(sbi, cur_age, tei.age); @@ -1114,6 +1114,7 @@ void f2fs_update_age_extent_cache_range(struct dnode_of_data *dn, struct extent_info ei = { .fofs = fofs, .len = len, + .last_blocks = F2FS_EXTENT_AGE_INVALID, }; if (!__may_extent_tree(dn->inode, EX_BLOCK_AGE)) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index c85384e8cf4208..d9b2777f09edee 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -707,6 +707,12 @@ enum extent_type { NR_EXTENT_CACHES, }; +/* + * Reserved value to mark invalid age extents, hence valid block range + * from 0 to ULLONG_MAX-1 + */ +#define F2FS_EXTENT_AGE_INVALID ULLONG_MAX + struct extent_info { unsigned int fofs; /* start offset in a file */ unsigned int len; /* length of the extent */ diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index b45eace879d74b..a473cd1fb37d5d 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3863,8 +3863,13 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio, locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_blkaddr)); - if (IS_DATASEG(curseg->seg_type)) - atomic64_inc(&sbi->allocated_data_blocks); + if (IS_DATASEG(curseg->seg_type)) { + unsigned long long new_val; + + new_val = atomic64_inc_return(&sbi->allocated_data_blocks); + if (unlikely(new_val == ULLONG_MAX)) + atomic64_set(&sbi->allocated_data_blocks, 0); + } up_write(&sit_i->sentry_lock); From 2e2e0d679a1fb88a960049496373f415b67f274f Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 28 Oct 2025 19:50:11 +0000 Subject: [PATCH 610/684] f2fs: add fadvise tracepoint This adds a tracepoint in the fadvise call path. Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 ++ include/trace/events/f2fs.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7b966f6d40d23f..d7047ca6b98d8a 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -5288,6 +5288,8 @@ static int f2fs_file_fadvise(struct file *filp, loff_t offset, loff_t len, struct inode *inode = file_inode(filp); int err; + trace_f2fs_fadvise(inode, offset, len, advice); + if (advice == POSIX_FADV_SEQUENTIAL) { if (S_ISFIFO(inode->i_mode)) return -ESPIPE; diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index e1fae78d64a585..e00611ead024dd 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -586,6 +586,38 @@ TRACE_EVENT(f2fs_file_write_iter, __entry->ret) ); +TRACE_EVENT(f2fs_fadvise, + + TP_PROTO(struct inode *inode, loff_t offset, loff_t len, int advice), + + TP_ARGS(inode, offset, len, advice), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(loff_t, size) + __field(loff_t, offset) + __field(loff_t, len) + __field(int, advice) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->size = i_size_read(inode); + __entry->offset = offset; + __entry->len = len; + __entry->advice = advice; + ), + + TP_printk("dev = (%d,%d), ino = %lu, i_size = %lld offset:%llu, len:%llu, advise:%d", + show_dev_ino(__entry), + (unsigned long long)__entry->size, + __entry->offset, + __entry->len, + __entry->advice) +); + TRACE_EVENT(f2fs_map_blocks, TP_PROTO(struct inode *inode, struct f2fs_map_blocks *map, int flag, int ret), From 01fba45deaddcce0d0b01c411435d1acf6feab7b Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 5 Nov 2025 14:50:22 +0800 Subject: [PATCH 611/684] f2fs: fix return value of f2fs_recover_fsync_data() With below scripts, it will trigger panic in f2fs: mkfs.f2fs -f /dev/vdd mount /dev/vdd /mnt/f2fs touch /mnt/f2fs/foo sync echo 111 >> /mnt/f2fs/foo f2fs_io fsync /mnt/f2fs/foo f2fs_io shutdown 2 /mnt/f2fs umount /mnt/f2fs mount -o ro,norecovery /dev/vdd /mnt/f2fs or mount -o ro,disable_roll_forward /dev/vdd /mnt/f2fs F2FS-fs (vdd): f2fs_recover_fsync_data: recovery fsync data, check_only: 0 F2FS-fs (vdd): Mounted with checkpoint version = 7f5c361f F2FS-fs (vdd): Stopped filesystem due to reason: 0 F2FS-fs (vdd): f2fs_recover_fsync_data: recovery fsync data, check_only: 1 Filesystem f2fs get_tree() didn't set fc->root, returned 1 ------------[ cut here ]------------ kernel BUG at fs/super.c:1761! Oops: invalid opcode: 0000 [#1] SMP PTI CPU: 3 UID: 0 PID: 722 Comm: mount Not tainted 6.18.0-rc2+ #721 PREEMPT(voluntary) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:vfs_get_tree.cold+0x18/0x1a Call Trace: fc_mount+0x13/0xa0 path_mount+0x34e/0xc50 __x64_sys_mount+0x121/0x150 do_syscall_64+0x84/0x800 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7fa6cc126cfe The root cause is we missed to handle error number returned from f2fs_recover_fsync_data() when mounting image w/ ro,norecovery or ro,disable_roll_forward mount option, result in returning a positive error number to vfs_get_tree(), fix it. Cc: stable@kernel.org Fixes: 6781eabba1bd ("f2fs: give -EINVAL for norecovery and rw mount") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 0b0ef8ba243b33..8cf98c40b16035 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -5211,11 +5211,15 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) } } else { err = f2fs_recover_fsync_data(sbi, true); - - if (!f2fs_readonly(sb) && err > 0) { - err = -EINVAL; - f2fs_err(sbi, "Need to recover fsync data"); - goto free_meta; + if (err > 0) { + if (!f2fs_readonly(sb)) { + f2fs_err(sbi, "Need to recover fsync data"); + err = -EINVAL; + goto free_meta; + } else { + f2fs_info(sbi, "drop all fsynced data"); + err = 0; + } } } From 68d05693f8c031257a0822464366e1c2a239a512 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 5 Nov 2025 14:50:23 +0800 Subject: [PATCH 612/684] f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes() mkfs.f2fs -f /dev/vdd mount /dev/vdd /mnt/f2fs touch /mnt/f2fs/foo sync # avoid CP_UMOUNT_FLAG in last f2fs_checkpoint.ckpt_flags touch /mnt/f2fs/bar f2fs_io fsync /mnt/f2fs/bar f2fs_io shutdown 2 /mnt/f2fs umount /mnt/f2fs blockdev --setro /dev/vdd mount /dev/vdd /mnt/f2fs mount: /mnt/f2fs: WARNING: source write-protected, mounted read-only. For the case if we create and fsync a new inode before sudden power-cut, without norecovery or disable_roll_forward mount option, the following mount will succeed w/o recovering last fsynced inode. The problem here is that we only check inode_list list after find_fsync_dnodes() in f2fs_recover_fsync_data() to find out whether there is recoverable data in the iamge, but there is a missed case, if last fsynced inode is not existing in last checkpoint, then, we will fail to get its inode due to nat of inode node is not existing in last checkpoint, so the inode won't be linked in inode_list. Let's detect such case in dyrun mode to fix this issue. After this change, mount will fail as expected below: mount: /mnt/f2fs: cannot mount /dev/vdd read-only. dmesg(1) may have more information after failed mount system call. demsg: F2FS-fs (vdd): Need to recover fsync data, but write access unavailable, please try mount w/ disable_roll_forward or norecovery Cc: stable@kernel.org Fixes: 6781eabba1bd ("f2fs: give -EINVAL for norecovery and rw mount") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/recovery.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 215e442db72c82..d7faebaa3c6b8e 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -399,7 +399,7 @@ static int sanity_check_node_chain(struct f2fs_sb_info *sbi, block_t blkaddr, } static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, - bool check_only) + bool check_only, bool *new_inode) { struct curseg_info *curseg; block_t blkaddr, blkaddr_fast; @@ -447,16 +447,19 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, quota_inode = true; } - /* - * CP | dnode(F) | inode(DF) - * For this case, we should not give up now. - */ entry = add_fsync_inode(sbi, head, ino_of_node(folio), quota_inode); if (IS_ERR(entry)) { err = PTR_ERR(entry); - if (err == -ENOENT) + /* + * CP | dnode(F) | inode(DF) + * For this case, we should not give up now. + */ + if (err == -ENOENT) { + if (check_only) + *new_inode = true; goto next; + } f2fs_folio_put(folio, true); break; } @@ -875,6 +878,7 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) int ret = 0; unsigned long s_flags = sbi->sb->s_flags; bool need_writecp = false; + bool new_inode = false; f2fs_notice(sbi, "f2fs_recover_fsync_data: recovery fsync data, " "check_only: %d", check_only); @@ -890,8 +894,8 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) f2fs_down_write(&sbi->cp_global_sem); /* step #1: find fsynced inode numbers */ - err = find_fsync_dnodes(sbi, &inode_list, check_only); - if (err || list_empty(&inode_list)) + err = find_fsync_dnodes(sbi, &inode_list, check_only, &new_inode); + if (err < 0 || (list_empty(&inode_list) && (!check_only || !new_inode))) goto skip; if (check_only) { From 7ee8bc3942f20964ad730871b885688ea3a2961a Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Tue, 11 Nov 2025 09:52:46 -0800 Subject: [PATCH 613/684] f2fs: revert summary entry count from 2048 to 512 in 16kb block support The recent increase in the number of Segment Summary Area (SSA) entries from 512 to 2048 was an unintentional change in logic of 16kb block support. This commit corrects the issue. To better utilize the space available from the erroneous 2048-entry calculation, we are implementing a solution to share the currently unused SSA space with neighboring segments. This enhances overall SSA utilization without impacting the established 8MB segment size. Fixes: d7e9a9037de2 ("f2fs: Support Block Size == Page Size") Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 + fs/f2fs/gc.c | 117 +++++++++++++++++++++++----------------- fs/f2fs/recovery.c | 2 +- fs/f2fs/segment.c | 38 +++++++++---- fs/f2fs/segment.h | 8 ++- fs/f2fs/super.c | 14 +++++ fs/f2fs/sysfs.c | 7 +++ include/linux/f2fs_fs.h | 5 +- 8 files changed, 130 insertions(+), 63 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d9b2777f09edee..860e9c69d3a6fb 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -245,6 +245,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_COMPRESSION 0x00002000 #define F2FS_FEATURE_RO 0x00004000 #define F2FS_FEATURE_DEVICE_ALIAS 0x00008000 +#define F2FS_FEATURE_PACKED_SSA 0x00010000 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ((raw_super->feature & cpu_to_le32(mask)) != 0) @@ -4704,6 +4705,7 @@ F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); +F2FS_FEATURE_FUNCS(packed_ssa, PACKED_SSA); #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_zone_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index e04aafee1f2c87..384fa7e2085bf9 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1735,7 +1735,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? SUM_TYPE_DATA : SUM_TYPE_NODE; unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE; - int submitted = 0; + int submitted = 0, sum_blk_cnt; if (__is_large_section(sbi)) { sec_end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); @@ -1769,22 +1769,28 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); + segno = rounddown(segno, SUMS_PER_BLOCK); + sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK); /* readahead multi ssa blocks those have contiguous address */ if (__is_large_section(sbi)) f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), - end_segno - segno, META_SSA, true); + sum_blk_cnt, META_SSA, true); /* reference all summary page */ while (segno < end_segno) { - struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno++); + struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno); + + segno += SUMS_PER_BLOCK; if (IS_ERR(sum_folio)) { int err = PTR_ERR(sum_folio); - end_segno = segno - 1; - for (segno = start_segno; segno < end_segno; segno++) { + end_segno = segno - SUMS_PER_BLOCK; + segno = rounddown(start_segno, SUMS_PER_BLOCK); + while (segno < end_segno) { sum_folio = filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); folio_put_refs(sum_folio, 2); + segno += SUMS_PER_BLOCK; } return err; } @@ -1793,68 +1799,83 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, blk_start_plug(&plug); - for (segno = start_segno; segno < end_segno; segno++) { - struct f2fs_summary_block *sum; + segno = start_segno; + while (segno < end_segno) { + unsigned int cur_segno; /* find segment summary of victim */ struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); + unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK) + + SUMS_PER_BLOCK; + + if (block_end_segno > end_segno) + block_end_segno = end_segno; if (is_cursec(sbi, GET_SEC_FROM_SEG(sbi, segno))) { f2fs_err(sbi, "%s: segment %u is used by log", __func__, segno); f2fs_bug_on(sbi, 1); - goto skip; + goto next_block; } - if (get_valid_blocks(sbi, segno, false) == 0) - goto freed; - if (gc_type == BG_GC && __is_large_section(sbi) && - migrated >= sbi->migration_granularity) - goto skip; if (!folio_test_uptodate(sum_folio) || unlikely(f2fs_cp_error(sbi))) - goto skip; + goto next_block; - sum = folio_address(sum_folio); - if (type != GET_SUM_TYPE((&sum->footer))) { - f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SIT and SSA", - segno, type, GET_SUM_TYPE((&sum->footer))); - f2fs_stop_checkpoint(sbi, false, - STOP_CP_REASON_CORRUPTED_SUMMARY); - goto skip; - } + for (cur_segno = segno; cur_segno < block_end_segno; + cur_segno++) { + struct f2fs_summary_block *sum; - /* - * this is to avoid deadlock: - * - lock_page(sum_page) - f2fs_replace_block - * - check_valid_map() - down_write(sentry_lock) - * - down_read(sentry_lock) - change_curseg() - * - lock_page(sum_page) - */ - if (type == SUM_TYPE_NODE) - submitted += gc_node_segment(sbi, sum->entries, segno, - gc_type); - else - submitted += gc_data_segment(sbi, sum->entries, gc_list, - segno, gc_type, - force_migrate); + if (get_valid_blocks(sbi, cur_segno, false) == 0) + goto freed; + if (gc_type == BG_GC && __is_large_section(sbi) && + migrated >= sbi->migration_granularity) + continue; - stat_inc_gc_seg_count(sbi, data_type, gc_type); - sbi->gc_reclaimed_segs[sbi->gc_mode]++; - migrated++; + sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno); + if (type != GET_SUM_TYPE((&sum->footer))) { + f2fs_err(sbi, "Inconsistent segment (%u) type " + "[%d, %d] in SSA and SIT", + cur_segno, type, + GET_SUM_TYPE((&sum->footer))); + f2fs_stop_checkpoint(sbi, false, + STOP_CP_REASON_CORRUPTED_SUMMARY); + continue; + } -freed: - if (gc_type == FG_GC && - get_valid_blocks(sbi, segno, false) == 0) - seg_freed++; + /* + * this is to avoid deadlock: + * - lock_page(sum_page) - f2fs_replace_block + * - check_valid_map() - down_write(sentry_lock) + * - down_read(sentry_lock) - change_curseg() + * - lock_page(sum_page) + */ + if (type == SUM_TYPE_NODE) + submitted += gc_node_segment(sbi, sum->entries, + cur_segno, gc_type); + else + submitted += gc_data_segment(sbi, sum->entries, + gc_list, cur_segno, + gc_type, force_migrate); - if (__is_large_section(sbi)) - sbi->next_victim_seg[gc_type] = - (segno + 1 < sec_end_segno) ? - segno + 1 : NULL_SEGNO; -skip: + stat_inc_gc_seg_count(sbi, data_type, gc_type); + sbi->gc_reclaimed_segs[sbi->gc_mode]++; + migrated++; + +freed: + if (gc_type == FG_GC && + get_valid_blocks(sbi, cur_segno, false) == 0) + seg_freed++; + + if (__is_large_section(sbi)) + sbi->next_victim_seg[gc_type] = + (cur_segno + 1 < sec_end_segno) ? + cur_segno + 1 : NULL_SEGNO; + } +next_block: folio_put_refs(sum_folio, 2); + segno = block_end_segno; } if (submitted) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index d7faebaa3c6b8e..62a0c71b5b75d6 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -522,7 +522,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, sum_folio = f2fs_get_sum_folio(sbi, segno); if (IS_ERR(sum_folio)) return PTR_ERR(sum_folio); - sum_node = folio_address(sum_folio); + sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno); sum = sum_node->entries[blkoff]; f2fs_folio_put(sum_folio, true); got_it: diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a473cd1fb37d5d..10d873d1b328cd 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2712,7 +2712,15 @@ struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno) void f2fs_update_meta_page(struct f2fs_sb_info *sbi, void *src, block_t blk_addr) { - struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr); + struct folio *folio; + + if (SUMS_PER_BLOCK == 1) + folio = f2fs_grab_meta_folio(sbi, blk_addr); + else + folio = f2fs_get_meta_folio_retry(sbi, blk_addr); + + if (IS_ERR(folio)) + return; memcpy(folio_address(folio), src, PAGE_SIZE); folio_mark_dirty(folio); @@ -2720,9 +2728,21 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi, } static void write_sum_page(struct f2fs_sb_info *sbi, - struct f2fs_summary_block *sum_blk, block_t blk_addr) + struct f2fs_summary_block *sum_blk, unsigned int segno) { - f2fs_update_meta_page(sbi, (void *)sum_blk, blk_addr); + struct folio *folio; + + if (SUMS_PER_BLOCK == 1) + return f2fs_update_meta_page(sbi, (void *)sum_blk, + GET_SUM_BLOCK(sbi, segno)); + + folio = f2fs_get_sum_folio(sbi, segno); + if (IS_ERR(folio)) + return; + + memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk)); + folio_mark_dirty(folio); + f2fs_folio_put(folio, true); } static void write_current_sum_page(struct f2fs_sb_info *sbi, @@ -2987,7 +3007,7 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) int ret; if (curseg->inited) - write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno)); + write_sum_page(sbi, curseg->sum_blk, segno); segno = __get_next_segno(sbi, type); ret = get_new_segment(sbi, &segno, new_sec, pinning); @@ -3046,7 +3066,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type) struct folio *sum_folio; if (curseg->inited) - write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); __set_test_and_inuse(sbi, new_segno); @@ -3065,7 +3085,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type) memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE); return PTR_ERR(sum_folio); } - sum_node = folio_address(sum_folio); + sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno); memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); f2fs_folio_put(sum_folio, true); return 0; @@ -3154,8 +3174,7 @@ static void __f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type) goto out; if (get_valid_blocks(sbi, curseg->segno, false)) { - write_sum_page(sbi, curseg->sum_blk, - GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); } else { mutex_lock(&DIRTY_I(sbi)->seglist_lock); __set_test_and_free(sbi, curseg->segno, true); @@ -3833,8 +3852,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio, if (segment_full) { if (type == CURSEG_COLD_DATA_PINNED && !((curseg->segno + 1) % sbi->segs_per_sec)) { - write_sum_page(sbi, curseg->sum_blk, - GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); reset_curseg_fields(curseg); goto skip_new_segment; } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 1ce2c8abaf4888..e883f14c228f26 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -85,8 +85,12 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, #define GET_ZONE_FROM_SEG(sbi, segno) \ GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) -#define GET_SUM_BLOCK(sbi, segno) \ - ((sbi)->sm_info->ssa_blkaddr + (segno)) +#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE) +#define GET_SUM_BLOCK(sbi, segno) \ + (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK)) +#define GET_SUM_BLKOFF(segno) (segno % SUMS_PER_BLOCK) +#define SUM_BLK_PAGE_ADDR(folio, segno) \ + (folio_address(folio) + GET_SUM_BLKOFF(segno) * F2FS_SUM_BLKSIZE) #define GET_SUM_TYPE(footer) ((footer)->entry_type) #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type)) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8cf98c40b16035..c2161b3469b37b 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4080,6 +4080,20 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, if (sanity_check_area_boundary(sbi, folio, index)) return -EFSCORRUPTED; + /* + * Check for legacy summary layout on 16KB+ block devices. + * Modern f2fs-tools packs multiple 4KB summary areas into one block, + * whereas legacy versions used one block per summary, leading + * to a much larger SSA. + */ + if (SUMS_PER_BLOCK > 1 && + !(__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_PACKED_SSA))) { + f2fs_info(sbi, "Error: Device formatted with a legacy version. " + "Please reformat with a tool supporting the packed ssa " + "feature for block sizes larger than 4kb."); + return -EOPNOTSUPP; + } + return 0; } diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6d2a4fba68a29f..5685b454bfd12d 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -235,6 +235,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_compression(sbi)) len += sysfs_emit_at(buf, len, "%s%s", len ? ", " : "", "compression"); + if (f2fs_sb_has_packed_ssa(sbi)) + len += sysfs_emit_at(buf, len, "%s%s", + len ? ", " : "", "packed_ssa"); len += sysfs_emit_at(buf, len, "%s%s", len ? ", " : "", "pin_file"); len += sysfs_emit_at(buf, len, "\n"); @@ -1296,6 +1299,7 @@ F2FS_FEATURE_RO_ATTR(pin_file); #ifdef CONFIG_UNICODE F2FS_FEATURE_RO_ATTR(linear_lookup); #endif +F2FS_FEATURE_RO_ATTR(packed_ssa); #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { @@ -1455,6 +1459,7 @@ static struct attribute *f2fs_feat_attrs[] = { #ifdef CONFIG_UNICODE BASE_ATTR_LIST(linear_lookup), #endif + BASE_ATTR_LIST(packed_ssa), NULL, }; ATTRIBUTE_GROUPS(f2fs_feat); @@ -1490,6 +1495,7 @@ F2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD); F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION); F2FS_SB_FEATURE_RO_ATTR(readonly, RO); F2FS_SB_FEATURE_RO_ATTR(device_alias, DEVICE_ALIAS); +F2FS_SB_FEATURE_RO_ATTR(packed_ssa, PACKED_SSA); static struct attribute *f2fs_sb_feat_attrs[] = { ATTR_LIST(sb_encryption), @@ -1507,6 +1513,7 @@ static struct attribute *f2fs_sb_feat_attrs[] = { ATTR_LIST(sb_compression), ATTR_LIST(sb_readonly), ATTR_LIST(sb_device_alias), + ATTR_LIST(sb_packed_ssa), NULL, }; ATTRIBUTE_GROUPS(f2fs_sb_feat); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 6afb4a13b81d65..a7880787cad366 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -17,6 +17,7 @@ #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ #define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */ #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ +#define F2FS_SUM_BLKSIZE 4096 /* only support 4096 byte sum block */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_EXTENSION_LEN 8 /* max size of extension */ @@ -441,7 +442,7 @@ struct f2fs_sit_block { * from node's page's beginning to get a data block address. * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node) */ -#define ENTRIES_IN_SUM (F2FS_BLKSIZE / 8) +#define ENTRIES_IN_SUM (F2FS_SUM_BLKSIZE / 8) #define SUMMARY_SIZE (7) /* sizeof(struct f2fs_summary) */ #define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ #define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) @@ -467,7 +468,7 @@ struct summary_footer { __le32 check_sum; /* summary checksum */ } __packed; -#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\ +#define SUM_JOURNAL_SIZE (F2FS_SUM_BLKSIZE - SUM_FOOTER_SIZE -\ SUM_ENTRY_SIZE) #define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ sizeof(struct nat_journal_entry)) From 24fd7f00161055e1ca0dd137a1d67f87fa781f99 Mon Sep 17 00:00:00 2001 From: Baolin Liu Date: Tue, 11 Nov 2025 20:17:28 +0800 Subject: [PATCH 614/684] f2fs: simplify list initialization in f2fs_recover_fsync_data() In f2fs_recover_fsync_data(),use LIST_HEAD() to declare and initialize the list_head in one step instead of using INIT_LIST_HEAD() separately. No functional change. Signed-off-by: Baolin Liu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/recovery.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 62a0c71b5b75d6..c3415ebb9f5053 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -872,8 +872,9 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) { - struct list_head inode_list, tmp_inode_list; - struct list_head dir_list; + LIST_HEAD(inode_list); + LIST_HEAD(tmp_inode_list); + LIST_HEAD(dir_list); int err; int ret = 0; unsigned long s_flags = sbi->sb->s_flags; @@ -886,10 +887,6 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE)) f2fs_info(sbi, "recover fsync data on readonly fs"); - INIT_LIST_HEAD(&inode_list); - INIT_LIST_HEAD(&tmp_inode_list); - INIT_LIST_HEAD(&dir_list); - /* prevent checkpoint */ f2fs_down_write(&sbi->cp_global_sem); From 581251e03077f2fb83f9d10f5e21ec7e546a82b4 Mon Sep 17 00:00:00 2001 From: Yongpeng Yang Date: Mon, 10 Nov 2025 16:22:21 +0800 Subject: [PATCH 615/684] f2fs: wrap all unusable_blocks_per_sec code in CONFIG_BLK_DEV_ZONED The usage of unusable_blocks_per_sec is already wrapped by CONFIG_BLK_DEV_ZONED, except for its declaration and the definitions of CAP_BLKS_PER_SEC and CAP_SEGS_PER_SEC. This patch ensures that all code related to unusable_blocks_per_sec is properly wrapped under the CONFIG_BLK_DEV_ZONED option. Signed-off-by: Yongpeng Yang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/segment.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 860e9c69d3a6fb..3d8b69628721e8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1669,6 +1669,7 @@ struct f2fs_sb_info { #ifdef CONFIG_BLK_DEV_ZONED unsigned int blocks_per_blkz; /* F2FS blocks per zone */ + unsigned int unusable_blocks_per_sec; /* unusable blocks per section */ unsigned int max_open_zones; /* max open zone resources of the zoned device */ /* For adjust the priority writing position of data in zone UFS */ unsigned int blkzone_alloc_policy; @@ -1741,7 +1742,6 @@ struct f2fs_sb_info { unsigned int meta_ino_num; /* meta inode number*/ unsigned int log_blocks_per_seg; /* log2 blocks per segment */ unsigned int blocks_per_seg; /* blocks per segment */ - unsigned int unusable_blocks_per_sec; /* unusable blocks per section */ unsigned int segs_per_sec; /* segments per section */ unsigned int secs_per_zone; /* sections per zone */ unsigned int total_sections; /* total section count */ diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index e883f14c228f26..0b54d87409b083 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -69,11 +69,16 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, ((!__is_valid_data_blkaddr(blk_addr)) ? \ NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \ GET_SEGNO_FROM_SEG0(sbi, blk_addr))) +#ifdef CONFIG_BLK_DEV_ZONED #define CAP_BLKS_PER_SEC(sbi) \ (BLKS_PER_SEC(sbi) - (sbi)->unusable_blocks_per_sec) #define CAP_SEGS_PER_SEC(sbi) \ (SEGS_PER_SEC(sbi) - \ BLKS_TO_SEGS(sbi, (sbi)->unusable_blocks_per_sec)) +#else +#define CAP_BLKS_PER_SEC(sbi) BLKS_PER_SEC(sbi) +#define CAP_SEGS_PER_SEC(sbi) SEGS_PER_SEC(sbi) +#endif #define GET_START_SEG_FROM_SEC(sbi, segno) \ (rounddown(segno, SEGS_PER_SEC(sbi))) #define GET_SEC_FROM_SEG(sbi, segno) \ From 89732017890e8ce0826e18c743b71dc564d3a674 Mon Sep 17 00:00:00 2001 From: Yongpeng Yang Date: Mon, 10 Nov 2025 16:22:22 +0800 Subject: [PATCH 616/684] f2fs: add a sysfs entry to show max open zones This patch adds a sysfs entry showing the max zones that F2FS can write concurrently. Signed-off-by: Yongpeng Yang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-fs-f2fs | 6 ++++++ fs/f2fs/sysfs.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index b590809869ca64..770470e0598b80 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -643,6 +643,12 @@ Contact: "Jaegeuk Kim" Description: Shows the number of unusable blocks in a section which was defined by the zone capacity reported by underlying zoned device. +What: /sys/fs/f2fs//max_open_zones +Date: November 2025 +Contact: "Yongpeng Yang" +Description: Shows the max number of zones that F2FS can write concurrently when a zoned + device is mounted. + What: /sys/fs/f2fs//current_atomic_write Date: July 2022 Contact: "Daeho Jeong" diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 5685b454bfd12d..c42f4f979d13f3 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -1213,6 +1213,7 @@ F2FS_SBI_GENERAL_RW_ATTR(last_age_weight); F2FS_SBI_GENERAL_RW_ATTR(max_read_extent_count); #ifdef CONFIG_BLK_DEV_ZONED F2FS_SBI_GENERAL_RO_ATTR(unusable_blocks_per_sec); +F2FS_SBI_GENERAL_RO_ATTR(max_open_zones); F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy); #endif F2FS_SBI_GENERAL_RW_ATTR(carve_out); @@ -1388,6 +1389,7 @@ static struct attribute *f2fs_attrs[] = { #endif #ifdef CONFIG_BLK_DEV_ZONED ATTR_LIST(unusable_blocks_per_sec), + ATTR_LIST(max_open_zones), ATTR_LIST(blkzone_alloc_policy), #endif #ifdef CONFIG_F2FS_FS_COMPRESSION From 30a8496694f1a93328e5d7f19206380346918b5a Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 12 Nov 2025 09:47:47 +0800 Subject: [PATCH 617/684] f2fs: use memalloc_retry_wait() as much as possible memalloc_retry_wait() is recommended in memory allocation retry logic, use it as much as possible. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.c | 2 +- fs/f2fs/super.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 10d873d1b328cd..d968a4250b1a5e 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -234,7 +234,7 @@ static int __replace_atomic_write_block(struct inode *inode, pgoff_t index, err = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE); if (err) { if (err == -ENOMEM) { - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + memalloc_retry_wait(GFP_NOFS); goto retry; } return err; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index c2161b3469b37b..2bd7c2320d4f05 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3139,7 +3139,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, &folio, &fsdata); if (unlikely(err)) { if (err == -ENOMEM) { - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + memalloc_retry_wait(GFP_NOFS); goto retry; } set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); From 76e780d88c771921ea643fb8a6c8d0b08c17cb7b Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 12 Nov 2025 09:47:48 +0800 Subject: [PATCH 618/684] f2fs: introduce f2fs_schedule_timeout() In f2fs retry logic, we will call f2fs_io_schedule_timeout() to sleep as uninterruptible state (waiting for IO) for a while, however, in several paths below, we are not blocked by IO: - f2fs_write_single_data_page() return -EAGAIN due to racing on cp_rwsem. - f2fs_flush_device_cache() failed to submit preflush command. - __issue_discard_cmd_range() sleeps periodically in between two in batch discard submissions. So, in order to reveal state of task more accurate, let's introduce f2fs_schedule_timeout() and call it in above paths in where we are waiting for non-IO reasons. Then we can get real reason of uninterruptible sleep for a thread in tracepoint, perfetto, etc. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 4 ++-- fs/f2fs/compress.c | 4 ++-- fs/f2fs/data.c | 4 ++-- fs/f2fs/f2fs.h | 22 +++++++++++++++------- fs/f2fs/segment.c | 4 ++-- fs/f2fs/super.c | 2 +- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index bbe07e3a6c75ac..4c401b5b29336b 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1318,7 +1318,7 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) f2fs_submit_merged_write(sbi, DATA); prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); - io_schedule_timeout(DEFAULT_IO_TIMEOUT); + io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); } finish_wait(&sbi->cp_wait, &wait); } @@ -1974,7 +1974,7 @@ void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi) /* Let's wait for the previous dispatched checkpoint. */ while (atomic_read(&cprc->queued_ckpt)) - io_schedule_timeout(DEFAULT_IO_TIMEOUT); + io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); } void f2fs_init_ckpt_req_control(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 716004ba44dc1e..148bb925b03b69 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1057,7 +1057,7 @@ static void cancel_cluster_writeback(struct compress_ctx *cc, f2fs_submit_merged_write(F2FS_I_SB(cc->inode), DATA); while (atomic_read(&cic->pending_pages) != (cc->valid_nr_cpages - submitted + 1)) - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); } /* Cancel writeback and stay locked. */ @@ -1574,7 +1574,7 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc, */ if (IS_NOQUOTA(cc->inode)) goto out; - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); goto retry_write; } goto out; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 7be0837a945661..9d4f46b8c25623 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3141,8 +3141,8 @@ static int f2fs_write_cache_pages(struct address_space *mapping, } else if (ret == -EAGAIN) { ret = 0; if (wbc->sync_mode == WB_SYNC_ALL) { - f2fs_io_schedule_timeout( - DEFAULT_IO_TIMEOUT); + f2fs_schedule_timeout( + DEFAULT_SCHEDULE_TIMEOUT); goto retry_write; } goto next; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 3d8b69628721e8..858ceb3d2ad6e3 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -656,8 +656,8 @@ enum { #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO or flush count */ -/* congestion wait timeout value, default: 20ms */ -#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(20)) +/* IO/non-IO congestion wait timeout value, default: 20ms */ +#define DEFAULT_SCHEDULE_TIMEOUT (msecs_to_jiffies(20)) /* timeout value injected, default: 1000ms */ #define DEFAULT_FAULT_TIMEOUT (msecs_to_jiffies(1000)) @@ -4908,22 +4908,30 @@ static inline bool f2fs_block_unit_discard(struct f2fs_sb_info *sbi) return F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_BLOCK; } -static inline void f2fs_io_schedule_timeout(long timeout) +static inline void __f2fs_schedule_timeout(long timeout, bool io) { set_current_state(TASK_UNINTERRUPTIBLE); - io_schedule_timeout(timeout); + if (io) + io_schedule_timeout(timeout); + else + schedule_timeout(timeout); } +#define f2fs_io_schedule_timeout(timeout) \ + __f2fs_schedule_timeout(timeout, true) +#define f2fs_schedule_timeout(timeout) \ + __f2fs_schedule_timeout(timeout, false) + static inline void f2fs_io_schedule_timeout_killable(long timeout) { while (timeout) { if (fatal_signal_pending(current)) return; set_current_state(TASK_UNINTERRUPTIBLE); - io_schedule_timeout(DEFAULT_IO_TIMEOUT); - if (timeout <= DEFAULT_IO_TIMEOUT) + io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + if (timeout <= DEFAULT_SCHEDULE_TIMEOUT) return; - timeout -= DEFAULT_IO_TIMEOUT; + timeout -= DEFAULT_SCHEDULE_TIMEOUT; } } diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d968a4250b1a5e..993ec8afe2dbbe 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -750,7 +750,7 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi) do { ret = __submit_flush_wait(sbi, FDEV(i).bdev); if (ret) - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); } while (ret && --count); if (ret) { @@ -3471,7 +3471,7 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi, blk_finish_plug(&plug); mutex_unlock(&dcc->cmd_lock); trimmed += __wait_all_discard_cmd(sbi, NULL); - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); goto next; } skip: diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 2bd7c2320d4f05..d47ec718f3be79 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2652,7 +2652,7 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) /* we should flush all the data to keep data consistency */ while (get_pages(sbi, F2FS_DIRTY_DATA)) { writeback_inodes_sb_nr(sbi->sb, nr_pages, WB_REASON_SYNC); - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); if (f2fs_time_over(sbi, ENABLE_TIME)) break; From d31e0de8b8625874d2fc4f5506b3bf30610555a0 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 12 Nov 2025 09:47:49 +0800 Subject: [PATCH 619/684] f2fs: change default schedule timeout value This patch changes default schedule timeout value from 20ms to 1ms, in order to give caller more chances to check whether IO or non-IO congestion condition has already been mitigable. In addition, default interval of periodical discard submission is kept to 20ms. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 6 ++++-- fs/f2fs/segment.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 858ceb3d2ad6e3..842dd1963b57c9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -407,6 +407,8 @@ struct discard_entry { #define DEFAULT_DISCARD_GRANULARITY 16 /* default maximum discard granularity of ordered discard, unit: block count */ #define DEFAULT_MAX_ORDERED_DISCARD_GRANULARITY 16 +/* default interval of periodical discard submission */ +#define DEFAULT_DISCARD_INTERVAL (msecs_to_jiffies(20)) /* max discard pend list number */ #define MAX_PLIST_NUM 512 @@ -656,8 +658,8 @@ enum { #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO or flush count */ -/* IO/non-IO congestion wait timeout value, default: 20ms */ -#define DEFAULT_SCHEDULE_TIMEOUT (msecs_to_jiffies(20)) +/* IO/non-IO congestion wait timeout value, default: 1ms */ +#define DEFAULT_SCHEDULE_TIMEOUT (msecs_to_jiffies(1)) /* timeout value injected, default: 1000ms */ #define DEFAULT_FAULT_TIMEOUT (msecs_to_jiffies(1000)) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 993ec8afe2dbbe..8375dca7ed9e49 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3471,7 +3471,7 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi, blk_finish_plug(&plug); mutex_unlock(&dcc->cmd_lock); trimmed += __wait_all_discard_cmd(sbi, NULL); - f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + f2fs_schedule_timeout(DEFAULT_DISCARD_INTERVAL); goto next; } skip: From 1627a303bca692edc6552630aa2f878c8a726a01 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 17 Nov 2025 20:45:59 +0800 Subject: [PATCH 620/684] f2fs: expand scalability of f2fs mount option opt field in structure f2fs_mount_info and opt_mask field in structure f2fs_fs_context is 32-bits variable, now we're running out of available bits in them, let's expand them to 64-bits for better scalability. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 85 ++++++++++++++++++++++++++----------------------- fs/f2fs/super.c | 36 ++++++++++----------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 842dd1963b57c9..55d29d50159e7b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -96,47 +96,52 @@ extern const char *f2fs_fault_name[FAULT_MAX]; /* * For mount options */ -#define F2FS_MOUNT_DISABLE_ROLL_FORWARD 0x00000001 -#define F2FS_MOUNT_DISCARD 0x00000002 -#define F2FS_MOUNT_NOHEAP 0x00000004 -#define F2FS_MOUNT_XATTR_USER 0x00000008 -#define F2FS_MOUNT_POSIX_ACL 0x00000010 -#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000020 -#define F2FS_MOUNT_INLINE_XATTR 0x00000040 -#define F2FS_MOUNT_INLINE_DATA 0x00000080 -#define F2FS_MOUNT_INLINE_DENTRY 0x00000100 -#define F2FS_MOUNT_FLUSH_MERGE 0x00000200 -#define F2FS_MOUNT_NOBARRIER 0x00000400 -#define F2FS_MOUNT_FASTBOOT 0x00000800 -#define F2FS_MOUNT_READ_EXTENT_CACHE 0x00001000 -#define F2FS_MOUNT_DATA_FLUSH 0x00002000 -#define F2FS_MOUNT_FAULT_INJECTION 0x00004000 -#define F2FS_MOUNT_USRQUOTA 0x00008000 -#define F2FS_MOUNT_GRPQUOTA 0x00010000 -#define F2FS_MOUNT_PRJQUOTA 0x00020000 -#define F2FS_MOUNT_QUOTA 0x00040000 -#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00080000 -#define F2FS_MOUNT_RESERVE_ROOT 0x00100000 -#define F2FS_MOUNT_DISABLE_CHECKPOINT 0x00200000 -#define F2FS_MOUNT_NORECOVERY 0x00400000 -#define F2FS_MOUNT_ATGC 0x00800000 -#define F2FS_MOUNT_MERGE_CHECKPOINT 0x01000000 -#define F2FS_MOUNT_GC_MERGE 0x02000000 -#define F2FS_MOUNT_COMPRESS_CACHE 0x04000000 -#define F2FS_MOUNT_AGE_EXTENT_CACHE 0x08000000 -#define F2FS_MOUNT_NAT_BITS 0x10000000 -#define F2FS_MOUNT_INLINECRYPT 0x20000000 -/* - * Some f2fs environments expect to be able to pass the "lazytime" option - * string rather than using the MS_LAZYTIME flag, so this must remain. - */ -#define F2FS_MOUNT_LAZYTIME 0x40000000 -#define F2FS_MOUNT_RESERVE_NODE 0x80000000 +enum f2fs_mount_opt { + F2FS_MOUNT_DISABLE_ROLL_FORWARD, + F2FS_MOUNT_DISCARD, + F2FS_MOUNT_NOHEAP, + F2FS_MOUNT_XATTR_USER, + F2FS_MOUNT_POSIX_ACL, + F2FS_MOUNT_DISABLE_EXT_IDENTIFY, + F2FS_MOUNT_INLINE_XATTR, + F2FS_MOUNT_INLINE_DATA, + F2FS_MOUNT_INLINE_DENTRY, + F2FS_MOUNT_FLUSH_MERGE, + F2FS_MOUNT_NOBARRIER, + F2FS_MOUNT_FASTBOOT, + F2FS_MOUNT_READ_EXTENT_CACHE, + F2FS_MOUNT_DATA_FLUSH, + F2FS_MOUNT_FAULT_INJECTION, + F2FS_MOUNT_USRQUOTA, + F2FS_MOUNT_GRPQUOTA, + F2FS_MOUNT_PRJQUOTA, + F2FS_MOUNT_QUOTA, + F2FS_MOUNT_INLINE_XATTR_SIZE, + F2FS_MOUNT_RESERVE_ROOT, + F2FS_MOUNT_DISABLE_CHECKPOINT, + F2FS_MOUNT_NORECOVERY, + F2FS_MOUNT_ATGC, + F2FS_MOUNT_MERGE_CHECKPOINT, + F2FS_MOUNT_GC_MERGE, + F2FS_MOUNT_COMPRESS_CACHE, + F2FS_MOUNT_AGE_EXTENT_CACHE, + F2FS_MOUNT_NAT_BITS, + F2FS_MOUNT_INLINECRYPT, + /* + * Some f2fs environments expect to be able to pass the "lazytime" option + * string rather than using the MS_LAZYTIME flag, so this must remain. + */ + F2FS_MOUNT_LAZYTIME, + F2FS_MOUNT_RESERVE_NODE, +}; #define F2FS_OPTION(sbi) ((sbi)->mount_opt) -#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) -#define set_opt(sbi, option) (F2FS_OPTION(sbi).opt |= F2FS_MOUNT_##option) -#define test_opt(sbi, option) (F2FS_OPTION(sbi).opt & F2FS_MOUNT_##option) +#define clear_opt(sbi, option) \ + (F2FS_OPTION(sbi).opt &= ~BIT(F2FS_MOUNT_##option)) +#define set_opt(sbi, option) \ + (F2FS_OPTION(sbi).opt |= BIT(F2FS_MOUNT_##option)) +#define test_opt(sbi, option) \ + (F2FS_OPTION(sbi).opt & BIT(F2FS_MOUNT_##option)) #define ver_after(a, b) (typecheck(unsigned long long, a) && \ typecheck(unsigned long long, b) && \ @@ -183,7 +188,7 @@ struct f2fs_rwsem { }; struct f2fs_mount_info { - unsigned int opt; + unsigned long long opt; block_t root_reserved_blocks; /* root reserved blocks */ block_t root_reserved_nodes; /* root reserved nodes */ kuid_t s_resuid; /* reserved blocks for uid */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index d47ec718f3be79..ccb47708644450 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -352,7 +352,7 @@ static match_table_t f2fs_checkpoint_tokens = { struct f2fs_fs_context { struct f2fs_mount_info info; - unsigned int opt_mask; /* Bits changed */ + unsigned long long opt_mask; /* Bits changed */ unsigned int spec_mask; unsigned short qname_mask; }; @@ -360,23 +360,23 @@ struct f2fs_fs_context { #define F2FS_CTX_INFO(ctx) ((ctx)->info) static inline void ctx_set_opt(struct f2fs_fs_context *ctx, - unsigned int flag) + enum f2fs_mount_opt flag) { - ctx->info.opt |= flag; - ctx->opt_mask |= flag; + ctx->info.opt |= BIT(flag); + ctx->opt_mask |= BIT(flag); } static inline void ctx_clear_opt(struct f2fs_fs_context *ctx, - unsigned int flag) + enum f2fs_mount_opt flag) { - ctx->info.opt &= ~flag; - ctx->opt_mask |= flag; + ctx->info.opt &= ~BIT(flag); + ctx->opt_mask |= BIT(flag); } static inline bool ctx_test_opt(struct f2fs_fs_context *ctx, - unsigned int flag) + enum f2fs_mount_opt flag) { - return ctx->info.opt & flag; + return ctx->info.opt & BIT(flag); } void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate, @@ -1371,7 +1371,7 @@ static int f2fs_check_compression(struct fs_context *fc, ctx_test_opt(ctx, F2FS_MOUNT_COMPRESS_CACHE)) f2fs_info(sbi, "Image doesn't support compression"); clear_compression_spec(ctx); - ctx->opt_mask &= ~F2FS_MOUNT_COMPRESS_CACHE; + ctx->opt_mask &= ~BIT(F2FS_MOUNT_COMPRESS_CACHE); return 0; } if (ctx->spec_mask & F2FS_SPEC_compress_extension) { @@ -1439,42 +1439,42 @@ static int f2fs_check_opt_consistency(struct fs_context *fc, return -EINVAL; if (f2fs_hw_should_discard(sbi) && - (ctx->opt_mask & F2FS_MOUNT_DISCARD) && + (ctx->opt_mask & BIT(F2FS_MOUNT_DISCARD)) && !ctx_test_opt(ctx, F2FS_MOUNT_DISCARD)) { f2fs_warn(sbi, "discard is required for zoned block devices"); return -EINVAL; } if (!f2fs_hw_support_discard(sbi) && - (ctx->opt_mask & F2FS_MOUNT_DISCARD) && + (ctx->opt_mask & BIT(F2FS_MOUNT_DISCARD)) && ctx_test_opt(ctx, F2FS_MOUNT_DISCARD)) { f2fs_warn(sbi, "device does not support discard"); ctx_clear_opt(ctx, F2FS_MOUNT_DISCARD); - ctx->opt_mask &= ~F2FS_MOUNT_DISCARD; + ctx->opt_mask &= ~BIT(F2FS_MOUNT_DISCARD); } if (f2fs_sb_has_device_alias(sbi) && - (ctx->opt_mask & F2FS_MOUNT_READ_EXTENT_CACHE) && + (ctx->opt_mask & BIT(F2FS_MOUNT_READ_EXTENT_CACHE)) && !ctx_test_opt(ctx, F2FS_MOUNT_READ_EXTENT_CACHE)) { f2fs_err(sbi, "device aliasing requires extent cache"); return -EINVAL; } if (test_opt(sbi, RESERVE_ROOT) && - (ctx->opt_mask & F2FS_MOUNT_RESERVE_ROOT) && + (ctx->opt_mask & BIT(F2FS_MOUNT_RESERVE_ROOT)) && ctx_test_opt(ctx, F2FS_MOUNT_RESERVE_ROOT)) { f2fs_info(sbi, "Preserve previous reserve_root=%u", F2FS_OPTION(sbi).root_reserved_blocks); ctx_clear_opt(ctx, F2FS_MOUNT_RESERVE_ROOT); - ctx->opt_mask &= ~F2FS_MOUNT_RESERVE_ROOT; + ctx->opt_mask &= ~BIT(F2FS_MOUNT_RESERVE_ROOT); } if (test_opt(sbi, RESERVE_NODE) && - (ctx->opt_mask & F2FS_MOUNT_RESERVE_NODE) && + (ctx->opt_mask & BIT(F2FS_MOUNT_RESERVE_NODE)) && ctx_test_opt(ctx, F2FS_MOUNT_RESERVE_NODE)) { f2fs_info(sbi, "Preserve previous reserve_node=%u", F2FS_OPTION(sbi).root_reserved_nodes); ctx_clear_opt(ctx, F2FS_MOUNT_RESERVE_NODE); - ctx->opt_mask &= ~F2FS_MOUNT_RESERVE_NODE; + ctx->opt_mask &= ~BIT(F2FS_MOUNT_RESERVE_NODE); } err = f2fs_check_test_dummy_encryption(fc, sb); From fbc0774b6d55722c90a4509ec8089071b9e7aa18 Mon Sep 17 00:00:00 2001 From: Masaharu Noguchi Date: Mon, 17 Nov 2025 21:27:54 +0900 Subject: [PATCH 621/684] docs: f2fs: wrap ASCII tables in literal blocks to fix LaTeX build Sphinx's LaTeX builder fails when converting the nested ASCII tables in f2fs.rst, producing the following error: "Markup is unsupported in LaTeX: longtable does not support nesting a table." Wrap the affected ASCII tables in literal code blocks to force Sphinx to render them verbatim. This prevents nested longtables and fixes the PDF build failure on Sphinx 8.2.x. Acked-by: Bagas Sanjaya Reviewed-by: Akira Yokosawa Signed-off-by: Masaharu Noguchi Acked-by: Jonathan Corbet Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- Documentation/filesystems/f2fs.rst | 131 +++++++++++++++-------------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index a8d02fe5be8399..cb90d1ae82d012 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -188,34 +188,36 @@ fault_type=%d Support configuring fault injection type, should be enabled with fault_injection option, fault type value is shown below, it supports single or combined type. - =========================== ========== - Type_Name Type_Value - =========================== ========== - FAULT_KMALLOC 0x00000001 - FAULT_KVMALLOC 0x00000002 - FAULT_PAGE_ALLOC 0x00000004 - FAULT_PAGE_GET 0x00000008 - FAULT_ALLOC_BIO 0x00000010 (obsolete) - FAULT_ALLOC_NID 0x00000020 - FAULT_ORPHAN 0x00000040 - FAULT_BLOCK 0x00000080 - FAULT_DIR_DEPTH 0x00000100 - FAULT_EVICT_INODE 0x00000200 - FAULT_TRUNCATE 0x00000400 - FAULT_READ_IO 0x00000800 - FAULT_CHECKPOINT 0x00001000 - FAULT_DISCARD 0x00002000 - FAULT_WRITE_IO 0x00004000 - FAULT_SLAB_ALLOC 0x00008000 - FAULT_DQUOT_INIT 0x00010000 - FAULT_LOCK_OP 0x00020000 - FAULT_BLKADDR_VALIDITY 0x00040000 - FAULT_BLKADDR_CONSISTENCE 0x00080000 - FAULT_NO_SEGMENT 0x00100000 - FAULT_INCONSISTENT_FOOTER 0x00200000 - FAULT_TIMEOUT 0x00400000 (1000ms) - FAULT_VMALLOC 0x00800000 - =========================== ========== + .. code-block:: none + + =========================== ========== + Type_Name Type_Value + =========================== ========== + FAULT_KMALLOC 0x00000001 + FAULT_KVMALLOC 0x00000002 + FAULT_PAGE_ALLOC 0x00000004 + FAULT_PAGE_GET 0x00000008 + FAULT_ALLOC_BIO 0x00000010 (obsolete) + FAULT_ALLOC_NID 0x00000020 + FAULT_ORPHAN 0x00000040 + FAULT_BLOCK 0x00000080 + FAULT_DIR_DEPTH 0x00000100 + FAULT_EVICT_INODE 0x00000200 + FAULT_TRUNCATE 0x00000400 + FAULT_READ_IO 0x00000800 + FAULT_CHECKPOINT 0x00001000 + FAULT_DISCARD 0x00002000 + FAULT_WRITE_IO 0x00004000 + FAULT_SLAB_ALLOC 0x00008000 + FAULT_DQUOT_INIT 0x00010000 + FAULT_LOCK_OP 0x00020000 + FAULT_BLKADDR_VALIDITY 0x00040000 + FAULT_BLKADDR_CONSISTENCE 0x00080000 + FAULT_NO_SEGMENT 0x00100000 + FAULT_INCONSISTENT_FOOTER 0x00200000 + FAULT_TIMEOUT 0x00400000 (1000ms) + FAULT_VMALLOC 0x00800000 + =========================== ========== mode=%s Control block allocation mode which supports "adaptive" and "lfs". In "lfs" mode, there should be no random writes towards main area. @@ -296,14 +298,15 @@ nocheckpoint_merge Disable checkpoint merge feature. compress_algorithm=%s Control compress algorithm, currently f2fs supports "lzo", "lz4", "zstd" and "lzo-rle" algorithm. compress_algorithm=%s:%d Control compress algorithm and its compress level, now, only - "lz4" and "zstd" support compress level config. - - ========= =========== - algorithm level range - ========= =========== - lz4 3 - 16 - zstd 1 - 22 - ========= =========== + "lz4" and "zstd" support compress level config:: + + ========= =========== + algorithm level range + ========= =========== + lz4 3 - 16 + zstd 1 - 22 + ========= =========== + compress_log_size=%u Support configuring compress cluster size. The size will be 4KB * (1 << %u). The default and minimum sizes are 16KB. compress_extension=%s Support adding specified extension, so that f2fs can enable @@ -368,38 +371,42 @@ errors=%s Specify f2fs behavior on critical errors. This supports modes: the partition in read-only mode. By default it uses "continue" mode. - ====================== =============== =============== ======== - mode continue remount-ro panic - ====================== =============== =============== ======== - access ops normal normal N/A - syscall errors -EIO -EROFS N/A - mount option rw ro N/A - pending dir write keep keep N/A - pending non-dir write drop keep N/A - pending node write drop keep N/A - pending meta write keep keep N/A - ====================== =============== =============== ======== + .. code-block:: none + + ====================== =============== =============== ======== + mode continue remount-ro panic + ====================== =============== =============== ======== + access ops normal normal N/A + syscall errors -EIO -EROFS N/A + mount option rw ro N/A + pending dir write keep keep N/A + pending non-dir write drop keep N/A + pending node write drop keep N/A + pending meta write keep keep N/A + ====================== =============== =============== ======== nat_bits Enable nat_bits feature to enhance full/empty nat blocks access, by default it's disabled. lookup_mode=%s Control the directory lookup behavior for casefolded directories. This option has no effect on directories that do not have the casefold feature enabled. - ================== ======================================== - Value Description - ================== ======================================== - perf (Default) Enforces a hash-only lookup. - The linear search fallback is always - disabled, ignoring the on-disk flag. - compat Enables the linear search fallback for - compatibility with directory entries - created by older kernel that used a - different case-folding algorithm. - This mode ignores the on-disk flag. - auto F2FS determines the mode based on the - on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL` - flag. - ================== ======================================== + .. code-block:: none + + ================== ======================================== + Value Description + ================== ======================================== + perf (Default) Enforces a hash-only lookup. + The linear search fallback is always + disabled, ignoring the on-disk flag. + compat Enables the linear search fallback for + compatibility with directory entries + created by older kernel that used a + different case-folding algorithm. + This mode ignores the on-disk flag. + auto F2FS determines the mode based on the + on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL` + flag. + ================== ======================================== ======================== ============================================================ Debugfs Entries From 8f11fe52fc1fa39ccfaa7c1e256f53e35d2839fa Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 28 Nov 2025 17:25:34 +0800 Subject: [PATCH 622/684] f2fs: support to show curseg.next_blkoff in debugfs cat /sys/kernel/debug/f2fs/status Main area: 17 segs, 17 secs 17 zones TYPE blkoff segno secno zoneno dirty_seg full_seg valid_blk - COLD data: 0 4 4 4 0 0 0 - WARM data: 0 7 7 7 0 0 0 - HOT data: 1 5 5 5 2 0 512 - Dir dnode: 3 0 0 0 1 0 2 - File dnode: 0 1 1 1 0 0 0 - Indir nodes: 0 2 2 2 0 0 0 - Pinned file: 0 -1 -1 -1 - ATGC data: 0 -1 -1 -1 Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/debug.c | 29 +++++++++++++++++++---------- fs/f2fs/f2fs.h | 1 + 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 43a83bbd3bc5ab..032683835569f8 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -251,6 +251,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) for (i = CURSEG_HOT_DATA; i < NO_CHECK_TYPE; i++) { struct curseg_info *curseg = CURSEG_I(sbi, i); + si->blkoff[i] = curseg->next_blkoff; si->curseg[i] = curseg->segno; si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno); si->curzone[i] = GET_ZONE_FROM_SEC(sbi, si->cursec[i]); @@ -508,55 +509,63 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", si->main_area_segs, si->main_area_sections, si->main_area_zones); - seq_printf(s, " TYPE %8s %8s %8s %10s %10s %10s\n", - "segno", "secno", "zoneno", "dirty_seg", "full_seg", "valid_blk"); - seq_printf(s, " - COLD data: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " TYPE %8s %8s %8s %8s %10s %10s %10s\n", + "blkoff", "segno", "secno", "zoneno", "dirty_seg", "full_seg", "valid_blk"); + seq_printf(s, " - COLD data: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_COLD_DATA], si->curseg[CURSEG_COLD_DATA], si->cursec[CURSEG_COLD_DATA], si->curzone[CURSEG_COLD_DATA], si->dirty_seg[CURSEG_COLD_DATA], si->full_seg[CURSEG_COLD_DATA], si->valid_blks[CURSEG_COLD_DATA]); - seq_printf(s, " - WARM data: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " - WARM data: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_WARM_DATA], si->curseg[CURSEG_WARM_DATA], si->cursec[CURSEG_WARM_DATA], si->curzone[CURSEG_WARM_DATA], si->dirty_seg[CURSEG_WARM_DATA], si->full_seg[CURSEG_WARM_DATA], si->valid_blks[CURSEG_WARM_DATA]); - seq_printf(s, " - HOT data: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " - HOT data: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_HOT_DATA], si->curseg[CURSEG_HOT_DATA], si->cursec[CURSEG_HOT_DATA], si->curzone[CURSEG_HOT_DATA], si->dirty_seg[CURSEG_HOT_DATA], si->full_seg[CURSEG_HOT_DATA], si->valid_blks[CURSEG_HOT_DATA]); - seq_printf(s, " - Dir dnode: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " - Dir dnode: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_HOT_NODE], si->curseg[CURSEG_HOT_NODE], si->cursec[CURSEG_HOT_NODE], si->curzone[CURSEG_HOT_NODE], si->dirty_seg[CURSEG_HOT_NODE], si->full_seg[CURSEG_HOT_NODE], si->valid_blks[CURSEG_HOT_NODE]); - seq_printf(s, " - File dnode: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " - File dnode: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_WARM_NODE], si->curseg[CURSEG_WARM_NODE], si->cursec[CURSEG_WARM_NODE], si->curzone[CURSEG_WARM_NODE], si->dirty_seg[CURSEG_WARM_NODE], si->full_seg[CURSEG_WARM_NODE], si->valid_blks[CURSEG_WARM_NODE]); - seq_printf(s, " - Indir nodes: %8d %8d %8d %10u %10u %10u\n", + seq_printf(s, " - Indir nodes: %8d %8d %8d %8d %10u %10u %10u\n", + si->blkoff[CURSEG_COLD_NODE], si->curseg[CURSEG_COLD_NODE], si->cursec[CURSEG_COLD_NODE], si->curzone[CURSEG_COLD_NODE], si->dirty_seg[CURSEG_COLD_NODE], si->full_seg[CURSEG_COLD_NODE], si->valid_blks[CURSEG_COLD_NODE]); - seq_printf(s, " - Pinned file: %8d %8d %8d\n", + seq_printf(s, " - Pinned file: %8d %8d %8d %8d\n", + si->blkoff[CURSEG_COLD_DATA_PINNED], si->curseg[CURSEG_COLD_DATA_PINNED], si->cursec[CURSEG_COLD_DATA_PINNED], si->curzone[CURSEG_COLD_DATA_PINNED]); - seq_printf(s, " - ATGC data: %8d %8d %8d\n", + seq_printf(s, " - ATGC data: %8d %8d %8d %8d\n", + si->blkoff[CURSEG_ALL_DATA_ATGC], si->curseg[CURSEG_ALL_DATA_ATGC], si->cursec[CURSEG_ALL_DATA_ATGC], si->curzone[CURSEG_ALL_DATA_ATGC]); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 55d29d50159e7b..007195a1d4eb6b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4188,6 +4188,7 @@ struct f2fs_stat_info { int gc_secs[2][2]; int tot_blks, data_blks, node_blks; int bg_data_blks, bg_node_blks; + int blkoff[NR_CURSEG_TYPE]; int curseg[NR_CURSEG_TYPE]; int cursec[NR_CURSEG_TYPE]; int curzone[NR_CURSEG_TYPE]; From 37345eae9deaa2e4f372eeb98f6594cd0ee0916e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 28 Nov 2025 17:25:07 +0800 Subject: [PATCH 623/684] f2fs: fix to not account invalid blocks in get_left_section_blocks() w/ LFS mode, in get_left_section_blocks(), we should not account the blocks which were used before and now are invalided, otherwise those blocks will be counted as freed one in has_curseg_enough_space(), result in missing to trigger GC in time. Cc: stable@kernel.org Fixes: 249ad438e1d9 ("f2fs: add a method for calculating the remaining blocks in the current segment in LFS mode.") Fixes: bf34c93d2645 ("f2fs: check curseg space before foreground GC") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 0b54d87409b083..07dcbcbeb7c6d3 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -612,10 +612,12 @@ static inline int reserved_sections(struct f2fs_sb_info *sbi) static inline unsigned int get_left_section_blocks(struct f2fs_sb_info *sbi, enum log_type type, unsigned int segno) { - if (f2fs_lfs_mode(sbi) && __is_large_section(sbi)) - return CAP_BLKS_PER_SEC(sbi) - SEGS_TO_BLKS(sbi, - (segno - GET_START_SEG_FROM_SEC(sbi, segno))) - + if (f2fs_lfs_mode(sbi)) { + unsigned int used_blocks = __is_large_section(sbi) ? SEGS_TO_BLKS(sbi, + (segno - GET_START_SEG_FROM_SEC(sbi, segno))) : 0; + return CAP_BLKS_PER_SEC(sbi) - used_blocks - CURSEG_I(sbi, type)->next_blkoff; + } return CAP_BLKS_PER_SEC(sbi) - get_ckpt_valid_blocks(sbi, segno, true); } From 8d1cb17aca466b361cca17834b8bb1cf3e3d1818 Mon Sep 17 00:00:00 2001 From: YH Lin Date: Fri, 28 Nov 2025 11:23:57 +0800 Subject: [PATCH 624/684] f2fs: optimize trace_f2fs_write_checkpoint with enums This patch optimizes the tracepoint by replacing these hardcoded strings with a new enumeration f2fs_cp_phase. 1.Defines enum f2fs_cp_phase with values for each checkpoint phase. 2.Updates trace_f2fs_write_checkpoint to accept a u16 phase argument instead of a string pointer. 3.Uses __print_symbolic in TP_printk to convert the enum values back to their corresponding strings for human-readable trace output. This change reduces the storage overhead for each trace event by replacing a variable-length string with a 2-byte integer, while maintaining the same readable output in ftrace. Signed-off-by: YH Lin Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 6 +++--- fs/f2fs/f2fs.h | 6 ++++++ include/trace/events/f2fs.h | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4c401b5b29336b..300664269eb624 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1673,7 +1673,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) goto out; } - trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops"); + trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_START_BLOCK_OPS); err = block_operations(sbi); if (err) @@ -1681,7 +1681,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) stat_cp_time(cpc, CP_TIME_OP_LOCK); - trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); + trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_FINISH_BLOCK_OPS); f2fs_flush_merged_writes(sbi); @@ -1747,7 +1747,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* update CP_TIME to trigger checkpoint periodically */ f2fs_update_time(sbi, CP_TIME); - trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); + trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_FINISH_CHECKPOINT); out: if (cpc->reason != CP_RESIZE) f2fs_up_write(&sbi->cp_global_sem); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 007195a1d4eb6b..20edbb99b814a7 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -319,6 +319,12 @@ struct cp_control { struct cp_stats stats; }; +enum f2fs_cp_phase { + CP_PHASE_START_BLOCK_OPS, + CP_PHASE_FINISH_BLOCK_OPS, + CP_PHASE_FINISH_CHECKPOINT, +}; + /* * indicate meta/data type */ diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index e00611ead024dd..df4017dcc7013b 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -50,6 +50,9 @@ TRACE_DEFINE_ENUM(CP_PAUSE); TRACE_DEFINE_ENUM(CP_RESIZE); TRACE_DEFINE_ENUM(EX_READ); TRACE_DEFINE_ENUM(EX_BLOCK_AGE); +TRACE_DEFINE_ENUM(CP_PHASE_START_BLOCK_OPS); +TRACE_DEFINE_ENUM(CP_PHASE_FINISH_BLOCK_OPS); +TRACE_DEFINE_ENUM(CP_PHASE_FINISH_CHECKPOINT); #define show_block_type(type) \ __print_symbolic(type, \ @@ -175,6 +178,12 @@ TRACE_DEFINE_ENUM(EX_BLOCK_AGE); #define S_ALL_PERM (S_ISUID | S_ISGID | S_ISVTX | \ S_IRWXU | S_IRWXG | S_IRWXO) +#define show_cp_phase(phase) \ + __print_symbolic(phase, \ + { CP_PHASE_START_BLOCK_OPS, "start block_ops" }, \ + { CP_PHASE_FINISH_BLOCK_OPS, "finish block_ops" }, \ + { CP_PHASE_FINISH_CHECKPOINT, "finish checkpoint" }) + struct f2fs_sb_info; struct f2fs_io_info; struct extent_info; @@ -1573,26 +1582,26 @@ TRACE_EVENT(f2fs_readpages, TRACE_EVENT(f2fs_write_checkpoint, - TP_PROTO(struct super_block *sb, int reason, const char *msg), + TP_PROTO(struct super_block *sb, int reason, u16 phase), - TP_ARGS(sb, reason, msg), + TP_ARGS(sb, reason, phase), TP_STRUCT__entry( __field(dev_t, dev) __field(int, reason) - __string(dest_msg, msg) + __field(u16, phase) ), TP_fast_assign( __entry->dev = sb->s_dev; __entry->reason = reason; - __assign_str(dest_msg); + __entry->phase = phase; ), TP_printk("dev = (%d,%d), checkpoint for %s, state = %s", show_dev(__entry->dev), show_cpreason(__entry->reason), - __get_str(dest_msg)) + show_cp_phase(__entry->phase)) ); DECLARE_EVENT_CLASS(f2fs_discard, From 76ee7fd6af6851ef78016139bd727057ba467c4e Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Mon, 24 Nov 2025 15:48:05 -0800 Subject: [PATCH 625/684] f2fs: ignore discard return value __blkdev_issue_discard() always returns 0, making the error assignment in __submit_discard_cmd() dead code. Initialize err to 0 and remove the error assignment from the __blkdev_issue_discard() call to err. Move fault injection code into already present if branch where err is set to -EIO. This preserves the fault injection behavior while removing dead error handling. Reviewed-by: Martin K. Petersen Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Reviewed-by: Chao Yu Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 8375dca7ed9e49..c26424f4768635 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1343,15 +1343,9 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, dc->di.len += len; + err = 0; if (time_to_inject(sbi, FAULT_DISCARD)) { err = -EIO; - } else { - err = __blkdev_issue_discard(bdev, - SECTOR_FROM_BLOCK(start), - SECTOR_FROM_BLOCK(len), - GFP_NOFS, &bio); - } - if (err) { spin_lock_irqsave(&dc->lock, flags); if (dc->state == D_PARTIAL) dc->state = D_SUBMIT; @@ -1360,6 +1354,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, break; } + __blkdev_issue_discard(bdev, SECTOR_FROM_BLOCK(start), + SECTOR_FROM_BLOCK(len), GFP_NOFS, &bio); f2fs_bug_on(sbi, !bio); /* From 6744c0b182c1f371135bc3f4e62b96ad884c9f89 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:00 -0800 Subject: [PATCH 626/684] perf stat: Allow no events to open if this is a "--null" run It is intended that a "--null" run doesn't open any events. Fixes: 2cc7aa995ce9 ("perf stat: Refactor retry/skip/fatal error handling") Tested-by: Ingo Molnar Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 5c06e9b61821d9..6410115ed9c5ef 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -923,7 +923,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) goto err_out; } } - if (!has_supported_counters) { + if (!has_supported_counters && !stat_config.null_run) { evsel__open_strerror(evlist__first(evsel_list), &target, open_err, msg, sizeof(msg)); ui__error("No supported events found.\n%s\n", msg); From a0a4173631bfcfd3520192c0a61cf911d6a52c3a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:01 -0800 Subject: [PATCH 627/684] libperf cpumap: Fix perf_cpu_map__max for an empty/NULL map Passing an empty map to perf_cpu_map__max triggered a SEGV. Explicitly test for the empty map. Reported-by: Ingo Molnar Closes: https://lore.kernel.org/linux-perf-users/aSwt7yzFjVJCEmVp@gmail.com/ Tested-by: Ingo Molnar Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/lib/perf/cpumap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c index 7e88417ba84d12..4160e7d2e120fe 100644 --- a/tools/lib/perf/cpumap.c +++ b/tools/lib/perf/cpumap.c @@ -368,10 +368,12 @@ struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map) .cpu = -1 }; - // cpu_map__trim_new() qsort()s it, cpu_map__default_new() sorts it as well. - return __perf_cpu_map__nr(map) > 0 - ? __perf_cpu_map__cpu(map, __perf_cpu_map__nr(map) - 1) - : result; + if (!map) + return result; + + // The CPUs are always sorted and nr is always > 0 as 0 length map is + // encoded as NULL. + return __perf_cpu_map__cpu(map, __perf_cpu_map__nr(map) - 1); } /** Is 'b' a subset of 'a'. */ From e2de90bdc9f55a2a98fe6ee014c070d5c1d7cfb7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:02 -0800 Subject: [PATCH 628/684] perf cpumap: Add "any" CPU handling to cpu_map__snprint_mask If the perf_cpu_map is empty or is just the any CPU value, then early return. Don't process the "any" CPU when creating the bitmap. Tested-by: Ingo Molnar Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/util/cpumap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 89570397a4b350..a80845038a5ebc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -684,16 +684,21 @@ size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size) unsigned char *bitmap; struct perf_cpu c, last_cpu = perf_cpu_map__max(map); - if (buf == NULL) + if (buf == NULL || size == 0) return 0; + if (last_cpu.cpu < 0) { + buf[0] = '\0'; + return 0; + } + bitmap = zalloc(last_cpu.cpu / 8 + 1); if (bitmap == NULL) { buf[0] = '\0'; return 0; } - perf_cpu_map__for_each_cpu(c, idx, map) + perf_cpu_map__for_each_cpu_skip_any(c, idx, map) bitmap[c.cpu / 8] |= 1 << (c.cpu % 8); for (int cpu = last_cpu.cpu / 4 * 4; cpu >= 0; cpu -= 4) { From 279b5a85ebdd17b8e6713583d0ad6cf00f53eb10 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:03 -0800 Subject: [PATCH 629/684] perf tests stat: Add "--null" coverage Ensure "--null" does a minimal run. Reported-by: Ingo Molnar Closes: https://lore.kernel.org/linux-perf-users/aSwt7yzFjVJCEmVp@gmail.com/ Tested-by: Ingo Molnar Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh index 985adc02749e2c..7885e875caf4b7 100755 --- a/tools/perf/tests/shell/stat.sh +++ b/tools/perf/tests/shell/stat.sh @@ -16,6 +16,17 @@ test_default_stat() { echo "Basic stat command test [Success]" } +test_null_stat() { + echo "Null stat command test" + if ! perf stat --null true 2>&1 | grep -E -q "Performance counter stats for 'true':" + then + echo "Null stat command test [Failed]" + err=1 + return + fi + echo "Null stat command test [Success]" +} + test_stat_record_report() { echo "stat record and report test" if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \ @@ -212,6 +223,7 @@ test_hybrid() { } test_default_stat +test_null_stat test_stat_record_report test_stat_record_script test_stat_repeat_weak_groups From c9a8c343ef2f9769a33650b7429f5a83ecba8380 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:04 -0800 Subject: [PATCH 630/684] perf stat: When no events, don't report an error if there is none Events may fail to open as no supported CPUs were specified on the command line. In this case a confusing "error" message of "success" can be reported. Let's skip the error in that case. Before: ``` $ perf stat -C2048 -e cycles -- true WARNING: A requested CPU in '2048' is not supported by PMU 'cpu' (CPUs 0-7) for event 'cycles' Error: No supported events found. The sys_perf_event_open() syscall returned with 0 (Success) for event (cpu/unknown-hardware/). "dmesg | grep -i perf" may provide additional information. ``` After: ``` $ perf stat -C2048 -e cycles -- true WARNING: A requested CPU in '2048' is not supported by PMU 'cpu' (CPUs 0-7) for event 'cycles' Error: No supported events found. ``` Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 6410115ed9c5ef..bd3c3de8d2009d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -924,8 +924,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) } } if (!has_supported_counters && !stat_config.null_run) { - evsel__open_strerror(evlist__first(evsel_list), &target, open_err, - msg, sizeof(msg)); + if (open_err) { + evsel__open_strerror(evlist__first(evsel_list), &target, open_err, + msg, sizeof(msg)); + } ui__error("No supported events found.\n%s\n", msg); if (child_pid != -1) From 84230ad2d2afbf0c44c32967e525c0ad92e26b4e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 1 Dec 2025 13:25:22 -0700 Subject: [PATCH 631/684] io_uring/poll: correctly handle io_poll_add() return value on update When the core of io_uring was updated to handle completions consistently and with fixed return codes, the POLL_REMOVE opcode with updates got slightly broken. If a POLL_ADD is pending and then POLL_REMOVE is used to update the events of that request, if that update causes the POLL_ADD to now trigger, then that completion is lost and a CQE is never posted. Additionally, ensure that if an update does cause an existing POLL_ADD to complete, that the completion value isn't always overwritten with -ECANCELED. For that case, whatever io_poll_add() set the value to should just be retained. Cc: stable@vger.kernel.org Fixes: 97b388d70b53 ("io_uring: handle completions in the core") Reported-by: syzbot+641eec6b7af1f62f2b99@syzkaller.appspotmail.com Tested-by: syzbot+641eec6b7af1f62f2b99@syzkaller.appspotmail.com Signed-off-by: Jens Axboe --- io_uring/poll.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/io_uring/poll.c b/io_uring/poll.c index 8aa4e3a31e730f..3f1d716dcfab33 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -937,12 +937,17 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags) ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED); /* successfully updated, don't complete poll request */ - if (!ret2 || ret2 == -EIOCBQUEUED) + if (ret2 == IOU_ISSUE_SKIP_COMPLETE) goto out; + /* request completed as part of the update, complete it */ + else if (ret2 == IOU_COMPLETE) + goto complete; } - req_set_fail(preq); io_req_set_res(preq, -ECANCELED, 0); +complete: + if (preq->cqe.res < 0) + req_set_fail(preq); preq->io_task_work.func = io_req_task_complete; io_req_task_work_add(preq); out: From 34c78b8610a9befdcc139d34a7c98365f018026d Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Tue, 2 Dec 2025 13:57:44 -0700 Subject: [PATCH 632/684] io_uring/io-wq: always retry worker create on ERESTART* If a task has a pending signal when create_io_thread() is called, copy_process() will return -ERESTARTNOINTR. io_should_retry_thread() will request a retry of create_io_thread() up to WORKER_INIT_LIMIT = 3 times. If all retries fail, the io_uring request will fail with ECANCELED. Commit 3918315c5dc ("io-wq: backoff when retrying worker creation") added a linear backoff to allow the thread to handle its signal before the retry. However, a thread receiving frequent signals may get unlucky and have a signal pending at every retry. Since the userspace task doesn't control when it receives signals, there's no easy way for it to prevent the create_io_thread() failure due to pending signals. The task may also lack the information necessary to regenerate the canceled SQE. So always retry the create_io_thread() on the ERESTART* errors, analogous to what a fork() syscall would do. EAGAIN can occur due to various persistent conditions such as exceeding RLIMIT_NPROC, so respect the WORKER_INIT_LIMIT retry limit for EAGAIN errors. Signed-off-by: Caleb Sander Mateos Signed-off-by: Jens Axboe --- io_uring/io-wq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c index 1d03b2fc4b2594..cd13d8aac3d26d 100644 --- a/io_uring/io-wq.c +++ b/io_uring/io-wq.c @@ -805,11 +805,12 @@ static inline bool io_should_retry_thread(struct io_worker *worker, long err) */ if (fatal_signal_pending(current)) return false; - if (worker->init_retries++ >= WORKER_INIT_LIMIT) - return false; + worker->init_retries++; switch (err) { case -EAGAIN: + return worker->init_retries <= WORKER_INIT_LIMIT; + /* Analogous to a fork() syscall, always retry on a restartable error */ case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTARTNOHAND: From f345be751b961ce91e0b883345eaa1d0993a4949 Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Tue, 2 Dec 2025 11:21:31 -0700 Subject: [PATCH 633/684] io_uring/trace: rename io_uring_queue_async_work event "rw" field The io_uring_queue_async_work tracepoint event stores an int rw field that represents whether the work item is hashed. Rename it to "hashed" and change its type to bool to more accurately reflect its value. Signed-off-by: Caleb Sander Mateos Signed-off-by: Jens Axboe --- include/trace/events/io_uring.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/trace/events/io_uring.h b/include/trace/events/io_uring.h index 45d15460b49532..34b31a855ea4a9 100644 --- a/include/trace/events/io_uring.h +++ b/include/trace/events/io_uring.h @@ -133,15 +133,15 @@ TRACE_EVENT(io_uring_file_get, * io_uring_queue_async_work - called before submitting a new async work * * @req: pointer to a submitted request - * @rw: type of workqueue, hashed or normal + * @hashed: whether async work is hashed * * Allows to trace asynchronous work submission. */ TRACE_EVENT(io_uring_queue_async_work, - TP_PROTO(struct io_kiocb *req, int rw), + TP_PROTO(struct io_kiocb *req, bool hashed), - TP_ARGS(req, rw), + TP_ARGS(req, hashed), TP_STRUCT__entry ( __field( void *, ctx ) @@ -150,7 +150,7 @@ TRACE_EVENT(io_uring_queue_async_work, __field( u8, opcode ) __field( unsigned long long, flags ) __field( struct io_wq_work *, work ) - __field( int, rw ) + __field( bool, hashed ) __string( op_str, io_uring_get_opcode(req->opcode) ) ), @@ -162,7 +162,7 @@ TRACE_EVENT(io_uring_queue_async_work, __entry->flags = (__force unsigned long long) req->flags; __entry->opcode = req->opcode; __entry->work = &req->work; - __entry->rw = rw; + __entry->hashed = hashed; __assign_str(op_str); ), @@ -170,7 +170,7 @@ TRACE_EVENT(io_uring_queue_async_work, TP_printk("ring %p, request %p, user_data 0x%llx, opcode %s, flags 0x%llx, %s queue, work %p", __entry->ctx, __entry->req, __entry->user_data, __get_str(op_str), __entry->flags, - __entry->rw ? "hashed" : "normal", __entry->work) + __entry->hashed ? "hashed" : "normal", __entry->work) ); /** From 05ce4c584cc6b783f3f113e9daa5a19f9bcd6e27 Mon Sep 17 00:00:00 2001 From: Fengnan Chang Date: Fri, 14 Nov 2025 17:21:48 +0800 Subject: [PATCH 634/684] block: use bio_alloc_bioset for passthru IO by default Use bio_alloc_bioset for passthru IO by default, so that we can enable bio cache for irq and polled passthru IO in later. Signed-off-by: Fengnan Chang Signed-off-by: Jens Axboe --- block/blk-map.c | 90 ++++++++++++++++----------------------- drivers/nvme/host/ioctl.c | 2 +- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index 17a1dc28867860..4533094d94583b 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -37,6 +37,25 @@ static struct bio_map_data *bio_alloc_map_data(struct iov_iter *data, return bmd; } +static inline void blk_mq_map_bio_put(struct bio *bio) +{ + bio_put(bio); +} + +static struct bio *blk_rq_map_bio_alloc(struct request *rq, + unsigned int nr_vecs, gfp_t gfp_mask) +{ + struct block_device *bdev = rq->q->disk ? rq->q->disk->part0 : NULL; + struct bio *bio; + + bio = bio_alloc_bioset(bdev, nr_vecs, rq->cmd_flags, gfp_mask, + &fs_bio_set); + if (!bio) + return NULL; + + return bio; +} + /** * bio_copy_from_iter - copy all pages from iov_iter to bio * @bio: The &struct bio which describes the I/O as destination @@ -154,10 +173,9 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data, nr_pages = bio_max_segs(DIV_ROUND_UP(offset + len, PAGE_SIZE)); ret = -ENOMEM; - bio = bio_kmalloc(nr_pages, gfp_mask); + bio = blk_rq_map_bio_alloc(rq, nr_pages, gfp_mask); if (!bio) goto out_bmd; - bio_init_inline(bio, NULL, nr_pages, req_op(rq)); if (map_data) { nr_pages = 1U << map_data->page_order; @@ -233,43 +251,12 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data, cleanup: if (!map_data) bio_free_pages(bio); - bio_uninit(bio); - kfree(bio); + blk_mq_map_bio_put(bio); out_bmd: kfree(bmd); return ret; } -static void blk_mq_map_bio_put(struct bio *bio) -{ - if (bio->bi_opf & REQ_ALLOC_CACHE) { - bio_put(bio); - } else { - bio_uninit(bio); - kfree(bio); - } -} - -static struct bio *blk_rq_map_bio_alloc(struct request *rq, - unsigned int nr_vecs, gfp_t gfp_mask) -{ - struct block_device *bdev = rq->q->disk ? rq->q->disk->part0 : NULL; - struct bio *bio; - - if (rq->cmd_flags & REQ_ALLOC_CACHE && (nr_vecs <= BIO_INLINE_VECS)) { - bio = bio_alloc_bioset(bdev, nr_vecs, rq->cmd_flags, gfp_mask, - &fs_bio_set); - if (!bio) - return NULL; - } else { - bio = bio_kmalloc(nr_vecs, gfp_mask); - if (!bio) - return NULL; - bio_init_inline(bio, bdev, nr_vecs, req_op(rq)); - } - return bio; -} - static int bio_map_user_iov(struct request *rq, struct iov_iter *iter, gfp_t gfp_mask) { @@ -318,25 +305,23 @@ static void bio_invalidate_vmalloc_pages(struct bio *bio) static void bio_map_kern_endio(struct bio *bio) { bio_invalidate_vmalloc_pages(bio); - bio_uninit(bio); - kfree(bio); + blk_mq_map_bio_put(bio); } -static struct bio *bio_map_kern(void *data, unsigned int len, enum req_op op, +static struct bio *bio_map_kern(struct request *rq, void *data, unsigned int len, gfp_t gfp_mask) { unsigned int nr_vecs = bio_add_max_vecs(data, len); struct bio *bio; - bio = bio_kmalloc(nr_vecs, gfp_mask); + bio = blk_rq_map_bio_alloc(rq, nr_vecs, gfp_mask); if (!bio) return ERR_PTR(-ENOMEM); - bio_init_inline(bio, NULL, nr_vecs, op); + if (is_vmalloc_addr(data)) { bio->bi_private = data; if (!bio_add_vmalloc(bio, data, len)) { - bio_uninit(bio); - kfree(bio); + blk_mq_map_bio_put(bio); return ERR_PTR(-EINVAL); } } else { @@ -349,8 +334,7 @@ static struct bio *bio_map_kern(void *data, unsigned int len, enum req_op op, static void bio_copy_kern_endio(struct bio *bio) { bio_free_pages(bio); - bio_uninit(bio); - kfree(bio); + blk_mq_map_bio_put(bio); } static void bio_copy_kern_endio_read(struct bio *bio) @@ -369,6 +353,7 @@ static void bio_copy_kern_endio_read(struct bio *bio) /** * bio_copy_kern - copy kernel address into bio + * @rq: request to fill * @data: pointer to buffer to copy * @len: length in bytes * @op: bio/request operation @@ -377,9 +362,10 @@ static void bio_copy_kern_endio_read(struct bio *bio) * copy the kernel address into a bio suitable for io to a block * device. Returns an error pointer in case of error. */ -static struct bio *bio_copy_kern(void *data, unsigned int len, enum req_op op, +static struct bio *bio_copy_kern(struct request *rq, void *data, unsigned int len, gfp_t gfp_mask) { + enum req_op op = req_op(rq); unsigned long kaddr = (unsigned long)data; unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = kaddr >> PAGE_SHIFT; @@ -394,10 +380,9 @@ static struct bio *bio_copy_kern(void *data, unsigned int len, enum req_op op, return ERR_PTR(-EINVAL); nr_pages = end - start; - bio = bio_kmalloc(nr_pages, gfp_mask); + bio = blk_rq_map_bio_alloc(rq, nr_pages, gfp_mask); if (!bio) return ERR_PTR(-ENOMEM); - bio_init_inline(bio, NULL, nr_pages, op); while (len) { struct page *page; @@ -431,8 +416,7 @@ static struct bio *bio_copy_kern(void *data, unsigned int len, enum req_op op, cleanup: bio_free_pages(bio); - bio_uninit(bio); - kfree(bio); + blk_mq_map_bio_put(bio); return ERR_PTR(-ENOMEM); } @@ -679,18 +663,16 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len, return -EINVAL; if (!blk_rq_aligned(rq->q, addr, len) || object_is_on_stack(kbuf)) - bio = bio_copy_kern(kbuf, len, req_op(rq), gfp_mask); + bio = bio_copy_kern(rq, kbuf, len, gfp_mask); else - bio = bio_map_kern(kbuf, len, req_op(rq), gfp_mask); + bio = bio_map_kern(rq, kbuf, len, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); ret = blk_rq_append_bio(rq, bio); - if (unlikely(ret)) { - bio_uninit(bio); - kfree(bio); - } + if (unlikely(ret)) + blk_mq_map_bio_put(bio); return ret; } EXPORT_SYMBOL(blk_rq_map_kern); diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index 4fa8400a5627ab..a9c097dacad6f7 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -447,7 +447,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, struct iov_iter iter; struct iov_iter *map_iter = NULL; struct request *req; - blk_opf_t rq_flags = REQ_ALLOC_CACHE; + blk_opf_t rq_flags = 0; blk_mq_req_flags_t blk_flags = 0; int ret; From 48f22f80938d94c34319f90674de6102ca37eabc Mon Sep 17 00:00:00 2001 From: Fengnan Chang Date: Fri, 14 Nov 2025 17:21:49 +0800 Subject: [PATCH 635/684] block: enable per-cpu bio cache by default Since after commit 12e4e8c7ab59 ("io_uring/rw: enable bio caches for IRQ rw"), bio_put is safe for task and irq context, bio_alloc_bioset is safe for task context and no one calls in irq context, so we can enable per cpu bio cache by default. Benchmarked with t/io_uring and ext4+nvme: taskset -c 6 /root/fio/t/io_uring -p0 -d128 -b4096 -s1 -c1 -F1 -B1 -R1 -X1 -n1 -P1 /mnt/testfile base IOPS is 562K, patch IOPS is 574K. The CPU usage of bio_alloc_bioset decrease from 1.42% to 1.22%. The worst case is allocate bio in CPU A but free in CPU B, still use t/io_uring and ext4+nvme: base IOPS is 648K, patch IOPS is 647K. Also use fio test ext4/xfs with libaio/sync/io_uring on null_blk and nvme, no obvious performance regression. Signed-off-by: Fengnan Chang Signed-off-by: Jens Axboe --- block/bio.c | 26 ++++++++++++-------------- block/fops.c | 4 ---- io_uring/rw.c | 1 - 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/block/bio.c b/block/bio.c index 7b13bdf72de09a..fa5ff36b443f91 100644 --- a/block/bio.c +++ b/block/bio.c @@ -517,20 +517,18 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, if (WARN_ON_ONCE(!mempool_initialized(&bs->bvec_pool) && nr_vecs > 0)) return NULL; - if (opf & REQ_ALLOC_CACHE) { - if (bs->cache && nr_vecs <= BIO_INLINE_VECS) { - bio = bio_alloc_percpu_cache(bdev, nr_vecs, opf, - gfp_mask, bs); - if (bio) - return bio; - /* - * No cached bio available, bio returned below marked with - * REQ_ALLOC_CACHE to particpate in per-cpu alloc cache. - */ - } else { - opf &= ~REQ_ALLOC_CACHE; - } - } + if (bs->cache && nr_vecs <= BIO_INLINE_VECS) { + opf |= REQ_ALLOC_CACHE; + bio = bio_alloc_percpu_cache(bdev, nr_vecs, opf, + gfp_mask, bs); + if (bio) + return bio; + /* + * No cached bio available, bio returned below marked with + * REQ_ALLOC_CACHE to participate in per-cpu alloc cache. + */ + } else + opf &= ~REQ_ALLOC_CACHE; /* * submit_bio_noacct() converts recursion to iteration; this means if diff --git a/block/fops.c b/block/fops.c index 4dad9c2d5796e6..4d32785b31d90e 100644 --- a/block/fops.c +++ b/block/fops.c @@ -184,8 +184,6 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos = iocb->ki_pos; int ret = 0; - if (iocb->ki_flags & IOCB_ALLOC_CACHE) - opf |= REQ_ALLOC_CACHE; bio = bio_alloc_bioset(bdev, nr_pages, opf, GFP_KERNEL, &blkdev_dio_pool); dio = container_of(bio, struct blkdev_dio, bio); @@ -333,8 +331,6 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, loff_t pos = iocb->ki_pos; int ret = 0; - if (iocb->ki_flags & IOCB_ALLOC_CACHE) - opf |= REQ_ALLOC_CACHE; bio = bio_alloc_bioset(bdev, nr_pages, opf, GFP_KERNEL, &blkdev_dio_pool); dio = container_of(bio, struct blkdev_dio, bio); diff --git a/io_uring/rw.c b/io_uring/rw.c index 331af6bf423483..70ca88cc1f5471 100644 --- a/io_uring/rw.c +++ b/io_uring/rw.c @@ -855,7 +855,6 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type) ret = kiocb_set_rw_flags(kiocb, rw->flags, rw_type); if (unlikely(ret)) return ret; - kiocb->ki_flags |= IOCB_ALLOC_CACHE; /* * If the file is marked O_NONBLOCK, still allow retry for it if it From ab4fb1d8f6e98575703474491538febff6b1a2c9 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 1 Dec 2025 16:43:26 -0500 Subject: [PATCH 636/684] scsi: sd: reject invalid pr_read_keys() num_keys values The pr_read_keys() interface has a u32 num_keys parameter. The SCSI PERSISTENT RESERVE IN command has a maximum READ KEYS service action size of 65536 bytes. Reject num_keys values that are too large to fit into the SCSI command. This will become important when pr_read_keys() is exposed to untrusted userspace via an ioctl. Signed-off-by: Stefan Hajnoczi Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0252d3f6bed173..32ae4898cea7cf 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1974,9 +1974,19 @@ static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info) { int result, i, data_offset, num_copy_keys; u32 num_keys = keys_info->num_keys; - int data_len = num_keys * 8 + 8; + int data_len; u8 *data; + /* + * Each reservation key takes 8 bytes and there is an 8-byte header + * before the reservation key list. The total size must fit into the + * 16-bit ALLOCATION LENGTH field. + */ + if (check_mul_overflow(num_keys, 8, &data_len) || + check_add_overflow(data_len, 8, &data_len) || + data_len > USHRT_MAX) + return -EINVAL; + data = kzalloc(data_len, GFP_KERNEL); if (!data) return -ENOMEM; From 38ec8469f39e0e96e7dd9b76f05e0f8eb78be681 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 1 Dec 2025 16:43:27 -0500 Subject: [PATCH 637/684] nvme: reject invalid pr_read_keys() num_keys values The pr_read_keys() interface has a u32 num_keys parameter. The NVMe Reservation Report command has a u32 maximum length. Reject num_keys values that are too large to fit. This will become important when pr_read_keys() is exposed to untrusted userspace via an ioctl. Signed-off-by: Stefan Hajnoczi Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Signed-off-by: Jens Axboe --- drivers/nvme/host/pr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c index ca6a74607b1397..ad2ecc2f49a972 100644 --- a/drivers/nvme/host/pr.c +++ b/drivers/nvme/host/pr.c @@ -228,7 +228,8 @@ static int nvme_pr_resv_report(struct block_device *bdev, void *data, static int nvme_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info) { - u32 rse_len, num_keys = keys_info->num_keys; + size_t rse_len; + u32 num_keys = keys_info->num_keys; struct nvme_reservation_status_ext *rse; int ret, i; bool eds; @@ -238,6 +239,9 @@ static int nvme_pr_read_keys(struct block_device *bdev, * enough to get enough keys to fill the return keys buffer. */ rse_len = struct_size(rse, regctl_eds, num_keys); + if (rse_len > U32_MAX) + return -EINVAL; + rse = kzalloc(rse_len, GFP_KERNEL); if (!rse) return -ENOMEM; From 22a1ffea5f805dfa21b64d1c7b5fe39c0c78c997 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 1 Dec 2025 16:43:28 -0500 Subject: [PATCH 638/684] block: add IOC_PR_READ_KEYS ioctl Add a Persistent Reservations ioctl to read the list of currently registered reservation keys. This calls the pr_ops->read_keys() function that was previously added in commit c787f1baa503 ("block: Add PR callouts for read keys and reservation") but was only used by the in-kernel SCSI target so far. The IOC_PR_READ_KEYS ioctl is necessary so that userspace applications that rely on Persistent Reservations ioctls have a way of inspecting the current state. Cluster managers and validation tests need this functionality. Signed-off-by: Stefan Hajnoczi Reviewed-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Signed-off-by: Jens Axboe --- block/ioctl.c | 56 +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/pr.h | 7 ++++++ 2 files changed, 63 insertions(+) diff --git a/block/ioctl.c b/block/ioctl.c index 2b3ab9bfc413da..c0802ebf54a635 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -423,6 +423,60 @@ static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode, return ops->pr_clear(bdev, c.key); } +static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode, + struct pr_read_keys __user *arg) +{ + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + struct pr_keys *keys_info; + struct pr_read_keys read_keys; + u64 __user *keys_ptr; + size_t keys_info_len; + size_t keys_copy_len; + int ret; + + if (!blkdev_pr_allowed(bdev, mode)) + return -EPERM; + if (!ops || !ops->pr_read_keys) + return -EOPNOTSUPP; + + if (copy_from_user(&read_keys, arg, sizeof(read_keys))) + return -EFAULT; + + keys_info_len = struct_size(keys_info, keys, read_keys.num_keys); + if (keys_info_len == SIZE_MAX) + return -EINVAL; + + keys_info = kzalloc(keys_info_len, GFP_KERNEL); + if (!keys_info) + return -ENOMEM; + + keys_info->num_keys = read_keys.num_keys; + + ret = ops->pr_read_keys(bdev, keys_info); + if (ret) + goto out; + + /* Copy out individual keys */ + keys_ptr = u64_to_user_ptr(read_keys.keys_ptr); + keys_copy_len = min(read_keys.num_keys, keys_info->num_keys) * + sizeof(keys_info->keys[0]); + + if (copy_to_user(keys_ptr, keys_info->keys, keys_copy_len)) { + ret = -EFAULT; + goto out; + } + + /* Copy out the arg struct */ + read_keys.generation = keys_info->generation; + read_keys.num_keys = keys_info->num_keys; + + if (copy_to_user(arg, &read_keys, sizeof(read_keys))) + ret = -EFAULT; +out: + kfree(keys_info); + return ret; +} + static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd, unsigned long arg) { @@ -645,6 +699,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode, return blkdev_pr_preempt(bdev, mode, argp, true); case IOC_PR_CLEAR: return blkdev_pr_clear(bdev, mode, argp); + case IOC_PR_READ_KEYS: + return blkdev_pr_read_keys(bdev, mode, argp); default: return blk_get_meta_cap(bdev, cmd, argp); } diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h index d8126415966f39..fcb74eab92c80c 100644 --- a/include/uapi/linux/pr.h +++ b/include/uapi/linux/pr.h @@ -56,6 +56,12 @@ struct pr_clear { __u32 __pad; }; +struct pr_read_keys { + __u32 generation; + __u32 num_keys; + __u64 keys_ptr; +}; + #define PR_FL_IGNORE_KEY (1 << 0) /* ignore existing key */ #define IOC_PR_REGISTER _IOW('p', 200, struct pr_registration) @@ -64,5 +70,6 @@ struct pr_clear { #define IOC_PR_PREEMPT _IOW('p', 203, struct pr_preempt) #define IOC_PR_PREEMPT_ABORT _IOW('p', 204, struct pr_preempt) #define IOC_PR_CLEAR _IOW('p', 205, struct pr_clear) +#define IOC_PR_READ_KEYS _IOWR('p', 206, struct pr_read_keys) #endif /* _UAPI_PR_H */ From 3e2cb9ee76c27f57bfdb7b4753b909594d4fa31a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 1 Dec 2025 16:43:29 -0500 Subject: [PATCH 639/684] block: add IOC_PR_READ_RESERVATION ioctl Add a Persistent Reservations ioctl to read the current reservation. This calls the pr_ops->read_reservation() function that was previously added in commit c787f1baa503 ("block: Add PR callouts for read keys and reservation") but was only used by the in-kernel SCSI target so far. The IOC_PR_READ_RESERVATION ioctl is necessary so that userspace applications that rely on Persistent Reservations ioctls have a way of inspecting the current state. Cluster managers and validation tests need this functionality. Signed-off-by: Stefan Hajnoczi Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Signed-off-by: Jens Axboe --- block/ioctl.c | 28 ++++++++++++++++++++++++++++ include/uapi/linux/pr.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/block/ioctl.c b/block/ioctl.c index c0802ebf54a635..61feed686418a6 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -477,6 +477,32 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode, return ret; } +static int blkdev_pr_read_reservation(struct block_device *bdev, + blk_mode_t mode, struct pr_read_reservation __user *arg) +{ + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + struct pr_held_reservation rsv = {}; + struct pr_read_reservation out = {}; + int ret; + + if (!blkdev_pr_allowed(bdev, mode)) + return -EPERM; + if (!ops || !ops->pr_read_reservation) + return -EOPNOTSUPP; + + ret = ops->pr_read_reservation(bdev, &rsv); + if (ret) + return ret; + + out.key = rsv.key; + out.generation = rsv.generation; + out.type = rsv.type; + + if (copy_to_user(arg, &out, sizeof(out))) + return -EFAULT; + return 0; +} + static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd, unsigned long arg) { @@ -701,6 +727,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode, return blkdev_pr_clear(bdev, mode, argp); case IOC_PR_READ_KEYS: return blkdev_pr_read_keys(bdev, mode, argp); + case IOC_PR_READ_RESERVATION: + return blkdev_pr_read_reservation(bdev, mode, argp); default: return blk_get_meta_cap(bdev, cmd, argp); } diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h index fcb74eab92c80c..847f3051057af7 100644 --- a/include/uapi/linux/pr.h +++ b/include/uapi/linux/pr.h @@ -62,6 +62,12 @@ struct pr_read_keys { __u64 keys_ptr; }; +struct pr_read_reservation { + __u64 key; + __u32 generation; + __u32 type; +}; + #define PR_FL_IGNORE_KEY (1 << 0) /* ignore existing key */ #define IOC_PR_REGISTER _IOW('p', 200, struct pr_registration) @@ -71,5 +77,6 @@ struct pr_read_keys { #define IOC_PR_PREEMPT_ABORT _IOW('p', 204, struct pr_preempt) #define IOC_PR_CLEAR _IOW('p', 205, struct pr_clear) #define IOC_PR_READ_KEYS _IOWR('p', 206, struct pr_read_keys) +#define IOC_PR_READ_RESERVATION _IOR('p', 207, struct pr_read_reservation) #endif /* _UAPI_PR_H */ From 71075d25ca5cae732fb57da065fbf14aeb3bcfc7 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Tue, 2 Dec 2025 19:58:09 -0800 Subject: [PATCH 640/684] blk-mq: add blk_rq_nr_bvec() helper Add a new helper function blk_rq_nr_bvec() that returns the number of bvecs in a request. This count represents the number of iterations rq_for_each_bvec() would perform on a request. Drivers need to pre-allocate bvec arrays before iterating through a request's bvecs. Currently, they manually count bvecs using rq_for_each_bvec() in a loop, which is repetitive. The new helper centralizes this logic. This pattern exists in loop and zloop drivers, where multi-bio requests require copying bvecs into a contiguous array before creating an iov_iter for file operations. Update loop and zloop drivers to use the new helper, eliminating duplicate code. This patch also provides a clear API to avoid any potential misuse of blk_nr_phys_segments() for calculating the bvecs since, one bvec can have more than one segments and use of blk_nr_phys_segments() can lead to extra memory allocation :- [ 6155.673749] nullb_bio: 128K bio as ONE bvec: sector=0, size=131072 [ 6155.673846] null_blk: #### null_handle_data_transfer:1375 [ 6155.673850] null_blk: nr_bvec=1 blk_rq_nr_phys_segments=2 [ 6155.674263] null_blk: #### null_handle_data_transfer:1375 [ 6155.674267] null_blk: nr_bvec=1 blk_rq_nr_phys_segments=1 Reviewed-by: Niklas Cassel Signed-off-by: Chaitanya Kulkarni Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/block/loop.c | 5 ++--- drivers/block/zloop.c | 5 ++--- include/linux/blk-mq.h | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index ebe751f3974267..272bc608e52824 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -348,11 +348,10 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, struct file *file = lo->lo_backing_file; struct bio_vec tmp; unsigned int offset; - int nr_bvec = 0; + unsigned int nr_bvec; int ret; - rq_for_each_bvec(tmp, rq, rq_iter) - nr_bvec++; + nr_bvec = blk_rq_nr_bvec(rq); if (rq->bio != rq->biotail) { diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 3f50321aa4a750..77bd6081b24452 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -394,7 +394,7 @@ static void zloop_rw(struct zloop_cmd *cmd) struct bio_vec tmp; unsigned long flags; sector_t zone_end; - int nr_bvec = 0; + unsigned int nr_bvec; int ret; atomic_set(&cmd->ref, 2); @@ -487,8 +487,7 @@ static void zloop_rw(struct zloop_cmd *cmd) spin_unlock_irqrestore(&zone->wp_lock, flags); } - rq_for_each_bvec(tmp, rq, rq_iter) - nr_bvec++; + nr_bvec = blk_rq_nr_bvec(rq); if (rq->bio != rq->biotail) { struct bio_vec *bvec; diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index eb7254b3ddddbb..cae9e857aea428 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -1213,6 +1213,24 @@ static inline unsigned short blk_rq_nr_discard_segments(struct request *rq) return max_t(unsigned short, rq->nr_phys_segments, 1); } +/** + * blk_rq_nr_bvec - return number of bvecs in a request + * @rq: request to calculate bvecs for + * + * Returns the number of bvecs. + */ +static inline unsigned int blk_rq_nr_bvec(struct request *rq) +{ + struct req_iterator rq_iter; + struct bio_vec bv; + unsigned int nr_bvec = 0; + + rq_for_each_bvec(bv, rq, rq_iter) + nr_bvec++; + + return nr_bvec; +} + int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist, struct scatterlist **last_sg); static inline int blk_rq_map_sg(struct request *rq, struct scatterlist *sglist) From c196bf43d706592d8801a7513603765080e495fb Mon Sep 17 00:00:00 2001 From: Cong Zhang Date: Wed, 3 Dec 2025 11:34:21 +0800 Subject: [PATCH 641/684] blk-mq: Abort suspend when wakeup events are pending During system suspend, wakeup capable IRQs for block device can be delayed, which can cause blk_mq_hctx_notify_offline() to hang indefinitely while waiting for pending request to complete. Skip the request waiting loop and abort suspend when wakeup events are pending to prevent the deadlock. Fixes: bf0beec0607d ("blk-mq: drain I/O when all CPUs in a hctx are offline") Signed-off-by: Cong Zhang Signed-off-by: Jens Axboe --- block/blk-mq.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 4e96bb2462475e..bd8b11c472a253 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -3718,6 +3719,7 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node) { struct blk_mq_hw_ctx *hctx = hlist_entry_safe(node, struct blk_mq_hw_ctx, cpuhp_online); + int ret = 0; if (blk_mq_hctx_has_online_cpu(hctx, cpu)) return 0; @@ -3738,12 +3740,24 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node) * frozen and there are no requests. */ if (percpu_ref_tryget(&hctx->queue->q_usage_counter)) { - while (blk_mq_hctx_has_requests(hctx)) + while (blk_mq_hctx_has_requests(hctx)) { + /* + * The wakeup capable IRQ handler of block device is + * not called during suspend. Skip the loop by checking + * pm_wakeup_pending to prevent the deadlock and improve + * suspend latency. + */ + if (pm_wakeup_pending()) { + clear_bit(BLK_MQ_S_INACTIVE, &hctx->state); + ret = -EBUSY; + break; + } msleep(5); + } percpu_ref_put(&hctx->queue->q_usage_counter); } - return 0; + return ret; } /* From 83c8f7b5e194eaf3fb268c513e23e23e892de8ed Mon Sep 17 00:00:00 2001 From: Joshua Hahn Date: Mon, 1 Dec 2025 10:07:38 -0800 Subject: [PATCH 642/684] mm/mm_init: Introduce a boot parameter for check_pages Use-after-free and double-free bugs can be very difficult to track down. The kernel is good at tracking these and preventing bad pages from being used/created through simple checks gated behind "check_pages_enabled". Currently, the only ways to enable this flag is by building with CONFIG_DEBUG_VM, or as a side effect of other checks such as init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others. These solutions are powerful, but may often be too coarse in balancing the performance vs. safety that a user may want, particularly in latency-sensitive production environments. Introduce a new boot parameter "check_pages", which enables page checking with no other side effects. It takes kstrbool-able inputs as an argument (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible; setting CONFIG_DEBUG_VM still enables page checking. Acked-by: SeongJae Park Acked-by: Michal Hocko Acked-by: Vlastimil Babka Reviewed-by: Anshuman Khandual Signed-off-by: Joshua Hahn Link: https://patch.msgid.link/20251201180739.2330474-1-joshua.hahnjy@gmail.com Signed-off-by: Mike Rapoport (Microsoft) --- Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++ mm/mm_init.c | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 6c42061ca20e58..acdc7fbdecacf0 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -669,6 +669,14 @@ nokmem -- Disable kernel memory accounting. nobpf -- Disable BPF memory accounting. + check_pages= [MM,EARLY] Enable sanity checking of pages after + allocations / before freeing. This adds checks to catch + double-frees, use-after-frees, and other sources of + page corruption by inspecting page internals (flags, + mapcount/refcount, memcg_data, etc.). + Format: { "0" | "1" } + Default: 0 (1 if CONFIG_DEBUG_VM is set) + checkreqprot= [SELINUX] Set initial checkreqprot flag value. Format: { "0" | "1" } See security/selinux/Kconfig help text. diff --git a/mm/mm_init.c b/mm/mm_init.c index 7712d887b6963b..220b7c6b5fb2ce 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -2525,6 +2525,14 @@ early_param("init_on_free", early_init_on_free); DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled); +static bool check_pages_enabled_early __initdata; + +static int __init early_check_pages(char *buf) +{ + return kstrtobool(buf, &check_pages_enabled_early); +} +early_param("check_pages", early_check_pages); + /* * Enable static keys related to various memory debugging and hardening options. * Some override others, and depend on early params that are evaluated in the @@ -2534,7 +2542,7 @@ DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled); static void __init mem_debugging_and_hardening_init(void) { bool page_poisoning_requested = false; - bool want_check_pages = false; + bool want_check_pages = check_pages_enabled_early; #ifdef CONFIG_PAGE_POISONING /* From 666065caa31aeb812978740bae21871067bb14b6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Dec 2025 10:50:14 +0100 Subject: [PATCH 643/684] pinctrl: add CONFIG_OF dependencies for microchip drivers The two newly added drivers fail to link on builds without CONFIG_OF: x86_64-linux-ld: drivers/pinctrl/pinctrl-pic64gx-gpio2.o: in function `pinconf_generic_dt_node_to_map_all': pinctrl-pic64gx-gpio2.c:(.text+0xc9): undefined reference to `pinconf_generic_dt_node_to_map' x86_64-linux-ld: drivers/pinctrl/pinctrl-mpfs-iomux0.o: in function `pinconf_generic_dt_node_to_map_all': pinctrl-mpfs-iomux0.c:(.text+0xc9): undefined reference to `pinconf_generic_dt_node_to_map' Add a Kconfig dependencies. Fixes: 38cf9d641314 ("pinctrl: add pic64gx "gpio2" pinmux driver") Fixes: 46397274da22 ("pinctrl: add polarfire soc iomux0 pinmux driver") Signed-off-by: Arnd Bergmann Acked-by: Conor Dooley Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 2e590913fa4417..bc7f37afc48bfa 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -489,6 +489,7 @@ config PINCTRL_PIC32MZDA config PINCTRL_PIC64GX bool "pic64gx gpio2 pinctrl driver" depends on ARCH_MICROCHIP || COMPILE_TEST + depends on OF select GENERIC_PINCONF default y help @@ -508,6 +509,7 @@ config PINCTRL_PISTACHIO config PINCTRL_POLARFIRE_SOC bool "Polarfire SoC pinctrl driver" depends on ARCH_MICROCHIP || COMPILE_TEST + depends on OF select GENERIC_PINCONF default y help From 552c1149af7ac0cffab6fccd13feeaf816dd1f53 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 4 Dec 2025 19:59:52 +0900 Subject: [PATCH 644/684] block: Clear BLK_ZONE_WPLUG_PLUGGED when aborting plugged BIOs Commit fe0418eb9bd6 ("block: Prevent potential deadlocks in zone write plug error recovery") added a WARN check in disk_put_zone_wplug() to verify that when the last reference to a zone write plug is dropped, this zone write plug does not have the BLK_ZONE_WPLUG_PLUGGED flag set, that is, that it is not plugged. However, the function disk_zone_wplug_abort(), which is called for zone reset and zone finish operations, does not clear this flag after emptying a zone write plug BIO list. This can result in the disk_put_zone_wplug() warning to trigger if the user (erroneously as that is bad pratcice) issues zone reset or zone finish operations while the target zone still has plugged BIOs. Modify disk_put_zone_wplug() to clear the BLK_ZONE_WPLUG_PLUGGED flag. And while at it, also add a lockdep annotation to ensure that this function is called with the zone write plug spinlock held. Fixes: fe0418eb9bd6 ("block: Prevent potential deadlocks in zone write plug error recovery") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- block/blk-zoned.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index dcc295721c2c08..394d8d74bba9b5 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -741,6 +741,8 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug) { struct bio *bio; + lockdep_assert_held(&zwplug->lock); + if (bio_list_empty(&zwplug->bio_list)) return; @@ -748,6 +750,8 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug) zwplug->disk->disk_name, zwplug->zone_no); while ((bio = bio_list_pop(&zwplug->bio_list))) blk_zone_wplug_bio_io_error(zwplug, bio); + + zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; } /* From 8a32282175c964eb15638e8dfe199fc13c060f67 Mon Sep 17 00:00:00 2001 From: shechenglong Date: Wed, 3 Dec 2025 23:17:49 +0800 Subject: [PATCH 645/684] block: fix comment for op_is_zone_mgmt() to include RESET_ALL REQ_OP_ZONE_RESET_ALL is a zone management request, and op_is_zone_mgmt() has returned true for it. Update the comment to remove the misleading exception note so the documentation matches the implementation. Fixes: 12a1c9353c47 ("block: fix op_is_zone_mgmt() to handle REQ_OP_ZONE_RESET_ALL") Signed-off-by: shechenglong Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- include/linux/blk_types.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index cbbcb9051ec374..5dc061d318a45d 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -479,10 +479,7 @@ static inline bool op_is_discard(blk_opf_t op) } /* - * Check if a bio or request operation is a zone management operation, with - * the exception of REQ_OP_ZONE_RESET_ALL which is treated as a special case - * due to its different handling in the block layer and device response in - * case of command failure. + * Check if a bio or request operation is a zone management operation. */ static inline bool op_is_zone_mgmt(enum req_op op) { From f7e3f852a42d7cd8f1af2c330d9d153e30c8adcf Mon Sep 17 00:00:00 2001 From: Shaurya Rane Date: Thu, 4 Dec 2025 23:42:59 +0530 Subject: [PATCH 646/684] block: fix memory leak in __blkdev_issue_zero_pages Move the fatal signal check before bio_alloc() to prevent a memory leak when BLKDEV_ZERO_KILLABLE is set and a fatal signal is pending. Previously, the bio was allocated before checking for a fatal signal. If a signal was pending, the code would break out of the loop without freeing or chaining the just-allocated bio, causing a memory leak. This matches the pattern already used in __blkdev_issue_write_zeroes() where the signal check precedes the allocation. Fixes: bf86bcdb4012 ("blk-lib: check for kill signal in ioctl BLKZEROOUT") Reported-by: syzbot+527a7e48a3d3d315d862@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=527a7e48a3d3d315d862 Signed-off-by: Shaurya Rane Reviewed-by: Keith Busch Tested-by: syzbot+527a7e48a3d3d315d862@syzkaller.appspotmail.com Signed-off-by: Jens Axboe --- block/blk-lib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-lib.c b/block/blk-lib.c index 19e0203cc18a9a..9e2cc58f881f89 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -202,13 +202,13 @@ static void __blkdev_issue_zero_pages(struct block_device *bdev, unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects); struct bio *bio; - bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask); - bio->bi_iter.bi_sector = sector; - if ((flags & BLKDEV_ZERO_KILLABLE) && fatal_signal_pending(current)) break; + bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask); + bio->bi_iter.bi_sector = sector; + do { unsigned int len; From 67582dfd870a138ec385de88c5f9df62a7c20254 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 28 Oct 2025 16:26:21 +0100 Subject: [PATCH 647/684] nvme-fc: check all request and response have been processed When the rport is removed there shouldn't be any in flight request or responses. Reviewed-by: Christoph Hellwig Signed-off-by: Daniel Wagner Signed-off-by: Keith Busch --- drivers/nvme/host/fc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 31fca144086572..6276347512bb21 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -520,6 +520,8 @@ nvme_fc_free_rport(struct kref *ref) WARN_ON(rport->remoteport.port_state != FC_OBJSTATE_DELETED); WARN_ON(!list_empty(&rport->ctrl_list)); + WARN_ON(!list_empty(&rport->ls_req_list)); + WARN_ON(!list_empty(&rport->ls_rcv_list)); /* remove from lport list */ spin_lock_irqsave(&nvme_fc_lock, flags); From f9929c518de861716117e52c363d140e0156e9ad Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 28 Oct 2025 16:26:22 +0100 Subject: [PATCH 648/684] nvmet-fcloop: check all request and response have been processed When the remoteport or the targetport are removed check that there are no inflight requests or responses. Reviewed-by: Christoph Hellwig Signed-off-by: Daniel Wagner Signed-off-by: Keith Busch --- drivers/nvme/target/fcloop.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index 5dffcc5becae86..4e429a1ea2bd12 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -1111,8 +1111,10 @@ fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport) rport->nport->rport = NULL; spin_unlock_irqrestore(&fcloop_lock, flags); - if (put_port) + if (put_port) { + WARN_ON(!list_empty(&rport->ls_list)); fcloop_nport_put(rport->nport); + } } static void @@ -1130,8 +1132,10 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport) tport->nport->tport = NULL; spin_unlock_irqrestore(&fcloop_lock, flags); - if (put_port) + if (put_port) { + WARN_ON(!list_empty(&tport->ls_list)); fcloop_nport_put(tport->nport); + } } #define FCLOOP_HW_QUEUES 4 From 86ef6f7fc7412e462a4e9ae7490862dfee06b913 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 28 Oct 2025 16:26:23 +0100 Subject: [PATCH 649/684] nvmet-fcloop: remove unused lsdir member. Nothing is using lsdir member in struct fcloop_lsreq. Reviewed-by: Christoph Hellwig Signed-off-by: Daniel Wagner Signed-off-by: Keith Busch --- drivers/nvme/target/fcloop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index 4e429a1ea2bd12..c30e9a3e014fb1 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -254,7 +254,6 @@ struct fcloop_nport { struct fcloop_lsreq { struct nvmefc_ls_req *lsreq; struct nvmefc_ls_rsp ls_rsp; - int lsdir; /* H2T or T2H */ int status; struct list_head ls_list; /* fcloop_rport->ls_list */ }; From b8201b50e403815f941d1c6581a27fdbfe7d0fd4 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Thu, 4 Dec 2025 13:51:14 -0800 Subject: [PATCH 650/684] io_uring/rsrc: clean up buffer cloning arg validation Get rid of some redundant checks and move the src arg validation to before the buffer table allocation, which simplifies error handling. Signed-off-by: Joanne Koong Signed-off-by: Jens Axboe --- io_uring/rsrc.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 3765a50329a8c5..5ad3d10413eb53 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -1186,12 +1186,16 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx return -EBUSY; nbufs = src_ctx->buf_table.nr; + if (!nbufs) + return -ENXIO; if (!arg->nr) arg->nr = nbufs; else if (arg->nr > nbufs) return -EINVAL; else if (arg->nr > IORING_MAX_REG_BUFFERS) return -EINVAL; + if (check_add_overflow(arg->nr, arg->src_off, &off) || off > nbufs) + return -EOVERFLOW; if (check_add_overflow(arg->nr, arg->dst_off, &nbufs)) return -EOVERFLOW; if (nbufs > IORING_MAX_REG_BUFFERS) @@ -1211,21 +1215,6 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx } } - ret = -ENXIO; - nbufs = src_ctx->buf_table.nr; - if (!nbufs) - goto out_free; - ret = -EINVAL; - if (!arg->nr) - arg->nr = nbufs; - else if (arg->nr > nbufs) - goto out_free; - ret = -EOVERFLOW; - if (check_add_overflow(arg->nr, arg->src_off, &off)) - goto out_free; - if (off > nbufs) - goto out_free; - off = arg->dst_off; i = arg->src_off; nr = arg->nr; @@ -1238,8 +1227,8 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx } else { dst_node = io_rsrc_node_alloc(ctx, IORING_RSRC_BUFFER); if (!dst_node) { - ret = -ENOMEM; - goto out_free; + io_rsrc_data_free(ctx, &data); + return -ENOMEM; } refcount_inc(&src_node->buf->refs); @@ -1265,10 +1254,6 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx WARN_ON_ONCE(ctx->buf_table.nr); ctx->buf_table = data; return 0; - -out_free: - io_rsrc_data_free(ctx, &data); - return ret; } /* From e29af2aba262833c8eba578b58d6bbb6b0866a67 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Thu, 4 Dec 2025 13:51:15 -0800 Subject: [PATCH 651/684] io_uring/rsrc: rename misleading src_node variable in io_clone_buffers() The variable holds nodes from the destination ring's existing buffer table. In io_clone_buffers(), the term "src" is used to refer to the source ring. Rename to node for clarity. Signed-off-by: Joanne Koong Signed-off-by: Jens Axboe --- io_uring/rsrc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 5ad3d10413eb53..04f56212398a57 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -1207,11 +1207,11 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx /* Fill entries in data from dst that won't overlap with src */ for (i = 0; i < min(arg->dst_off, ctx->buf_table.nr); i++) { - struct io_rsrc_node *src_node = ctx->buf_table.nodes[i]; + struct io_rsrc_node *node = ctx->buf_table.nodes[i]; - if (src_node) { - data.nodes[i] = src_node; - src_node->refs++; + if (node) { + data.nodes[i] = node; + node->refs++; } } From 57413f0899fab78be87bdb4272ac2f8be83a9b39 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 28 Oct 2025 16:26:24 +0100 Subject: [PATCH 652/684] nvmet-fc: use pr_* print macros instead of dev_* Many of the nvmet-fc log messages cannot print the device used, because it's not there yet: (NULL device *): {0:0} Association deleted Use the pr_* macros consistently throughout the module and match the output of the nvme-fc module. Using port:association ids are more useful when debugging what's going on, because these match now with the log entries from nvme-fc. Reviewed-by: Christoph Hellwig Signed-off-by: Daniel Wagner Signed-off-by: Keith Busch --- drivers/nvme/target/fc.c | 48 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index 7d84527d5a43ef..0d9784004c9b27 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -490,8 +490,7 @@ nvmet_fc_xmt_disconnect_assoc(struct nvmet_fc_tgt_assoc *assoc) sizeof(*discon_rqst) + sizeof(*discon_acc) + tgtport->ops->lsrqst_priv_sz), GFP_KERNEL); if (!lsop) { - dev_info(tgtport->dev, - "{%d:%d} send Disconnect Association failed: ENOMEM\n", + pr_info("{%d:%d}: send Disconnect Association failed: ENOMEM\n", tgtport->fc_target_port.port_num, assoc->a_id); return; } @@ -513,8 +512,7 @@ nvmet_fc_xmt_disconnect_assoc(struct nvmet_fc_tgt_assoc *assoc) ret = nvmet_fc_send_ls_req_async(tgtport, lsop, nvmet_fc_disconnect_assoc_done); if (ret) { - dev_info(tgtport->dev, - "{%d:%d} XMT Disconnect Association failed: %d\n", + pr_info("{%d:%d}: XMT Disconnect Association failed: %d\n", tgtport->fc_target_port.port_num, assoc->a_id, ret); kfree(lsop); } @@ -1187,8 +1185,7 @@ nvmet_fc_target_assoc_free(struct kref *ref) if (oldls) nvmet_fc_xmt_ls_rsp(tgtport, oldls); ida_free(&tgtport->assoc_cnt, assoc->a_id); - dev_info(tgtport->dev, - "{%d:%d} Association freed\n", + pr_info("{%d:%d}: Association freed\n", tgtport->fc_target_port.port_num, assoc->a_id); kfree(assoc); } @@ -1224,8 +1221,7 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) flush_workqueue(assoc->queues[i]->work_q); } - dev_info(tgtport->dev, - "{%d:%d} Association deleted\n", + pr_info("{%d:%d}: Association deleted\n", tgtport->fc_target_port.port_num, assoc->a_id); nvmet_fc_tgtport_put(tgtport); @@ -1716,9 +1712,9 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, } if (ret) { - dev_err(tgtport->dev, - "Create Association LS failed: %s\n", - validation_errors[ret]); + pr_err("{%d}: Create Association LS failed: %s\n", + tgtport->fc_target_port.port_num, + validation_errors[ret]); iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, sizeof(*acc), rqst->w0.ls_cmd, FCNVME_RJT_RC_LOGIC, @@ -1730,8 +1726,7 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, atomic_set(&queue->connected, 1); queue->sqhd = 0; /* best place to init value */ - dev_info(tgtport->dev, - "{%d:%d} Association created\n", + pr_info("{%d:%d}: Association created\n", tgtport->fc_target_port.port_num, iod->assoc->a_id); /* format a response */ @@ -1809,9 +1804,9 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport, } if (ret) { - dev_err(tgtport->dev, - "Create Connection LS failed: %s\n", - validation_errors[ret]); + pr_err("{%d}: Create Connection LS failed: %s\n", + tgtport->fc_target_port.port_num, + validation_errors[ret]); iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, sizeof(*acc), rqst->w0.ls_cmd, (ret == VERR_NO_ASSOC) ? @@ -1871,9 +1866,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, } if (ret || !assoc) { - dev_err(tgtport->dev, - "Disconnect LS failed: %s\n", - validation_errors[ret]); + pr_err("{%d}: Disconnect LS failed: %s\n", + tgtport->fc_target_port.port_num, + validation_errors[ret]); iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, sizeof(*acc), rqst->w0.ls_cmd, (ret == VERR_NO_ASSOC) ? @@ -1907,8 +1902,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, spin_unlock_irqrestore(&tgtport->lock, flags); if (oldls) { - dev_info(tgtport->dev, - "{%d:%d} Multiple Disconnect Association LS's " + pr_info("{%d:%d}: Multiple Disconnect Association LS's " "received\n", tgtport->fc_target_port.port_num, assoc->a_id); /* overwrite good response with bogus failure */ @@ -2051,8 +2045,8 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port, struct fcnvme_ls_rqst_w0 *w0 = (struct fcnvme_ls_rqst_w0 *)lsreqbuf; if (lsreqbuf_len > sizeof(union nvmefc_ls_requests)) { - dev_info(tgtport->dev, - "RCV %s LS failed: payload too large (%d)\n", + pr_info("{%d}: RCV %s LS failed: payload too large (%d)\n", + tgtport->fc_target_port.port_num, (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ? nvmefc_ls_names[w0->ls_cmd] : "", lsreqbuf_len); @@ -2060,8 +2054,8 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port, } if (!nvmet_fc_tgtport_get(tgtport)) { - dev_info(tgtport->dev, - "RCV %s LS failed: target deleting\n", + pr_info("{%d}: RCV %s LS failed: target deleting\n", + tgtport->fc_target_port.port_num, (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ? nvmefc_ls_names[w0->ls_cmd] : ""); return -ESHUTDOWN; @@ -2069,8 +2063,8 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port, iod = nvmet_fc_alloc_ls_iod(tgtport); if (!iod) { - dev_info(tgtport->dev, - "RCV %s LS failed: context allocation failed\n", + pr_info("{%d}: RCV %s LS failed: context allocation failed\n", + tgtport->fc_target_port.port_num, (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ? nvmefc_ls_names[w0->ls_cmd] : ""); nvmet_fc_tgtport_put(tgtport); From 525916ce496615f531091855604eab9ca573b195 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Thu, 4 Dec 2025 13:51:16 -0800 Subject: [PATCH 653/684] io_uring/rsrc: fix lost entries after cloned range When cloning with node replacements (IORING_REGISTER_DST_REPLACE), destination entries after the cloned range are not copied over. Add logic to copy them over to the new destination table. Fixes: c1329532d5aa ("io_uring/rsrc: allow cloning with node replacements") Cc: stable@vger.kernel.org Signed-off-by: Joanne Koong Signed-off-by: Jens Axboe --- io_uring/rsrc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 04f56212398a57..a63474b331bf89 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -1205,7 +1205,7 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx if (ret) return ret; - /* Fill entries in data from dst that won't overlap with src */ + /* Copy original dst nodes from before the cloned range */ for (i = 0; i < min(arg->dst_off, ctx->buf_table.nr); i++) { struct io_rsrc_node *node = ctx->buf_table.nodes[i]; @@ -1238,6 +1238,16 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx i++; } + /* Copy original dst nodes from after the cloned range */ + for (i = nbufs; i < ctx->buf_table.nr; i++) { + struct io_rsrc_node *node = ctx->buf_table.nodes[i]; + + if (node) { + data.nodes[i] = node; + node->refs++; + } + } + /* * If asked for replace, put the old table. data->nodes[] holds both * old and new nodes at this point. From b645d5a25d49a515026ec444f2ccb087fe9daa7f Mon Sep 17 00:00:00 2001 From: Chu Guangqing Date: Mon, 3 Nov 2025 10:41:31 +0800 Subject: [PATCH 654/684] nvme: fix typo error in nvme target Fix two spelling mistakes. Reviewed-by: Christoph Hellwig Signed-off-by: Chu Guangqing Signed-off-by: Keith Busch --- drivers/nvme/target/admin-cmd.c | 2 +- drivers/nvme/target/core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index 3e378153a78174..3da31bb1183eb7 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -708,7 +708,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req) /* * We don't really have a practical limit on the number of abort - * comands. But we don't do anything useful for abort either, so + * commands. But we don't do anything useful for abort either, so * no point in allowing more abort commands than the spec requires. */ id->acl = 3; diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index da94d1c7699eba..cc88e5a28c8a9d 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -40,7 +40,7 @@ EXPORT_SYMBOL_GPL(nvmet_wq); * - the nvmet_transports array * * When updating any of those lists/structures write lock should be obtained, - * while when reading (popolating discovery log page or checking host-subsystem + * while when reading (populating discovery log page or checking host-subsystem * link) read lock is obtained to allow concurrent reads. */ DECLARE_RWSEM(nvmet_config_sem); From ce234d838d3b0566bcbf3fd13b546f176564ca07 Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Mon, 24 Nov 2025 08:49:20 +0200 Subject: [PATCH 655/684] nvmet-rdma: use kvcalloc for commands and responses arrays Replace kcalloc with kvcalloc for allocation of the commands and responses arrays. Each command structure is 272 bytes and each response structure is 672 bytes. These arrays typically exceed a single page, and grow much larger with high queue depths (e.g., commands >2MB, responses >170KB) kvcalloc automatically falls back to vmalloc for large or fragmented allocations, improving reliability. In our case, this memory is not aimed for DMA operations and could be safely allocated by kvcalloc. Using virtually contiguous memory helps to avoid allocation failures and out-of-memory conditions common with kcalloc on large pools. Signed-off-by: Israel Rukshin Reviewed-by: Max Gurtovoy Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/target/rdma.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 0485e25ab797c0..9c12b2361a6d7a 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -367,7 +367,7 @@ nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev, struct nvmet_rdma_cmd *cmds; int ret = -EINVAL, i; - cmds = kcalloc(nr_cmds, sizeof(struct nvmet_rdma_cmd), GFP_KERNEL); + cmds = kvcalloc(nr_cmds, sizeof(struct nvmet_rdma_cmd), GFP_KERNEL); if (!cmds) goto out; @@ -382,7 +382,7 @@ nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev, out_free: while (--i >= 0) nvmet_rdma_free_cmd(ndev, cmds + i, admin); - kfree(cmds); + kvfree(cmds); out: return ERR_PTR(ret); } @@ -394,7 +394,7 @@ static void nvmet_rdma_free_cmds(struct nvmet_rdma_device *ndev, for (i = 0; i < nr_cmds; i++) nvmet_rdma_free_cmd(ndev, cmds + i, admin); - kfree(cmds); + kvfree(cmds); } static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev, @@ -455,7 +455,7 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue) NUMA_NO_NODE, false, true)) goto out; - queue->rsps = kcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp), + queue->rsps = kvcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp), GFP_KERNEL); if (!queue->rsps) goto out_free_sbitmap; @@ -473,7 +473,7 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue) out_free: while (--i >= 0) nvmet_rdma_free_rsp(ndev, &queue->rsps[i]); - kfree(queue->rsps); + kvfree(queue->rsps); out_free_sbitmap: sbitmap_free(&queue->rsp_tags); out: @@ -487,7 +487,7 @@ static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue) for (i = 0; i < nr_rsps; i++) nvmet_rdma_free_rsp(ndev, &queue->rsps[i]); - kfree(queue->rsps); + kvfree(queue->rsps); sbitmap_free(&queue->rsp_tags); } From 5c8d134f01556affce430a25e1551d78d45ebc9d Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Mon, 24 Nov 2025 08:49:21 +0200 Subject: [PATCH 656/684] nvmet-tcp: use kvcalloc for commands array Replace kcalloc with kvcalloc for allocation of the commands array. Each command structure is 712 bytes. The array typically exceeds a single page, and grows much larger with high queue depths (e.g., commands >182KB). kvcalloc automatically falls back to vmalloc for large or fragmented allocations, improving reliability. In our case, this memory is not aimed for DMA operations and could be safely allocated by kvcalloc. Using virtually contiguous memory helps to avoid allocation failures and out-of-memory conditions common with kcalloc on large pools. Signed-off-by: Israel Rukshin Reviewed-by: Max Gurtovoy Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/target/tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 470bf37e5a6372..23623a95d2b9e9 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1484,7 +1484,7 @@ static int nvmet_tcp_alloc_cmds(struct nvmet_tcp_queue *queue) struct nvmet_tcp_cmd *cmds; int i, ret = -EINVAL, nr_cmds = queue->nr_cmds; - cmds = kcalloc(nr_cmds, sizeof(struct nvmet_tcp_cmd), GFP_KERNEL); + cmds = kvcalloc(nr_cmds, sizeof(struct nvmet_tcp_cmd), GFP_KERNEL); if (!cmds) goto out; @@ -1500,7 +1500,7 @@ static int nvmet_tcp_alloc_cmds(struct nvmet_tcp_queue *queue) out_free: while (--i >= 0) nvmet_tcp_free_cmd(cmds + i); - kfree(cmds); + kvfree(cmds); out: return ret; } @@ -1514,7 +1514,7 @@ static void nvmet_tcp_free_cmds(struct nvmet_tcp_queue *queue) nvmet_tcp_free_cmd(cmds + i); nvmet_tcp_free_cmd(&queue->connect); - kfree(cmds); + kvfree(cmds); } static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue) From bb9f4cca7c031de6f0e85f7ba24abf0172829f85 Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Sun, 23 Nov 2025 16:46:48 +0200 Subject: [PATCH 657/684] nvme-auth: use kvfree() for memory allocated with kvcalloc() Memory allocated by kvcalloc() may come from vmalloc or kmalloc, so use kvfree() instead of kfree() for proper deallocation. Fixes: aa36d711e945 ("nvme-auth: convert dhchap_auth_list to an array") Signed-off-by: Israel Rukshin Reviewed-by: Max Gurtovoy Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/host/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c index a01178caf15bb5..8f3ccb317e4de6 100644 --- a/drivers/nvme/host/auth.c +++ b/drivers/nvme/host/auth.c @@ -1122,7 +1122,7 @@ void nvme_auth_free(struct nvme_ctrl *ctrl) if (ctrl->dhchap_ctxs) { for (i = 0; i < ctrl_max_dhchaps(ctrl); i++) nvme_auth_free_dhchap(&ctrl->dhchap_ctxs[i]); - kfree(ctrl->dhchap_ctxs); + kvfree(ctrl->dhchap_ctxs); } if (ctrl->host_key) { nvme_auth_free_key(ctrl->host_key); From 13989207ee29c40501e719512e8dc90768325895 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Mon, 17 Nov 2025 10:43:43 -0800 Subject: [PATCH 658/684] nvme-fabrics: add ENOKEY to no retry criteria for authentication failures With authentication, in addition to EKEYREJECTED there is also no point in retrying reconnects when status is ENOKEY. Thus, add -ENOKEY as another criteria to determine when to stop retries. Cc: Daniel Wagner Cc: Hannes Reinecke Closes: https://lore.kernel.org/linux-nvme/20250829-nvme-fc-sync-v3-0-d69c87e63aee@kernel.org/ Signed-off-by: Justin Tee Tested-by: Daniel Wagner Reviewed-by: Daniel Wagner Reviewed-by: Hannes Reinecke Signed-off-by: Keith Busch --- drivers/nvme/host/fabrics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 2e58a7ce109052..55a8afd2efd503 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -592,7 +592,7 @@ bool nvmf_should_reconnect(struct nvme_ctrl *ctrl, int status) if (status > 0 && (status & NVME_STATUS_DNR)) return false; - if (status == -EKEYREJECTED) + if (status == -EKEYREJECTED || status == -ENOKEY) return false; if (ctrl->opts->max_reconnects == -1 || From 78385c7299f7514697d196b3233a91bd5e485591 Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Thu, 4 Dec 2025 15:43:31 -0700 Subject: [PATCH 659/684] io_uring/kbuf: use READ_ONCE() for userspace-mapped memory The struct io_uring_buf elements in a buffer ring are in a memory region accessible from userspace. A malicious/buggy userspace program could therefore write to them at any time, so they should be accessed with READ_ONCE() in the kernel. Commit 98b6fa62c84f ("io_uring/kbuf: always use READ_ONCE() to read ring provided buffer lengths") already switched the reads of the len field to READ_ONCE(). Do the same for bid and addr. Signed-off-by: Caleb Sander Mateos Fixes: c7fb19428d67 ("io_uring: add support for ring mapped supplied buffers") Cc: Joanne Koong Signed-off-by: Jens Axboe --- io_uring/kbuf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 8a329556f8dff3..52b636d00a6b23 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -44,7 +44,7 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) buf_len -= this_len; /* Stop looping for invalid buffer length of 0 */ if (buf_len || !this_len) { - buf->addr += this_len; + buf->addr = READ_ONCE(buf->addr) + this_len; buf->len = buf_len; return false; } @@ -198,9 +198,9 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len, if (*len == 0 || *len > buf_len) *len = buf_len; req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT; - req->buf_index = buf->bid; + req->buf_index = READ_ONCE(buf->bid); sel.buf_list = bl; - sel.addr = u64_to_user_ptr(buf->addr); + sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); if (io_should_commit(req, issue_flags)) { io_kbuf_commit(req, sel.buf_list, *len, 1); @@ -280,7 +280,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, if (!arg->max_len) arg->max_len = INT_MAX; - req->buf_index = buf->bid; + req->buf_index = READ_ONCE(buf->bid); do { u32 len = READ_ONCE(buf->len); @@ -295,7 +295,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, } } - iov->iov_base = u64_to_user_ptr(buf->addr); + iov->iov_base = u64_to_user_ptr(READ_ONCE(buf->addr)); iov->iov_len = len; iov++; From 5123509628e1ebe74bb5ec801de088f36df07d64 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:05 -0800 Subject: [PATCH 660/684] perf tests stat: Add test for error for an offline CPU Add a test that if an offline CPU is requested perf stat will fail. $ perf test -vv "perf stat tests" 101: perf stat tests: --- start --- test child forked, pid 46965 Basic stat command test Basic stat command test [Success] Null stat command test Null stat command test [Success] Offline CPU stat command test (cpu 8) Offline CPU stat command test [Success] stat record and report test stat record and report test [Success] stat record and script test stat record and script test [Success] stat repeat weak groups test stat repeat weak groups test [Success] Topdown event group test Topdown event group test [Success] Topdown weak groups test Topdown weak groups test [Skipped event parsing failed] cputype test cputype test [Success] hybrid test hybrid test [Success] ---- end(0) ---- 101: perf stat tests : Ok Reported-by: Thomas Richter Closes: https://lore.kernel.org/linux-perf-users/94313b82-888b-4f42-9fb0-4585f9e90080@linux.ibm.com/ Signed-off-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/stat.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh index 7885e875caf4b7..0b2f0f88ca1667 100755 --- a/tools/perf/tests/shell/stat.sh +++ b/tools/perf/tests/shell/stat.sh @@ -27,6 +27,32 @@ test_null_stat() { echo "Null stat command test [Success]" } +find_offline_cpu() { + for i in $(seq 1 4096) + do + if [[ ! -f /sys/devices/system/cpu/cpu$i/online || \ + $(cat /sys/devices/system/cpu/cpu$i/online) == "0" ]] + then + echo $i + return + fi + done + echo "Failed to find offline CPU" + exit 1 +} + +test_offline_cpu_stat() { + cpu=$(find_offline_cpu) + echo "Offline CPU stat command test (cpu $cpu)" + if ! perf stat "-C$cpu" -e cycles true 2>&1 | grep -E -q "No supported events found." + then + echo "Offline CPU stat command test [Failed]" + err=1 + return + fi + echo "Offline CPU stat command test [Success]" +} + test_stat_record_report() { echo "stat record and report test" if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \ @@ -224,6 +250,7 @@ test_hybrid() { test_default_stat test_null_stat +test_offline_cpu_stat test_stat_record_report test_stat_record_script test_stat_repeat_weak_groups From d509d14fff783969904954eaf5d94f092c6fce19 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Dec 2025 13:47:06 -0800 Subject: [PATCH 661/684] perf stat: Improve handling of termination by signal When interrupting perf stat in repeat mode with a signal the signal is passed to the child process but the repeat doesn't terminate: ``` $ perf stat -v --null --repeat 10 sleep 1 Control descriptor is not initialized [ perf stat: executing run #1 ... ] [ perf stat: executing run #2 ... ] ^Csleep: Interrupt [ perf stat: executing run #3 ... ] [ perf stat: executing run #4 ... ] [ perf stat: executing run #5 ... ] [ perf stat: executing run #6 ... ] [ perf stat: executing run #7 ... ] [ perf stat: executing run #8 ... ] [ perf stat: executing run #9 ... ] [ perf stat: executing run #10 ... ] Performance counter stats for 'sleep 1' (10 runs): 0.9500 +- 0.0512 seconds time elapsed ( +- 5.39% ) 0.01user 0.02system 0:09.53elapsed 0%CPU (0avgtext+0avgdata 18940maxresident)k 29944inputs+0outputs (0major+2629minor)pagefaults 0swaps ``` Terminate the repeated run and give a reasonable exit value: ``` $ perf stat -v --null --repeat 10 sleep 1 Control descriptor is not initialized [ perf stat: executing run #1 ... ] [ perf stat: executing run #2 ... ] [ perf stat: executing run #3 ... ] ^Csleep: Interrupt Performance counter stats for 'sleep 1' (10 runs): 0.680 +- 0.321 seconds time elapsed ( +- 47.16% ) Command exited with non-zero status 130 0.00user 0.01system 0:02.05elapsed 0%CPU (0avgtext+0avgdata 70688maxresident)k 0inputs+0outputs (0major+5002minor)pagefaults 0swaps ``` Note, this also changes the exit value for non-repeat runs when interrupted by a signal. Reported-by: Ingo Molnar Closes: https://lore.kernel.org/lkml/aS5wjmbAM9ka3M2g@gmail.com/ Signed-off-by: Ian Rogers Tested-by: Thomas Richter Signed-off-by: Namhyung Kim --- tools/perf/builtin-stat.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index bd3c3de8d2009d..ab40d85fb1259f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1007,10 +1007,20 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) goto err_out; } - if (WIFSIGNALED(status)) + if (WIFSIGNALED(status)) { + /* + * We want to indicate failure to stop a repeat run, + * hence negative. We want the value to be the exit code + * of perf, which for termination by a signal is 128 + * plus the signal number. + */ + err = 0 - (128 + WTERMSIG(status)); psignal(WTERMSIG(status), argv[0]); + } else { + err = WEXITSTATUS(status); + } } else { - status = dispatch_events(forks, timeout, interval, ×); + err = dispatch_events(forks, timeout, interval, ×); } disable_counters(); @@ -1050,7 +1060,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) if (!STAT_RECORD) evlist__close(evsel_list); - return WEXITSTATUS(status); + return err; err_out: if (forks) @@ -2969,7 +2979,7 @@ int cmd_stat(int argc, const char **argv) evlist__reset_prev_raw_counts(evsel_list); status = run_perf_stat(argc, argv, run_idx); - if (status == -1) + if (status < 0) break; if (forever && !interval) { @@ -3039,5 +3049,6 @@ int cmd_stat(int argc, const char **argv) evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close); - return status; + /* Only the low byte of status becomes the exit code. */ + return abs(status); } From f0445613314f474c1a0ec6fa8a5cd153a618f1b6 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 2 Dec 2025 16:30:53 -0600 Subject: [PATCH 662/684] 9p: fix cache/debug options printing in v9fs_show_options commit 4eb3117888a92 changed the cache= option to accept either string shortcuts or bitfield values. It also changed /proc/mounts to emit the option as the hexadecimal numeric value rather than the shortcut string. However, by printing "cache=%x" without the leading 0x, shortcuts such as "cache=loose" will emit "cache=f" and 'f' is not a string that is parseable by kstrtoint(), so remounting may fail if a remount with "cache=f" is attempted. debug=%x has had the same problem since options have been displayed in c4fac9100456 ("9p: Implement show_options") Fix these by adding the 0x prefix to the hexadecimal value shown in /proc/mounts. Fixes: 4eb3117888a92 ("fs/9p: Rework cache modes and add new options to Documentation") Signed-off-by: Eric Sandeen Message-ID: <54b93378-dcf1-4b04-922d-c8b4393da299@redhat.com> [Dominique: use %#x at Al Viro's suggestion, also handle debug] Tested-by: Remi Pommarel Signed-off-by: Dominique Martinet --- fs/9p/v9fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 05fc2ba3c5d42e..2f5c5f3123b73d 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -132,7 +132,7 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root) struct v9fs_session_info *v9ses = root->d_sb->s_fs_info; if (v9ses->debug) - seq_printf(m, ",debug=%x", v9ses->debug); + seq_printf(m, ",debug=%#x", v9ses->debug); if (!uid_eq(v9ses->dfltuid, V9FS_DEFUID)) seq_printf(m, ",dfltuid=%u", from_kuid_munged(&init_user_ns, v9ses->dfltuid)); @@ -148,7 +148,7 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root) if (v9ses->nodev) seq_puts(m, ",nodevmap"); if (v9ses->cache) - seq_printf(m, ",cache=%x", v9ses->cache); + seq_printf(m, ",cache=%#x", v9ses->cache); #ifdef CONFIG_9P_FSCACHE if (v9ses->cachetag && (v9ses->cache & CACHE_FSCACHE)) seq_printf(m, ",cachetag=%s", v9ses->cachetag); From 3e281113f871d7f9c69ca55a4d806a72180b7e8a Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 2 Dec 2025 16:34:51 -0600 Subject: [PATCH 663/684] 9p: fix new mount API cache option handling After commit 4eb3117888a92, 9p needs to be able to accept numerical cache= mount options as well as the string "shortcuts" because the option is printed numerically in /proc/mounts rather than by string. This was missed in the mount API conversion, which used an enum for the shortcuts and therefore could not handle a numeric equivalent as an argument to the cache option. Fix this by removing the enum and reverting to the slightly more open-coded option handling for Opt_cache, with the reinstated get_cache_mode() helper. Signed-off-by: Eric Sandeen Message-ID: <48cdeec9-5bb9-4c7a-a203-39bb8e0ef443@redhat.com> Tested-by: Remi Pommarel Signed-off-by: Dominique Martinet --- fs/9p/v9fs.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 2f5c5f3123b73d..057487efaaeb2d 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -72,15 +72,6 @@ static const struct constant_table p9_versions[] = { {} }; -static const struct constant_table p9_cache_mode[] = { - { "loose", CACHE_SC_LOOSE }, - { "fscache", CACHE_SC_FSCACHE }, - { "mmap", CACHE_SC_MMAP }, - { "readahead", CACHE_SC_READAHEAD }, - { "none", CACHE_SC_NONE }, - {} -}; - /* * This structure contains all parameters used for the core code, * the client, and all the transports. @@ -97,7 +88,7 @@ const struct fs_parameter_spec v9fs_param_spec[] = { fsparam_flag ("noxattr", Opt_noxattr), fsparam_flag ("directio", Opt_directio), fsparam_flag ("ignoreqv", Opt_ignoreqv), - fsparam_enum ("cache", Opt_cache, p9_cache_mode), + fsparam_string ("cache", Opt_cache), fsparam_string ("cachetag", Opt_cachetag), fsparam_string ("access", Opt_access), fsparam_flag ("posixacl", Opt_posixacl), @@ -124,6 +115,33 @@ const struct fs_parameter_spec v9fs_param_spec[] = { {} }; +/* Interpret mount options for cache mode */ +static int get_cache_mode(char *s) +{ + int version = -EINVAL; + + if (!strcmp(s, "loose")) { + version = CACHE_SC_LOOSE; + p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); + } else if (!strcmp(s, "fscache")) { + version = CACHE_SC_FSCACHE; + p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); + } else if (!strcmp(s, "mmap")) { + version = CACHE_SC_MMAP; + p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n"); + } else if (!strcmp(s, "readahead")) { + version = CACHE_SC_READAHEAD; + p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n"); + } else if (!strcmp(s, "none")) { + version = CACHE_SC_NONE; + p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); + } else if (kstrtoint(s, 0, &version) != 0) { + version = -EINVAL; + pr_info("Unknown Cache mode or invalid value %s\n", s); + } + return version; +} + /* * Display the mount options in /proc/mounts. */ @@ -269,8 +287,10 @@ int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param) #endif break; case Opt_cache: - session_opts->cache = result.uint_32; - p9_debug(P9_DEBUG_9P, "Cache mode: %s\n", param->string); + r = get_cache_mode(param->string); + if (r < 0) + return r; + session_opts->cache = r; break; case Opt_access: s = param->string; From a4c694bfc2455e82b7caf6045ca893d123e0ed11 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Thu, 4 Dec 2025 15:54:50 -0800 Subject: [PATCH 664/684] io_uring/kbuf: use WRITE_ONCE() for userspace-shared buffer ring fields buf->addr and buf->len reside in memory shared with userspace. They should be written with WRITE_ONCE() to guarantee atomic stores and prevent tearing or other unsafe compiler optimizations. Signed-off-by: Joanne Koong Cc: Caleb Sander Mateos Signed-off-by: Jens Axboe --- io_uring/kbuf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 52b636d00a6b23..796d131107ddb9 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -44,11 +44,11 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) buf_len -= this_len; /* Stop looping for invalid buffer length of 0 */ if (buf_len || !this_len) { - buf->addr = READ_ONCE(buf->addr) + this_len; - buf->len = buf_len; + WRITE_ONCE(buf->addr, READ_ONCE(buf->addr) + this_len); + WRITE_ONCE(buf->len, buf_len); return false; } - buf->len = 0; + WRITE_ONCE(buf->len, 0); bl->head++; len -= this_len; } @@ -291,7 +291,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, arg->partial_map = 1; if (iov != arg->iovs) break; - buf->len = len; + WRITE_ONCE(buf->len, len); } } From 55d57b3bcc7efcab812a8179e2dc17d781302997 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 5 Dec 2025 10:20:47 -0700 Subject: [PATCH 665/684] io_uring/poll: unify poll waitqueue entry and list removal For some cases, the order in which the waitq entry list and head writing happens is important, for others it doesn't really matter. But it's somewhat confusing to have them spread out over the file. Abstract out the nicely documented code in io_pollfree_wake() and move it into a helper, and use that helper consistently rather than having other call sites manually do the same thing. While at it, correct a comment function name as well. Signed-off-by: Jens Axboe --- io_uring/poll.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/io_uring/poll.c b/io_uring/poll.c index 3f1d716dcfab33..aac4b3b881fb71 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -138,14 +138,32 @@ static void io_init_poll_iocb(struct io_poll *poll, __poll_t events) init_waitqueue_func_entry(&poll->wait, io_poll_wake); } +static void io_poll_remove_waitq(struct io_poll *poll) +{ + /* + * If the waitqueue is being freed early but someone is already holds + * ownership over it, we have to tear down the request as best we can. + * That means immediately removing the request from its waitqueue and + * preventing all further accesses to the waitqueue via the request. + */ + list_del_init(&poll->wait.entry); + + /* + * Careful: this *must* be the last step, since as soon as req->head is + * NULL'ed out, the request can be completed and freed, since + * io_poll_remove_entry() will no longer need to take the waitqueue + * lock. + */ + smp_store_release(&poll->head, NULL); +} + static inline void io_poll_remove_entry(struct io_poll *poll) { struct wait_queue_head *head = smp_load_acquire(&poll->head); if (head) { spin_lock_irq(&head->lock); - list_del_init(&poll->wait.entry); - poll->head = NULL; + io_poll_remove_waitq(poll); spin_unlock_irq(&head->lock); } } @@ -368,23 +386,7 @@ static __cold int io_pollfree_wake(struct io_kiocb *req, struct io_poll *poll) io_poll_mark_cancelled(req); /* we have to kick tw in case it's not already */ io_poll_execute(req, 0); - - /* - * If the waitqueue is being freed early but someone is already - * holds ownership over it, we have to tear down the request as - * best we can. That means immediately removing the request from - * its waitqueue and preventing all further accesses to the - * waitqueue via the request. - */ - list_del_init(&poll->wait.entry); - - /* - * Careful: this *must* be the last step, since as soon - * as req->head is NULL'ed out, the request can be - * completed and freed, since aio_poll_complete_work() - * will no longer need to take the waitqueue lock. - */ - smp_store_release(&poll->head, NULL); + io_poll_remove_waitq(poll); return 1; } @@ -413,8 +415,7 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, /* optional, saves extra locking for removal in tw handler */ if (mask && poll->events & EPOLLONESHOT) { - list_del_init(&poll->wait.entry); - poll->head = NULL; + io_poll_remove_waitq(poll); if (wqe_is_double(wait)) req->flags &= ~REQ_F_DOUBLE_POLL; else From 2eeb09fe1c5173b659929f92fee4461796ca8c14 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Dec 2025 13:11:49 -0300 Subject: [PATCH 666/684] libperf: Use 'extern' in LIBPERF_API visibility macro Use 'extern' on LIBPERF_API to address this issue that started appearing with gcc 15, first seen in ubuntu 25.10: evlist.c: In function 'perf_evlist__purge': evlist.c:202:17: error: implicit declaration of function 'perf_evsel__delete'; did you mean 'perf_evsel__exit'? [-Wimplicit-function-declaration] 202 | perf_evsel__delete(pos); | ^~~~~~~~~~~~~~~~~~ | perf_evsel__exit evlist.c:202:17: error: nested extern declaration of 'perf_evsel__delete' [-Werror=nested-externs] evlist.c: In function 'perf_evlist__open': evlist.c:261:23: error: implicit declaration of function 'perf_evsel__open'; did you mean 'perf_evsel__exit'? [-Wimplicit-function-declaration] 261 | err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); | ^~~~~~~~~~~~~~~~ | perf_evsel__exit evlist.c:261:23: error: nested extern declaration of 'perf_evsel__open' [-Werror=nested-externs] Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim --- tools/lib/perf/include/perf/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/perf/include/perf/core.h b/tools/lib/perf/include/perf/core.h index a3f6d68edad762..06cc132d88cf34 100644 --- a/tools/lib/perf/include/perf/core.h +++ b/tools/lib/perf/include/perf/core.h @@ -5,7 +5,7 @@ #include #ifndef LIBPERF_API -#define LIBPERF_API __attribute__((visibility("default"))) +#define LIBPERF_API extern __attribute__((visibility("default"))) #endif enum libperf_print_level { From 7bfe3b8ea6e30437e01fcb8e4f56ef6e4d986d0f Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Thu, 13 Nov 2025 04:41:49 +0000 Subject: [PATCH 667/684] Drivers: hv: Introduce mshv_vtl driver Provide an interface for Virtual Machine Monitor like OpenVMM and its use as OpenHCL paravisor to control VTL0 (Virtual trust Level). Expose devices and support IOCTLs for features like VTL creation, VTL0 memory management, context switch, making hypercalls, mapping VTL0 address space to VTL2 userspace, getting new VMBus messages and channel events in VTL2 etc. Co-developed-by: Roman Kisel Signed-off-by: Roman Kisel Co-developed-by: Saurabh Sengar Signed-off-by: Saurabh Sengar Reviewed-by: Michael Kelley Signed-off-by: Naman Jain Signed-off-by: Wei Liu --- arch/x86/hyperv/Makefile | 10 +- arch/x86/hyperv/hv_vtl.c | 30 + arch/x86/hyperv/mshv-asm-offsets.c | 37 + arch/x86/hyperv/mshv_vtl_asm.S | 116 +++ arch/x86/include/asm/mshyperv.h | 34 + drivers/hv/Kconfig | 27 +- drivers/hv/Makefile | 7 +- drivers/hv/mshv_vtl.h | 25 + drivers/hv/mshv_vtl_main.c | 1392 ++++++++++++++++++++++++++++ include/hyperv/hvgdk_mini.h | 106 +++ include/uapi/linux/mshv.h | 80 ++ 11 files changed, 1861 insertions(+), 3 deletions(-) create mode 100644 arch/x86/hyperv/mshv-asm-offsets.c create mode 100644 arch/x86/hyperv/mshv_vtl_asm.S create mode 100644 drivers/hv/mshv_vtl.h create mode 100644 drivers/hv/mshv_vtl_main.c diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 6f5d97cddd8056..56292102af6231 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1,7 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y := hv_init.o mmu.o nested.o irqdomain.o ivm.o obj-$(CONFIG_X86_64) += hv_apic.o -obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o +obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o mshv_vtl_asm.o + +$(obj)/mshv_vtl_asm.o: $(obj)/mshv-asm-offsets.h + +$(obj)/mshv-asm-offsets.h: $(obj)/mshv-asm-offsets.s FORCE + $(call filechk,offsets,__MSHV_ASM_OFFSETS_H__) ifdef CONFIG_X86_64 obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o @@ -12,3 +17,6 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o obj-$(CONFIG_CRASH_DUMP) += hv_crash.o hv_trampoline.o endif endif + +targets += mshv-asm-offsets.s +clean-files += mshv-asm-offsets.h diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 042e8712d8dea6..c0edaed0efb303 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -9,12 +9,17 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include #include <../kernel/smpboot.h> +#include "../../kernel/fpu/legacy.h" extern struct boot_params boot_params; static struct real_mode_header hv_vtl_real_mode_header; @@ -249,3 +254,28 @@ int __init hv_vtl_early_init(void) return 0; } + +DEFINE_STATIC_CALL_NULL(__mshv_vtl_return_hypercall, void (*)(void)); + +void mshv_vtl_return_call_init(u64 vtl_return_offset) +{ + static_call_update(__mshv_vtl_return_hypercall, + (void *)((u8 *)hv_hypercall_pg + vtl_return_offset)); +} +EXPORT_SYMBOL(mshv_vtl_return_call_init); + +void mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0) +{ + struct hv_vp_assist_page *hvp; + + hvp = hv_vp_assist_page[smp_processor_id()]; + hvp->vtl_ret_x64rax = vtl0->rax; + hvp->vtl_ret_x64rcx = vtl0->rcx; + + kernel_fpu_begin_mask(0); + fxrstor(&vtl0->fx_state); + __mshv_vtl_return_call(vtl0); + fxsave(&vtl0->fx_state); + kernel_fpu_end(); +} +EXPORT_SYMBOL(mshv_vtl_return_call); diff --git a/arch/x86/hyperv/mshv-asm-offsets.c b/arch/x86/hyperv/mshv-asm-offsets.c new file mode 100644 index 00000000000000..882c1db6df16c9 --- /dev/null +++ b/arch/x86/hyperv/mshv-asm-offsets.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed to extract + * and format the required data. + * + * Copyright (c) 2025, Microsoft Corporation. + * + * Author: + * Naman Jain + */ +#define COMPILE_OFFSETS + +#include +#include + +static void __used common(void) +{ + if (IS_ENABLED(CONFIG_HYPERV_VTL_MODE)) { + OFFSET(MSHV_VTL_CPU_CONTEXT_rax, mshv_vtl_cpu_context, rax); + OFFSET(MSHV_VTL_CPU_CONTEXT_rcx, mshv_vtl_cpu_context, rcx); + OFFSET(MSHV_VTL_CPU_CONTEXT_rdx, mshv_vtl_cpu_context, rdx); + OFFSET(MSHV_VTL_CPU_CONTEXT_rbx, mshv_vtl_cpu_context, rbx); + OFFSET(MSHV_VTL_CPU_CONTEXT_rbp, mshv_vtl_cpu_context, rbp); + OFFSET(MSHV_VTL_CPU_CONTEXT_rsi, mshv_vtl_cpu_context, rsi); + OFFSET(MSHV_VTL_CPU_CONTEXT_rdi, mshv_vtl_cpu_context, rdi); + OFFSET(MSHV_VTL_CPU_CONTEXT_r8, mshv_vtl_cpu_context, r8); + OFFSET(MSHV_VTL_CPU_CONTEXT_r9, mshv_vtl_cpu_context, r9); + OFFSET(MSHV_VTL_CPU_CONTEXT_r10, mshv_vtl_cpu_context, r10); + OFFSET(MSHV_VTL_CPU_CONTEXT_r11, mshv_vtl_cpu_context, r11); + OFFSET(MSHV_VTL_CPU_CONTEXT_r12, mshv_vtl_cpu_context, r12); + OFFSET(MSHV_VTL_CPU_CONTEXT_r13, mshv_vtl_cpu_context, r13); + OFFSET(MSHV_VTL_CPU_CONTEXT_r14, mshv_vtl_cpu_context, r14); + OFFSET(MSHV_VTL_CPU_CONTEXT_r15, mshv_vtl_cpu_context, r15); + OFFSET(MSHV_VTL_CPU_CONTEXT_cr2, mshv_vtl_cpu_context, cr2); + } +} diff --git a/arch/x86/hyperv/mshv_vtl_asm.S b/arch/x86/hyperv/mshv_vtl_asm.S new file mode 100644 index 00000000000000..f595eefad9abfd --- /dev/null +++ b/arch/x86/hyperv/mshv_vtl_asm.S @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Assembly level code for mshv_vtl VTL transition + * + * Copyright (c) 2025, Microsoft Corporation. + * + * Author: + * Naman Jain + */ + +#include +#include +#include +#include +#include +#include "mshv-asm-offsets.h" + + .text + .section .noinstr.text, "ax" +/* + * void __mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0) + * + * This function is used to context switch between different Virtual Trust Levels. + * It is marked as 'noinstr' to prevent against instrumentation and debugging facilities. + * NMIs aren't a problem because the NMI handler saves/restores CR2 specifically to guard + * against #PFs in NMI context clobbering the guest state. + */ +SYM_FUNC_START(__mshv_vtl_return_call) + /* Push callee save registers */ + pushq %rbp + mov %rsp, %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + + /* register switch to VTL0 clobbers all registers except rax/rcx */ + mov %_ASM_ARG1, %rax + + /* grab rbx/rbp/rsi/rdi/r8-r15 */ + mov MSHV_VTL_CPU_CONTEXT_rbx(%rax), %rbx + mov MSHV_VTL_CPU_CONTEXT_rbp(%rax), %rbp + mov MSHV_VTL_CPU_CONTEXT_rsi(%rax), %rsi + mov MSHV_VTL_CPU_CONTEXT_rdi(%rax), %rdi + mov MSHV_VTL_CPU_CONTEXT_r8(%rax), %r8 + mov MSHV_VTL_CPU_CONTEXT_r9(%rax), %r9 + mov MSHV_VTL_CPU_CONTEXT_r10(%rax), %r10 + mov MSHV_VTL_CPU_CONTEXT_r11(%rax), %r11 + mov MSHV_VTL_CPU_CONTEXT_r12(%rax), %r12 + mov MSHV_VTL_CPU_CONTEXT_r13(%rax), %r13 + mov MSHV_VTL_CPU_CONTEXT_r14(%rax), %r14 + mov MSHV_VTL_CPU_CONTEXT_r15(%rax), %r15 + + mov MSHV_VTL_CPU_CONTEXT_cr2(%rax), %rdx + mov %rdx, %cr2 + mov MSHV_VTL_CPU_CONTEXT_rdx(%rax), %rdx + + /* stash host registers on stack */ + pushq %rax + pushq %rcx + + xor %ecx, %ecx + + /* make a hypercall to switch VTL */ + call STATIC_CALL_TRAMP_STR(__mshv_vtl_return_hypercall) + + /* stash guest registers on stack, restore saved host copies */ + pushq %rax + pushq %rcx + mov 16(%rsp), %rcx + mov 24(%rsp), %rax + + mov %rdx, MSHV_VTL_CPU_CONTEXT_rdx(%rax) + mov %cr2, %rdx + mov %rdx, MSHV_VTL_CPU_CONTEXT_cr2(%rax) + pop MSHV_VTL_CPU_CONTEXT_rcx(%rax) + pop MSHV_VTL_CPU_CONTEXT_rax(%rax) + add $16, %rsp + + /* save rbx/rbp/rsi/rdi/r8-r15 */ + mov %rbx, MSHV_VTL_CPU_CONTEXT_rbx(%rax) + mov %rbp, MSHV_VTL_CPU_CONTEXT_rbp(%rax) + mov %rsi, MSHV_VTL_CPU_CONTEXT_rsi(%rax) + mov %rdi, MSHV_VTL_CPU_CONTEXT_rdi(%rax) + mov %r8, MSHV_VTL_CPU_CONTEXT_r8(%rax) + mov %r9, MSHV_VTL_CPU_CONTEXT_r9(%rax) + mov %r10, MSHV_VTL_CPU_CONTEXT_r10(%rax) + mov %r11, MSHV_VTL_CPU_CONTEXT_r11(%rax) + mov %r12, MSHV_VTL_CPU_CONTEXT_r12(%rax) + mov %r13, MSHV_VTL_CPU_CONTEXT_r13(%rax) + mov %r14, MSHV_VTL_CPU_CONTEXT_r14(%rax) + mov %r15, MSHV_VTL_CPU_CONTEXT_r15(%rax) + + /* pop callee-save registers r12-r15, rbx */ + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + + pop %rbp + RET +SYM_FUNC_END(__mshv_vtl_return_call) +/* + * Make sure that static_call_key symbol: __SCK____mshv_vtl_return_hypercall is accessible here. + * Below code is inspired from __ADDRESSABLE(sym) macro. Symbol name is kept simple, to avoid + * naming it something like "__UNIQUE_ID_addressable___SCK____mshv_vtl_return_hypercall_662.0" + * which would otherwise have been generated by the macro. + */ + .section .discard.addressable,"aw" + .align 8 + .type mshv_vtl_return_sym, @object + .size mshv_vtl_return_sym, 8 +mshv_vtl_return_sym: + .quad __SCK____mshv_vtl_return_hypercall diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 1342d55c2545ce..10037125099a15 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -11,6 +11,7 @@ #include #include #include +#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. @@ -269,13 +270,46 @@ static inline u64 hv_get_non_nested_msr(unsigned int reg) { return 0; } static inline int hv_apicid_to_vp_index(u32 apic_id) { return -EINVAL; } #endif /* CONFIG_HYPERV */ +struct mshv_vtl_cpu_context { + union { + struct { + u64 rax; + u64 rcx; + u64 rdx; + u64 rbx; + u64 cr2; + u64 rbp; + u64 rsi; + u64 rdi; + u64 r8; + u64 r9; + u64 r10; + u64 r11; + u64 r12; + u64 r13; + u64 r14; + u64 r15; + }; + u64 gp_regs[16]; + }; + + struct fxregs_state fx_state; +}; #ifdef CONFIG_HYPERV_VTL_MODE void __init hv_vtl_init_platform(void); int __init hv_vtl_early_init(void); +void mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0); +void mshv_vtl_return_call_init(u64 vtl_return_offset); +void mshv_vtl_return_hypercall(void); +void __mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0); #else static inline void __init hv_vtl_init_platform(void) {} static inline int __init hv_vtl_early_init(void) { return 0; } +static inline void mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0) {} +static inline void mshv_vtl_return_call_init(u64 vtl_return_offset) {} +static inline void mshv_vtl_return_hypercall(void) {} +static inline void __mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0) {} #endif #include diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 0b8c391a03424b..d4a8d349200c89 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -17,7 +17,8 @@ config HYPERV config HYPERV_VTL_MODE bool "Enable Linux to boot in VTL context" - depends on (X86_64 || ARM64) && HYPERV + depends on (X86_64 && HAVE_STATIC_CALL) || ARM64 + depends on HYPERV depends on SMP default n help @@ -82,4 +83,28 @@ config MSHV_ROOT If unsure, say N. +config MSHV_VTL + tristate "Microsoft Hyper-V VTL driver" + depends on X86_64 && HYPERV_VTL_MODE + depends on HYPERV_VMBUS + # Mapping VTL0 memory to a userspace process in VTL2 is supported in OpenHCL. + # VTL2 for OpenHCL makes use of Huge Pages to improve performance on VMs, + # specially with large memory requirements. + depends on TRANSPARENT_HUGEPAGE + # MTRRs are controlled by VTL0, and are not specific to individual VTLs. + # Therefore, do not attempt to access or modify MTRRs here. + depends on !MTRR + select CPUMASK_OFFSTACK + select VIRT_XFER_TO_GUEST_WORK + default n + help + Select this option to enable Hyper-V VTL driver support. + This driver provides interfaces for Virtual Machine Manager (VMM) running in VTL2 + userspace to create VTLs and partitions, setup and manage VTL0 memory and + allow userspace to make direct hypercalls. This also allows to map VTL0's address + space to a usermode process in VTL2 and supports getting new VMBus messages and channel + events in VTL2. + + If unsure, say N. + endmenu diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index 1a1677bf4dacaf..6d929fb0e13d26 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_HYPERV_VMBUS) += hv_vmbus.o obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o obj-$(CONFIG_MSHV_ROOT) += mshv_root.o +obj-$(CONFIG_MSHV_VTL) += mshv_vtl.o CFLAGS_hv_trace.o = -I$(src) CFLAGS_hv_balloon.o = -I$(src) @@ -14,7 +15,11 @@ hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o mshv_root-y := mshv_root_main.o mshv_synic.o mshv_eventfd.o mshv_irq.o \ mshv_root_hv_call.o mshv_portid_table.o +mshv_vtl-y := mshv_vtl_main.o # Code that must be built-in obj-$(CONFIG_HYPERV) += hv_common.o -obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o mshv_common.o +obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o +ifneq ($(CONFIG_MSHV_ROOT)$(CONFIG_MSHV_VTL),) + obj-y += mshv_common.o +endif diff --git a/drivers/hv/mshv_vtl.h b/drivers/hv/mshv_vtl.h new file mode 100644 index 00000000000000..a6eea52f7aa20c --- /dev/null +++ b/drivers/hv/mshv_vtl.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _MSHV_VTL_H +#define _MSHV_VTL_H + +#include +#include + +struct mshv_vtl_run { + u32 cancel; + u32 vtl_ret_action_size; + u32 pad[2]; + char exit_message[MSHV_MAX_RUN_MSG_SIZE]; + union { + struct mshv_vtl_cpu_context cpu_context; + + /* + * Reserving room for the cpu context to grow and to maintain compatibility + * with user mode. + */ + char reserved[1024]; + }; + char vtl_ret_actions[MSHV_MAX_RUN_MSG_SIZE]; +}; + +#endif /* _MSHV_VTL_H */ diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c new file mode 100644 index 00000000000000..2cebe9de5a5a21 --- /dev/null +++ b/drivers/hv/mshv_vtl_main.c @@ -0,0 +1,1392 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Microsoft Corporation. + * + * Author: + * Roman Kisel + * Saurabh Sengar + * Naman Jain + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../kernel/fpu/legacy.h" +#include "mshv.h" +#include "mshv_vtl.h" +#include "hyperv_vmbus.h" + +MODULE_AUTHOR("Microsoft"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Microsoft Hyper-V VTL Driver"); + +#define MSHV_ENTRY_REASON_LOWER_VTL_CALL 0x1 +#define MSHV_ENTRY_REASON_INTERRUPT 0x2 +#define MSHV_ENTRY_REASON_INTERCEPT 0x3 + +#define MSHV_REAL_OFF_SHIFT 16 +#define MSHV_PG_OFF_CPU_MASK (BIT_ULL(MSHV_REAL_OFF_SHIFT) - 1) +#define MSHV_RUN_PAGE_OFFSET 0 +#define MSHV_REG_PAGE_OFFSET 1 +#define VTL2_VMBUS_SINT_INDEX 7 + +static struct device *mem_dev; + +static struct tasklet_struct msg_dpc; +static wait_queue_head_t fd_wait_queue; +static bool has_message; +static struct eventfd_ctx *flag_eventfds[HV_EVENT_FLAGS_COUNT]; +static DEFINE_MUTEX(flag_lock); +static bool __read_mostly mshv_has_reg_page; + +/* hvcall code is of type u16, allocate a bitmap of size (1 << 16) to accommodate it */ +#define MAX_BITMAP_SIZE ((U16_MAX + 1) / 8) + +struct mshv_vtl_hvcall_fd { + u8 allow_bitmap[MAX_BITMAP_SIZE]; + bool allow_map_initialized; + /* + * Used to protect hvcall setup in IOCTLs + */ + struct mutex init_mutex; + struct miscdevice *dev; +}; + +struct mshv_vtl_poll_file { + struct file *file; + wait_queue_entry_t wait; + wait_queue_head_t *wqh; + poll_table pt; + int cpu; +}; + +struct mshv_vtl { + struct device *module_dev; + u64 id; +}; + +struct mshv_vtl_per_cpu { + struct mshv_vtl_run *run; + struct page *reg_page; +}; + +/* SYNIC_OVERLAY_PAGE_MSR - internal, identical to hv_synic_simp */ +union hv_synic_overlay_page_msr { + u64 as_uint64; + struct { + u64 enabled: 1; + u64 reserved: 11; + u64 pfn: 52; + } __packed; +}; + +static struct mutex mshv_vtl_poll_file_lock; +static union hv_register_vsm_page_offsets mshv_vsm_page_offsets; +static union hv_register_vsm_capabilities mshv_vsm_capabilities; + +static DEFINE_PER_CPU(struct mshv_vtl_poll_file, mshv_vtl_poll_file); +static DEFINE_PER_CPU(unsigned long long, num_vtl0_transitions); +static DEFINE_PER_CPU(struct mshv_vtl_per_cpu, mshv_vtl_per_cpu); + +static const union hv_input_vtl input_vtl_zero; +static const union hv_input_vtl input_vtl_normal = { + .use_target_vtl = 1, +}; + +static const struct file_operations mshv_vtl_fops; + +static long +mshv_ioctl_create_vtl(void __user *user_arg, struct device *module_dev) +{ + struct mshv_vtl *vtl; + struct file *file; + int fd; + + vtl = kzalloc(sizeof(*vtl), GFP_KERNEL); + if (!vtl) + return -ENOMEM; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) { + kfree(vtl); + return fd; + } + file = anon_inode_getfile("mshv_vtl", &mshv_vtl_fops, + vtl, O_RDWR); + if (IS_ERR(file)) { + kfree(vtl); + return PTR_ERR(file); + } + vtl->module_dev = module_dev; + fd_install(fd, file); + + return fd; +} + +static long +mshv_ioctl_check_extension(void __user *user_arg) +{ + u32 arg; + + if (copy_from_user(&arg, user_arg, sizeof(arg))) + return -EFAULT; + + switch (arg) { + case MSHV_CAP_CORE_API_STABLE: + return 0; + case MSHV_CAP_REGISTER_PAGE: + return mshv_has_reg_page; + case MSHV_CAP_VTL_RETURN_ACTION: + return mshv_vsm_capabilities.return_action_available; + case MSHV_CAP_DR6_SHARED: + return mshv_vsm_capabilities.dr6_shared; + } + + return -EOPNOTSUPP; +} + +static long +mshv_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) +{ + struct miscdevice *misc = filp->private_data; + + switch (ioctl) { + case MSHV_CHECK_EXTENSION: + return mshv_ioctl_check_extension((void __user *)arg); + case MSHV_CREATE_VTL: + return mshv_ioctl_create_vtl((void __user *)arg, misc->this_device); + } + + return -ENOTTY; +} + +static const struct file_operations mshv_dev_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mshv_dev_ioctl, + .llseek = noop_llseek, +}; + +static struct miscdevice mshv_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "mshv", + .fops = &mshv_dev_fops, + .mode = 0600, +}; + +static struct mshv_vtl_run *mshv_vtl_this_run(void) +{ + return *this_cpu_ptr(&mshv_vtl_per_cpu.run); +} + +static struct mshv_vtl_run *mshv_vtl_cpu_run(int cpu) +{ + return *per_cpu_ptr(&mshv_vtl_per_cpu.run, cpu); +} + +static struct page *mshv_vtl_cpu_reg_page(int cpu) +{ + return *per_cpu_ptr(&mshv_vtl_per_cpu.reg_page, cpu); +} + +static void mshv_vtl_configure_reg_page(struct mshv_vtl_per_cpu *per_cpu) +{ + struct hv_register_assoc reg_assoc = {}; + union hv_synic_overlay_page_msr overlay = {}; + struct page *reg_page; + + reg_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_RETRY_MAYFAIL); + if (!reg_page) { + WARN(1, "failed to allocate register page\n"); + return; + } + + overlay.enabled = 1; + overlay.pfn = page_to_hvpfn(reg_page); + reg_assoc.name = HV_X64_REGISTER_REG_PAGE; + reg_assoc.value.reg64 = overlay.as_uint64; + + if (hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + 1, input_vtl_zero, ®_assoc)) { + WARN(1, "failed to setup register page\n"); + __free_page(reg_page); + return; + } + + per_cpu->reg_page = reg_page; + mshv_has_reg_page = true; +} + +static void mshv_vtl_synic_enable_regs(unsigned int cpu) +{ + union hv_synic_sint sint; + + sint.as_uint64 = 0; + sint.vector = HYPERVISOR_CALLBACK_VECTOR; + sint.masked = false; + sint.auto_eoi = hv_recommend_using_aeoi(); + + /* Enable intercepts */ + if (!mshv_vsm_capabilities.intercept_page_available) + hv_set_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, + sint.as_uint64); + + /* VTL2 Host VSP SINT is (un)masked when the user mode requests that */ +} + +static int mshv_vtl_get_vsm_regs(void) +{ + struct hv_register_assoc registers[2]; + int ret, count = 2; + + registers[0].name = HV_REGISTER_VSM_CODE_PAGE_OFFSETS; + registers[1].name = HV_REGISTER_VSM_CAPABILITIES; + + ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + count, input_vtl_zero, registers); + if (ret) + return ret; + + mshv_vsm_page_offsets.as_uint64 = registers[0].value.reg64; + mshv_vsm_capabilities.as_uint64 = registers[1].value.reg64; + + return ret; +} + +static int mshv_vtl_configure_vsm_partition(struct device *dev) +{ + union hv_register_vsm_partition_config config; + struct hv_register_assoc reg_assoc; + + config.as_uint64 = 0; + config.default_vtl_protection_mask = HV_MAP_GPA_PERMISSIONS_MASK; + config.enable_vtl_protection = 1; + config.zero_memory_on_reset = 1; + config.intercept_vp_startup = 1; + config.intercept_cpuid_unimplemented = 1; + + if (mshv_vsm_capabilities.intercept_page_available) { + dev_dbg(dev, "using intercept page\n"); + config.intercept_page = 1; + } + + reg_assoc.name = HV_REGISTER_VSM_PARTITION_CONFIG; + reg_assoc.value.reg64 = config.as_uint64; + + return hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + 1, input_vtl_zero, ®_assoc); +} + +static void mshv_vtl_vmbus_isr(void) +{ + struct hv_per_cpu_context *per_cpu; + struct hv_message *msg; + u32 message_type; + union hv_synic_event_flags *event_flags; + struct eventfd_ctx *eventfd; + u16 i; + + per_cpu = this_cpu_ptr(hv_context.cpu_context); + if (smp_processor_id() == 0) { + msg = (struct hv_message *)per_cpu->hyp_synic_message_page + VTL2_VMBUS_SINT_INDEX; + message_type = READ_ONCE(msg->header.message_type); + if (message_type != HVMSG_NONE) + tasklet_schedule(&msg_dpc); + } + + event_flags = (union hv_synic_event_flags *)per_cpu->hyp_synic_event_page + + VTL2_VMBUS_SINT_INDEX; + for_each_set_bit(i, event_flags->flags, HV_EVENT_FLAGS_COUNT) { + if (!sync_test_and_clear_bit(i, event_flags->flags)) + continue; + rcu_read_lock(); + eventfd = READ_ONCE(flag_eventfds[i]); + if (eventfd) + eventfd_signal(eventfd); + rcu_read_unlock(); + } + + vmbus_isr(); +} + +static int mshv_vtl_alloc_context(unsigned int cpu) +{ + struct mshv_vtl_per_cpu *per_cpu = this_cpu_ptr(&mshv_vtl_per_cpu); + + per_cpu->run = (struct mshv_vtl_run *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + if (!per_cpu->run) + return -ENOMEM; + + if (mshv_vsm_capabilities.intercept_page_available) + mshv_vtl_configure_reg_page(per_cpu); + + mshv_vtl_synic_enable_regs(cpu); + + return 0; +} + +static int mshv_vtl_cpuhp_online; + +static int hv_vtl_setup_synic(void) +{ + int ret; + + /* Use our isr to first filter out packets destined for userspace */ + hv_setup_vmbus_handler(mshv_vtl_vmbus_isr); + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vtl:online", + mshv_vtl_alloc_context, NULL); + if (ret < 0) { + hv_setup_vmbus_handler(vmbus_isr); + return ret; + } + + mshv_vtl_cpuhp_online = ret; + + return 0; +} + +static void hv_vtl_remove_synic(void) +{ + cpuhp_remove_state(mshv_vtl_cpuhp_online); + hv_setup_vmbus_handler(vmbus_isr); +} + +static int vtl_get_vp_register(struct hv_register_assoc *reg) +{ + return hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + 1, input_vtl_normal, reg); +} + +static int vtl_set_vp_register(struct hv_register_assoc *reg) +{ + return hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + 1, input_vtl_normal, reg); +} + +static int mshv_vtl_ioctl_add_vtl0_mem(struct mshv_vtl *vtl, void __user *arg) +{ + struct mshv_vtl_ram_disposition vtl0_mem; + struct dev_pagemap *pgmap; + void *addr; + + if (copy_from_user(&vtl0_mem, arg, sizeof(vtl0_mem))) + return -EFAULT; + /* vtl0_mem.last_pfn is excluded in the pagemap range for VTL0 as per design */ + if (vtl0_mem.last_pfn <= vtl0_mem.start_pfn) { + dev_err(vtl->module_dev, "range start pfn (%llx) > end pfn (%llx)\n", + vtl0_mem.start_pfn, vtl0_mem.last_pfn); + return -EFAULT; + } + + pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL); + if (!pgmap) + return -ENOMEM; + + pgmap->ranges[0].start = PFN_PHYS(vtl0_mem.start_pfn); + pgmap->ranges[0].end = PFN_PHYS(vtl0_mem.last_pfn) - 1; + pgmap->nr_range = 1; + pgmap->type = MEMORY_DEVICE_GENERIC; + + /* + * Determine the highest page order that can be used for the given memory range. + * This works best when the range is aligned; i.e. both the start and the length. + */ + pgmap->vmemmap_shift = count_trailing_zeros(vtl0_mem.start_pfn | vtl0_mem.last_pfn); + dev_dbg(vtl->module_dev, + "Add VTL0 memory: start: 0x%llx, end_pfn: 0x%llx, page order: %lu\n", + vtl0_mem.start_pfn, vtl0_mem.last_pfn, pgmap->vmemmap_shift); + + addr = devm_memremap_pages(mem_dev, pgmap); + if (IS_ERR(addr)) { + dev_err(vtl->module_dev, "devm_memremap_pages error: %ld\n", PTR_ERR(addr)); + kfree(pgmap); + return -EFAULT; + } + + /* Don't free pgmap, since it has to stick around until the memory + * is unmapped, which will never happen as there is no scenario + * where VTL0 can be released/shutdown without bringing down VTL2. + */ + return 0; +} + +static void mshv_vtl_cancel(int cpu) +{ + int here = get_cpu(); + + if (here != cpu) { + if (!xchg_relaxed(&mshv_vtl_cpu_run(cpu)->cancel, 1)) + smp_send_reschedule(cpu); + } else { + WRITE_ONCE(mshv_vtl_this_run()->cancel, 1); + } + put_cpu(); +} + +static int mshv_vtl_poll_file_wake(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key) +{ + struct mshv_vtl_poll_file *poll_file = container_of(wait, struct mshv_vtl_poll_file, wait); + + mshv_vtl_cancel(poll_file->cpu); + + return 0; +} + +static void mshv_vtl_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, poll_table *pt) +{ + struct mshv_vtl_poll_file *poll_file = container_of(pt, struct mshv_vtl_poll_file, pt); + + WARN_ON(poll_file->wqh); + poll_file->wqh = wqh; + add_wait_queue(wqh, &poll_file->wait); +} + +static int mshv_vtl_ioctl_set_poll_file(struct mshv_vtl_set_poll_file __user *user_input) +{ + struct file *file, *old_file; + struct mshv_vtl_poll_file *poll_file; + struct mshv_vtl_set_poll_file input; + + if (copy_from_user(&input, user_input, sizeof(input))) + return -EFAULT; + + if (input.cpu >= num_possible_cpus() || !cpu_online(input.cpu)) + return -EINVAL; + /* + * CPU Hotplug is not supported in VTL2 in OpenHCL, where this kernel driver exists. + * CPU is expected to remain online after above cpu_online() check. + */ + + file = NULL; + file = fget(input.fd); + if (!file) + return -EBADFD; + + poll_file = per_cpu_ptr(&mshv_vtl_poll_file, READ_ONCE(input.cpu)); + if (!poll_file) + return -EINVAL; + + mutex_lock(&mshv_vtl_poll_file_lock); + + if (poll_file->wqh) + remove_wait_queue(poll_file->wqh, &poll_file->wait); + poll_file->wqh = NULL; + + old_file = poll_file->file; + poll_file->file = file; + poll_file->cpu = input.cpu; + + if (file) { + init_waitqueue_func_entry(&poll_file->wait, mshv_vtl_poll_file_wake); + init_poll_funcptr(&poll_file->pt, mshv_vtl_ptable_queue_proc); + vfs_poll(file, &poll_file->pt); + } + + mutex_unlock(&mshv_vtl_poll_file_lock); + + if (old_file) + fput(old_file); + + return 0; +} + +/* Static table mapping register names to their corresponding actions */ +static const struct { + enum hv_register_name reg_name; + int debug_reg_num; /* -1 if not a debug register */ + u32 msr_addr; /* 0 if not an MSR */ +} reg_table[] = { + /* Debug registers */ + {HV_X64_REGISTER_DR0, 0, 0}, + {HV_X64_REGISTER_DR1, 1, 0}, + {HV_X64_REGISTER_DR2, 2, 0}, + {HV_X64_REGISTER_DR3, 3, 0}, + {HV_X64_REGISTER_DR6, 6, 0}, + /* MTRR MSRs */ + {HV_X64_REGISTER_MSR_MTRR_CAP, -1, MSR_MTRRcap}, + {HV_X64_REGISTER_MSR_MTRR_DEF_TYPE, -1, MSR_MTRRdefType}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0, -1, MTRRphysBase_MSR(0)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE1, -1, MTRRphysBase_MSR(1)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE2, -1, MTRRphysBase_MSR(2)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE3, -1, MTRRphysBase_MSR(3)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE4, -1, MTRRphysBase_MSR(4)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE5, -1, MTRRphysBase_MSR(5)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE6, -1, MTRRphysBase_MSR(6)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE7, -1, MTRRphysBase_MSR(7)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE8, -1, MTRRphysBase_MSR(8)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASE9, -1, MTRRphysBase_MSR(9)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASEA, -1, MTRRphysBase_MSR(0xa)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASEB, -1, MTRRphysBase_MSR(0xb)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASEC, -1, MTRRphysBase_MSR(0xc)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASED, -1, MTRRphysBase_MSR(0xd)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASEE, -1, MTRRphysBase_MSR(0xe)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_BASEF, -1, MTRRphysBase_MSR(0xf)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0, -1, MTRRphysMask_MSR(0)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK1, -1, MTRRphysMask_MSR(1)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK2, -1, MTRRphysMask_MSR(2)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK3, -1, MTRRphysMask_MSR(3)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK4, -1, MTRRphysMask_MSR(4)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK5, -1, MTRRphysMask_MSR(5)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK6, -1, MTRRphysMask_MSR(6)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK7, -1, MTRRphysMask_MSR(7)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK8, -1, MTRRphysMask_MSR(8)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASK9, -1, MTRRphysMask_MSR(9)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKA, -1, MTRRphysMask_MSR(0xa)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKB, -1, MTRRphysMask_MSR(0xb)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKC, -1, MTRRphysMask_MSR(0xc)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKD, -1, MTRRphysMask_MSR(0xd)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKE, -1, MTRRphysMask_MSR(0xe)}, + {HV_X64_REGISTER_MSR_MTRR_PHYS_MASKF, -1, MTRRphysMask_MSR(0xf)}, + {HV_X64_REGISTER_MSR_MTRR_FIX64K00000, -1, MSR_MTRRfix64K_00000}, + {HV_X64_REGISTER_MSR_MTRR_FIX16K80000, -1, MSR_MTRRfix16K_80000}, + {HV_X64_REGISTER_MSR_MTRR_FIX16KA0000, -1, MSR_MTRRfix16K_A0000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KC0000, -1, MSR_MTRRfix4K_C0000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KC8000, -1, MSR_MTRRfix4K_C8000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KD0000, -1, MSR_MTRRfix4K_D0000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KD8000, -1, MSR_MTRRfix4K_D8000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KE0000, -1, MSR_MTRRfix4K_E0000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KE8000, -1, MSR_MTRRfix4K_E8000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KF0000, -1, MSR_MTRRfix4K_F0000}, + {HV_X64_REGISTER_MSR_MTRR_FIX4KF8000, -1, MSR_MTRRfix4K_F8000}, +}; + +static int mshv_vtl_get_set_reg(struct hv_register_assoc *regs, bool set) +{ + u64 *reg64; + enum hv_register_name gpr_name; + int i; + + gpr_name = regs->name; + reg64 = ®s->value.reg64; + + /* Search for the register in the table */ + for (i = 0; i < ARRAY_SIZE(reg_table); i++) { + if (reg_table[i].reg_name != gpr_name) + continue; + if (reg_table[i].debug_reg_num != -1) { + /* Handle debug registers */ + if (gpr_name == HV_X64_REGISTER_DR6 && + !mshv_vsm_capabilities.dr6_shared) + goto hypercall; + if (set) + native_set_debugreg(reg_table[i].debug_reg_num, *reg64); + else + *reg64 = native_get_debugreg(reg_table[i].debug_reg_num); + } else { + /* Handle MSRs */ + if (set) + wrmsrl(reg_table[i].msr_addr, *reg64); + else + rdmsrl(reg_table[i].msr_addr, *reg64); + } + return 0; + } + +hypercall: + return 1; +} + +static void mshv_vtl_return(struct mshv_vtl_cpu_context *vtl0) +{ + struct hv_vp_assist_page *hvp; + + hvp = hv_vp_assist_page[smp_processor_id()]; + + /* + * Process signal event direct set in the run page, if any. + */ + if (mshv_vsm_capabilities.return_action_available) { + u32 offset = READ_ONCE(mshv_vtl_this_run()->vtl_ret_action_size); + + WRITE_ONCE(mshv_vtl_this_run()->vtl_ret_action_size, 0); + + /* + * Hypervisor will take care of clearing out the actions + * set in the assist page. + */ + memcpy(hvp->vtl_ret_actions, + mshv_vtl_this_run()->vtl_ret_actions, + min_t(u32, offset, sizeof(hvp->vtl_ret_actions))); + } + + mshv_vtl_return_call(vtl0); +} + +static bool mshv_vtl_process_intercept(void) +{ + struct hv_per_cpu_context *mshv_cpu; + void *synic_message_page; + struct hv_message *msg; + u32 message_type; + + mshv_cpu = this_cpu_ptr(hv_context.cpu_context); + synic_message_page = mshv_cpu->hyp_synic_message_page; + if (unlikely(!synic_message_page)) + return true; + + msg = (struct hv_message *)synic_message_page + HV_SYNIC_INTERCEPTION_SINT_INDEX; + message_type = READ_ONCE(msg->header.message_type); + if (message_type == HVMSG_NONE) + return true; + + memcpy(mshv_vtl_this_run()->exit_message, msg, sizeof(*msg)); + vmbus_signal_eom(msg, message_type); + + return false; +} + +static int mshv_vtl_ioctl_return_to_lower_vtl(void) +{ + preempt_disable(); + for (;;) { + unsigned long irq_flags; + struct hv_vp_assist_page *hvp; + int ret; + + if (__xfer_to_guest_mode_work_pending()) { + preempt_enable(); + ret = xfer_to_guest_mode_handle_work(); + if (ret) + return ret; + preempt_disable(); + } + + local_irq_save(irq_flags); + if (READ_ONCE(mshv_vtl_this_run()->cancel)) { + local_irq_restore(irq_flags); + preempt_enable(); + return -EINTR; + } + + mshv_vtl_return(&mshv_vtl_this_run()->cpu_context); + local_irq_restore(irq_flags); + + hvp = hv_vp_assist_page[smp_processor_id()]; + this_cpu_inc(num_vtl0_transitions); + switch (hvp->vtl_entry_reason) { + case MSHV_ENTRY_REASON_INTERRUPT: + if (!mshv_vsm_capabilities.intercept_page_available && + likely(!mshv_vtl_process_intercept())) + goto done; + break; + + case MSHV_ENTRY_REASON_INTERCEPT: + WARN_ON(!mshv_vsm_capabilities.intercept_page_available); + memcpy(mshv_vtl_this_run()->exit_message, hvp->intercept_message, + sizeof(hvp->intercept_message)); + goto done; + + default: + panic("unknown entry reason: %d", hvp->vtl_entry_reason); + } + } + +done: + preempt_enable(); + + return 0; +} + +static long +mshv_vtl_ioctl_get_regs(void __user *user_args) +{ + struct mshv_vp_registers args; + struct hv_register_assoc reg; + long ret; + + if (copy_from_user(&args, user_args, sizeof(args))) + return -EFAULT; + + /* This IOCTL supports processing only one register at a time. */ + if (args.count != 1) + return -EINVAL; + + if (copy_from_user(®, (void __user *)args.regs_ptr, + sizeof(reg))) + return -EFAULT; + + ret = mshv_vtl_get_set_reg(®, false); + if (!ret) + goto copy_args; /* No need of hypercall */ + ret = vtl_get_vp_register(®); + if (ret) + return ret; + +copy_args: + if (copy_to_user((void __user *)args.regs_ptr, ®, sizeof(reg))) + ret = -EFAULT; + + return ret; +} + +static long +mshv_vtl_ioctl_set_regs(void __user *user_args) +{ + struct mshv_vp_registers args; + struct hv_register_assoc reg; + long ret; + + if (copy_from_user(&args, user_args, sizeof(args))) + return -EFAULT; + + /* This IOCTL supports processing only one register at a time. */ + if (args.count != 1) + return -EINVAL; + + if (copy_from_user(®, (void __user *)args.regs_ptr, sizeof(reg))) + return -EFAULT; + + ret = mshv_vtl_get_set_reg(®, true); + if (!ret) + return ret; /* No need of hypercall */ + ret = vtl_set_vp_register(®); + + return ret; +} + +static long +mshv_vtl_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) +{ + long ret; + struct mshv_vtl *vtl = filp->private_data; + + switch (ioctl) { + case MSHV_SET_POLL_FILE: + ret = mshv_vtl_ioctl_set_poll_file((struct mshv_vtl_set_poll_file __user *)arg); + break; + case MSHV_GET_VP_REGISTERS: + ret = mshv_vtl_ioctl_get_regs((void __user *)arg); + break; + case MSHV_SET_VP_REGISTERS: + ret = mshv_vtl_ioctl_set_regs((void __user *)arg); + break; + case MSHV_RETURN_TO_LOWER_VTL: + ret = mshv_vtl_ioctl_return_to_lower_vtl(); + break; + case MSHV_ADD_VTL0_MEMORY: + ret = mshv_vtl_ioctl_add_vtl0_mem(vtl, (void __user *)arg); + break; + default: + dev_err(vtl->module_dev, "invalid vtl ioctl: %#x\n", ioctl); + ret = -ENOTTY; + } + + return ret; +} + +static vm_fault_t mshv_vtl_fault(struct vm_fault *vmf) +{ + struct page *page; + int cpu = vmf->pgoff & MSHV_PG_OFF_CPU_MASK; + int real_off = vmf->pgoff >> MSHV_REAL_OFF_SHIFT; + + if (!cpu_online(cpu)) + return VM_FAULT_SIGBUS; + /* + * CPU Hotplug is not supported in VTL2 in OpenHCL, where this kernel driver exists. + * CPU is expected to remain online after above cpu_online() check. + */ + + if (real_off == MSHV_RUN_PAGE_OFFSET) { + page = virt_to_page(mshv_vtl_cpu_run(cpu)); + } else if (real_off == MSHV_REG_PAGE_OFFSET) { + if (!mshv_has_reg_page) + return VM_FAULT_SIGBUS; + page = mshv_vtl_cpu_reg_page(cpu); + } else { + return VM_FAULT_NOPAGE; + } + + get_page(page); + vmf->page = page; + + return 0; +} + +static const struct vm_operations_struct mshv_vtl_vm_ops = { + .fault = mshv_vtl_fault, +}; + +static int mshv_vtl_mmap(struct file *filp, struct vm_area_struct *vma) +{ + vma->vm_ops = &mshv_vtl_vm_ops; + + return 0; +} + +static int mshv_vtl_release(struct inode *inode, struct file *filp) +{ + struct mshv_vtl *vtl = filp->private_data; + + kfree(vtl); + + return 0; +} + +static const struct file_operations mshv_vtl_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mshv_vtl_ioctl, + .release = mshv_vtl_release, + .mmap = mshv_vtl_mmap, +}; + +static void mshv_vtl_synic_mask_vmbus_sint(const u8 *mask) +{ + union hv_synic_sint sint; + + sint.as_uint64 = 0; + sint.vector = HYPERVISOR_CALLBACK_VECTOR; + sint.masked = (*mask != 0); + sint.auto_eoi = hv_recommend_using_aeoi(); + + hv_set_msr(HV_MSR_SINT0 + VTL2_VMBUS_SINT_INDEX, + sint.as_uint64); + + if (!sint.masked) + pr_debug("%s: Unmasking VTL2 VMBUS SINT on VP %d\n", __func__, smp_processor_id()); + else + pr_debug("%s: Masking VTL2 VMBUS SINT on VP %d\n", __func__, smp_processor_id()); +} + +static void mshv_vtl_read_remote(void *buffer) +{ + struct hv_per_cpu_context *mshv_cpu = this_cpu_ptr(hv_context.cpu_context); + struct hv_message *msg = (struct hv_message *)mshv_cpu->hyp_synic_message_page + + VTL2_VMBUS_SINT_INDEX; + u32 message_type = READ_ONCE(msg->header.message_type); + + WRITE_ONCE(has_message, false); + if (message_type == HVMSG_NONE) + return; + + memcpy(buffer, msg, sizeof(*msg)); + vmbus_signal_eom(msg, message_type); +} + +static bool vtl_synic_mask_vmbus_sint_masked = true; + +static ssize_t mshv_vtl_sint_read(struct file *filp, char __user *arg, size_t size, loff_t *offset) +{ + struct hv_message msg = {}; + int ret; + + if (size < sizeof(msg)) + return -EINVAL; + + for (;;) { + smp_call_function_single(VMBUS_CONNECT_CPU, mshv_vtl_read_remote, &msg, true); + if (msg.header.message_type != HVMSG_NONE) + break; + + if (READ_ONCE(vtl_synic_mask_vmbus_sint_masked)) + return 0; /* EOF */ + + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + ret = wait_event_interruptible(fd_wait_queue, + READ_ONCE(has_message) || + READ_ONCE(vtl_synic_mask_vmbus_sint_masked)); + if (ret) + return ret; + } + + if (copy_to_user(arg, &msg, sizeof(msg))) + return -EFAULT; + + return sizeof(msg); +} + +static __poll_t mshv_vtl_sint_poll(struct file *filp, poll_table *wait) +{ + __poll_t mask = 0; + + poll_wait(filp, &fd_wait_queue, wait); + if (READ_ONCE(has_message) || READ_ONCE(vtl_synic_mask_vmbus_sint_masked)) + mask |= EPOLLIN | EPOLLRDNORM; + + return mask; +} + +static void mshv_vtl_sint_on_msg_dpc(unsigned long data) +{ + WRITE_ONCE(has_message, true); + wake_up_interruptible_poll(&fd_wait_queue, EPOLLIN); +} + +static int mshv_vtl_sint_ioctl_post_msg(struct mshv_vtl_sint_post_msg __user *arg) +{ + struct mshv_vtl_sint_post_msg message; + u8 payload[HV_MESSAGE_PAYLOAD_BYTE_COUNT]; + + if (copy_from_user(&message, arg, sizeof(message))) + return -EFAULT; + if (message.payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) + return -EINVAL; + if (copy_from_user(payload, (void __user *)message.payload_ptr, + message.payload_size)) + return -EFAULT; + + return hv_post_message((union hv_connection_id)message.connection_id, + message.message_type, (void *)payload, + message.payload_size); +} + +static int mshv_vtl_sint_ioctl_signal_event(struct mshv_vtl_signal_event __user *arg) +{ + u64 input, status; + struct mshv_vtl_signal_event signal_event; + + if (copy_from_user(&signal_event, arg, sizeof(signal_event))) + return -EFAULT; + + input = signal_event.connection_id | ((u64)signal_event.flag << 32); + + status = hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, input); + + return hv_result_to_errno(status); +} + +static int mshv_vtl_sint_ioctl_set_eventfd(struct mshv_vtl_set_eventfd __user *arg) +{ + struct mshv_vtl_set_eventfd set_eventfd; + struct eventfd_ctx *eventfd, *old_eventfd; + + if (copy_from_user(&set_eventfd, arg, sizeof(set_eventfd))) + return -EFAULT; + if (set_eventfd.flag >= HV_EVENT_FLAGS_COUNT) + return -EINVAL; + + eventfd = NULL; + if (set_eventfd.fd >= 0) { + eventfd = eventfd_ctx_fdget(set_eventfd.fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + } + + guard(mutex)(&flag_lock); + old_eventfd = READ_ONCE(flag_eventfds[set_eventfd.flag]); + WRITE_ONCE(flag_eventfds[set_eventfd.flag], eventfd); + + if (old_eventfd) { + synchronize_rcu(); + eventfd_ctx_put(old_eventfd); + } + + return 0; +} + +static int mshv_vtl_sint_ioctl_pause_msg_stream(struct mshv_sint_mask __user *arg) +{ + static DEFINE_MUTEX(vtl2_vmbus_sint_mask_mutex); + struct mshv_sint_mask mask; + + if (copy_from_user(&mask, arg, sizeof(mask))) + return -EFAULT; + guard(mutex)(&vtl2_vmbus_sint_mask_mutex); + on_each_cpu((smp_call_func_t)mshv_vtl_synic_mask_vmbus_sint, &mask.mask, 1); + WRITE_ONCE(vtl_synic_mask_vmbus_sint_masked, mask.mask != 0); + if (mask.mask) + wake_up_interruptible_poll(&fd_wait_queue, EPOLLIN); + + return 0; +} + +static long mshv_vtl_sint_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case MSHV_SINT_POST_MESSAGE: + return mshv_vtl_sint_ioctl_post_msg((struct mshv_vtl_sint_post_msg __user *)arg); + case MSHV_SINT_SIGNAL_EVENT: + return mshv_vtl_sint_ioctl_signal_event((struct mshv_vtl_signal_event __user *)arg); + case MSHV_SINT_SET_EVENTFD: + return mshv_vtl_sint_ioctl_set_eventfd((struct mshv_vtl_set_eventfd __user *)arg); + case MSHV_SINT_PAUSE_MESSAGE_STREAM: + return mshv_vtl_sint_ioctl_pause_msg_stream((struct mshv_sint_mask __user *)arg); + default: + return -ENOIOCTLCMD; + } +} + +static const struct file_operations mshv_vtl_sint_ops = { + .owner = THIS_MODULE, + .read = mshv_vtl_sint_read, + .poll = mshv_vtl_sint_poll, + .unlocked_ioctl = mshv_vtl_sint_ioctl, +}; + +static struct miscdevice mshv_vtl_sint_dev = { + .name = "mshv_sint", + .fops = &mshv_vtl_sint_ops, + .mode = 0600, + .minor = MISC_DYNAMIC_MINOR, +}; + +static int mshv_vtl_hvcall_dev_open(struct inode *node, struct file *f) +{ + struct miscdevice *dev = f->private_data; + struct mshv_vtl_hvcall_fd *fd; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + fd = vzalloc(sizeof(*fd)); + if (!fd) + return -ENOMEM; + fd->dev = dev; + f->private_data = fd; + mutex_init(&fd->init_mutex); + + return 0; +} + +static int mshv_vtl_hvcall_dev_release(struct inode *node, struct file *f) +{ + struct mshv_vtl_hvcall_fd *fd; + + fd = f->private_data; + if (fd) { + vfree(fd); + f->private_data = NULL; + } + + return 0; +} + +static int mshv_vtl_hvcall_do_setup(struct mshv_vtl_hvcall_fd *fd, + struct mshv_vtl_hvcall_setup __user *hvcall_setup_user) +{ + struct mshv_vtl_hvcall_setup hvcall_setup; + + guard(mutex)(&fd->init_mutex); + + if (fd->allow_map_initialized) { + dev_err(fd->dev->this_device, + "Hypercall allow map has already been set, pid %d\n", + current->pid); + return -EINVAL; + } + + if (copy_from_user(&hvcall_setup, hvcall_setup_user, + sizeof(struct mshv_vtl_hvcall_setup))) { + return -EFAULT; + } + if (hvcall_setup.bitmap_array_size > ARRAY_SIZE(fd->allow_bitmap)) + return -EINVAL; + + if (copy_from_user(&fd->allow_bitmap, + (void __user *)hvcall_setup.allow_bitmap_ptr, + hvcall_setup.bitmap_array_size)) { + return -EFAULT; + } + + dev_info(fd->dev->this_device, "Hypercall allow map has been set, pid %d\n", + current->pid); + fd->allow_map_initialized = true; + return 0; +} + +static bool mshv_vtl_hvcall_is_allowed(struct mshv_vtl_hvcall_fd *fd, u16 call_code) +{ + return test_bit(call_code, (unsigned long *)fd->allow_bitmap); +} + +static int mshv_vtl_hvcall_call(struct mshv_vtl_hvcall_fd *fd, + struct mshv_vtl_hvcall __user *hvcall_user) +{ + struct mshv_vtl_hvcall hvcall; + void *in, *out; + int ret; + + if (copy_from_user(&hvcall, hvcall_user, sizeof(struct mshv_vtl_hvcall))) + return -EFAULT; + if (hvcall.input_size > HV_HYP_PAGE_SIZE) + return -EINVAL; + if (hvcall.output_size > HV_HYP_PAGE_SIZE) + return -EINVAL; + + /* + * By default, all hypercalls are not allowed. + * The user mode code has to set up the allow bitmap once. + */ + + if (!mshv_vtl_hvcall_is_allowed(fd, hvcall.control & 0xFFFF)) { + dev_err(fd->dev->this_device, + "Hypercall with control data %#llx isn't allowed\n", + hvcall.control); + return -EPERM; + } + + /* + * This may create a problem for Confidential VM (CVM) usecase where we need to use + * Hyper-V driver allocated per-cpu input and output pages (hyperv_pcpu_input_arg and + * hyperv_pcpu_output_arg) for making a hypervisor call. + * + * TODO: Take care of this when CVM support is added. + */ + in = (void *)__get_free_page(GFP_KERNEL); + out = (void *)__get_free_page(GFP_KERNEL); + + if (copy_from_user(in, (void __user *)hvcall.input_ptr, hvcall.input_size)) { + ret = -EFAULT; + goto free_pages; + } + + hvcall.status = hv_do_hypercall(hvcall.control, in, out); + + if (copy_to_user((void __user *)hvcall.output_ptr, out, hvcall.output_size)) { + ret = -EFAULT; + goto free_pages; + } + ret = put_user(hvcall.status, &hvcall_user->status); +free_pages: + free_page((unsigned long)in); + free_page((unsigned long)out); + + return ret; +} + +static long mshv_vtl_hvcall_dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + struct mshv_vtl_hvcall_fd *fd = f->private_data; + + switch (cmd) { + case MSHV_HVCALL_SETUP: + return mshv_vtl_hvcall_do_setup(fd, (struct mshv_vtl_hvcall_setup __user *)arg); + case MSHV_HVCALL: + return mshv_vtl_hvcall_call(fd, (struct mshv_vtl_hvcall __user *)arg); + default: + break; + } + + return -ENOIOCTLCMD; +} + +static const struct file_operations mshv_vtl_hvcall_dev_file_ops = { + .owner = THIS_MODULE, + .open = mshv_vtl_hvcall_dev_open, + .release = mshv_vtl_hvcall_dev_release, + .unlocked_ioctl = mshv_vtl_hvcall_dev_ioctl, +}; + +static struct miscdevice mshv_vtl_hvcall_dev = { + .name = "mshv_hvcall", + .nodename = "mshv_hvcall", + .fops = &mshv_vtl_hvcall_dev_file_ops, + .mode = 0600, + .minor = MISC_DYNAMIC_MINOR, +}; + +static int mshv_vtl_low_open(struct inode *inodep, struct file *filp) +{ + pid_t pid = task_pid_vnr(current); + uid_t uid = current_uid().val; + int ret = 0; + + pr_debug("%s: Opening VTL low, task group %d, uid %d\n", __func__, pid, uid); + + if (capable(CAP_SYS_ADMIN)) { + filp->private_data = inodep; + } else { + pr_err("%s: VTL low open failed: CAP_SYS_ADMIN required. task group %d, uid %d", + __func__, pid, uid); + ret = -EPERM; + } + + return ret; +} + +static bool can_fault(struct vm_fault *vmf, unsigned long size, unsigned long *pfn) +{ + unsigned long mask = size - 1; + unsigned long start = vmf->address & ~mask; + unsigned long end = start + size; + bool is_valid; + + is_valid = (vmf->address & mask) == ((vmf->pgoff << PAGE_SHIFT) & mask) && + start >= vmf->vma->vm_start && + end <= vmf->vma->vm_end; + + if (is_valid) + *pfn = vmf->pgoff & ~(mask >> PAGE_SHIFT); + + return is_valid; +} + +static vm_fault_t mshv_vtl_low_huge_fault(struct vm_fault *vmf, unsigned int order) +{ + unsigned long pfn = vmf->pgoff; + vm_fault_t ret = VM_FAULT_FALLBACK; + + switch (order) { + case 0: + return vmf_insert_mixed(vmf->vma, vmf->address, pfn); + + case PMD_ORDER: + if (can_fault(vmf, PMD_SIZE, &pfn)) + ret = vmf_insert_pfn_pmd(vmf, pfn, vmf->flags & FAULT_FLAG_WRITE); + return ret; + + case PUD_ORDER: + if (can_fault(vmf, PUD_SIZE, &pfn)) + ret = vmf_insert_pfn_pud(vmf, pfn, vmf->flags & FAULT_FLAG_WRITE); + return ret; + + default: + return VM_FAULT_SIGBUS; + } +} + +static vm_fault_t mshv_vtl_low_fault(struct vm_fault *vmf) +{ + return mshv_vtl_low_huge_fault(vmf, 0); +} + +static const struct vm_operations_struct mshv_vtl_low_vm_ops = { + .fault = mshv_vtl_low_fault, + .huge_fault = mshv_vtl_low_huge_fault, +}; + +static int mshv_vtl_low_mmap(struct file *filp, struct vm_area_struct *vma) +{ + vma->vm_ops = &mshv_vtl_low_vm_ops; + vm_flags_set(vma, VM_HUGEPAGE | VM_MIXEDMAP); + + return 0; +} + +static const struct file_operations mshv_vtl_low_file_ops = { + .owner = THIS_MODULE, + .open = mshv_vtl_low_open, + .mmap = mshv_vtl_low_mmap, +}; + +static struct miscdevice mshv_vtl_low = { + .name = "mshv_vtl_low", + .nodename = "mshv_vtl_low", + .fops = &mshv_vtl_low_file_ops, + .mode = 0600, + .minor = MISC_DYNAMIC_MINOR, +}; + +static int __init mshv_vtl_init(void) +{ + int ret; + struct device *dev = mshv_dev.this_device; + + /* + * This creates /dev/mshv which provides functionality to create VTLs and partitions. + */ + ret = misc_register(&mshv_dev); + if (ret) { + dev_err(dev, "mshv device register failed: %d\n", ret); + goto free_dev; + } + + tasklet_init(&msg_dpc, mshv_vtl_sint_on_msg_dpc, 0); + init_waitqueue_head(&fd_wait_queue); + + if (mshv_vtl_get_vsm_regs()) { + dev_emerg(dev, "Unable to get VSM capabilities !!\n"); + ret = -ENODEV; + goto free_dev; + } + if (mshv_vtl_configure_vsm_partition(dev)) { + dev_emerg(dev, "VSM configuration failed !!\n"); + ret = -ENODEV; + goto free_dev; + } + + mshv_vtl_return_call_init(mshv_vsm_page_offsets.vtl_return_offset); + ret = hv_vtl_setup_synic(); + if (ret) + goto free_dev; + + /* + * mshv_sint device adds VMBus relay ioctl support. + * This provides a channel for VTL0 to communicate with VTL2. + */ + ret = misc_register(&mshv_vtl_sint_dev); + if (ret) + goto free_synic; + + /* + * mshv_hvcall device adds interface to enable userspace for direct hypercalls support. + */ + ret = misc_register(&mshv_vtl_hvcall_dev); + if (ret) + goto free_sint; + + /* + * mshv_vtl_low device is used to map VTL0 address space to a user-mode process in VTL2. + * It implements mmap() to allow a user-mode process in VTL2 to map to the address of VTL0. + */ + ret = misc_register(&mshv_vtl_low); + if (ret) + goto free_hvcall; + + /* + * "mshv vtl mem dev" device is later used to setup VTL0 memory. + */ + mem_dev = kzalloc(sizeof(*mem_dev), GFP_KERNEL); + if (!mem_dev) { + ret = -ENOMEM; + goto free_low; + } + + mutex_init(&mshv_vtl_poll_file_lock); + + device_initialize(mem_dev); + dev_set_name(mem_dev, "mshv vtl mem dev"); + ret = device_add(mem_dev); + if (ret) { + dev_err(dev, "mshv vtl mem dev add: %d\n", ret); + goto free_mem; + } + + return 0; + +free_mem: + kfree(mem_dev); +free_low: + misc_deregister(&mshv_vtl_low); +free_hvcall: + misc_deregister(&mshv_vtl_hvcall_dev); +free_sint: + misc_deregister(&mshv_vtl_sint_dev); +free_synic: + hv_vtl_remove_synic(); +free_dev: + misc_deregister(&mshv_dev); + + return ret; +} + +static void __exit mshv_vtl_exit(void) +{ + device_del(mem_dev); + kfree(mem_dev); + misc_deregister(&mshv_vtl_low); + misc_deregister(&mshv_vtl_hvcall_dev); + misc_deregister(&mshv_vtl_sint_dev); + hv_vtl_remove_synic(); + misc_deregister(&mshv_dev); +} + +module_init(mshv_vtl_init); +module_exit(mshv_vtl_exit); diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index 7499a679e60ac2..1d5ce11be8b63a 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -885,6 +885,48 @@ struct hv_get_vp_from_apic_id_in { u32 apic_ids[]; } __packed; +union hv_register_vsm_partition_config { + u64 as_uint64; + struct { + u64 enable_vtl_protection : 1; + u64 default_vtl_protection_mask : 4; + u64 zero_memory_on_reset : 1; + u64 deny_lower_vtl_startup : 1; + u64 intercept_acceptance : 1; + u64 intercept_enable_vtl_protection : 1; + u64 intercept_vp_startup : 1; + u64 intercept_cpuid_unimplemented : 1; + u64 intercept_unrecoverable_exception : 1; + u64 intercept_page : 1; + u64 mbz : 51; + } __packed; +}; + +union hv_register_vsm_capabilities { + u64 as_uint64; + struct { + u64 dr6_shared: 1; + u64 mbec_vtl_mask: 16; + u64 deny_lower_vtl_startup: 1; + u64 supervisor_shadow_stack: 1; + u64 hardware_hvpt_available: 1; + u64 software_hvpt_available: 1; + u64 hardware_hvpt_range_bits: 6; + u64 intercept_page_available: 1; + u64 return_action_available: 1; + u64 reserved: 35; + } __packed; +}; + +union hv_register_vsm_page_offsets { + struct { + u64 vtl_call_offset : 12; + u64 vtl_return_offset : 12; + u64 reserved_mbz : 40; + } __packed; + u64 as_uint64; +}; + struct hv_nested_enlightenments_control { struct { u32 directhypercall : 1; @@ -1007,6 +1049,70 @@ enum hv_register_name { /* VSM */ HV_REGISTER_VSM_VP_STATUS = 0x000D0003, + + /* Synthetic VSM registers */ + HV_REGISTER_VSM_CODE_PAGE_OFFSETS = 0x000D0002, + HV_REGISTER_VSM_CAPABILITIES = 0x000D0006, + HV_REGISTER_VSM_PARTITION_CONFIG = 0x000D0007, + +#if defined(CONFIG_X86) + /* X64 Debug Registers */ + HV_X64_REGISTER_DR0 = 0x00050000, + HV_X64_REGISTER_DR1 = 0x00050001, + HV_X64_REGISTER_DR2 = 0x00050002, + HV_X64_REGISTER_DR3 = 0x00050003, + HV_X64_REGISTER_DR6 = 0x00050004, + HV_X64_REGISTER_DR7 = 0x00050005, + + /* X64 Cache control MSRs */ + HV_X64_REGISTER_MSR_MTRR_CAP = 0x0008000D, + HV_X64_REGISTER_MSR_MTRR_DEF_TYPE = 0x0008000E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 = 0x00080010, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE1 = 0x00080011, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE2 = 0x00080012, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE3 = 0x00080013, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE4 = 0x00080014, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE5 = 0x00080015, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE6 = 0x00080016, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE7 = 0x00080017, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE8 = 0x00080018, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE9 = 0x00080019, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEA = 0x0008001A, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEB = 0x0008001B, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEC = 0x0008001C, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASED = 0x0008001D, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEE = 0x0008001E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEF = 0x0008001F, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 = 0x00080040, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK1 = 0x00080041, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK2 = 0x00080042, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK3 = 0x00080043, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK4 = 0x00080044, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK5 = 0x00080045, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK6 = 0x00080046, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK7 = 0x00080047, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK8 = 0x00080048, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK9 = 0x00080049, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKA = 0x0008004A, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKB = 0x0008004B, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKC = 0x0008004C, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKD = 0x0008004D, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKE = 0x0008004E, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKF = 0x0008004F, + HV_X64_REGISTER_MSR_MTRR_FIX64K00000 = 0x00080070, + HV_X64_REGISTER_MSR_MTRR_FIX16K80000 = 0x00080071, + HV_X64_REGISTER_MSR_MTRR_FIX16KA0000 = 0x00080072, + HV_X64_REGISTER_MSR_MTRR_FIX4KC0000 = 0x00080073, + HV_X64_REGISTER_MSR_MTRR_FIX4KC8000 = 0x00080074, + HV_X64_REGISTER_MSR_MTRR_FIX4KD0000 = 0x00080075, + HV_X64_REGISTER_MSR_MTRR_FIX4KD8000 = 0x00080076, + HV_X64_REGISTER_MSR_MTRR_FIX4KE0000 = 0x00080077, + HV_X64_REGISTER_MSR_MTRR_FIX4KE8000 = 0x00080078, + HV_X64_REGISTER_MSR_MTRR_FIX4KF0000 = 0x00080079, + HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, + + HV_X64_REGISTER_REG_PAGE = 0x0009001C, +#endif }; /* diff --git a/include/uapi/linux/mshv.h b/include/uapi/linux/mshv.h index b645d17cc5314e..dee3ece28ce58e 100644 --- a/include/uapi/linux/mshv.h +++ b/include/uapi/linux/mshv.h @@ -322,4 +322,84 @@ struct mshv_get_set_vp_state { * #define MSHV_ROOT_HVCALL _IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall) */ +/* Structure definitions, macros and IOCTLs for mshv_vtl */ + +#define MSHV_CAP_CORE_API_STABLE 0x0 +#define MSHV_CAP_REGISTER_PAGE 0x1 +#define MSHV_CAP_VTL_RETURN_ACTION 0x2 +#define MSHV_CAP_DR6_SHARED 0x3 +#define MSHV_MAX_RUN_MSG_SIZE 256 + +struct mshv_vp_registers { + __u32 count; /* supports only 1 register at a time */ + __u32 reserved; /* Reserved for alignment or future use */ + __u64 regs_ptr; /* pointer to struct hv_register_assoc */ +}; + +struct mshv_vtl_set_eventfd { + __s32 fd; + __u32 flag; +}; + +struct mshv_vtl_signal_event { + __u32 connection_id; + __u32 flag; +}; + +struct mshv_vtl_sint_post_msg { + __u64 message_type; + __u32 connection_id; + __u32 payload_size; /* Must not exceed HV_MESSAGE_PAYLOAD_BYTE_COUNT */ + __u64 payload_ptr; /* pointer to message payload (bytes) */ +}; + +struct mshv_vtl_ram_disposition { + __u64 start_pfn; + __u64 last_pfn; +}; + +struct mshv_vtl_set_poll_file { + __u32 cpu; + __u32 fd; +}; + +struct mshv_vtl_hvcall_setup { + __u64 bitmap_array_size; /* stores number of bytes */ + __u64 allow_bitmap_ptr; +}; + +struct mshv_vtl_hvcall { + __u64 control; /* Hypercall control code */ + __u64 input_size; /* Size of the input data */ + __u64 input_ptr; /* Pointer to the input struct */ + __u64 status; /* Status of the hypercall (output) */ + __u64 output_size; /* Size of the output data */ + __u64 output_ptr; /* Pointer to the output struct */ +}; + +struct mshv_sint_mask { + __u8 mask; + __u8 reserved[7]; +}; + +/* /dev/mshv device IOCTL */ +#define MSHV_CHECK_EXTENSION _IOW(MSHV_IOCTL, 0x00, __u32) + +/* vtl device */ +#define MSHV_CREATE_VTL _IOR(MSHV_IOCTL, 0x1D, char) +#define MSHV_ADD_VTL0_MEMORY _IOW(MSHV_IOCTL, 0x21, struct mshv_vtl_ram_disposition) +#define MSHV_SET_POLL_FILE _IOW(MSHV_IOCTL, 0x25, struct mshv_vtl_set_poll_file) +#define MSHV_RETURN_TO_LOWER_VTL _IO(MSHV_IOCTL, 0x27) +#define MSHV_GET_VP_REGISTERS _IOWR(MSHV_IOCTL, 0x05, struct mshv_vp_registers) +#define MSHV_SET_VP_REGISTERS _IOW(MSHV_IOCTL, 0x06, struct mshv_vp_registers) + +/* VMBus device IOCTLs */ +#define MSHV_SINT_SIGNAL_EVENT _IOW(MSHV_IOCTL, 0x22, struct mshv_vtl_signal_event) +#define MSHV_SINT_POST_MESSAGE _IOW(MSHV_IOCTL, 0x23, struct mshv_vtl_sint_post_msg) +#define MSHV_SINT_SET_EVENTFD _IOW(MSHV_IOCTL, 0x24, struct mshv_vtl_set_eventfd) +#define MSHV_SINT_PAUSE_MESSAGE_STREAM _IOW(MSHV_IOCTL, 0x25, struct mshv_sint_mask) + +/* hv_hvcall device */ +#define MSHV_HVCALL_SETUP _IOW(MSHV_IOCTL, 0x1E, struct mshv_vtl_hvcall_setup) +#define MSHV_HVCALL _IOWR(MSHV_IOCTL, 0x1F, struct mshv_vtl_hvcall) #endif From c720e6a873cc97bdfe8912986e26ceaeeaa6b240 Mon Sep 17 00:00:00 2001 From: "Anirudh Rayabharam (Microsoft)" Date: Wed, 19 Nov 2025 17:17:08 +0000 Subject: [PATCH 668/684] mshv: Add ioctl for self targeted passthrough hvcalls Allow MSHV_ROOT_HVCALL IOCTL on the /dev/mshv fd. This IOCTL would execute a passthrough hypercall targeting the root/parent partition i.e. HV_PARTITION_ID_SELF. This will be useful for the VMM to query things like supported synthetic processor features, supported VMM capabiliites etc. Since hypercalls targeting the host partition could potentially perform privileged operations, allow only a limited set of hypercalls. To begin with, allow only: HVCALL_GET_PARTITION_PROPERTY HVCALL_GET_PARTITION_PROPERTY_EX Signed-off-by: Anirudh Rayabharam (Microsoft) Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 47 ++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 45c7a5fea1cf5b..bc15d6f6922fa4 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -122,6 +122,7 @@ static struct miscdevice mshv_dev = { */ static u16 mshv_passthru_hvcalls[] = { HVCALL_GET_PARTITION_PROPERTY, + HVCALL_GET_PARTITION_PROPERTY_EX, HVCALL_SET_PARTITION_PROPERTY, HVCALL_INSTALL_INTERCEPT, HVCALL_GET_VP_REGISTERS, @@ -136,6 +137,16 @@ static u16 mshv_passthru_hvcalls[] = { HVCALL_GET_VP_CPUID_VALUES, }; +/* + * Only allow hypercalls that are safe to be called by the VMM with the host + * partition as target (i.e. HV_PARTITION_ID_SELF). Carefully audit that a + * hypercall cannot be misused by the VMM before adding it to this list. + */ +static u16 mshv_self_passthru_hvcalls[] = { + HVCALL_GET_PARTITION_PROPERTY, + HVCALL_GET_PARTITION_PROPERTY_EX, +}; + static bool mshv_hvcall_is_async(u16 code) { switch (code) { @@ -147,12 +158,30 @@ static bool mshv_hvcall_is_async(u16 code) return false; } +static bool mshv_passthru_hvcall_allowed(u16 code, u64 pt_id) +{ + int i; + int n = ARRAY_SIZE(mshv_passthru_hvcalls); + u16 *allowed_hvcalls = mshv_passthru_hvcalls; + + if (pt_id == HV_PARTITION_ID_SELF) { + n = ARRAY_SIZE(mshv_self_passthru_hvcalls); + allowed_hvcalls = mshv_self_passthru_hvcalls; + } + + for (i = 0; i < n; ++i) + if (allowed_hvcalls[i] == code) + return true; + + return false; +} + static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, bool partition_locked, void __user *user_args) { u64 status; - int ret = 0, i; + int ret = 0; bool is_async; struct mshv_root_hvcall args; struct page *page; @@ -160,6 +189,7 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, void *input_pg = NULL; void *output_pg = NULL; u16 reps_completed; + u64 pt_id = partition ? partition->pt_id : HV_PARTITION_ID_SELF; if (copy_from_user(&args, user_args, sizeof(args))) return -EFAULT; @@ -171,17 +201,13 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, if (args.out_ptr && (!args.out_sz || args.out_sz > HV_HYP_PAGE_SIZE)) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(mshv_passthru_hvcalls); ++i) - if (args.code == mshv_passthru_hvcalls[i]) - break; - - if (i >= ARRAY_SIZE(mshv_passthru_hvcalls)) + if (!mshv_passthru_hvcall_allowed(args.code, pt_id)) return -EINVAL; is_async = mshv_hvcall_is_async(args.code); if (is_async) { /* async hypercalls can only be called from partition fd */ - if (!partition_locked) + if (!partition || !partition_locked) return -EINVAL; ret = mshv_init_async_handler(partition); if (ret) @@ -209,7 +235,7 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, * NOTE: This only works because all the allowed hypercalls' input * structs begin with a u64 partition_id field. */ - *(u64 *)input_pg = partition->pt_id; + *(u64 *)input_pg = pt_id; reps_completed = 0; do { @@ -238,7 +264,7 @@ static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, ret = hv_result_to_errno(status); else ret = hv_call_deposit_pages(NUMA_NO_NODE, - partition->pt_id, 1); + pt_id, 1); } while (!ret); args.status = hv_result(status); @@ -2050,6 +2076,9 @@ static long mshv_dev_ioctl(struct file *filp, unsigned int ioctl, case MSHV_CREATE_PARTITION: return mshv_ioctl_create_partition((void __user *)arg, misc->this_device); + case MSHV_ROOT_HVCALL: + return mshv_ioctl_passthru_hvcall(NULL, false, + (void __user *)arg); } return -ENOTTY; From b5110eaf67530091343b519d8abd0cddd14660f2 Mon Sep 17 00:00:00 2001 From: Gongwei Li Date: Fri, 21 Nov 2025 11:10:41 +0800 Subject: [PATCH 669/684] Drivers: hv: use kmalloc_array() instead of kmalloc() Replace kmalloc() with kmalloc_array() to prevent potential overflow, as recommended in Documentation/process/deprecated.rst. Signed-off-by: Gongwei Li Signed-off-by: Wei Liu --- drivers/hv/hv_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 36ee89c0358bd0..7e9c8e169c66a6 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -586,7 +586,7 @@ static int util_probe(struct hv_device *dev, (struct hv_util_service *)dev_id->driver_data; int ret; - srv->recv_buffer = kmalloc(HV_HYP_PAGE_SIZE * 4, GFP_KERNEL); + srv->recv_buffer = kmalloc_array(4, HV_HYP_PAGE_SIZE, GFP_KERNEL); if (!srv->recv_buffer) return -ENOMEM; srv->channel = dev->channel; From 9d70ef7a18e0ec1653ac63020a13a5d4dda7cc0d Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Mon, 24 Nov 2025 14:25:59 +0000 Subject: [PATCH 670/684] mshv: adjust interrupt control structure for ARM64 Interrupt control structure (union hv_interupt_control) has different fields when it comes to x86 vs ARM64. Bring in the correct structure from HyperV header files and adjust the existing interrupt routing code accordingly. Signed-off-by: Jinank Jain Signed-off-by: Anirudh Rayabharam (Microsoft) Signed-off-by: Wei Liu --- drivers/hv/mshv_eventfd.c | 6 ++++++ drivers/hv/mshv_irq.c | 4 ++++ drivers/hv/mshv_root_hv_call.c | 6 ++++++ include/hyperv/hvhdk.h | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c index 2a80af1d610ad8..d93a18f09c7640 100644 --- a/drivers/hv/mshv_eventfd.c +++ b/drivers/hv/mshv_eventfd.c @@ -163,8 +163,10 @@ static int mshv_try_assert_irq_fast(struct mshv_irqfd *irqfd) if (hv_scheduler_type != HV_SCHEDULER_TYPE_ROOT) return -EOPNOTSUPP; +#if IS_ENABLED(CONFIG_X86) if (irq->lapic_control.logical_dest_mode) return -EOPNOTSUPP; +#endif vp = partition->pt_vp_array[irq->lapic_apic_id]; @@ -196,8 +198,10 @@ static void mshv_assert_irq_slow(struct mshv_irqfd *irqfd) unsigned int seq; int idx; +#if IS_ENABLED(CONFIG_X86) WARN_ON(irqfd->irqfd_resampler && !irq->lapic_control.level_triggered); +#endif idx = srcu_read_lock(&partition->pt_irq_srcu); if (irqfd->irqfd_girq_ent.guest_irq_num) { @@ -469,6 +473,7 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, init_poll_funcptr(&irqfd->irqfd_polltbl, mshv_irqfd_queue_proc); spin_lock_irq(&pt->pt_irqfds_lock); +#if IS_ENABLED(CONFIG_X86) if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) && !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) { /* @@ -479,6 +484,7 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, ret = -EINVAL; goto fail; } +#endif ret = 0; hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) { if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx) diff --git a/drivers/hv/mshv_irq.c b/drivers/hv/mshv_irq.c index d0fb9ef734f426..798e7e1ab06e24 100644 --- a/drivers/hv/mshv_irq.c +++ b/drivers/hv/mshv_irq.c @@ -119,6 +119,10 @@ void mshv_copy_girq_info(struct mshv_guest_irq_ent *ent, lirq->lapic_vector = ent->girq_irq_data & 0xFF; lirq->lapic_apic_id = (ent->girq_addr_lo >> 12) & 0xFF; lirq->lapic_control.interrupt_type = (ent->girq_irq_data & 0x700) >> 8; +#if IS_ENABLED(CONFIG_X86) lirq->lapic_control.level_triggered = (ent->girq_irq_data >> 15) & 0x1; lirq->lapic_control.logical_dest_mode = (ent->girq_addr_lo >> 2) & 0x1; +#elif IS_ENABLED(CONFIG_ARM64) + lirq->lapic_control.asserted = 1; +#endif } diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c index caf02cfa49c93a..598eaff4ff2994 100644 --- a/drivers/hv/mshv_root_hv_call.c +++ b/drivers/hv/mshv_root_hv_call.c @@ -388,7 +388,13 @@ int hv_call_assert_virtual_interrupt(u64 partition_id, u32 vector, memset(input, 0, sizeof(*input)); input->partition_id = partition_id; input->vector = vector; + /* + * NOTE: dest_addr only needs to be provided while asserting an + * interrupt on x86 platform + */ +#if IS_ENABLED(CONFIG_X86) input->dest_addr = dest_addr; +#endif input->control = control; status = hv_do_hypercall(HVCALL_ASSERT_VIRTUAL_INTERRUPT, input, NULL); local_irq_restore(flags); diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h index 416c0d45b79342..469186df782667 100644 --- a/include/hyperv/hvhdk.h +++ b/include/hyperv/hvhdk.h @@ -579,9 +579,15 @@ union hv_interrupt_control { u64 as_uint64; struct { u32 interrupt_type; /* enum hv_interrupt_type */ +#if IS_ENABLED(CONFIG_X86) u32 level_triggered : 1; u32 logical_dest_mode : 1; u32 rsvd : 30; +#elif IS_ENABLED(CONFIG_ARM64) + u32 rsvd1 : 2; + u32 asserted : 1; + u32 rsvd2 : 29; +#endif } __packed; }; From df4ff5f6cf7864714d66c65ec7df582240a596a4 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:40:39 +0000 Subject: [PATCH 671/684] mshv: Refactor and rename memory region handling functions Simplify and unify memory region management to improve code clarity and reliability. Consolidate pinning and invalidation logic, adopt consistent naming, and remove redundant checks to reduce complexity. Enhance documentation and update call sites for maintainability. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Nuno Das Neves Reviewed-by: Anirudh Rayabharam (Microsoft) Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 80 +++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index bc15d6f6922fa4..fec82619684a6f 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1114,8 +1114,8 @@ mshv_region_map(struct mshv_mem_region *region) } static void -mshv_region_evict_pages(struct mshv_mem_region *region, - u64 page_offset, u64 page_count) +mshv_region_invalidate_pages(struct mshv_mem_region *region, + u64 page_offset, u64 page_count) { if (region->flags.range_pinned) unpin_user_pages(region->pages + page_offset, page_count); @@ -1125,29 +1125,24 @@ mshv_region_evict_pages(struct mshv_mem_region *region, } static void -mshv_region_evict(struct mshv_mem_region *region) +mshv_region_invalidate(struct mshv_mem_region *region) { - mshv_region_evict_pages(region, 0, region->nr_pages); + mshv_region_invalidate_pages(region, 0, region->nr_pages); } static int -mshv_region_populate_pages(struct mshv_mem_region *region, - u64 page_offset, u64 page_count) +mshv_region_pin(struct mshv_mem_region *region) { u64 done_count, nr_pages; struct page **pages; __u64 userspace_addr; int ret; - if (page_offset + page_count > region->nr_pages) - return -EINVAL; - - for (done_count = 0; done_count < page_count; done_count += ret) { - pages = region->pages + page_offset + done_count; + for (done_count = 0; done_count < region->nr_pages; done_count += ret) { + pages = region->pages + done_count; userspace_addr = region->start_uaddr + - (page_offset + done_count) * - HV_HYP_PAGE_SIZE; - nr_pages = min(page_count - done_count, + done_count * HV_HYP_PAGE_SIZE; + nr_pages = min(region->nr_pages - done_count, MSHV_PIN_PAGES_BATCH_SIZE); /* @@ -1158,34 +1153,23 @@ mshv_region_populate_pages(struct mshv_mem_region *region, * with the FOLL_LONGTERM flag does a large temporary * allocation of contiguous memory. */ - if (region->flags.range_pinned) - ret = pin_user_pages_fast(userspace_addr, - nr_pages, - FOLL_WRITE | FOLL_LONGTERM, - pages); - else - ret = -EOPNOTSUPP; - + ret = pin_user_pages_fast(userspace_addr, nr_pages, + FOLL_WRITE | FOLL_LONGTERM, + pages); if (ret < 0) goto release_pages; } - if (PageHuge(region->pages[page_offset])) + if (PageHuge(region->pages[0])) region->flags.large_pages = true; return 0; release_pages: - mshv_region_evict_pages(region, page_offset, done_count); + mshv_region_invalidate_pages(region, 0, done_count); return ret; } -static int -mshv_region_populate(struct mshv_mem_region *region) -{ - return mshv_region_populate_pages(region, 0, region->nr_pages); -} - static struct mshv_mem_region * mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn) { @@ -1245,19 +1229,27 @@ static int mshv_partition_create_region(struct mshv_partition *partition, return 0; } -/* - * Map guest ram. if snp, make sure to release that from the host first - * Side Effects: In case of failure, pages are unpinned when feasible. +/** + * mshv_prepare_pinned_region - Pin and map memory regions + * @region: Pointer to the memory region structure + * + * This function processes memory regions that are explicitly marked as pinned. + * Pinned regions are preallocated, mapped upfront, and do not rely on fault-based + * population. The function ensures the region is properly populated, handles + * encryption requirements for SNP partitions if applicable, maps the region, + * and performs necessary sharing or eviction operations based on the mapping + * result. + * + * Return: 0 on success, negative error code on failure. */ -static int -mshv_partition_mem_region_map(struct mshv_mem_region *region) +static int mshv_prepare_pinned_region(struct mshv_mem_region *region) { struct mshv_partition *partition = region->partition; int ret; - ret = mshv_region_populate(region); + ret = mshv_region_pin(region); if (ret) { - pt_err(partition, "Failed to populate memory region: %d\n", + pt_err(partition, "Failed to pin memory region: %d\n", ret); goto err_out; } @@ -1275,7 +1267,7 @@ mshv_partition_mem_region_map(struct mshv_mem_region *region) pt_err(partition, "Failed to unshare memory region (guest_pfn: %llu): %d\n", region->start_gfn, ret); - goto evict_region; + goto invalidate_region; } } @@ -1285,7 +1277,7 @@ mshv_partition_mem_region_map(struct mshv_mem_region *region) shrc = mshv_partition_region_share(region); if (!shrc) - goto evict_region; + goto invalidate_region; pt_err(partition, "Failed to share memory region (guest_pfn: %llu): %d\n", @@ -1299,8 +1291,8 @@ mshv_partition_mem_region_map(struct mshv_mem_region *region) return 0; -evict_region: - mshv_region_evict(region); +invalidate_region: + mshv_region_invalidate(region); err_out: return ret; } @@ -1349,7 +1341,7 @@ mshv_map_user_memory(struct mshv_partition *partition, ret = hv_call_map_mmio_pages(partition->pt_id, mem.guest_pfn, mmio_pfn, HVPFN_DOWN(mem.size)); else - ret = mshv_partition_mem_region_map(region); + ret = mshv_prepare_pinned_region(region); if (ret) goto errout; @@ -1394,7 +1386,7 @@ mshv_unmap_user_memory(struct mshv_partition *partition, hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, region->nr_pages, unmap_flags); - mshv_region_evict(region); + mshv_region_invalidate(region); vfree(region); return 0; @@ -1812,7 +1804,7 @@ static void destroy_partition(struct mshv_partition *partition) } } - mshv_region_evict(region); + mshv_region_invalidate(region); vfree(region); } From 6f6aed2c497e8d80d8ed6b5a87c6f65dc7548b8f Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:40:45 +0000 Subject: [PATCH 672/684] mshv: Centralize guest memory region destruction Centralize guest memory region destruction to prevent resource leaks and inconsistent cleanup across unmap and partition destruction paths. Unify region removal, encrypted partition access recovery, and region invalidation to improve maintainability and reliability. Reduce code duplication and make future updates less error-prone by encapsulating cleanup logic in a single helper. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Nuno Das Neves Reviewed-by: Anirudh Rayabharam (Microsoft) Signed-off-by: Wei Liu --- drivers/hv/mshv_root_main.c | 65 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index fec82619684a6f..ec18984c3f2d6e 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1356,13 +1356,42 @@ mshv_map_user_memory(struct mshv_partition *partition, return ret; } +static void mshv_partition_destroy_region(struct mshv_mem_region *region) +{ + struct mshv_partition *partition = region->partition; + u32 unmap_flags = 0; + int ret; + + hlist_del(®ion->hnode); + + if (mshv_partition_encrypted(partition)) { + ret = mshv_partition_region_share(region); + if (ret) { + pt_err(partition, + "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n", + ret); + return; + } + } + + if (region->flags.large_pages) + unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE; + + /* ignore unmap failures and continue as process may be exiting */ + hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, + region->nr_pages, unmap_flags); + + mshv_region_invalidate(region); + + vfree(region); +} + /* Called for unmapping both the guest ram and the mmio space */ static long mshv_unmap_user_memory(struct mshv_partition *partition, struct mshv_user_mem_region mem) { struct mshv_mem_region *region; - u32 unmap_flags = 0; if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP))) return -EINVAL; @@ -1377,18 +1406,8 @@ mshv_unmap_user_memory(struct mshv_partition *partition, region->nr_pages != HVPFN_DOWN(mem.size)) return -EINVAL; - hlist_del(®ion->hnode); + mshv_partition_destroy_region(region); - if (region->flags.large_pages) - unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE; - - /* ignore unmap failures and continue as process may be exiting */ - hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, - region->nr_pages, unmap_flags); - - mshv_region_invalidate(region); - - vfree(region); return 0; } @@ -1724,8 +1743,8 @@ static void destroy_partition(struct mshv_partition *partition) { struct mshv_vp *vp; struct mshv_mem_region *region; - int i, ret; struct hlist_node *n; + int i; if (refcount_read(&partition->pt_ref_count)) { pt_err(partition, @@ -1789,25 +1808,9 @@ static void destroy_partition(struct mshv_partition *partition) remove_partition(partition); - /* Remove regions, regain access to the memory and unpin the pages */ hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions, - hnode) { - hlist_del(®ion->hnode); - - if (mshv_partition_encrypted(partition)) { - ret = mshv_partition_region_share(region); - if (ret) { - pt_err(partition, - "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n", - ret); - return; - } - } - - mshv_region_invalidate(region); - - vfree(region); - } + hnode) + mshv_partition_destroy_region(region); /* Withdraw and free all pages we deposited */ hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id); From e950c30a1051d27fd6dd9a48c53ffbc41ee773f2 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:40:50 +0000 Subject: [PATCH 673/684] mshv: Move region management to mshv_regions.c Refactor memory region management functions from mshv_root_main.c into mshv_regions.c for better modularity and code organization. Adjust function calls and headers to use the new implementation. Improve maintainability and separation of concerns in the mshv_root module. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Anirudh Rayabharam (Microsoft) Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/Makefile | 2 +- drivers/hv/mshv_regions.c | 175 +++++++++++++++++++++++++++++++++++ drivers/hv/mshv_root.h | 10 ++ drivers/hv/mshv_root_main.c | 176 +++--------------------------------- 4 files changed, 198 insertions(+), 165 deletions(-) create mode 100644 drivers/hv/mshv_regions.c diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index 6d929fb0e13d26..a49f93c2d2454c 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -14,7 +14,7 @@ hv_vmbus-y := vmbus_drv.o \ hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o mshv_root-y := mshv_root_main.o mshv_synic.o mshv_eventfd.o mshv_irq.o \ - mshv_root_hv_call.o mshv_portid_table.o + mshv_root_hv_call.o mshv_portid_table.o mshv_regions.o mshv_vtl-y := mshv_vtl_main.o # Code that must be built-in diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c new file mode 100644 index 00000000000000..35b866670840ed --- /dev/null +++ b/drivers/hv/mshv_regions.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025, Microsoft Corporation. + * + * Memory region management for mshv_root module. + * + * Authors: Microsoft Linux virtualization team + */ + +#include +#include + +#include + +#include "mshv_root.h" + +struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, + u64 uaddr, u32 flags, + bool is_mmio) +{ + struct mshv_mem_region *region; + + region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages); + if (!region) + return ERR_PTR(-ENOMEM); + + region->nr_pages = nr_pages; + region->start_gfn = guest_pfn; + region->start_uaddr = uaddr; + region->hv_map_flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_ADJUSTABLE; + if (flags & BIT(MSHV_SET_MEM_BIT_WRITABLE)) + region->hv_map_flags |= HV_MAP_GPA_WRITABLE; + if (flags & BIT(MSHV_SET_MEM_BIT_EXECUTABLE)) + region->hv_map_flags |= HV_MAP_GPA_EXECUTABLE; + + /* Note: large_pages flag populated when we pin the pages */ + if (!is_mmio) + region->flags.range_pinned = true; + + return region; +} + +int mshv_region_share(struct mshv_mem_region *region) +{ + u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED; + + if (region->flags.large_pages) + flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; + + return hv_call_modify_spa_host_access(region->partition->pt_id, + region->pages, region->nr_pages, + HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, + flags, true); +} + +int mshv_region_unshare(struct mshv_mem_region *region) +{ + u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE; + + if (region->flags.large_pages) + flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; + + return hv_call_modify_spa_host_access(region->partition->pt_id, + region->pages, region->nr_pages, + 0, + flags, false); +} + +static int mshv_region_remap_pages(struct mshv_mem_region *region, + u32 map_flags, + u64 page_offset, u64 page_count) +{ + if (page_offset + page_count > region->nr_pages) + return -EINVAL; + + if (region->flags.large_pages) + map_flags |= HV_MAP_GPA_LARGE_PAGE; + + return hv_call_map_gpa_pages(region->partition->pt_id, + region->start_gfn + page_offset, + page_count, map_flags, + region->pages + page_offset); +} + +int mshv_region_map(struct mshv_mem_region *region) +{ + u32 map_flags = region->hv_map_flags; + + return mshv_region_remap_pages(region, map_flags, + 0, region->nr_pages); +} + +static void mshv_region_invalidate_pages(struct mshv_mem_region *region, + u64 page_offset, u64 page_count) +{ + if (region->flags.range_pinned) + unpin_user_pages(region->pages + page_offset, page_count); + + memset(region->pages + page_offset, 0, + page_count * sizeof(struct page *)); +} + +void mshv_region_invalidate(struct mshv_mem_region *region) +{ + mshv_region_invalidate_pages(region, 0, region->nr_pages); +} + +int mshv_region_pin(struct mshv_mem_region *region) +{ + u64 done_count, nr_pages; + struct page **pages; + __u64 userspace_addr; + int ret; + + for (done_count = 0; done_count < region->nr_pages; done_count += ret) { + pages = region->pages + done_count; + userspace_addr = region->start_uaddr + + done_count * HV_HYP_PAGE_SIZE; + nr_pages = min(region->nr_pages - done_count, + MSHV_PIN_PAGES_BATCH_SIZE); + + /* + * Pinning assuming 4k pages works for large pages too. + * All page structs within the large page are returned. + * + * Pin requests are batched because pin_user_pages_fast + * with the FOLL_LONGTERM flag does a large temporary + * allocation of contiguous memory. + */ + ret = pin_user_pages_fast(userspace_addr, nr_pages, + FOLL_WRITE | FOLL_LONGTERM, + pages); + if (ret < 0) + goto release_pages; + } + + if (PageHuge(region->pages[0])) + region->flags.large_pages = true; + + return 0; + +release_pages: + mshv_region_invalidate_pages(region, 0, done_count); + return ret; +} + +void mshv_region_destroy(struct mshv_mem_region *region) +{ + struct mshv_partition *partition = region->partition; + u32 unmap_flags = 0; + int ret; + + hlist_del(®ion->hnode); + + if (mshv_partition_encrypted(partition)) { + ret = mshv_region_share(region); + if (ret) { + pt_err(partition, + "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n", + ret); + return; + } + } + + if (region->flags.large_pages) + unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE; + + /* ignore unmap failures and continue as process may be exiting */ + hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, + region->nr_pages, unmap_flags); + + mshv_region_invalidate(region); + + vfree(region); +} diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 3eb815011b46b2..0366f416c2f0da 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -312,4 +312,14 @@ extern struct mshv_root mshv_root; extern enum hv_scheduler_type hv_scheduler_type; extern u8 * __percpu *hv_synic_eventring_tail; +struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, + u64 uaddr, u32 flags, + bool is_mmio); +int mshv_region_share(struct mshv_mem_region *region); +int mshv_region_unshare(struct mshv_mem_region *region); +int mshv_region_map(struct mshv_mem_region *region); +void mshv_region_invalidate(struct mshv_mem_region *region); +int mshv_region_pin(struct mshv_mem_region *region); +void mshv_region_destroy(struct mshv_mem_region *region); + #endif /* _MSHV_ROOT_H_ */ diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index ec18984c3f2d6e..5dfb933da981ec 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1059,117 +1059,6 @@ static void mshv_async_hvcall_handler(void *data, u64 *status) *status = partition->async_hypercall_status; } -static int -mshv_partition_region_share(struct mshv_mem_region *region) -{ - u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED; - - if (region->flags.large_pages) - flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; - - return hv_call_modify_spa_host_access(region->partition->pt_id, - region->pages, region->nr_pages, - HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, - flags, true); -} - -static int -mshv_partition_region_unshare(struct mshv_mem_region *region) -{ - u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE; - - if (region->flags.large_pages) - flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; - - return hv_call_modify_spa_host_access(region->partition->pt_id, - region->pages, region->nr_pages, - 0, - flags, false); -} - -static int -mshv_region_remap_pages(struct mshv_mem_region *region, u32 map_flags, - u64 page_offset, u64 page_count) -{ - if (page_offset + page_count > region->nr_pages) - return -EINVAL; - - if (region->flags.large_pages) - map_flags |= HV_MAP_GPA_LARGE_PAGE; - - /* ask the hypervisor to map guest ram */ - return hv_call_map_gpa_pages(region->partition->pt_id, - region->start_gfn + page_offset, - page_count, map_flags, - region->pages + page_offset); -} - -static int -mshv_region_map(struct mshv_mem_region *region) -{ - u32 map_flags = region->hv_map_flags; - - return mshv_region_remap_pages(region, map_flags, - 0, region->nr_pages); -} - -static void -mshv_region_invalidate_pages(struct mshv_mem_region *region, - u64 page_offset, u64 page_count) -{ - if (region->flags.range_pinned) - unpin_user_pages(region->pages + page_offset, page_count); - - memset(region->pages + page_offset, 0, - page_count * sizeof(struct page *)); -} - -static void -mshv_region_invalidate(struct mshv_mem_region *region) -{ - mshv_region_invalidate_pages(region, 0, region->nr_pages); -} - -static int -mshv_region_pin(struct mshv_mem_region *region) -{ - u64 done_count, nr_pages; - struct page **pages; - __u64 userspace_addr; - int ret; - - for (done_count = 0; done_count < region->nr_pages; done_count += ret) { - pages = region->pages + done_count; - userspace_addr = region->start_uaddr + - done_count * HV_HYP_PAGE_SIZE; - nr_pages = min(region->nr_pages - done_count, - MSHV_PIN_PAGES_BATCH_SIZE); - - /* - * Pinning assuming 4k pages works for large pages too. - * All page structs within the large page are returned. - * - * Pin requests are batched because pin_user_pages_fast - * with the FOLL_LONGTERM flag does a large temporary - * allocation of contiguous memory. - */ - ret = pin_user_pages_fast(userspace_addr, nr_pages, - FOLL_WRITE | FOLL_LONGTERM, - pages); - if (ret < 0) - goto release_pages; - } - - if (PageHuge(region->pages[0])) - region->flags.large_pages = true; - - return 0; - -release_pages: - mshv_region_invalidate_pages(region, 0, done_count); - return ret; -} - static struct mshv_mem_region * mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn) { @@ -1193,7 +1082,7 @@ static int mshv_partition_create_region(struct mshv_partition *partition, struct mshv_mem_region **regionpp, bool is_mmio) { - struct mshv_mem_region *region, *rg; + struct mshv_mem_region *rg; u64 nr_pages = HVPFN_DOWN(mem->size); /* Reject overlapping regions */ @@ -1205,26 +1094,15 @@ static int mshv_partition_create_region(struct mshv_partition *partition, return -EEXIST; } - region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages); - if (!region) - return -ENOMEM; - - region->nr_pages = nr_pages; - region->start_gfn = mem->guest_pfn; - region->start_uaddr = mem->userspace_addr; - region->hv_map_flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_ADJUSTABLE; - if (mem->flags & BIT(MSHV_SET_MEM_BIT_WRITABLE)) - region->hv_map_flags |= HV_MAP_GPA_WRITABLE; - if (mem->flags & BIT(MSHV_SET_MEM_BIT_EXECUTABLE)) - region->hv_map_flags |= HV_MAP_GPA_EXECUTABLE; - - /* Note: large_pages flag populated when we pin the pages */ - if (!is_mmio) - region->flags.range_pinned = true; + rg = mshv_region_create(mem->guest_pfn, nr_pages, + mem->userspace_addr, mem->flags, + is_mmio); + if (IS_ERR(rg)) + return PTR_ERR(rg); - region->partition = partition; + rg->partition = partition; - *regionpp = region; + *regionpp = rg; return 0; } @@ -1262,7 +1140,7 @@ static int mshv_prepare_pinned_region(struct mshv_mem_region *region) * access to guest memory regions. */ if (mshv_partition_encrypted(partition)) { - ret = mshv_partition_region_unshare(region); + ret = mshv_region_unshare(region); if (ret) { pt_err(partition, "Failed to unshare memory region (guest_pfn: %llu): %d\n", @@ -1275,7 +1153,7 @@ static int mshv_prepare_pinned_region(struct mshv_mem_region *region) if (ret && mshv_partition_encrypted(partition)) { int shrc; - shrc = mshv_partition_region_share(region); + shrc = mshv_region_share(region); if (!shrc) goto invalidate_region; @@ -1356,36 +1234,6 @@ mshv_map_user_memory(struct mshv_partition *partition, return ret; } -static void mshv_partition_destroy_region(struct mshv_mem_region *region) -{ - struct mshv_partition *partition = region->partition; - u32 unmap_flags = 0; - int ret; - - hlist_del(®ion->hnode); - - if (mshv_partition_encrypted(partition)) { - ret = mshv_partition_region_share(region); - if (ret) { - pt_err(partition, - "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n", - ret); - return; - } - } - - if (region->flags.large_pages) - unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE; - - /* ignore unmap failures and continue as process may be exiting */ - hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, - region->nr_pages, unmap_flags); - - mshv_region_invalidate(region); - - vfree(region); -} - /* Called for unmapping both the guest ram and the mmio space */ static long mshv_unmap_user_memory(struct mshv_partition *partition, @@ -1406,7 +1254,7 @@ mshv_unmap_user_memory(struct mshv_partition *partition, region->nr_pages != HVPFN_DOWN(mem.size)) return -EINVAL; - mshv_partition_destroy_region(region); + mshv_region_destroy(region); return 0; } @@ -1810,7 +1658,7 @@ static void destroy_partition(struct mshv_partition *partition) hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions, hnode) - mshv_partition_destroy_region(region); + mshv_region_destroy(region); /* Withdraw and free all pages we deposited */ hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id); From abceb4297bf88340ce06016895babe292510a262 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:40:56 +0000 Subject: [PATCH 674/684] mshv: Fix huge page handling in memory region traversal The previous code assumed that if a region's first page was huge, the entire region consisted of huge pages and stored this in a large_pages flag. This premise is incorrect not only for movable regions (where pages can be split and merged on invalidate callbacks or page faults), but even for pinned regions: THPs can be split and merged during allocation, so a large, pinned region may contain a mix of huge and regular pages. This change removes the large_pages flag and replaces region-wide assumptions with per-chunk inspection of the actual page size when mapping, unmapping, sharing, and unsharing. This makes huge page handling correct for mixed-page regions and avoids relying on stale metadata that can easily become invalid as memory is remapped. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Anirudh Rayabharam (Microsoft) Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/mshv_regions.c | 219 +++++++++++++++++++++++++++++++++----- drivers/hv/mshv_root.h | 3 +- 2 files changed, 191 insertions(+), 31 deletions(-) diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c index 35b866670840ed..40126c12ab335d 100644 --- a/drivers/hv/mshv_regions.c +++ b/drivers/hv/mshv_regions.c @@ -14,6 +14,124 @@ #include "mshv_root.h" +/** + * mshv_region_process_chunk - Processes a contiguous chunk of memory pages + * in a region. + * @region : Pointer to the memory region structure. + * @flags : Flags to pass to the handler. + * @page_offset: Offset into the region's pages array to start processing. + * @page_count : Number of pages to process. + * @handler : Callback function to handle the chunk. + * + * This function scans the region's pages starting from @page_offset, + * checking for contiguous present pages of the same size (normal or huge). + * It invokes @handler for the chunk of contiguous pages found. Returns the + * number of pages handled, or a negative error code if the first page is + * not present or the handler fails. + * + * Note: The @handler callback must be able to handle both normal and huge + * pages. + * + * Return: Number of pages handled, or negative error code. + */ +static long mshv_region_process_chunk(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, u64 page_count, + int (*handler)(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, + u64 page_count)) +{ + u64 count, stride; + unsigned int page_order; + struct page *page; + int ret; + + page = region->pages[page_offset]; + if (!page) + return -EINVAL; + + page_order = folio_order(page_folio(page)); + /* The hypervisor only supports 4K and 2M page sizes */ + if (page_order && page_order != HPAGE_PMD_ORDER) + return -EINVAL; + + stride = 1 << page_order; + + /* Start at stride since the first page is validated */ + for (count = stride; count < page_count; count += stride) { + page = region->pages[page_offset + count]; + + /* Break if current page is not present */ + if (!page) + break; + + /* Break if page size changes */ + if (page_order != folio_order(page_folio(page))) + break; + } + + ret = handler(region, flags, page_offset, count); + if (ret) + return ret; + + return count; +} + +/** + * mshv_region_process_range - Processes a range of memory pages in a + * region. + * @region : Pointer to the memory region structure. + * @flags : Flags to pass to the handler. + * @page_offset: Offset into the region's pages array to start processing. + * @page_count : Number of pages to process. + * @handler : Callback function to handle each chunk of contiguous + * pages. + * + * Iterates over the specified range of pages in @region, skipping + * non-present pages. For each contiguous chunk of present pages, invokes + * @handler via mshv_region_process_chunk. + * + * Note: The @handler callback must be able to handle both normal and huge + * pages. + * + * Returns 0 on success, or a negative error code on failure. + */ +static int mshv_region_process_range(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, u64 page_count, + int (*handler)(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, + u64 page_count)) +{ + long ret; + + if (page_offset + page_count > region->nr_pages) + return -EINVAL; + + while (page_count) { + /* Skip non-present pages */ + if (!region->pages[page_offset]) { + page_offset++; + page_count--; + continue; + } + + ret = mshv_region_process_chunk(region, flags, + page_offset, + page_count, + handler); + if (ret < 0) + return ret; + + page_offset += ret; + page_count -= ret; + } + + return 0; +} + struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, u64 uaddr, u32 flags, bool is_mmio) @@ -33,55 +151,86 @@ struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, if (flags & BIT(MSHV_SET_MEM_BIT_EXECUTABLE)) region->hv_map_flags |= HV_MAP_GPA_EXECUTABLE; - /* Note: large_pages flag populated when we pin the pages */ if (!is_mmio) region->flags.range_pinned = true; return region; } +static int mshv_region_chunk_share(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, u64 page_count) +{ + struct page *page = region->pages[page_offset]; + + if (PageHuge(page) || PageTransCompound(page)) + flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; + + return hv_call_modify_spa_host_access(region->partition->pt_id, + region->pages + page_offset, + page_count, + HV_MAP_GPA_READABLE | + HV_MAP_GPA_WRITABLE, + flags, true); +} + int mshv_region_share(struct mshv_mem_region *region) { u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED; - if (region->flags.large_pages) + return mshv_region_process_range(region, flags, + 0, region->nr_pages, + mshv_region_chunk_share); +} + +static int mshv_region_chunk_unshare(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, u64 page_count) +{ + struct page *page = region->pages[page_offset]; + + if (PageHuge(page) || PageTransCompound(page)) flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; return hv_call_modify_spa_host_access(region->partition->pt_id, - region->pages, region->nr_pages, - HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, - flags, true); + region->pages + page_offset, + page_count, 0, + flags, false); } int mshv_region_unshare(struct mshv_mem_region *region) { u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE; - if (region->flags.large_pages) - flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE; - - return hv_call_modify_spa_host_access(region->partition->pt_id, - region->pages, region->nr_pages, - 0, - flags, false); + return mshv_region_process_range(region, flags, + 0, region->nr_pages, + mshv_region_chunk_unshare); } -static int mshv_region_remap_pages(struct mshv_mem_region *region, - u32 map_flags, +static int mshv_region_chunk_remap(struct mshv_mem_region *region, + u32 flags, u64 page_offset, u64 page_count) { - if (page_offset + page_count > region->nr_pages) - return -EINVAL; + struct page *page = region->pages[page_offset]; - if (region->flags.large_pages) - map_flags |= HV_MAP_GPA_LARGE_PAGE; + if (PageHuge(page) || PageTransCompound(page)) + flags |= HV_MAP_GPA_LARGE_PAGE; return hv_call_map_gpa_pages(region->partition->pt_id, region->start_gfn + page_offset, - page_count, map_flags, + page_count, flags, region->pages + page_offset); } +static int mshv_region_remap_pages(struct mshv_mem_region *region, + u32 map_flags, + u64 page_offset, u64 page_count) +{ + return mshv_region_process_range(region, map_flags, + page_offset, page_count, + mshv_region_chunk_remap); +} + int mshv_region_map(struct mshv_mem_region *region) { u32 map_flags = region->hv_map_flags; @@ -134,9 +283,6 @@ int mshv_region_pin(struct mshv_mem_region *region) goto release_pages; } - if (PageHuge(region->pages[0])) - region->flags.large_pages = true; - return 0; release_pages: @@ -144,10 +290,30 @@ int mshv_region_pin(struct mshv_mem_region *region) return ret; } +static int mshv_region_chunk_unmap(struct mshv_mem_region *region, + u32 flags, + u64 page_offset, u64 page_count) +{ + struct page *page = region->pages[page_offset]; + + if (PageHuge(page) || PageTransCompound(page)) + flags |= HV_UNMAP_GPA_LARGE_PAGE; + + return hv_call_unmap_gpa_pages(region->partition->pt_id, + region->start_gfn + page_offset, + page_count, flags); +} + +static int mshv_region_unmap(struct mshv_mem_region *region) +{ + return mshv_region_process_range(region, 0, + 0, region->nr_pages, + mshv_region_chunk_unmap); +} + void mshv_region_destroy(struct mshv_mem_region *region) { struct mshv_partition *partition = region->partition; - u32 unmap_flags = 0; int ret; hlist_del(®ion->hnode); @@ -162,12 +328,7 @@ void mshv_region_destroy(struct mshv_mem_region *region) } } - if (region->flags.large_pages) - unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE; - - /* ignore unmap failures and continue as process may be exiting */ - hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn, - region->nr_pages, unmap_flags); + mshv_region_unmap(region); mshv_region_invalidate(region); diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 0366f416c2f0da..ff3374f13691da 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -77,9 +77,8 @@ struct mshv_mem_region { u64 start_uaddr; u32 hv_map_flags; struct { - u64 large_pages: 1; /* 2MiB */ u64 range_pinned: 1; - u64 reserved: 62; + u64 reserved: 63; } flags; struct mshv_partition *partition; struct page *pages[]; From c39dda08286f4d5ce4d114f8d5dbfdb85effbd6a Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:41:02 +0000 Subject: [PATCH 675/684] mshv: Add refcount and locking to mem regions Introduce kref-based reference counting and spinlock protection for memory regions in Hyper-V partition management. This change improves memory region lifecycle management and ensures thread-safe access to the region list. Previously, the regions list was protected by the partition mutex. However, this approach is too heavy for frequent fault and invalidation operations. Finer grained locking is now used to improve efficiency and concurrency. This is a precursor to supporting movable memory regions. Fault and invalidation handling for movable regions will require safe traversal of the region list and holding a region reference while performing invalidation or fault operations. Signed-off-by: Stanislav Kinsburskii Signed-off-by: Wei Liu --- drivers/hv/mshv_regions.c | 19 ++++++++++++++++--- drivers/hv/mshv_root.h | 6 +++++- drivers/hv/mshv_root_main.c | 32 ++++++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c index 40126c12ab335d..4ec78fdaf56d6f 100644 --- a/drivers/hv/mshv_regions.c +++ b/drivers/hv/mshv_regions.c @@ -7,6 +7,7 @@ * Authors: Microsoft Linux virtualization team */ +#include #include #include @@ -154,6 +155,8 @@ struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, if (!is_mmio) region->flags.range_pinned = true; + kref_init(®ion->refcount); + return region; } @@ -311,13 +314,13 @@ static int mshv_region_unmap(struct mshv_mem_region *region) mshv_region_chunk_unmap); } -void mshv_region_destroy(struct mshv_mem_region *region) +static void mshv_region_destroy(struct kref *ref) { + struct mshv_mem_region *region = + container_of(ref, struct mshv_mem_region, refcount); struct mshv_partition *partition = region->partition; int ret; - hlist_del(®ion->hnode); - if (mshv_partition_encrypted(partition)) { ret = mshv_region_share(region); if (ret) { @@ -334,3 +337,13 @@ void mshv_region_destroy(struct mshv_mem_region *region) vfree(region); } + +void mshv_region_put(struct mshv_mem_region *region) +{ + kref_put(®ion->refcount, mshv_region_destroy); +} + +int mshv_region_get(struct mshv_mem_region *region) +{ + return kref_get_unless_zero(®ion->refcount); +} diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index ff3374f13691da..4249534ba9007e 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -72,6 +72,7 @@ do { \ struct mshv_mem_region { struct hlist_node hnode; + struct kref refcount; u64 nr_pages; u64 start_gfn; u64 start_uaddr; @@ -97,6 +98,8 @@ struct mshv_partition { u64 pt_id; refcount_t pt_ref_count; struct mutex pt_mutex; + + spinlock_t pt_mem_regions_lock; struct hlist_head pt_mem_regions; // not ordered u32 pt_vp_count; @@ -319,6 +322,7 @@ int mshv_region_unshare(struct mshv_mem_region *region); int mshv_region_map(struct mshv_mem_region *region); void mshv_region_invalidate(struct mshv_mem_region *region); int mshv_region_pin(struct mshv_mem_region *region); -void mshv_region_destroy(struct mshv_mem_region *region); +void mshv_region_put(struct mshv_mem_region *region); +int mshv_region_get(struct mshv_mem_region *region); #endif /* _MSHV_ROOT_H_ */ diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index 5dfb933da981ec..aa1a11f4dc3e7a 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -1086,13 +1086,15 @@ static int mshv_partition_create_region(struct mshv_partition *partition, u64 nr_pages = HVPFN_DOWN(mem->size); /* Reject overlapping regions */ + spin_lock(&partition->pt_mem_regions_lock); hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) { if (mem->guest_pfn + nr_pages <= rg->start_gfn || rg->start_gfn + rg->nr_pages <= mem->guest_pfn) continue; - + spin_unlock(&partition->pt_mem_regions_lock); return -EEXIST; } + spin_unlock(&partition->pt_mem_regions_lock); rg = mshv_region_create(mem->guest_pfn, nr_pages, mem->userspace_addr, mem->flags, @@ -1224,8 +1226,9 @@ mshv_map_user_memory(struct mshv_partition *partition, if (ret) goto errout; - /* Install the new region */ + spin_lock(&partition->pt_mem_regions_lock); hlist_add_head(®ion->hnode, &partition->pt_mem_regions); + spin_unlock(&partition->pt_mem_regions_lock); return 0; @@ -1244,17 +1247,27 @@ mshv_unmap_user_memory(struct mshv_partition *partition, if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP))) return -EINVAL; + spin_lock(&partition->pt_mem_regions_lock); + region = mshv_partition_region_by_gfn(partition, mem.guest_pfn); - if (!region) - return -EINVAL; + if (!region) { + spin_unlock(&partition->pt_mem_regions_lock); + return -ENOENT; + } /* Paranoia check */ if (region->start_uaddr != mem.userspace_addr || region->start_gfn != mem.guest_pfn || - region->nr_pages != HVPFN_DOWN(mem.size)) + region->nr_pages != HVPFN_DOWN(mem.size)) { + spin_unlock(&partition->pt_mem_regions_lock); return -EINVAL; + } + + hlist_del(®ion->hnode); - mshv_region_destroy(region); + spin_unlock(&partition->pt_mem_regions_lock); + + mshv_region_put(region); return 0; } @@ -1657,8 +1670,10 @@ static void destroy_partition(struct mshv_partition *partition) remove_partition(partition); hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions, - hnode) - mshv_region_destroy(region); + hnode) { + hlist_del(®ion->hnode); + mshv_region_put(region); + } /* Withdraw and free all pages we deposited */ hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id); @@ -1856,6 +1871,7 @@ mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev) INIT_HLIST_HEAD(&partition->pt_devices); + spin_lock_init(&partition->pt_mem_regions_lock); INIT_HLIST_HEAD(&partition->pt_mem_regions); mshv_eventfd_init(partition); From b9a66cd5ccbb9fade15d0e427e19470d8ad35b75 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Wed, 3 Dec 2025 21:41:09 +0000 Subject: [PATCH 676/684] mshv: Add support for movable memory regions Introduce support for movable memory regions in the Hyper-V root partition driver to improve memory management flexibility and enable advanced use cases such as dynamic memory remapping. Mirror the address space between the Linux root partition and guest VMs using HMM. The root partition owns the memory, while guest VMs act as devices with page tables managed via hypercalls. MSHV handles VP intercepts by invoking hmm_range_fault() and updating SLAT entries. When memory is reclaimed, HMM invalidates the relevant regions, prompting MSHV to clear SLAT entries; guest VMs will fault again on access. Integrate mmu_interval_notifier for movable regions, implement handlers for HMM faults and memory invalidation, and update memory region mapping logic to support movable regions. While MMU notifiers are commonly used in virtualization drivers, this implementation leverages HMM (Heterogeneous Memory Management) for its specialized functionality. HMM provides a framework for mirroring, invalidation, and fault handling, reducing boilerplate and improving maintainability compared to generic MMU notifiers. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- drivers/hv/Kconfig | 2 + drivers/hv/mshv_regions.c | 218 +++++++++++++++++++++++++++++++++++- drivers/hv/mshv_root.h | 20 +++- drivers/hv/mshv_root_main.c | 142 +++++++++++++++++++---- 4 files changed, 346 insertions(+), 36 deletions(-) diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index d4a8d349200c89..7937ac0cbd0ff8 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -76,6 +76,8 @@ config MSHV_ROOT depends on PAGE_SIZE_4KB select EVENTFD select VIRT_XFER_TO_GUEST_WORK + select HMM_MIRROR + select MMU_NOTIFIER default n help Select this option to enable support for booting and running as root diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c index 4ec78fdaf56d6f..202b9d551e3934 100644 --- a/drivers/hv/mshv_regions.c +++ b/drivers/hv/mshv_regions.c @@ -7,6 +7,8 @@ * Authors: Microsoft Linux virtualization team */ +#include +#include #include #include #include @@ -15,6 +17,8 @@ #include "mshv_root.h" +#define MSHV_MAP_FAULT_IN_PAGES PTRS_PER_PMD + /** * mshv_region_process_chunk - Processes a contiguous chunk of memory pages * in a region. @@ -134,8 +138,7 @@ static int mshv_region_process_range(struct mshv_mem_region *region, } struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, - u64 uaddr, u32 flags, - bool is_mmio) + u64 uaddr, u32 flags) { struct mshv_mem_region *region; @@ -152,9 +155,6 @@ struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, if (flags & BIT(MSHV_SET_MEM_BIT_EXECUTABLE)) region->hv_map_flags |= HV_MAP_GPA_EXECUTABLE; - if (!is_mmio) - region->flags.range_pinned = true; - kref_init(®ion->refcount); return region; @@ -245,7 +245,7 @@ int mshv_region_map(struct mshv_mem_region *region) static void mshv_region_invalidate_pages(struct mshv_mem_region *region, u64 page_offset, u64 page_count) { - if (region->flags.range_pinned) + if (region->type == MSHV_REGION_TYPE_MEM_PINNED) unpin_user_pages(region->pages + page_offset, page_count); memset(region->pages + page_offset, 0, @@ -321,6 +321,9 @@ static void mshv_region_destroy(struct kref *ref) struct mshv_partition *partition = region->partition; int ret; + if (region->type == MSHV_REGION_TYPE_MEM_MOVABLE) + mshv_region_movable_fini(region); + if (mshv_partition_encrypted(partition)) { ret = mshv_region_share(region); if (ret) { @@ -347,3 +350,206 @@ int mshv_region_get(struct mshv_mem_region *region) { return kref_get_unless_zero(®ion->refcount); } + +/** + * mshv_region_hmm_fault_and_lock - Handle HMM faults and lock the memory region + * @region: Pointer to the memory region structure + * @range: Pointer to the HMM range structure + * + * This function performs the following steps: + * 1. Reads the notifier sequence for the HMM range. + * 2. Acquires a read lock on the memory map. + * 3. Handles HMM faults for the specified range. + * 4. Releases the read lock on the memory map. + * 5. If successful, locks the memory region mutex. + * 6. Verifies if the notifier sequence has changed during the operation. + * If it has, releases the mutex and returns -EBUSY to match with + * hmm_range_fault() return code for repeating. + * + * Return: 0 on success, a negative error code otherwise. + */ +static int mshv_region_hmm_fault_and_lock(struct mshv_mem_region *region, + struct hmm_range *range) +{ + int ret; + + range->notifier_seq = mmu_interval_read_begin(range->notifier); + mmap_read_lock(region->mni.mm); + ret = hmm_range_fault(range); + mmap_read_unlock(region->mni.mm); + if (ret) + return ret; + + mutex_lock(®ion->mutex); + + if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) { + mutex_unlock(®ion->mutex); + cond_resched(); + return -EBUSY; + } + + return 0; +} + +/** + * mshv_region_range_fault - Handle memory range faults for a given region. + * @region: Pointer to the memory region structure. + * @page_offset: Offset of the page within the region. + * @page_count: Number of pages to handle. + * + * This function resolves memory faults for a specified range of pages + * within a memory region. It uses HMM (Heterogeneous Memory Management) + * to fault in the required pages and updates the region's page array. + * + * Return: 0 on success, negative error code on failure. + */ +static int mshv_region_range_fault(struct mshv_mem_region *region, + u64 page_offset, u64 page_count) +{ + struct hmm_range range = { + .notifier = ®ion->mni, + .default_flags = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE, + }; + unsigned long *pfns; + int ret; + u64 i; + + pfns = kmalloc_array(page_count, sizeof(*pfns), GFP_KERNEL); + if (!pfns) + return -ENOMEM; + + range.hmm_pfns = pfns; + range.start = region->start_uaddr + page_offset * HV_HYP_PAGE_SIZE; + range.end = range.start + page_count * HV_HYP_PAGE_SIZE; + + do { + ret = mshv_region_hmm_fault_and_lock(region, &range); + } while (ret == -EBUSY); + + if (ret) + goto out; + + for (i = 0; i < page_count; i++) + region->pages[page_offset + i] = hmm_pfn_to_page(pfns[i]); + + ret = mshv_region_remap_pages(region, region->hv_map_flags, + page_offset, page_count); + + mutex_unlock(®ion->mutex); +out: + kfree(pfns); + return ret; +} + +bool mshv_region_handle_gfn_fault(struct mshv_mem_region *region, u64 gfn) +{ + u64 page_offset, page_count; + int ret; + + /* Align the page offset to the nearest MSHV_MAP_FAULT_IN_PAGES. */ + page_offset = ALIGN_DOWN(gfn - region->start_gfn, + MSHV_MAP_FAULT_IN_PAGES); + + /* Map more pages than requested to reduce the number of faults. */ + page_count = min(region->nr_pages - page_offset, + MSHV_MAP_FAULT_IN_PAGES); + + ret = mshv_region_range_fault(region, page_offset, page_count); + + WARN_ONCE(ret, + "p%llu: GPA intercept failed: region %#llx-%#llx, gfn %#llx, page_offset %llu, page_count %llu\n", + region->partition->pt_id, region->start_uaddr, + region->start_uaddr + (region->nr_pages << HV_HYP_PAGE_SHIFT), + gfn, page_offset, page_count); + + return !ret; +} + +/** + * mshv_region_interval_invalidate - Invalidate a range of memory region + * @mni: Pointer to the mmu_interval_notifier structure + * @range: Pointer to the mmu_notifier_range structure + * @cur_seq: Current sequence number for the interval notifier + * + * This function invalidates a memory region by remapping its pages with + * no access permissions. It locks the region's mutex to ensure thread safety + * and updates the sequence number for the interval notifier. If the range + * is blockable, it uses a blocking lock; otherwise, it attempts a non-blocking + * lock and returns false if unsuccessful. + * + * NOTE: Failure to invalidate a region is a serious error, as the pages will + * be considered freed while they are still mapped by the hypervisor. + * Any attempt to access such pages will likely crash the system. + * + * Return: true if the region was successfully invalidated, false otherwise. + */ +static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni, + const struct mmu_notifier_range *range, + unsigned long cur_seq) +{ + struct mshv_mem_region *region = container_of(mni, + struct mshv_mem_region, + mni); + u64 page_offset, page_count; + unsigned long mstart, mend; + int ret = -EPERM; + + if (mmu_notifier_range_blockable(range)) + mutex_lock(®ion->mutex); + else if (!mutex_trylock(®ion->mutex)) + goto out_fail; + + mmu_interval_set_seq(mni, cur_seq); + + mstart = max(range->start, region->start_uaddr); + mend = min(range->end, region->start_uaddr + + (region->nr_pages << HV_HYP_PAGE_SHIFT)); + + page_offset = HVPFN_DOWN(mstart - region->start_uaddr); + page_count = HVPFN_DOWN(mend - mstart); + + ret = mshv_region_remap_pages(region, HV_MAP_GPA_NO_ACCESS, + page_offset, page_count); + if (ret) + goto out_fail; + + mshv_region_invalidate_pages(region, page_offset, page_count); + + mutex_unlock(®ion->mutex); + + return true; + +out_fail: + WARN_ONCE(ret, + "Failed to invalidate region %#llx-%#llx (range %#lx-%#lx, event: %u, pages %#llx-%#llx, mm: %#llx): %d\n", + region->start_uaddr, + region->start_uaddr + (region->nr_pages << HV_HYP_PAGE_SHIFT), + range->start, range->end, range->event, + page_offset, page_offset + page_count - 1, (u64)range->mm, ret); + return false; +} + +static const struct mmu_interval_notifier_ops mshv_region_mni_ops = { + .invalidate = mshv_region_interval_invalidate, +}; + +void mshv_region_movable_fini(struct mshv_mem_region *region) +{ + mmu_interval_notifier_remove(®ion->mni); +} + +bool mshv_region_movable_init(struct mshv_mem_region *region) +{ + int ret; + + ret = mmu_interval_notifier_insert(®ion->mni, current->mm, + region->start_uaddr, + region->nr_pages << HV_HYP_PAGE_SHIFT, + &mshv_region_mni_ops); + if (ret) + return false; + + mutex_init(®ion->mutex); + + return true; +} diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h index 4249534ba9007e..3c1d88b367412d 100644 --- a/drivers/hv/mshv_root.h +++ b/drivers/hv/mshv_root.h @@ -15,6 +15,7 @@ #include #include #include +#include #include /* @@ -70,6 +71,12 @@ do { \ #define vp_info(v, fmt, ...) vp_devprintk(info, v, fmt, ##__VA_ARGS__) #define vp_dbg(v, fmt, ...) vp_devprintk(dbg, v, fmt, ##__VA_ARGS__) +enum mshv_region_type { + MSHV_REGION_TYPE_MEM_PINNED, + MSHV_REGION_TYPE_MEM_MOVABLE, + MSHV_REGION_TYPE_MMIO +}; + struct mshv_mem_region { struct hlist_node hnode; struct kref refcount; @@ -77,11 +84,10 @@ struct mshv_mem_region { u64 start_gfn; u64 start_uaddr; u32 hv_map_flags; - struct { - u64 range_pinned: 1; - u64 reserved: 63; - } flags; struct mshv_partition *partition; + enum mshv_region_type type; + struct mmu_interval_notifier mni; + struct mutex mutex; /* protects region pages remapping */ struct page *pages[]; }; @@ -315,8 +321,7 @@ extern enum hv_scheduler_type hv_scheduler_type; extern u8 * __percpu *hv_synic_eventring_tail; struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages, - u64 uaddr, u32 flags, - bool is_mmio); + u64 uaddr, u32 flags); int mshv_region_share(struct mshv_mem_region *region); int mshv_region_unshare(struct mshv_mem_region *region); int mshv_region_map(struct mshv_mem_region *region); @@ -324,5 +329,8 @@ void mshv_region_invalidate(struct mshv_mem_region *region); int mshv_region_pin(struct mshv_mem_region *region); void mshv_region_put(struct mshv_mem_region *region); int mshv_region_get(struct mshv_mem_region *region); +bool mshv_region_handle_gfn_fault(struct mshv_mem_region *region, u64 gfn); +void mshv_region_movable_fini(struct mshv_mem_region *region); +bool mshv_region_movable_init(struct mshv_mem_region *region); #endif /* _MSHV_ROOT_H_ */ diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c index aa1a11f4dc3e7a..9cf28a3f12fe7f 100644 --- a/drivers/hv/mshv_root_main.c +++ b/drivers/hv/mshv_root_main.c @@ -594,14 +594,98 @@ static long mshv_run_vp_with_root_scheduler(struct mshv_vp *vp) static_assert(sizeof(struct hv_message) <= MSHV_RUN_VP_BUF_SZ, "sizeof(struct hv_message) must not exceed MSHV_RUN_VP_BUF_SZ"); +static struct mshv_mem_region * +mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn) +{ + struct mshv_mem_region *region; + + hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) { + if (gfn >= region->start_gfn && + gfn < region->start_gfn + region->nr_pages) + return region; + } + + return NULL; +} + +#ifdef CONFIG_X86_64 +static struct mshv_mem_region * +mshv_partition_region_by_gfn_get(struct mshv_partition *p, u64 gfn) +{ + struct mshv_mem_region *region; + + spin_lock(&p->pt_mem_regions_lock); + region = mshv_partition_region_by_gfn(p, gfn); + if (!region || !mshv_region_get(region)) { + spin_unlock(&p->pt_mem_regions_lock); + return NULL; + } + spin_unlock(&p->pt_mem_regions_lock); + + return region; +} + +/** + * mshv_handle_gpa_intercept - Handle GPA (Guest Physical Address) intercepts. + * @vp: Pointer to the virtual processor structure. + * + * This function processes GPA intercepts by identifying the memory region + * corresponding to the intercepted GPA, aligning the page offset, and + * mapping the required pages. It ensures that the region is valid and + * handles faults efficiently by mapping multiple pages at once. + * + * Return: true if the intercept was handled successfully, false otherwise. + */ +static bool mshv_handle_gpa_intercept(struct mshv_vp *vp) +{ + struct mshv_partition *p = vp->vp_partition; + struct mshv_mem_region *region; + struct hv_x64_memory_intercept_message *msg; + bool ret; + u64 gfn; + + msg = (struct hv_x64_memory_intercept_message *) + vp->vp_intercept_msg_page->u.payload; + + gfn = HVPFN_DOWN(msg->guest_physical_address); + + region = mshv_partition_region_by_gfn_get(p, gfn); + if (!region) + return false; + + /* Only movable memory ranges are supported for GPA intercepts */ + if (region->type == MSHV_REGION_TYPE_MEM_MOVABLE) + ret = mshv_region_handle_gfn_fault(region, gfn); + else + ret = false; + + mshv_region_put(region); + + return ret; +} +#else /* CONFIG_X86_64 */ +static bool mshv_handle_gpa_intercept(struct mshv_vp *vp) { return false; } +#endif /* CONFIG_X86_64 */ + +static bool mshv_vp_handle_intercept(struct mshv_vp *vp) +{ + switch (vp->vp_intercept_msg_page->header.message_type) { + case HVMSG_GPA_INTERCEPT: + return mshv_handle_gpa_intercept(vp); + } + return false; +} + static long mshv_vp_ioctl_run_vp(struct mshv_vp *vp, void __user *ret_msg) { long rc; - if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) - rc = mshv_run_vp_with_root_scheduler(vp); - else - rc = mshv_run_vp_with_hyp_scheduler(vp); + do { + if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT) + rc = mshv_run_vp_with_root_scheduler(vp); + else + rc = mshv_run_vp_with_hyp_scheduler(vp); + } while (rc == 0 && mshv_vp_handle_intercept(vp)); if (rc) return rc; @@ -1059,20 +1143,6 @@ static void mshv_async_hvcall_handler(void *data, u64 *status) *status = partition->async_hypercall_status; } -static struct mshv_mem_region * -mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn) -{ - struct mshv_mem_region *region; - - hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) { - if (gfn >= region->start_gfn && - gfn < region->start_gfn + region->nr_pages) - return region; - } - - return NULL; -} - /* * NB: caller checks and makes sure mem->size is page aligned * Returns: 0 with regionpp updated on success, or -errno @@ -1097,11 +1167,18 @@ static int mshv_partition_create_region(struct mshv_partition *partition, spin_unlock(&partition->pt_mem_regions_lock); rg = mshv_region_create(mem->guest_pfn, nr_pages, - mem->userspace_addr, mem->flags, - is_mmio); + mem->userspace_addr, mem->flags); if (IS_ERR(rg)) return PTR_ERR(rg); + if (is_mmio) + rg->type = MSHV_REGION_TYPE_MMIO; + else if (mshv_partition_encrypted(partition) || + !mshv_region_movable_init(rg)) + rg->type = MSHV_REGION_TYPE_MEM_PINNED; + else + rg->type = MSHV_REGION_TYPE_MEM_MOVABLE; + rg->partition = partition; *regionpp = rg; @@ -1217,11 +1294,28 @@ mshv_map_user_memory(struct mshv_partition *partition, if (ret) return ret; - if (is_mmio) - ret = hv_call_map_mmio_pages(partition->pt_id, mem.guest_pfn, - mmio_pfn, HVPFN_DOWN(mem.size)); - else + switch (region->type) { + case MSHV_REGION_TYPE_MEM_PINNED: ret = mshv_prepare_pinned_region(region); + break; + case MSHV_REGION_TYPE_MEM_MOVABLE: + /* + * For movable memory regions, remap with no access to let + * the hypervisor track dirty pages, enabling pre-copy live + * migration. + */ + ret = hv_call_map_gpa_pages(partition->pt_id, + region->start_gfn, + region->nr_pages, + HV_MAP_GPA_NO_ACCESS, NULL); + break; + case MSHV_REGION_TYPE_MMIO: + ret = hv_call_map_mmio_pages(partition->pt_id, + region->start_gfn, + mmio_pfn, + region->nr_pages); + break; + } if (ret) goto errout; From 723c47a221ee407901055c9d9b4434e68c5d650e Mon Sep 17 00:00:00 2001 From: Praveen K Paladugu Date: Fri, 5 Dec 2025 14:17:06 -0600 Subject: [PATCH 677/684] mshv: Add definitions for MSHV sleep state configuration Add the definitions required to configure sleep states in mshv hypervsior. Signed-off-by: Praveen K Paladugu Co-developed-by: Anatol Belski Signed-off-by: Anatol Belski Reviewed-by: Easwar Hariharan Reviewed-by: Nuno Das Neves Acked-by: Stanislav Kinsburskii Signed-off-by: Wei Liu --- include/hyperv/hvgdk_mini.h | 4 +++- include/hyperv/hvhdk_mini.h | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index 1d5ce11be8b63a..04b18d0e37af36 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -465,19 +465,21 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_RESET_DEBUG_SESSION 0x006b #define HVCALL_MAP_STATS_PAGE 0x006c #define HVCALL_UNMAP_STATS_PAGE 0x006d +#define HVCALL_SET_SYSTEM_PROPERTY 0x006f #define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076 #define HVCALL_GET_SYSTEM_PROPERTY 0x007b #define HVCALL_MAP_DEVICE_INTERRUPT 0x007c #define HVCALL_UNMAP_DEVICE_INTERRUPT 0x007d #define HVCALL_RETARGET_INTERRUPT 0x007e #define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 +#define HVCALL_ENTER_SLEEP_STATE 0x0084 #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b #define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 #define HVCALL_CREATE_PORT 0x0095 #define HVCALL_CONNECT_PORT 0x0096 #define HVCALL_START_VP 0x0099 -#define HVCALL_GET_VP_INDEX_FROM_APIC_ID 0x009a +#define HVCALL_GET_VP_INDEX_FROM_APIC_ID 0x009a #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0 #define HVCALL_SIGNAL_EVENT_DIRECT 0x00c0 diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index f2d7b50de7a42c..41a29bf8ec145c 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -140,6 +140,7 @@ enum hv_snp_status { enum hv_system_property { /* Add more values when needed */ + HV_SYSTEM_PROPERTY_SLEEP_STATE = 3, HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15, HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21, HV_SYSTEM_PROPERTY_CRASHDUMPAREA = 47, @@ -155,6 +156,19 @@ union hv_pfn_range { /* HV_SPA_PAGE_RANGE */ } __packed; }; +enum hv_sleep_state { + HV_SLEEP_STATE_S1 = 1, + HV_SLEEP_STATE_S2 = 2, + HV_SLEEP_STATE_S3 = 3, + HV_SLEEP_STATE_S4 = 4, + HV_SLEEP_STATE_S5 = 5, + /* + * After hypervisor has received this, any follow up sleep + * state registration requests will be rejected. + */ + HV_SLEEP_STATE_LOCK = 6 +}; + enum hv_dynamic_processor_feature_property { /* Add more values when needed */ HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13, @@ -184,6 +198,32 @@ struct hv_output_get_system_property { }; } __packed; +struct hv_sleep_state_info { + u32 sleep_state; /* enum hv_sleep_state */ + u8 pm1a_slp_typ; + u8 pm1b_slp_typ; +} __packed; + +struct hv_input_set_system_property { + u32 property_id; /* enum hv_system_property */ + u32 reserved; + union { + /* More fields to be filled in when needed */ + struct hv_sleep_state_info set_sleep_state_info; + + /* + * Add a reserved field to ensure the union is 8-byte aligned as + * existing members may not be. This is a temporary measure + * until all remaining members are added. + */ + u64 reserved0[8]; + }; +} __packed; + +struct hv_input_enter_sleep_state { /* HV_INPUT_ENTER_SLEEP_STATE */ + u32 sleep_state; /* enum hv_sleep_state */ +} __packed; + struct hv_input_map_stats_page { u32 type; /* enum hv_stats_object_type */ u32 padding; From f0be2600ac55a5845d536c56787daca50dbcb2a1 Mon Sep 17 00:00:00 2001 From: Praveen K Paladugu Date: Fri, 5 Dec 2025 14:17:07 -0600 Subject: [PATCH 678/684] mshv: Use reboot notifier to configure sleep state Configure sleep state information from ACPI in MSHV hypervisor using a reboot notifier. This data allows the hypervisor to correctly power off the host during shutdown. Signed-off-by: Praveen K Paladugu Co-developed-by: Anatol Belski Signed-off-by: Anatol Belski Reviewed-by: Easwar Hariharan Reviewed-by: Stansialv Kinsburskii Acked-by: Ingo Molnar Reviewed-by: Nuno Das Neves Signed-off-by: Wei Liu --- arch/x86/hyperv/hv_init.c | 1 + arch/x86/include/asm/mshyperv.h | 1 + drivers/hv/mshv_common.c | 78 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index e28737ec7054fe..daf97a984b78d7 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -555,6 +555,7 @@ void __init hyperv_init(void) hv_remap_tsc_clocksource(); hv_root_crash_init(); + hv_sleep_notifiers_register(); } else { hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 10037125099a15..62a89debfbce45 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -177,6 +177,7 @@ int hyperv_flush_guest_mapping_range(u64 as, int hyperv_fill_flush_guest_mapping_list( struct hv_guest_mapping_flush_list *flush, u64 start_gfn, u64 end_gfn); +void hv_sleep_notifiers_register(void); #ifdef CONFIG_X86_64 void hv_apic_init(void); diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c index aa2be51979fd68..ee733ba1575e1a 100644 --- a/drivers/hv/mshv_common.c +++ b/drivers/hv/mshv_common.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "mshv.h" @@ -138,3 +141,78 @@ int hv_call_get_partition_property(u64 partition_id, return 0; } EXPORT_SYMBOL_GPL(hv_call_get_partition_property); + +/* + * Corresponding sleep states have to be initialized in order for a subsequent + * HVCALL_ENTER_SLEEP_STATE call to succeed. Currently only S5 state as per + * ACPI 6.4 chapter 7.4.2 is relevant, while S1, S2 and S3 can be supported. + * + * In order to pass proper PM values to mshv, ACPI should be initialized and + * should support S5 sleep state when this method is invoked. + */ +static int hv_initialize_sleep_states(void) +{ + u64 status; + unsigned long flags; + struct hv_input_set_system_property *in; + acpi_status acpi_status; + u8 sleep_type_a, sleep_type_b; + + if (!acpi_sleep_state_supported(ACPI_STATE_S5)) { + pr_err("%s: S5 sleep state not supported.\n", __func__); + return -ENODEV; + } + + acpi_status = acpi_get_sleep_type_data(ACPI_STATE_S5, &sleep_type_a, + &sleep_type_b); + if (ACPI_FAILURE(acpi_status)) + return -ENODEV; + + local_irq_save(flags); + in = *this_cpu_ptr(hyperv_pcpu_input_arg); + memset(in, 0, sizeof(*in)); + + in->property_id = HV_SYSTEM_PROPERTY_SLEEP_STATE; + in->set_sleep_state_info.sleep_state = HV_SLEEP_STATE_S5; + in->set_sleep_state_info.pm1a_slp_typ = sleep_type_a; + in->set_sleep_state_info.pm1b_slp_typ = sleep_type_b; + + status = hv_do_hypercall(HVCALL_SET_SYSTEM_PROPERTY, in, NULL); + local_irq_restore(flags); + + if (!hv_result_success(status)) { + hv_status_err(status, "\n"); + return hv_result_to_errno(status); + } + + return 0; +} + +/* + * This notifier initializes sleep states in mshv hypervisor which will be + * used during power off. + */ +static int hv_reboot_notifier_handler(struct notifier_block *this, + unsigned long code, void *another) +{ + int ret = 0; + + if (code == SYS_HALT || code == SYS_POWER_OFF) + ret = hv_initialize_sleep_states(); + + return ret ? NOTIFY_DONE : NOTIFY_OK; +} + +static struct notifier_block hv_reboot_notifier = { + .notifier_call = hv_reboot_notifier_handler, +}; + +void hv_sleep_notifiers_register(void) +{ + int ret; + + ret = register_reboot_notifier(&hv_reboot_notifier); + if (ret) + pr_err("%s: cannot register reboot notifier %d\n", __func__, + ret); +} From 615a6e7d83f958e7ef3bc818e818f7c6433b4c2a Mon Sep 17 00:00:00 2001 From: Praveen K Paladugu Date: Fri, 5 Dec 2025 14:17:08 -0600 Subject: [PATCH 679/684] mshv: Cleanly shutdown root partition with MSHV Root partitions running on MSHV currently attempt ACPI power-off, which MSHV intercepts and triggers a Machine Check Exception (MCE), leading to a kernel panic. Root partitions panic with a trace similar to: [ 81.306348] reboot: Power down [ 81.314709] mce: [Hardware Error]: CPU 0: Machine Check Exception: 4 Bank 0: b2000000c0060001 [ 81.314711] mce: [Hardware Error]: TSC 3b8cb60a66 PPIN 11d98332458e4ea9 [ 81.314713] mce: [Hardware Error]: PROCESSOR 0:606a6 TIME 1759339405 SOCKET 0 APIC 0 microcode ffffffff [ 81.314715] mce: [Hardware Error]: Run the above through 'mcelog --ascii' [ 81.314716] mce: [Hardware Error]: Machine check: Processor context corrupt [ 81.314717] Kernel panic - not syncing: Fatal machine check To avoid this, configure the sleep state in the hypervisor and invoke the HVCALL_ENTER_SLEEP_STATE hypercall as the final step in the shutdown sequence. This ensures a clean and safe shutdown of the root partition. Signed-off-by: Praveen K Paladugu Co-developed-by: Anatol Belski Signed-off-by: Anatol Belski Reviewed-by: Easwar Hariharan Acked-by: Stanislav Kinsburskii Signed-off-by: Wei Liu --- arch/x86/include/asm/mshyperv.h | 1 + arch/x86/kernel/cpu/mshyperv.c | 2 ++ drivers/hv/mshv_common.c | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 62a89debfbce45..eef4c3a5ba28ee 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -178,6 +178,7 @@ int hyperv_fill_flush_guest_mapping_list( struct hv_guest_mapping_flush_list *flush, u64 start_gfn, u64 end_gfn); void hv_sleep_notifiers_register(void); +void hv_machine_power_off(void); #ifdef CONFIG_X86_64 void hv_apic_init(void); diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index fac9953a72eff6..579fb2c64cfd46 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -621,6 +621,8 @@ static void __init ms_hyperv_init_platform(void) #endif #if IS_ENABLED(CONFIG_HYPERV) + if (hv_root_partition()) + machine_ops.power_off = hv_machine_power_off; #if defined(CONFIG_KEXEC_CORE) machine_ops.shutdown = hv_machine_shutdown; #endif diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c index ee733ba1575e1a..58027b23c20660 100644 --- a/drivers/hv/mshv_common.c +++ b/drivers/hv/mshv_common.c @@ -216,3 +216,24 @@ void hv_sleep_notifiers_register(void) pr_err("%s: cannot register reboot notifier %d\n", __func__, ret); } + +/* + * Power off the machine by entering S5 sleep state via Hyper-V hypercall. + * This call does not return if successful. + */ +void hv_machine_power_off(void) +{ + unsigned long flags; + struct hv_input_enter_sleep_state *in; + + local_irq_save(flags); + in = *this_cpu_ptr(hyperv_pcpu_input_arg); + in->sleep_state = HV_SLEEP_STATE_S5; + + (void)hv_do_hypercall(HVCALL_ENTER_SLEEP_STATE, in, NULL); + local_irq_restore(flags); + + /* should never reach here */ + BUG(); + +} From 670d7ef945d3a84683594429aea6ab2cdfa5ceb4 Mon Sep 17 00:00:00 2001 From: Gui-Dong Han Date: Wed, 3 Dec 2025 02:01:05 +0800 Subject: [PATCH 680/684] hwmon: (w83791d) Convert macros to functions to avoid TOCTOU The macro FAN_FROM_REG evaluates its arguments multiple times. When used in lockless contexts involving shared driver data, this leads to Time-of-Check to Time-of-Use (TOCTOU) race conditions, potentially causing divide-by-zero errors. Convert the macro to a static function. This guarantees that arguments are evaluated only once (pass-by-value), preventing the race conditions. Additionally, in store_fan_div, move the calculation of the minimum limit inside the update lock. This ensures that the read-modify-write sequence operates on consistent data. Adhere to the principle of minimal changes by only converting macros that evaluate arguments multiple times and are used in lockless contexts. Link: https://lore.kernel.org/all/CALbr=LYJ_ehtp53HXEVkSpYoub+XYSTU8Rg=o1xxMJ8=5z8B-g@mail.gmail.com/ Fixes: 9873964d6eb2 ("[PATCH] HWMON: w83791d: New hardware monitoring driver for the Winbond W83791D") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han Link: https://lore.kernel.org/r/20251202180105.12842-1-hanguidong02@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/w83791d.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index ace854b370a054..996e36951f9dad 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -218,9 +218,14 @@ static u8 fan_to_reg(long rpm, int div) return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254); } -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ - ((val) == 255 ? 0 : \ - 1350000 / ((val) * (div)))) +static int fan_from_reg(int val, int div) +{ + if (val == 0) + return -1; + if (val == 255) + return 0; + return 1350000 / (val * div); +} /* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */ #define TEMP1_FROM_REG(val) ((val) * 1000) @@ -521,7 +526,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ struct w83791d_data *data = w83791d_update_device(dev); \ int nr = sensor_attr->index; \ return sprintf(buf, "%d\n", \ - FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ + fan_from_reg(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ } show_fan_reg(fan); @@ -585,10 +590,10 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, if (err) return err; + mutex_lock(&data->update_lock); /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + min = fan_from_reg(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - mutex_lock(&data->update_lock); data->fan_div[nr] = div_to_reg(nr, val); switch (nr) { From fae00a7186cecf90a57757a63b97a0cbcf384fe9 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Wed, 3 Dec 2025 21:21:09 +0100 Subject: [PATCH 681/684] hwmon: (dell-smm) Fix off-by-one error in dell_smm_is_visible() The documentation states that on machines supporting only global fan mode control, the pwmX_enable attributes should only be created for the first fan channel (pwm1_enable, aka channel 0). Fix the off-by-one error caused by the fact that fan channels have a zero-based index. Cc: stable@vger.kernel.org Fixes: 1c1658058c99 ("hwmon: (dell-smm) Add support for automatic fan mode") Signed-off-by: Armin Wolf Link: https://lore.kernel.org/r/20251203202109.331528-1-W_Armin@gmx.de Signed-off-by: Guenter Roeck --- drivers/hwmon/dell-smm-hwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 683baf361c4c84..a34753fc29733a 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -861,9 +861,9 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types if (auto_fan) { /* * The setting affects all fans, so only create a - * single attribute. + * single attribute for the first fan channel. */ - if (channel != 1) + if (channel != 0) return 0; /* From 541dfb49dcb80c2509e030842de77adfb77820f5 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Fri, 5 Dec 2025 10:02:41 +0800 Subject: [PATCH 682/684] hwmon: (emc2305) fix double put in emc2305_probe_childs_from_dt ./drivers/hwmon/emc2305.c:597:4-15: ERROR: probable double put Device node iterators put the previous value of the index variable, so an explicit put causes a double put. Signed-off-by: Pei Xiao Link: https://lore.kernel.org/r/tencent_CD373F952BE48697C949E39CB5EB77841D06@qq.com Signed-off-by: Guenter Roeck --- drivers/hwmon/emc2305.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 60809289f8169d..b0f2318c97e333 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -593,10 +593,8 @@ static int emc2305_probe_childs_from_dt(struct device *dev) for_each_child_of_node(dev->of_node, child) { if (of_property_present(child, "reg")) { ret = emc2305_of_parse_pwm_child(dev, child, data); - if (ret) { - of_node_put(child); + if (ret) continue; - } count++; } } From 4910da6b36b122db50a27fabf6ab7f8611b60bf8 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Fri, 5 Dec 2025 11:15:13 +0800 Subject: [PATCH 683/684] hwmon: (emc2305) fix device node refcount leak in error path The for_each_child_of_node() macro automatically manages device node reference counts during normal iteration. However, when breaking out of the loop early with return, the current iteration's node is not automatically released, leading to a reference count leak. Fix this by adding of_node_put(child) before returning from the loop when emc2305_set_single_tz() fails. This issue could lead to memory leaks over multiple probe cycles. Signed-off-by: Pei Xiao Link: https://lore.kernel.org/r/tencent_5CDC08544C901D5ECA270573D5AEE3117108@qq.com Signed-off-by: Guenter Roeck --- drivers/hwmon/emc2305.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index b0f2318c97e333..ceae96c07ac45b 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -683,8 +683,10 @@ static int emc2305_probe(struct i2c_client *client) i = 0; for_each_child_of_node(dev->of_node, child) { ret = emc2305_set_single_tz(dev, child, i); - if (ret != 0) + if (ret != 0) { + of_node_put(child); return ret; + } i++; } } else { From 08bfcf4ff9d39228150a757803fc02dffce84ab0 Mon Sep 17 00:00:00 2001 From: Kathara Sasikumar Date: Fri, 5 Dec 2025 21:58:35 +0000 Subject: [PATCH 684/684] docs: hwmon: fix link to g762 devicetree binding The devicetree binding for g762 was converted to YAML to match vendor prefix conventions. Update the reference accordingly. Signed-off-by: Kathara Sasikumar Link: https://lore.kernel.org/r/20251205215835.783273-1-katharasasikumar007@gmail.com Fixes: 3d8e25372417 ("dt-bindings: hwmon: g762: Convert to yaml schema") Signed-off-by: Guenter Roeck --- Documentation/hwmon/g762.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/hwmon/g762.rst b/Documentation/hwmon/g762.rst index 0371b3365c48cf..f224552a2d3cc0 100644 --- a/Documentation/hwmon/g762.rst +++ b/Documentation/hwmon/g762.rst @@ -17,7 +17,7 @@ done via a userland daemon like fancontrol. Note that those entries do not provide ways to setup the specific hardware characteristics of the system (reference clock, pulses per fan revolution, ...); Those can be modified via devicetree bindings -documented in Documentation/devicetree/bindings/hwmon/g762.txt or +documented in Documentation/devicetree/bindings/hwmon/gmt,g762.yaml or using a specific platform_data structure in board initialization file (see include/linux/platform_data/g762.h).