* Re: [PATCH 0/2] Update Energy Model with perfromance limits
From: Lukasz Luba @ 2024-04-05 10:11 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-kernel, linux-pm, dietmar.eggemann, linux-arm-kernel,
sudeep.holla, cristian.marussi, linux-samsung-soc, rafael,
viresh.kumar, quic_sibis
In-Reply-To: <20240405105600.000019fd@Huawei.com>
On 4/5/24 10:56, Jonathan Cameron wrote:
> On Wed, 3 Apr 2024 17:23:13 +0100
> Lukasz Luba <lukasz.luba@arm.com> wrote:
>
> Typo in patch title. performance
Thank you, good catch!
Regards,
Lukasz
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: rockchip: add Protonic MECSBC device-tree
From: Sascha Hauer @ 2024-04-05 10:14 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
David Jander, Sascha Hauer
In-Reply-To: <20240405-protonic-mecsbc-v2-0-0a6fedc78b9f@pengutronix.de>
From: David Jander <david@protonic.nl>
MECSBC is a single board computer for blood analysis machines from
RR-Mechatronics, designed and manufactured by Protonic Holland, based on
the Rockchip RK3568 SoC.
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm64/boot/dts/rockchip/Makefile | 1 +
arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts | 404 +++++++++++++++++++++++++
2 files changed, 405 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index f906a868b71ac..51c242c462b04 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -100,6 +100,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-fastrhino-r66s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-fastrhino-r68s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-lubancat-2.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mecsbc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5c.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts b/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts
new file mode 100644
index 0000000000000..edd54c5932337
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3568.dtsi"
+
+/ {
+ model = "Protonic MECSBC";
+ compatible = "prt,mecsbc", "rockchip,rk3568";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ };
+
+ chosen: chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ tas2562-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Speaker";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&tas2562>;
+ };
+ };
+
+ vdd_gpu: regulator-vdd-gpu {
+ compatible = "pwm-regulator";
+ pwms = <&pwm1 0 5000 PWM_POLARITY_INVERTED>;
+ regulator-name = "vdd_gpu";
+ regulator-min-microvolt = <915000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-settling-time-up-us = <250>;
+ pwm-dutycycle-range = <0 100>; /* dutycycle inverted 0% => 0.915V */
+ };
+
+ vcc_sd: regulator-sd {
+ compatible = "regulator-gpio";
+ enable-gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+ regulator-name = "sdcard-gpio-supply";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ states = <1800000 0x1>, <3300000 0x0>;
+ };
+
+ vdd_npu: regulator-vdd-npu {
+ compatible = "pwm-regulator";
+ pwms = <&pwm2 0 5000 PWM_POLARITY_INVERTED>;
+ regulator-name = "vdd_npu";
+ regulator-min-microvolt = <915000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-settling-time-up-us = <250>;
+ pwm-dutycycle-range = <0 100>; /* dutycycle inverted 0% => 0.915V */
+ };
+
+ p3v3: regulator-p3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "p3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ p1v8: regulator-p1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "p1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+};
+
+&combphy0 {
+ status = "okay";
+};
+
+&combphy1 {
+ status = "okay";
+};
+
+&combphy2 {
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&gmac1 {
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>;
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-id";
+ clock_in_out = "output";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_clkinout
+ &gmac1m1_rgmii_bus>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ vdd_cpu: regulator@60 {
+ compatible = "fcs,fan53555";
+ reg = <0x60>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-ramp-delay = <2300>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2m0_xfer>;
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3m0_xfer>;
+ status = "okay";
+
+ tas2562: amplifier@4c {
+ compatible = "ti,tas2562";
+ reg = <0x4c>;
+ #sound-dai-cells = <0>;
+ shutdown-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&gpio1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tas2562>;
+ interrupts = <RK_PD1 IRQ_TYPE_LEVEL_LOW>;
+ ti,imon-slot-no = <0>;
+ };
+};
+
+&i2c5 {
+ status = "okay";
+
+ temperature-sensor@48 {
+ compatible = "ti,tmp1075";
+ reg = <0x48>;
+ };
+
+ rtc@51 {
+ compatible = "nxp,pcf85363";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "rtcic_32kout";
+ };
+};
+
+&i2s1_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1m0_sclktx &i2s1m0_lrcktx &i2s1m0_sdi0 &i2s1m0_sdo0>;
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <ð_phy1_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20m1_pins>;
+ reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x2m1_pins>;
+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&p3v3>;
+ status = "okay";
+};
+
+&pinctrl {
+ ethernet {
+ eth_phy1_rst: eth-phy1-rst {
+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ tas2562 {
+ pinctrl_tas2562: tas2562 {
+ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&p3v3>;
+ pmuio2-supply = <&p3v3>;
+ vccio1-supply = <&p1v8>;
+ vccio2-supply = <&p1v8>;
+ vccio3-supply = <&vcc_sd>;
+ vccio4-supply = <&p1v8>;
+ vccio5-supply = <&p3v3>;
+ vccio6-supply = <&p1v8>;
+ vccio7-supply = <&p3v3>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&p1v8>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
+ vmmc-supply = <&p3v3>;
+ vqmmc-supply = <&p1v8>;
+ mmc-hs200-1_8v;
+ non-removable;
+ no-sd;
+ no-sdio;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&p3v3>;
+ vqmmc-supply = <&vcc_sd>;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ extcon = <&usb2phy0>;
+ status = "okay";
+ dr_mode = "host";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ status = "okay";
+};
+
+&usb2phy1 {
+ status = "okay";
+};
+
+&usb2phy1_host {
+ status = "okay";
+};
+
+&usb2phy1_otg {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm1m0_pins>;
+};
+
+&pwm2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2m0_pins>;
+};
+
+&gpu_opp_table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <915000>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <915000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <915000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <920000>;
+ };
+
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <950000>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1000000>;
+ };
+};
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: arm: rockchip: Add Protonic MECSBC board
From: Sascha Hauer @ 2024-04-05 10:14 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
David Jander, Sascha Hauer, Krzysztof Kozlowski
In-Reply-To: <20240405-protonic-mecsbc-v2-0-0a6fedc78b9f@pengutronix.de>
MECSBC is a single board computer for blood analysis machines from
RR-Mechatronics, designed and manufactured by Protonic Holland, based on
the Rockchip RK3568 SoC.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index fcf7316ecd74c..4847fe072d550 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -700,6 +700,11 @@ properties:
- powkiddy,x55
- const: rockchip,rk3566
+ - description: Protonic MECSBC board
+ items:
+ - const: prt,mecsbc
+ - const: rockchip,rk3568
+
- description: QNAP TS-433-4G 4-Bay NAS
items:
- const: qnap,ts433
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 0/2] Add Protonic MECSBC board support
From: Sascha Hauer @ 2024-04-05 10:14 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
David Jander, Sascha Hauer, Krzysztof Kozlowski
This series adds support for the Protonic MECSBC. MECSBC is a single
board computer for blood analysis machines from RR-Mechatronics,
designed and manufactured by Protonic Holland, based on the Rockchip
RK3568 SoC.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Changes in v2:
- use generic node names (Krzysztof)
- name regulators consistently (Krzysztof)
- do not use underscores in node names (Krzysztof)
- keep alphabetic order in arch/arm64/boot/dts/rockchip/Makefile (Heiko)
- use rgmii-id mode and drop [tr]x_delay (Andrew)
- add SD card regulator to support 1.8V modes
- Link to v1: https://lore.kernel.org/r/20240404-protonic-mecsbc-v1-0-ad5b42ade6c6@pengutronix.de
---
David Jander (1):
arm64: dts: rockchip: add Protonic MECSBC device-tree
Sascha Hauer (1):
dt-bindings: arm: rockchip: Add Protonic MECSBC board
.../devicetree/bindings/arm/rockchip.yaml | 5 +
arch/arm64/boot/dts/rockchip/Makefile | 1 +
arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts | 404 +++++++++++++++++++++
3 files changed, 410 insertions(+)
---
base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
change-id: 20240404-protonic-mecsbc-6cfa56a48fb7
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC 5/8] KVM: arm64: Explicitly handle MDSELR_EL1 traps as UNDEFINED
From: Marc Zyngier @ 2024-04-05 10:15 UTC (permalink / raw)
To: Anshuman Khandual
Cc: linux-arm-kernel, Jonathan Corbet, Oliver Upton, James Morse,
Suzuki K Poulose, Catalin Marinas, Will Deacon, Mark Brown,
Mark Rutland, kvmarm, linux-kernel
In-Reply-To: <20240405080008.1225223-6-anshuman.khandual@arm.com>
On Fri, 05 Apr 2024 09:00:05 +0100,
Anshuman Khandual <anshuman.khandual@arm.com> wrote:
>
> Currently read_sanitised_id_aa64dfr0_el1() caps the ID_AA64DFR0.DebugVer to
> ID_AA64DFR0_DebugVer_V8P8, resulting in FEAT_Debugv8p9 not being exposed to
> the guest. MDSELR_EL1 register access in the guest, is currently trapped by
> the existing configuration of the fine-grained traps.
Please add support for the HDFGxTR2_EL2 registers in the trap routing
arrays, add support for the corresponding FGUs in the corresponding
structure, and condition the UNDEF on the lack of *guest* support for
the feature.
In short, implement the architecture as described in the pseudocode,
and not a cheap shortcut.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH net] net: sparx5: fix reconfiguration of PCS on link mode change
From: Russell King (Oracle) @ 2024-04-05 10:20 UTC (permalink / raw)
To: Daniel Machon
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Lars Povlsen, Steen Hegelund, UNGLinuxDriver, Bjarni Jonasson,
netdev, linux-arm-kernel, linux-kernel
In-Reply-To: <20240405-link-mode-reconfiguration-fix-v1-1-c1480bc2346a@microchip.com>
On Fri, Apr 05, 2024 at 11:53:15AM +0200, Daniel Machon wrote:
> It was observed that the PCS would be misconfigured on link mode change,
> if the negotiated link mode went from no-inband capabilities to in-band
> capabilities. This bug appeared after the neg_mode change of phylink [1],
> but is really due to the wrong config being used when reconfiguring the PCS.
I don't see how the change you point to could have changed the
behaviour. Old code:
conf.inband = phylink_autoneg_inband(mode);
conf.autoneg = phylink_test(advertising, Autoneg);
New code:
conf.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED ||
neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
conf.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
where, for SGMII or 802.3z modes, neg_mode will be one of
PHYLINK_PCS_NEG_INBAND_DISABLED or PHYLINK_PCS_NEG_INBAND_ENABLED if
phylink_autoneg_inband(mode) is true, or PHYLINK_PCS_NEG_OUTBAND if
not.
It does change conf.autoneg slightly in that this will always be true
for SGMII, but will only be true for Autoneg + 802.3z modes.
As far as your code change goes, it looks correct to me, but I think
it's fixing a bug that goes back long before the commit you have
identified.
However, I think there's another issue here which is more relevant to
the problem you describe in your commit message. If you look at
port_conf_has_changed(), you will notice that it fails to compare
conf.inband, and thus fails to notice any change in the setting of
that configuration item. This will result in sparx5_port_pcs_set()
not even being called if only conf.inband changes state.
Thus, changing from in-band to out-of-band or vice versa won't have
any effect if this is the only change that occurs, and this also
exists prior to my change.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 18/25] dt-bindings: media: imx258: Add alternate compatible strings
From: Dave Stevenson @ 2024-04-05 10:25 UTC (permalink / raw)
To: Conor Dooley
Cc: git, linux-media, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, pavel, phone-devel
In-Reply-To: <20240403-vista-defendant-ebadbaa52059@spud>
Hi Conor
On Wed, 3 Apr 2024 at 17:14, Conor Dooley <conor@kernel.org> wrote:
>
> On Wed, Apr 03, 2024 at 09:03:47AM -0600, git@luigi311.com wrote:
> > From: Dave Stevenson <dave.stevenson@raspberrypi.com>
> >
> > There are a number of variants of the imx258 modules that can not
> > be differentiated at runtime, so add compatible strings for the
> > PDAF variant.
> >
> > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > Signed-off-by: Luis Garcia <git@luigi311.com>
> > ---
> > .../devicetree/bindings/media/i2c/sony,imx258.yaml | 9 +++++++--
> > 1 file changed, 7 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
> > index bee61a443b23..c978abc0cdb3 100644
> > --- a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
> > +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
> > @@ -13,11 +13,16 @@ description: |-
> > IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel
> > type stacked image sensor with a square pixel array of size 4208 x 3120. It
> > is programmable through I2C interface. Image data is sent through MIPI
> > - CSI-2.
> > + CSI-2. The sensor exists in two different models, a standard variant
> > + (IMX258) and a variant with phase detection autofocus (IMX258-PDAF).
> > + The camera module does not expose the model through registers, so the
> > + exact model needs to be specified.
> >
> > properties:
> > compatible:
> > - const: sony,imx258
> > + enum:
> > + - sony,imx258
> > + - sony,imx258-pdaf
>
> Does the pdaf variant support all of the features/is it register
> compatible with the regular variant? If it is, the regular variant
> should be a fallback compatible.
It has the same register set, but certain registers have to be
programmed differently so that the image is corrected for the
partially shielded pixels used for phase detect auto focus (PDAF).
Either compatible will "work" on either variant of the module, but
you'll get weird image artifacts when using the wrong one.
Dave
> Cheers,
> Conor.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC 8/8] arm64/hw_breakpoint: Enable FEAT_Debugv8p9
From: Marc Zyngier @ 2024-04-05 10:26 UTC (permalink / raw)
To: Anshuman Khandual
Cc: linux-arm-kernel, Jonathan Corbet, Oliver Upton, James Morse,
Suzuki K Poulose, Catalin Marinas, Will Deacon, Mark Brown,
Mark Rutland, kvmarm, linux-kernel
In-Reply-To: <20240405080008.1225223-9-anshuman.khandual@arm.com>
On Fri, 05 Apr 2024 09:00:08 +0100,
Anshuman Khandual <anshuman.khandual@arm.com> wrote:
>
> Currently there can be maximum 16 breakpoints, and 16 watchpoints available
> on a given platform - as detected from ID_AA64DFR0_EL1.[BRPs|WRPs] register
> fields. But these breakpoint, and watchpoints can be extended further up to
> 64 via a new arch feature FEAT_Debugv8p9.
>
> This first enables banked access for the breakpoint and watchpoint register
> set via MDSELR_EL1, extended exceptions via MDSCR_EL1.EMBWE and determining
> available breakpoints and watchpoints in the platform from ID_AA64DFR1_EL1,
> when FEAT_Debugv8p9 is enabled.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> arch/arm64/include/asm/debug-monitors.h | 2 +-
> arch/arm64/include/asm/hw_breakpoint.h | 46 +++++++++++++++++++------
> arch/arm64/kernel/debug-monitors.c | 16 ++++++---
> arch/arm64/kernel/hw_breakpoint.c | 33 ++++++++++++++++++
> 4 files changed, 82 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
> index 13d437bcbf58..75eedba2abbe 100644
> --- a/arch/arm64/include/asm/debug-monitors.h
> +++ b/arch/arm64/include/asm/debug-monitors.h
> @@ -19,7 +19,7 @@
> /* MDSCR_EL1 enabling bits */
> #define DBG_MDSCR_KDE (1 << 13)
> #define DBG_MDSCR_MDE (1 << 15)
> -#define DBG_MDSCR_MASK ~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
> +#define DBG_MDSCR_EMBWE (1UL << 32)
>
> #define DBG_ESR_EVT(x) (((x) >> 27) & 0x7)
>
> diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
> index bd81cf17744a..6b9822140f71 100644
> --- a/arch/arm64/include/asm/hw_breakpoint.h
> +++ b/arch/arm64/include/asm/hw_breakpoint.h
> @@ -79,8 +79,8 @@ static inline void decode_ctrl_reg(u32 reg,
> * Limits.
> * Changing these will require modifications to the register accessors.
> */
> -#define ARM_MAX_BRP 16
> -#define ARM_MAX_WRP 16
> +#define ARM_MAX_BRP 64
> +#define ARM_MAX_WRP 64
>
> /* Virtual debug register bases. */
> #define AARCH64_DBG_REG_BVR 0
> @@ -135,22 +135,48 @@ static inline void ptrace_hw_copy_thread(struct task_struct *task)
> }
> #endif
>
> +static inline bool is_debug_v8p9_enabled(void)
> +{
> + u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
> + int dver = cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_DebugVer_SHIFT);
> +
> + return dver == ID_AA64DFR0_EL1_DebugVer_V8P9;
> +}
> +
> /* Determine number of BRP registers available. */
> static inline int get_num_brps(void)
> {
> - u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
> - return 1 +
> - cpuid_feature_extract_unsigned_field(dfr0,
> - ID_AA64DFR0_EL1_BRPs_SHIFT);
> + u64 dfr0, dfr1;
> + int dver, brps;
> +
> + dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
> + dver = cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_DebugVer_SHIFT);
> + if (dver == ID_AA64DFR0_EL1_DebugVer_V8P9) {
> + dfr1 = read_sanitised_ftr_reg(SYS_ID_AA64DFR1_EL1);
> + brps = cpuid_feature_extract_unsigned_field_width(dfr1,
> + ID_AA64DFR1_EL1_BRPs_SHIFT, 8);
> + } else {
> + brps = cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_BRPs_SHIFT);
> + }
> + return 1 + brps;
> }
>
> /* Determine number of WRP registers available. */
> static inline int get_num_wrps(void)
> {
> - u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
> - return 1 +
> - cpuid_feature_extract_unsigned_field(dfr0,
> - ID_AA64DFR0_EL1_WRPs_SHIFT);
> + u64 dfr0, dfr1;
> + int dver, wrps;
> +
> + dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
> + dver = cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_DebugVer_SHIFT);
> + if (dver == ID_AA64DFR0_EL1_DebugVer_V8P9) {
> + dfr1 = read_sanitised_ftr_reg(SYS_ID_AA64DFR1_EL1);
> + wrps = cpuid_feature_extract_unsigned_field_width(dfr1,
> + ID_AA64DFR1_EL1_WRPs_SHIFT, 8);
> + } else {
> + wrps = cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_WRPs_SHIFT);
> + }
> + return 1 + wrps;
> }
>
> #ifdef CONFIG_CPU_PM
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 64f2ecbdfe5c..3299d1e8dc61 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -23,6 +23,7 @@
> #include <asm/debug-monitors.h>
> #include <asm/system_misc.h>
> #include <asm/traps.h>
> +#include <asm/hw_breakpoint.h>
include order.
>
> /* Determine debug architecture. */
> u8 debug_monitors_arch(void)
> @@ -34,7 +35,7 @@ u8 debug_monitors_arch(void)
> /*
> * MDSCR access routines.
> */
> -static void mdscr_write(u32 mdscr)
> +static void mdscr_write(u64 mdscr)
> {
> unsigned long flags;
> flags = local_daif_save();
> @@ -43,7 +44,7 @@ static void mdscr_write(u32 mdscr)
> }
> NOKPROBE_SYMBOL(mdscr_write);
>
> -static u32 mdscr_read(void)
> +static u64 mdscr_read(void)
> {
> return read_sysreg(mdscr_el1);
> }
> @@ -76,10 +77,11 @@ early_param("nodebugmon", early_debug_disable);
> */
> static DEFINE_PER_CPU(int, mde_ref_count);
> static DEFINE_PER_CPU(int, kde_ref_count);
> +static DEFINE_PER_CPU(int, embwe_ref_count);
>
> void enable_debug_monitors(enum dbg_active_el el)
> {
> - u32 mdscr, enable = 0;
> + u64 mdscr, enable = 0;
>
> WARN_ON(preemptible());
>
> @@ -90,6 +92,9 @@ void enable_debug_monitors(enum dbg_active_el el)
> this_cpu_inc_return(kde_ref_count) == 1)
> enable |= DBG_MDSCR_KDE;
>
> + if (is_debug_v8p9_enabled() && this_cpu_inc_return(embwe_ref_count) == 1)
> + enable |= DBG_MDSCR_EMBWE;
> +
> if (enable && debug_enabled) {
> mdscr = mdscr_read();
> mdscr |= enable;
> @@ -100,7 +105,7 @@ NOKPROBE_SYMBOL(enable_debug_monitors);
>
> void disable_debug_monitors(enum dbg_active_el el)
> {
> - u32 mdscr, disable = 0;
> + u64 mdscr, disable = 0;
>
> WARN_ON(preemptible());
>
> @@ -111,6 +116,9 @@ void disable_debug_monitors(enum dbg_active_el el)
> this_cpu_dec_return(kde_ref_count) == 0)
> disable &= ~DBG_MDSCR_KDE;
>
> + if (is_debug_v8p9_enabled() && this_cpu_dec_return(embwe_ref_count) == 0)
> + disable &= ~DBG_MDSCR_EMBWE;
> +
> if (disable) {
> mdscr = mdscr_read();
> mdscr &= disable;
> diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
> index 2f5755192c2b..7b9169535b76 100644
> --- a/arch/arm64/kernel/hw_breakpoint.c
> +++ b/arch/arm64/kernel/hw_breakpoint.c
> @@ -103,10 +103,40 @@ int hw_breakpoint_slots(int type)
> WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \
> WRITE_WB_REG_CASE(OFF, 15, REG, VAL)
>
> +static int set_bank_index(int n)
> +{
> + int mdsel_bank;
> + int bank = n / 16, index = n % 16;
> +
> + switch (bank) {
> + case 0:
> + mdsel_bank = MDSELR_EL1_BANK_BANK_0;
> + break;
> + case 1:
> + mdsel_bank = MDSELR_EL1_BANK_BANK_1;
> + break;
> + case 2:
> + mdsel_bank = MDSELR_EL1_BANK_BANK_2;
> + break;
> + case 3:
> + mdsel_bank = MDSELR_EL1_BANK_BANK_3;
> + break;
> + default:
> + pr_warn("Unknown register bank %d\n", bank);
> + return -EINVAL;
> + }
> + write_sysreg_s(mdsel_bank << MDSELR_EL1_BANK_SHIFT, SYS_MDSELR_EL1);
> + isb();
> + return index;
> +}
> +
> static u64 read_wb_reg(int reg, int n)
> {
> u64 val = 0;
>
> + if (is_debug_v8p9_enabled())
> + n = set_bank_index(n);
> +
> switch (reg + n) {
> GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val);
> GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val);
> @@ -122,6 +152,9 @@ NOKPROBE_SYMBOL(read_wb_reg);
>
> static void write_wb_reg(int reg, int n, u64 val)
> {
> + if (is_debug_v8p9_enabled())
> + n = set_bank_index(n);
> +
> switch (reg + n) {
> GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val);
> GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val);
Are these things guaranteed to be only used in contexts where there
can be no interleaving of such operations? If any interleaving can
occur, this is broken.
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 2/2] mailbox: arm_mhuv3: Add driver
From: Jonathan Cameron @ 2024-04-05 10:32 UTC (permalink / raw)
To: Cristian Marussi
Cc: linux-kernel, linux-arm-kernel, devicetree, sudeep.holla,
jassisinghbrar, robh+dt, krzysztof.kozlowski+dt, conor+dt
In-Reply-To: <20240404062347.3219795-3-cristian.marussi@arm.com>
On Thu, 4 Apr 2024 07:23:47 +0100
Cristian Marussi <cristian.marussi@arm.com> wrote:
> Add support for ARM MHUv3 mailbox controller.
>
> Support is limited to the MHUv3 Doorbell extension using only the PBX/MBX
> combined interrupts.
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Drive by review (I was curious what this was :)
> diff --git a/drivers/mailbox/arm_mhuv3.c b/drivers/mailbox/arm_mhuv3.c
> new file mode 100644
> index 000000000000..e4125568bec0
> --- /dev/null
> +++ b/drivers/mailbox/arm_mhuv3.c
> @@ -0,0 +1,1063 @@
> +struct dummy_page {
> + u8 pad[0x1000];
> +} __packed;
> +
> +struct mhu3_pbx_frame_reg {
> + struct ctrl_page ctrl;
> + struct pdbcw_page dbcw[MHUV3_DBCW_MAX];
> + struct dummy_page ffcw;
> + struct dummy_page fcw;
> + u8 pad[0xF000 - 0x4000];
> + struct dummy_page impdef;
> +} __packed;
> +
> +struct mhu3_mbx_frame_reg {
> + struct ctrl_page ctrl;
> + struct mdbcw_page dbcw[MHUV3_DBCW_MAX];
> + struct dummy_page ffcw;
> + struct dummy_page fcw;
> + u8 pad[0xF000 - 0x4000];
Magic, numbers, Maybe give them a definition or base them on something
meaningful such as structure offsets?
> + struct dummy_page impdef;
> +} __packed;
> +
> +/* Macro for reading a bitfield within a physically mapped packed struct */
> +#define readl_relaxed_bitfield(_regptr, _field) \
> + ({ \
> + u32 _rval; \
> + typeof(_regptr) _rptr = _regptr; \
> + _rval = readl_relaxed(_rptr); \
> + ((typeof(*_rptr) __force *)(&_rval))->_field; \
> + })
> +
> +/* Macro for writing a bitfield within a physically mapped packed struct */
> +#define writel_relaxed_bitfield(_value, _regptr, _field) \
> + ({ \
> + u32 _rval; \
> + typeof(_regptr) _rptr = _regptr; \
> + _rval = readl_relaxed(_rptr); \
> + ((typeof(*_rptr) __force *)(&_rval))->_field = _value; \
> + writel_relaxed(_rval, _rptr); \
> + })
Similar, yet slightly different from ones in arm_mhuv2.c? Why the differences
and can these be shared code in a suitable header?
> +
> +/* ====== MHUv3 data structures ====== */
> +
> +enum mhuv3_frame {
> + PBX_FRAME,
> + MBX_FRAME
Trailing commas for last entries in enums unless they are in some sense terminators.
> +};
> +
> +static char *mhuv3_str[] = {
> + "PBX",
> + "MBX"
> +};
> +
> +enum mhuv3_extension_type {
> + FIRST_EXT = 0,
As mentioned inline, 0 is kind of default assumption for first so I wouldn't define it.
> + DBE_EXT = FIRST_EXT,
> + FCE_EXT,
> + FE_EXT,
> + MAX_EXT
That's one past normal meeting of MAX, maybe call it COUNT, or NUM?
> +};
> +static int mhuv3_doorbell_send_data(struct mhuv3 *mhu, struct mbox_chan *chan,
> + void *arg)
> +{
> + int ret = 0;
> + struct mhuv3_mbox_chan_priv *priv = chan->con_priv;
> + struct mhuv3_extension *e = mhu->ext[DBE_EXT];
> + unsigned long flags;
> +
> + spin_lock_irqsave(&e->pending_lock, flags);
guard() then you can do earlier returns and end up with cleaner code.
> + /* Only one in-flight Transfer is allowed per-doorbell */
> + if (!(e->pending_db[priv->ch_idx] & BIT(priv->doorbell))) {
> + e->pending_db[priv->ch_idx] |= BIT(priv->doorbell);
> + writel_relaxed(BIT(priv->doorbell),
> + &mhu->pbx->dbcw[priv->ch_idx].set);
> + } else {
> + ret = -EBUSY;
> + }
> + spin_unlock_irqrestore(&e->pending_lock, flags);
> +
> + return ret;
> +}
>
> +
> +static struct mbox_chan *mhuv3_dbe_chan_from_comb_irq_get(struct mhuv3 *mhu)
> +{
> + int i;
> + struct mhuv3_extension *e = mhu->ext[DBE_EXT];
> + struct device *dev = mhu->mbox.dev;
> +
> + for (i = 0; i < MHUV3_DBCH_CMB_INT_ST_REG_CNT; i++) {
> + unsigned int channel, db = MHUV3_INVALID_DOORBELL;
> + u32 cmb_st, st;
> +
> + cmb_st = readl_relaxed(&mhu->ctrl->dbch_int_st[i]);
> + if (!cmb_st)
> + continue;
> +
> + channel = i * MHUV3_STAT_BITS + __builtin_ctz(cmb_st);
> + if (channel >= e->max_chans) {
> + dev_err(dev, "Invalid %s channel:%d\n",
> + mhuv3_str[mhu->frame], channel);
return here rather than breaking out the loop. It is easier to follow
given nothing is done after the loop
> + break;
> + }
> +
> + if (mhu->frame == PBX_FRAME) {
> + unsigned long flags;
> + u32 active_dbs, fired_dbs;
> +
> + st = readl_relaxed_bitfield(&mhu->pbx->dbcw[channel].int_st,
> + tfr_ack);
> + if (!st) {
> + dev_warn(dev, "Spurios IRQ on %s channel:%d\n",
Spell check. Spurious.
> + mhuv3_str[mhu->frame], channel);
> + continue;
> + }
> +
> + active_dbs = readl_relaxed(&mhu->pbx->dbcw[channel].st);
> + spin_lock_irqsave(&e->pending_lock, flags);
> + fired_dbs = e->pending_db[channel] & ~active_dbs;
> + if (fired_dbs) {
> + db = __builtin_ctz(fired_dbs);
> + e->pending_db[channel] &= ~BIT(db);
> + fired_dbs &= ~BIT(db);
> + }
> + spin_unlock_irqrestore(&e->pending_lock, flags);
> +
> + /* Clear TFR Ack if no more doorbells pending */
> + if (!fired_dbs)
> + writel_relaxed_bitfield(0x1,
> + &mhu->pbx->dbcw[channel].int_clr,
> + tfr_ack);
> + } else {
> + st = readl_relaxed(&mhu->mbx->dbcw[channel].st_msk);
> + if (!st) {
> + dev_warn(dev, "Spurios IRQ on %s channel:%d\n",
> + mhuv3_str[mhu->frame], channel);
> + continue;
> + }
> + db = __builtin_ctz(st);
> + }
> +
> + if (db != MHUV3_INVALID_DOORBELL) {
> + dev_dbg(dev, "Found %s ch[%d]/db[%d]\n",
> + mhuv3_str[mhu->frame], channel, db);
> +
> + return &mhu->mbox.chans[channel * MHUV3_STAT_BITS + db];
> + }
> + }
> +
> + return ERR_PTR(-EIO);
> +}
> +
> +static int mhuv3_dbe_init(struct mhuv3 *mhu)
> +{
> + struct mhuv3_extension *e;
> + struct device *dev = mhu->mbox.dev;
> +
> + if (!readl_relaxed_bitfield(&mhu->ctrl->feat_spt0, dbe_spt))
> + return 0;
> +
> + dev_dbg(dev, "%s: Initializing DBE Extension.\n", mhuv3_str[mhu->frame]);
> +
> + e = devm_kzalloc(dev, sizeof(*e), GFP_KERNEL);
> + if (!e)
> + return -ENOMEM;
> +
> + e->type = DBE_EXT;
> + /* Note that, by the spec, the number of channels is (num_dbch + 1) */
> + e->max_chans =
> + readl_relaxed_bitfield(&mhu->ctrl->dbch_cfg0, num_dbch) + 1;
> + e->mbox_of_xlate = mhuv3_dbe_mbox_of_xlate;
> + e->combined_irq_setup = mhuv3_dbe_combined_irq_setup;
> + e->channels_init = mhuv3_dbe_channels_init;
> + e->chan_from_comb_irq_get = mhuv3_dbe_chan_from_comb_irq_get;
> +
> + mhu->tot_chans += e->max_chans * MHUV3_STAT_BITS;
> + mhu->ext[DBE_EXT] = e;
> +
> + dev_info(dev, "%s: found %d DBE channels.\n",
> + mhuv3_str[mhu->frame], e->max_chans);
dev_dbg() probably more appropriate.
> +
> + return 0;
> +}
> +
> +static int mhuv3_fce_init(struct mhuv3 *mhu)
> +{
> + struct device *dev = mhu->mbox.dev;
> +
> + if (!readl_relaxed_bitfield(&mhu->ctrl->feat_spt0, fce_spt))
> + return 0;
> +
> + dev_dbg(dev, "%s: FCE Extension not supported by driver.\n",
> + mhuv3_str[mhu->frame]);
> +
> + return 0;
> +}
> +
> +static int mhuv3_fe_init(struct mhuv3 *mhu)
> +{
> + struct device *dev = mhu->mbox.dev;
> +
> + if (!readl_relaxed_bitfield(&mhu->ctrl->feat_spt0, fe_spt))
> + return 0;
> +
> + dev_dbg(dev, "%s: FE Extension not supported by driver.\n",
> + mhuv3_str[mhu->frame]);
> +
> + return 0;
> +}
> +
> +static mhuv3_extension_initializer mhuv3_extension_init[MAX_EXT] = {
> + mhuv3_dbe_init,
> + mhuv3_fce_init,
> + mhuv3_fe_init,
> +};
> +
> +static int mhuv3_initialize_channels(struct device *dev, struct mhuv3 *mhu)
> +{
> + int i, ret = 0;
> + struct mbox_controller *mbox = &mhu->mbox;
> +
> + mbox->chans = devm_kcalloc(dev, mhu->tot_chans,
> + sizeof(*mbox->chans), GFP_KERNEL);
> + if (!mbox->chans)
> + return -ENOMEM;
> +
> + for (i = FIRST_EXT; i < MAX_EXT && !ret; i++)
Why this dance with FIRST_EXT if it is always 0? Cleaner to just use 0.
> + if (mhu->ext[i])
> + ret = mhu->ext[i]->channels_init(mhu);
> +
> + return ret;
> +}
> +
> +static struct mbox_chan *mhuv3_mbox_of_xlate(struct mbox_controller *mbox,
> + const struct of_phandle_args *pa)
> +{
> + unsigned int type, channel, param;
> + struct mhuv3 *mhu = mhu_from_mbox(mbox);
> +
> + if (pa->args_count != MHUV3_MBOX_CELLS)
> + return ERR_PTR(-EINVAL);
> +
> + type = pa->args[MHUV3_MBOX_CELL_TYPE];
> + if (type >= MAX_EXT)
> + return ERR_PTR(-EINVAL);
> +
> + channel = pa->args[MHUV3_MBOX_CELL_CHWN];
> + param = pa->args[MHUV3_MBOX_CELL_PARAM];
> +
> + return mhu->ext[type]->mbox_of_xlate(mhu, channel, param);
> +}
> +
> +static int mhuv3_frame_init(struct mhuv3 *mhu, void __iomem *regs)
> +{
> + int i, ret = 0;
> + struct device *dev = mhu->mbox.dev;
> +
> + mhu->ctrl = regs;
> + mhu->frame = readl_relaxed_bitfield(&mhu->ctrl->blk_id, blk_id);
> + if (mhu->frame > MBX_FRAME) {
> + dev_err(dev, "Invalid Frame type- %d\n", mhu->frame);
> + return -EINVAL;
dev_err_probe() etc (see later)
> + }
> +
> + mhu->major = readl_relaxed_bitfield(&mhu->ctrl->aidr, arch_major_rev);
> + mhu->minor = readl_relaxed_bitfield(&mhu->ctrl->aidr, arch_minor_rev);
> + if (mhu->major != MHUV3_MAJOR_VERSION) {
> + dev_warn(dev, "Unsupported MHU %s block - major:%d minor:%d\n",
> + mhuv3_str[mhu->frame], mhu->major, mhu->minor);
You are treating it as an error, so why only a warning?
> + return -EINVAL;
> + }
> + mhu->auto_op_full = !!readl_relaxed_bitfield(&mhu->ctrl->feat_spt1,
> + auto_op_spt);
> + /* Request the PBX/MBX to remain operational */
> + if (mhu->auto_op_full)
> + writel_relaxed_bitfield(0x1, &mhu->ctrl->ctrl, op_req);
> +
> + dev_dbg(dev, "Found MHU %s block - major:%d minor:%d\n",
> + mhuv3_str[mhu->frame], mhu->major, mhu->minor);
> +
> + if (mhu->frame == PBX_FRAME)
> + mhu->pbx = regs;
> + else
> + mhu->mbx = regs;
> +
> + for (i = FIRST_EXT; i < MAX_EXT && !ret; i++)
> + ret = mhuv3_extension_init[i](mhu);
Only dbe_init() returns any errors, so if I ready this correctly you always
eat that error.
> +
> + return ret;
> +}
> +
> +static irqreturn_t mhuv3_pbx_comb_interrupt(int irq, void *arg)
> +{
> + int ret = IRQ_NONE;
> + unsigned int i, found = 0;
> + struct mhuv3 *mhu = arg;
> + struct device *dev = mhu->mbox.dev;
> + struct mbox_chan *chan;
> +
> + for (i = FIRST_EXT; i < MAX_EXT; i++) {
> + /* FCE does not participate to the PBX combined */
> + if (i == FCE_EXT || !mhu->ext[i])
> + continue;
> +
> + chan = mhu->ext[i]->chan_from_comb_irq_get(mhu);
> + if (!IS_ERR(chan)) {
if (IS_ERR(chan))
continue;
will reduce indent and give more readable code.
> + struct mhuv3_mbox_chan_priv *priv = chan->con_priv;
> +
> + found++;
> + if (chan->cl) {
> + mbox_chan_txdone(chan, 0);
> + ret = IRQ_HANDLED;
> + } else {
> + dev_warn(dev,
> + "TX Ack on UNBOUND channel (%u)\n",
> + priv->ch_idx);
> + }
> + }
> + }
> +
> + if (!found)
> + dev_warn_once(dev, "Failed to find channel for the TX interrupt\n");
> +
> + return ret;
> +}
> +
> +static irqreturn_t mhuv3_mbx_comb_interrupt(int irq, void *arg)
> +{
> + int ret = IRQ_NONE;
> + unsigned int i, found = 0;
> + struct mhuv3 *mhu = arg;
> + struct device *dev = mhu->mbox.dev;
> + struct mbox_chan *chan;
> +
> + for (i = FIRST_EXT; i < MAX_EXT; i++) {
> + if (!mhu->ext[i])
> + continue;
> +
> + /* Process any extension which could be source of the IRQ */
> + chan = mhu->ext[i]->chan_from_comb_irq_get(mhu);
> + if (!IS_ERR(chan)) {
if (IS_ERR(chan))
continue;
is going to be easier to read.
> + void *data = NULL;
> + struct mhuv3_mbox_chan_priv *priv = chan->con_priv;
> +
> + found++;
> + /* Read and acknowledge optional in-band LE data first. */
> + if (priv->ops->read_data)
> + data = priv->ops->read_data(mhu, chan);
> +
> + if (chan->cl && !IS_ERR(data)) {
> + mbox_chan_received_data(chan, data);
> + ret = IRQ_HANDLED;
> + } else if (!chan->cl) {
> + dev_warn(dev,
> + "RX Data on UNBOUND channel (%u)\n",
> + priv->ch_idx);
> + } else {
> + dev_err(dev, "Failed to read data: %lu\n",
> + PTR_ERR(data));
> + }
I'd be tempted to factor out this code block into another function as I think
that will allow you to deal with the errors more directly.
> +
> + if (!IS_ERR(data))
> + kfree(data);
> +
> + /*
> + * Acknowledge transfer after any possible optional
> + * out-of-band data has also been retrieved via
> + * mbox_chan_received_data().
> + */
> + if (priv->ops->rx_complete)
> + priv->ops->rx_complete(mhu, chan);
> + }
> + }
> +
> + if (!found)
> + dev_warn_once(dev, "Failed to find channel for the RX interrupt\n");
> +
> + return ret;
> +}
> +
> +static int mhuv3_setup_pbx(struct mhuv3 *mhu)
> +{
> + struct device *dev = mhu->mbox.dev;
> +
> + mhu->mbox.ops = &mhuv3_sender_ops;
> +
> + if (mhu->cmb_irq > 0) {
> + int ret;
> +
> + ret = devm_request_threaded_irq(dev, mhu->cmb_irq, NULL,
> + mhuv3_pbx_comb_interrupt,
> + IRQF_ONESHOT, "mhuv3-pbx", mhu);
> + if (!ret) {
> + int i;
> +
> + mhu->mbox.txdone_irq = true;
> + mhu->mbox.txdone_poll = false;
> +
> + for (i = FIRST_EXT; i < MAX_EXT; i++)
> + if (mhu->ext[i])
> + mhu->ext[i]->combined_irq_setup(mhu);
> +
> + dev_dbg(dev, "MHUv3 PBX IRQs initialized.\n");
> +
> + return 0;
> + }
> +
> + dev_err(dev, "Failed to request PBX IRQ - ret:%d", ret);
If an irq was provided and it failed, I'd just return an error, not muddle on.
Broken system. If it's not an 'error' then don't use dev_err()
Papering over this leads to an odd code flow with if (!ret) so it would
be nice not to bother unless there is a strong reason to carry on.
> + }
> +
> + dev_info(dev, "Using PBX in Tx polling mode.\n");
That's noisy. dev_dbg() perhaps?
> + mhu->mbox.txdone_irq = false;
> + mhu->mbox.txdone_poll = true;
> + mhu->mbox.txpoll_period = 1;
> +
> + return 0;
> +}
> +
> +static int mhuv3_setup_mbx(struct mhuv3 *mhu)
> +{
> + int ret, i;
> + struct device *dev = mhu->mbox.dev;
> +
> + mhu->mbox.ops = &mhuv3_receiver_ops;
> +
> + if (mhu->cmb_irq <= 0) {
> + dev_err(dev, "Missing MBX combined IRQ !\n");
return dev_err_probe()
here as I think it's only called form init. Sure you might not
need the deferred handling it provides but it still leads to
cleaner code and no one has to think about whether deferal might
happen or not.
> + return -EINVAL;
> + }
> +
> + ret = devm_request_threaded_irq(dev, mhu->cmb_irq, NULL,
> + mhuv3_mbx_comb_interrupt, IRQF_ONESHOT,
> + "mhuv3-mbx", mhu);
> + if (ret) {
> + dev_err(dev, "Failed to request MBX IRQ - ret:%d\n", ret);
> + return ret;
return dev_err_probe()
> + }
> +
> + for (i = FIRST_EXT; i < MAX_EXT; i++)
> + if (mhu->ext[i])
> + mhu->ext[i]->combined_irq_setup(mhu);
> +
> + dev_dbg(dev, "MHUv3 MBX IRQs initialized.\n");
> +
> + return ret;
> +}
> +
> +static int mhuv3_irqs_init(struct mhuv3 *mhu, struct platform_device *pdev)
> +{
> + int ret;
> +
> + dev_dbg(mhu->mbox.dev, "Initializing %s block.\n", mhuv3_str[mhu->frame]);
> +
> + if (mhu->frame == PBX_FRAME) {
> + mhu->cmb_irq = platform_get_irq_byname_optional(pdev, "combined");
> + ret = mhuv3_setup_pbx(mhu);
return early is both shorter and easier to follow if people
are looking at particular paths through the function.
> + } else {
> + mhu->cmb_irq = platform_get_irq_byname(pdev, "combined");
> + ret = mhuv3_setup_mbx(mhu);
> + }
> +
> + return ret;
> +}
> +
> +static int mhuv3_probe(struct platform_device *pdev)
> +{
> + int ret;
> + struct mhuv3 *mhu;
> + void __iomem *regs;
> + struct device *dev = &pdev->dev;
> +
> + mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
> + if (!mhu)
> + return -ENOMEM;
> +
> + regs = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + mhu->mbox.dev = dev;
> + ret = mhuv3_frame_init(mhu, regs);
> + if (ret)
> + return ret;
> +
> + ret = mhuv3_irqs_init(mhu, pdev);
> + if (ret)
> + return ret;
> +
> + mhu->mbox.of_xlate = mhuv3_mbox_of_xlate;
> + ret = mhuv3_initialize_channels(dev, mhu);
> + if (ret)
> + return ret;
> +
> + ret = devm_mbox_controller_register(dev, &mhu->mbox);
> + if (ret)
> + dev_err(dev, "failed to register ARM MHUv3 driver %d\n", ret);
Use dev_err_probe() to get a few things for free in probe time error messages message.
return dev_err_probe(dev, reg, "failed to register ARM HMUv3 driver\n");
return 0;
> +
> + platform_set_drvdata(pdev, mhu);
With all devm as suggested below, can I think drop this.
> +
> + return ret;
> +}
> +
> +static int mhuv3_remove(struct platform_device *pdev)
> +{
> + struct mhuv3 *mhu = platform_get_drvdata(pdev);
> +
> + if (mhu->auto_op_full)
> + writel_relaxed_bitfield(0x0, &mhu->ctrl->ctrl, op_req);
> +
From a quick glance probably better to use a
devm_add_action_or_reset() so that this is turned off at
equivalent place in remove() path as where it is turned on in _init()
Only register the callback if auto_op_full()
Mixing and matching devm_ and calls in remove is a path to weird
races and corner cases so better to go all in on devm handling.
> + return 0;
> +}
> +
> +static const struct of_device_id mhuv3_of_match[] = {
> + { .compatible = "arm,mhuv3", .data = NULL },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, mhuv3_of_match);
> +
> +static struct platform_driver mhuv3_driver = {
> + .driver = {
> + .name = "arm-mhuv3-mailbox",
> + .of_match_table = mhuv3_of_match,
> + },
> + .probe = mhuv3_probe,
> + .remove = mhuv3_remove,
> +};
> +module_platform_driver(mhuv3_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("ARM MHUv3 Driver");
> +MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 21/25] drivers: media: i2c: imx258: Use macros
From: Luis Garcia @ 2024-04-05 10:33 UTC (permalink / raw)
To: Sakari Ailus
Cc: linux-media, dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, devicetree, imx, linux-arm-kernel, linux-kernel, pavel,
phone-devel, Ondrej Jirman
In-Reply-To: <Zg5Mz0QSqNDXzY4o@kekkonen.localdomain>
On 4/4/24 00:46, Sakari Ailus wrote:
> On Wed, Apr 03, 2024 at 01:17:26PM -0600, Luigi311 wrote:
>> On 4/3/24 10:23, Sakari Ailus wrote:
>>> Hi Luis,
>>>
>>> On Wed, Apr 03, 2024 at 09:03:50AM -0600, git@luigi311.com wrote:
>>>> From: Luis Garcia <git@luigi311.com>
>>>>
>>>> Use understandable macros instead of raw values.
>>>>
>>>> Signed-off-by: Ondrej Jirman <megi@xff.cz>
>>>> Signed-off-by: Luis Garcia <git@luigi311.com>
>>>> ---
>>>> drivers/media/i2c/imx258.c | 434 ++++++++++++++++++-------------------
>>>> 1 file changed, 207 insertions(+), 227 deletions(-)
>>>>
>>>> diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
>>>> index e2ecf6109516..30352c33f63c 100644
>>>> --- a/drivers/media/i2c/imx258.c
>>>> +++ b/drivers/media/i2c/imx258.c
>>>> @@ -33,8 +33,6 @@
>>>> #define IMX258_VTS_30FPS_VGA 0x034c
>>>> #define IMX258_VTS_MAX 65525
>>>>
>>>> -#define IMX258_REG_VTS 0x0340
>>>> -
>>>> /* HBLANK control - read only */
>>>> #define IMX258_PPL_DEFAULT 5352
>>>>
>>>> @@ -90,6 +88,53 @@
>>>> #define IMX258_PIXEL_ARRAY_WIDTH 4208U
>>>> #define IMX258_PIXEL_ARRAY_HEIGHT 3120U
>>>>
>>>> +/* regs */
>>>> +#define IMX258_REG_PLL_MULT_DRIV 0x0310
>>>> +#define IMX258_REG_IVTPXCK_DIV 0x0301
>>>> +#define IMX258_REG_IVTSYCK_DIV 0x0303
>>>> +#define IMX258_REG_PREPLLCK_VT_DIV 0x0305
>>>> +#define IMX258_REG_IOPPXCK_DIV 0x0309
>>>> +#define IMX258_REG_IOPSYCK_DIV 0x030b
>>>> +#define IMX258_REG_PREPLLCK_OP_DIV 0x030d
>>>> +#define IMX258_REG_PHASE_PIX_OUTEN 0x3030
>>>> +#define IMX258_REG_PDPIX_DATA_RATE 0x3032
>>>> +#define IMX258_REG_SCALE_MODE 0x0401
>>>> +#define IMX258_REG_SCALE_MODE_EXT 0x3038
>>>> +#define IMX258_REG_AF_WINDOW_MODE 0x7bcd
>>>> +#define IMX258_REG_FRM_LENGTH_CTL 0x0350
>>>> +#define IMX258_REG_CSI_LANE_MODE 0x0114
>>>> +#define IMX258_REG_X_EVN_INC 0x0381
>>>> +#define IMX258_REG_X_ODD_INC 0x0383
>>>> +#define IMX258_REG_Y_EVN_INC 0x0385
>>>> +#define IMX258_REG_Y_ODD_INC 0x0387
>>>> +#define IMX258_REG_BINNING_MODE 0x0900
>>>> +#define IMX258_REG_BINNING_TYPE_V 0x0901
>>>> +#define IMX258_REG_FORCE_FD_SUM 0x300d
>>>> +#define IMX258_REG_DIG_CROP_X_OFFSET 0x0408
>>>> +#define IMX258_REG_DIG_CROP_Y_OFFSET 0x040a
>>>> +#define IMX258_REG_DIG_CROP_IMAGE_WIDTH 0x040c
>>>> +#define IMX258_REG_DIG_CROP_IMAGE_HEIGHT 0x040e
>>>> +#define IMX258_REG_SCALE_M 0x0404
>>>> +#define IMX258_REG_X_OUT_SIZE 0x034c
>>>> +#define IMX258_REG_Y_OUT_SIZE 0x034e
>>>> +#define IMX258_REG_X_ADD_STA 0x0344
>>>> +#define IMX258_REG_Y_ADD_STA 0x0346
>>>> +#define IMX258_REG_X_ADD_END 0x0348
>>>> +#define IMX258_REG_Y_ADD_END 0x034a
>>>> +#define IMX258_REG_EXCK_FREQ 0x0136
>>>> +#define IMX258_REG_CSI_DT_FMT 0x0112
>>>> +#define IMX258_REG_LINE_LENGTH_PCK 0x0342
>>>> +#define IMX258_REG_SCALE_M_EXT 0x303a
>>>> +#define IMX258_REG_FRM_LENGTH_LINES 0x0340
>>>> +#define IMX258_REG_FINE_INTEG_TIME 0x0200
>>>> +#define IMX258_REG_PLL_IVT_MPY 0x0306
>>>> +#define IMX258_REG_PLL_IOP_MPY 0x030e
>>>> +#define IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H 0x0820
>>>> +#define IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L 0x0822
>>>> +
>>>> +#define REG8(a, v) { a, v }
>>>> +#define REG16(a, v) { a, ((v) >> 8) & 0xff }, { (a) + 1, (v) & 0xff }
>>>
>>> The patch is nice but these macros are better replaced by the V4L2 CCI
>>> helper that also offers register access functions. Could you add a patch to
>>> convert the driver to use it (maybe after this one)?
>>>
>>
>> Ohh perfect, using something else would be great. Ill go ahead and see
>> if I can get that working.
>
> Thanks. It may be easier to just do it in this one actually. Up to you.
>
I've made the swap but looks like its not playing nice with my ppp,
its causing a crash and showing a call trace as soon as it does its
first read to check the identity. I went in and dropped the cci_read
and left it with the original implementation and I'm getting a very
similar crash with cci_write too so it looks like its not liking
how I'm implementing it. Looking at the few other drivers that were
swapped over to use that, I don't seem to be missing anything. It's
a big change so its not really something I can describe what I've
changed but I do have the change on my github here
https://github.com/luigi311/linux/commit/840593acb20eee87ce361e6929edf51eefbbe737
if you can provide some guidance, if not I can skip this change
all together and we can do a separate attempt at swapping over to it.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] arm64: dts: mediatek: mt7981: fix code alignment for PWM clocks
From: Rafał Miłecki @ 2024-04-05 10:50 UTC (permalink / raw)
To: Matthias Brugger, AngeloGioacchino Del Regno, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: devicetree, linux-arm-kernel, linux-mediatek, linux-kernel,
Rafał Miłecki
From: Rafał Miłecki <rafal@milecki.pl>
Align "clocks" array entries to start at the same column.
Fixes: cf29427573cc ("arm64: dts: mediatek: Add initial MT7981B and Xiaomi AX3000T")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
arch/arm64/boot/dts/mediatek/mt7981b.dtsi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
index 5674ac81d1f8..8a6263cc569c 100644
--- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
@@ -86,10 +86,10 @@ pwm@10048000 {
compatible = "mediatek,mt7981-pwm";
reg = <0 0x10048000 0 0x1000>;
clocks = <&infracfg CLK_INFRA_PWM_STA>,
- <&infracfg CLK_INFRA_PWM_HCK>,
- <&infracfg CLK_INFRA_PWM1_CK>,
- <&infracfg CLK_INFRA_PWM2_CK>,
- <&infracfg CLK_INFRA_PWM3_CK>;
+ <&infracfg CLK_INFRA_PWM_HCK>,
+ <&infracfg CLK_INFRA_PWM1_CK>,
+ <&infracfg CLK_INFRA_PWM2_CK>,
+ <&infracfg CLK_INFRA_PWM3_CK>;
clock-names = "top", "main", "pwm1", "pwm2", "pwm3";
#pwm-cells = <2>;
};
--
2.35.3
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 19/25] media: i2c: imx258: Change register settings for variants of the sensor
From: Sakari Ailus @ 2024-04-05 10:59 UTC (permalink / raw)
To: Luigi311
Cc: linux-media, dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, devicetree, imx, linux-arm-kernel, linux-kernel, pavel,
phone-devel
In-Reply-To: <998efafa-699b-4226-91d4-2ebba85d63ec@luigi311.com>
Hi Luis, Dave,
On Thu, Apr 04, 2024 at 04:44:05PM -0600, Luigi311 wrote:
> On 4/3/24 10:18, Sakari Ailus wrote:
> > Hi Luis, Dave,
> >
> > On Wed, Apr 03, 2024 at 09:03:48AM -0600, git@luigi311.com wrote:
> >> From: Dave Stevenson <dave.stevenson@raspberrypi.com>
> >>
> >> Sony have advised that there are variants of the IMX258 sensor which
> >> require slightly different register configuration to the mainline
> >> imx258 driver defaults.
> >>
> >> There is no available run-time detection for the variant, so add
> >> configuration via the DT compatible string.
> >>
> >> The Vision Components imx258 module supports PDAF, so add the
> >> register differences for that variant
> >>
> >> Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> >> Signed-off-by: Luis Garcia <git@luigi311.com>
> >> ---
> >> drivers/media/i2c/imx258.c | 48 ++++++++++++++++++++++++++++++++++----
> >> 1 file changed, 44 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
> >> index 775d957c9b87..fa48da212037 100644
> >> --- a/drivers/media/i2c/imx258.c
> >> +++ b/drivers/media/i2c/imx258.c
> >> @@ -6,6 +6,7 @@
> >> #include <linux/delay.h>
> >> #include <linux/i2c.h>
> >> #include <linux/module.h>
> >> +#include <linux/of_device.h>
> >> #include <linux/pm_runtime.h>
> >> #include <linux/regulator/consumer.h>
> >> #include <media/v4l2-ctrls.h>
> >> @@ -321,8 +322,6 @@ static const struct imx258_reg mipi_642mbps_24mhz_4l[] = {
> >>
> >> static const struct imx258_reg mode_common_regs[] = {
> >> { 0x3051, 0x00 },
> >> - { 0x3052, 0x00 },
> >> - { 0x4E21, 0x14 },
> >> { 0x6B11, 0xCF },
> >> { 0x7FF0, 0x08 },
> >> { 0x7FF1, 0x0F },
> >> @@ -345,7 +344,6 @@ static const struct imx258_reg mode_common_regs[] = {
> >> { 0x7FA8, 0x03 },
> >> { 0x7FA9, 0xFE },
> >> { 0x7B24, 0x81 },
> >> - { 0x7B25, 0x00 },
> >> { 0x6564, 0x07 },
> >> { 0x6B0D, 0x41 },
> >> { 0x653D, 0x04 },
> >> @@ -460,6 +458,33 @@ static const struct imx258_reg mode_1048_780_regs[] = {
> >> { 0x034F, 0x0C },
> >> };
> >>
> >> +struct imx258_variant_cfg {
> >> + const struct imx258_reg *regs;
> >> + unsigned int num_regs;
> >> +};
> >> +
> >> +static const struct imx258_reg imx258_cfg_regs[] = {
> >> + { 0x3052, 0x00 },
> >> + { 0x4E21, 0x14 },
> >> + { 0x7B25, 0x00 },
> >> +};
> >> +
> >> +static const struct imx258_variant_cfg imx258_cfg = {
> >> + .regs = imx258_cfg_regs,
> >> + .num_regs = ARRAY_SIZE(imx258_cfg_regs),
> >> +};
> >> +
> >> +static const struct imx258_reg imx258_pdaf_cfg_regs[] = {
> >> + { 0x3052, 0x01 },
> >> + { 0x4E21, 0x10 },
> >> + { 0x7B25, 0x01 },
> >> +};
> >> +
> >> +static const struct imx258_variant_cfg imx258_pdaf_cfg = {
> >> + .regs = imx258_pdaf_cfg_regs,
> >> + .num_regs = ARRAY_SIZE(imx258_pdaf_cfg_regs),
> >> +};
> >> +
> >> static const char * const imx258_test_pattern_menu[] = {
> >> "Disabled",
> >> "Solid Colour",
> >> @@ -637,6 +662,8 @@ struct imx258 {
> >> struct v4l2_subdev sd;
> >> struct media_pad pad;
> >>
> >> + const struct imx258_variant_cfg *variant_cfg;
> >> +
> >> struct v4l2_ctrl_handler ctrl_handler;
> >> /* V4L2 Controls */
> >> struct v4l2_ctrl *link_freq;
> >> @@ -1104,6 +1131,14 @@ static int imx258_start_streaming(struct imx258 *imx258)
> >> return ret;
> >> }
> >>
> >> + ret = imx258_write_regs(imx258, imx258->variant_cfg->regs,
> >> + imx258->variant_cfg->num_regs);
> >> + if (ret) {
> >> + dev_err(&client->dev, "%s failed to set variant config\n",
> >> + __func__);
> >> + return ret;
> >> + }
> >> +
> >> ret = imx258_write_reg(imx258, IMX258_CLK_BLANK_STOP,
> >> IMX258_REG_VALUE_08BIT,
> >> imx258->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
> >> @@ -1492,6 +1527,10 @@ static int imx258_probe(struct i2c_client *client)
> >>
> >> imx258->csi2_flags = ep.bus.mipi_csi2.flags;
> >>
> >> + imx258->variant_cfg = of_device_get_match_data(&client->dev);
> >
> > You'll also need to keep this working for ACPI based systems. I.e. in
> > practice remove "of_" prefix here and add the non-PDAF variant data to the
> > relevant ACPI ID list.
> >
>
> Removing of_ is easy enough and looking at all the other commits that make
> this change in other drivers I dont see anything else being done besides
> adding in the .data section that is down below for both imx258 and pdaf
> versions. Is that what you are referencing or is there some other place
> to add variant data to ACPI ID list?
Speaking of which---are you absolutely certain there are two variants of
this sensor? Many sensors that have a different pixel pattern (PDAF pixels
or a non-Bayer pattern) can produce Bayer data when condigured so. The fact
that you have differing register configuration for the PDAF and non-PDAF
cases suggests this may well be the case.
>
> >> + if (!imx258->variant_cfg)
> >> + imx258->variant_cfg = &imx258_cfg;
> >> +
> >> /* Initialize subdev */
> >> v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
> >>
> >> @@ -1579,7 +1618,8 @@ MODULE_DEVICE_TABLE(acpi, imx258_acpi_ids);
> >> #endif
> >>
> >> static const struct of_device_id imx258_dt_ids[] = {
> >> - { .compatible = "sony,imx258" },
> >> + { .compatible = "sony,imx258", .data = &imx258_cfg },
> >> + { .compatible = "sony,imx258-pdaf", .data = &imx258_pdaf_cfg },
> >> { /* sentinel */ }
> >> };
> >> MODULE_DEVICE_TABLE(of, imx258_dt_ids);
> >
>
--
Regards,
Sakari Ailus
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [syzbot] [mm?] BUG: unable to handle kernel paging request in copy_from_kernel_nofault (2)
From: Mark Rutland @ 2024-04-05 11:02 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Andrew Morton, linux-arm-kernel, syzbot, LKML, linux-mm,
syzkaller-bugs, bpf
In-Reply-To: <CAADnVQ+meL1kvXUehDT3iO2mxiZNeSUqeRKYx1C=3c0h=NSiqA@mail.gmail.com>
On Thu, Apr 04, 2024 at 03:57:04PM -0700, Alexei Starovoitov wrote:
> On Wed, Apr 3, 2024 at 6:56 PM Andrew Morton <akpm@linux-foundationorg> wrote:
> >
> > On Mon, 01 Apr 2024 22:19:25 -0700 syzbot <syzbot+186522670e6722692d86@syzkaller.appspotmail.com> wrote:
> >
> > > Hello,
> >
> > Thanks. Cc: bpf@vger.kernel.org
>
> I suspect the issue is not on bpf side.
> Looks like the bug is somewhere in arm32 bits.
> copy_from_kernel_nofault() is called from lots of places.
> bpf is just one user that is easy for syzbot to fuzz.
> Interestingly arm defines copy_from_kernel_nofault_allowed()
> that should have filtered out user addresses.
> In this case ffffffe9 is probably a kernel address?
It's at the end of the kernel range, and it's ERR_PTR(-EINVAL).
0xffffffe9 is -0x16, which is -22, which is -EINVAL.
> But the kernel is doing a write?
> Which makes no sense, since copy_from_kernel_nofault is probe reading.
It makes perfect sense; the read from 'src' happened, then the kernel tries to
write the result to 'dst', and that aligns with the disassembly in the report
below, which I beleive is:
8: e4942000 ldr r2, [r4], #0 <-- Read of 'src', fault fixup is elsewhere
c: e3530000 cmp r3, #0
* 10: e5852000 str r2, [r5] <-- Write to 'dst'
As above, it looks like 'dst' is ERR_PTR(-EINVAL).
Are you certain that BPF is passing a sane value for 'dst'? Where does that
come from in the first place?
Mark.
> arm folks,
> pls take a look.
>
> > > syzbot found the following issue on:
> > >
> > > HEAD commit: 317c7bc0ef03 Merge tag 'mmc-v6.9-rc1' of git://git.kernel...
> > > git tree: upstream
> > > console output: https://syzkaller.appspot.com/x/log.txt?x=1060bd41180000
> > > kernel config: https://syzkaller.appspot.com/x/.config?x=43f1e0cbdb852271
> > > dashboard link: https://syzkaller.appspot.com/bug?extid=186522670e6722692d86
> > > compiler: arm-linux-gnueabi-gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> > > userspace arch: arm
> > > syz repro: https://syzkaller.appspot.com/x/repro.syz?x=15751129180000
> > > C reproducer: https://syzkaller.appspot.com/x/repro.c?x=10136341180000
> > >
> > > Downloadable assets:
> > > disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/8ead8862021c/non_bootable_disk-317c7bc0.raw.xz
> > > vmlinux: https://storage.googleapis.com/syzbot-assets/49458dc4ddf2/vmlinux-317c7bc0.xz
> > > kernel image: https://storage.googleapis.com/syzbot-assets/031f516e5544/zImage-317c7bc0.xz
> > >
> > > IMPORTANT: if you fix the issue, please add the following tag to the commit:
> > > Reported-by: syzbot+186522670e6722692d86@syzkaller.appspotmail.com
> > >
> > > 8<--- cut here ---
> > > Unable to handle kernel paging request at virtual address ffffffe9 when write
> > > [ffffffe9] *pgd=80000080007003, *pmd=deffd003, *pte=00000000
> > > Internal error: Oops: a07 [#1] PREEMPT SMP ARM
> > > Modules linked in:
> > > CPU: 1 PID: 3001 Comm: syz-executor291 Not tainted 6.9.0-rc1-syzkaller #0
> > > Hardware name: ARM-Versatile Express
> > > PC is at copy_from_kernel_nofault mm/maccess.c:38 [inline]
> > > PC is at copy_from_kernel_nofault+0xb8/0x12c mm/maccess.c:24
> > > LR is at copy_from_kernel_nofault+0x24/0x12c mm/maccess.c:31
> > > pc : [<804361f0>] lr : [<8043615c>] psr: a0000013
> > > sp : df96dc90 ip : df96dc90 fp : df96dcac
> > > r10: 00000000 r9 : df96dd40 r8 : ffffffe9
> > > r7 : 83d33c00 r6 : 00000005 r5 : ffffffe9 r4 : ffffffe9
> > > r3 : fffffff2 r2 : 00000000 r1 : 00000005 r0 : 00000001
> > > Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
> > > Control: 30c5387d Table: 8434d080 DAC: 00000000
> > > Register r0 information: non-paged memory
> > > Register r1 information: non-paged memory
> > > Register r2 information: NULL pointer
> > > Register r3 information: non-paged memory
> > > Register r4 information: non-paged memory
> > > Register r5 information: non-paged memory
> > > Register r6 information: non-paged memory
> > > Register r7 information: slab task_struct start 83d33c00 pointer offset 0 size 3072
> > > Register r8 information: non-paged memory
> > > Register r9 information: 2-page vmalloc region starting at 0xdf96c000 allocated at kernel_clone+0xac/0x3cc kernel/fork.c:2796
> > > Register r10 information: NULL pointer
> > > Register r11 information: 2-page vmalloc region starting at 0xdf96c000 allocated at kernel_clone+0xac/0x3cc kernel/fork.c:2796
> > > Register r12 information: 2-page vmalloc region starting at 0xdf96c000 allocated at kernel_clone+0xac/0x3cc kernel/fork.c:2796
> > > Process syz-executor291 (pid: 3001, stack limit = 0xdf96c000)
> > > Stack: (0xdf96dc90 to 0xdf96e000)
> > > dc80: df96ddb8 ffffffe9 00000005 ffffffff
> > > dca0: df96dccc df96dcb0 8037c428 80436144 df96ddb8 00000000 8037c40c ffffffff
> > > dcc0: df96dd64 df96dcd0 7f011aa0 8037c418 ffffffe9 df96dd40 802ff648 81182b54
> > > dce0: df96dd64 df96dd30 35702575 00000000 828c0a94 40000013 00000000 00000000
> > > dd00: df96dcf0 00000000 df96dd74 df96dd18 df96dd2c df96dd20 81182b64 81898a78
> > > dd20: df96dd64 df96dd30 802ff648 81182b54 ffffffe9 df96dd40 00000005 00000000
> > > dd40: df96ddb8 00000000 df969000 842879c0 df969030 df96de30 df96ddfc df96dd68
> > > dd60: 8149c734 7f011a00 804d0184 8089c164 00000000 83d33c00 804b4cdc 804d0124
> > > dd80: 8260ca3c df96de30 00000001 df96de2c 80468494 00000000 df96ddb8 00000000
> > > dda0: 00000001 00000000 19df2b20 00000014 00000000 00000000 df969000 00000000
> > > ddc0: 00000000 00000000 84497800 f655f23e df96ddfc 842879c0 00000000 df96dec0
> > > dde0: 83f79c00 84497800 00000000 0000000e df96de64 df96de00 8149d6a0 8149c5d0
> > > de00: df96de30 00000000 00000000 df96de98 20000080 00000000 df969000 00000000
> > > de20: 828ffe80 82fe0000 8051cdd4 00000000 00000000 f655f23e 80395130 df969000
> > > de40: 00000028 df96de98 0000000a 20000080 00000028 00000000 df96df8c df96de68
> > > de60: 8039c858 8149d388 81c66394 84342c0c fcd9275f 00a00000 20000000 83d33c00
> > > de80: df96dee0 df96dfb0 df96dea4 df96de98 8089c348 df96dee0 20000080 00000000
> > > dea0: 83d33c00 df96ded0 00000008 00000000 00000008 80426e10 df96deec df96dec8
> > > dec0: 00000003 02000000 0000000e 00000055 20000140 00000000 20000380 00000000
> > > dee0: 00000000 04000000 00000000 00000000 00000000 00000000 00000000 00000000
> > > df00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > > df20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > > df40: 00000000 00000000 00000000 00000000 00000000 00000000 20000000 f655f23e
> > > df60: 80216078 ffffffff 00000000 0008e050 00000182 80200288 83d33c00 00000182
> > > df80: df96dfa4 df96df90 8039dd98 8039b934 20000080 00000000 00000000 df96dfa8
> > > dfa0: 80200060 8039dd78 ffffffff 00000000 0000000a 20000080 00000028 00000000
> > > dfc0: ffffffff 00000000 0008e050 00000182 20000100 00000000 00000001 00003a97
> > > dfe0: 7ec66c70 7ec66c60 00010748 0002e890 00000010 0000000a 00000000 00000000
> > > Call trace:
> > > [<80436138>] (copy_from_kernel_nofault) from [<8037c428>] (bpf_probe_read_kernel_common include/linux/bpf.h:2909 [inline])
> > > [<80436138>] (copy_from_kernel_nofault) from [<8037c428>] (____bpf_probe_read_kernel kernel/trace/bpf_trace.c:240 [inline])
> > > [<80436138>] (copy_from_kernel_nofault) from [<8037c428>] (bpf_probe_read_kernel+0x1c/0x44 kernel/trace/bpf_trace.c:237)
> > > r7:ffffffff r6:00000005 r5:ffffffe9 r4:df96ddb8
> > > [<8037c40c>] (bpf_probe_read_kernel) from [<7f011aa0>] (bpf_prog_244768d4818575ac+0xac/0xc0)
> > > r7:ffffffff r6:8037c40c r5:00000000 r4:df96ddb8
> > > [<7f0119f4>] (bpf_prog_244768d4818575ac) from [<8149c734>] (bpf_dispatcher_nop_func include/linux/bpf.h:1234 [inline])
> > > [<7f0119f4>] (bpf_prog_244768d4818575ac) from [<8149c734>] (__bpf_prog_run include/linux/filter.h:657 [inline])
> > > [<7f0119f4>] (bpf_prog_244768d4818575ac) from [<8149c734>] (bpf_prog_run include/linux/filter.h:664 [inline])
> > > [<7f0119f4>] (bpf_prog_244768d4818575ac) from [<8149c734>] (bpf_test_run+0x170/0x388 net/bpf/test_run.c:425)
> > > r9:df96de30 r8:df969030 r7:842879c0 r6:df969000 r5:00000000 r4:df96ddb8
> > > [<8149c5c4>] (bpf_test_run) from [<8149d6a0>] (bpf_prog_test_run_skb+0x324/0x6cc net/bpf/test_run.c:1058)
> > > r10:0000000e r9:00000000 r8:84497800 r7:83f79c00 r6:df96dec0 r5:00000000
> > > r4:842879c0
> > > [<8149d37c>] (bpf_prog_test_run_skb) from [<8039c858>] (bpf_prog_test_run kernel/bpf/syscall.c:4240 [inline])
> > > [<8149d37c>] (bpf_prog_test_run_skb) from [<8039c858>] (__sys_bpf+0xf30/0x1ef0 kernel/bpf/syscall.c:5649)
> > > r10:00000000 r9:00000028 r8:20000080 r7:0000000a r6:df96de98 r5:00000028
> > > r4:df969000
> > > [<8039b928>] (__sys_bpf) from [<8039dd98>] (__do_sys_bpf kernel/bpf/syscall.c:5738 [inline])
> > > [<8039b928>] (__sys_bpf) from [<8039dd98>] (sys_bpf+0x2c/0x48 kernel/bpf/syscall.c:5736)
> > > r10:00000182 r9:83d33c00 r8:80200288 r7:00000182 r6:0008e050 r5:00000000
> > > r4:ffffffff
> > > [<8039dd6c>] (sys_bpf) from [<80200060>] (ret_fast_syscall+0x0/0x1c arch/arm/mm/proc-v7.S:66)
> > > Exception stack(0xdf96dfa8 to 0xdf96dff0)
> > > dfa0: ffffffff 00000000 0000000a 20000080 00000028 00000000
> > > dfc0: ffffffff 00000000 0008e050 00000182 20000100 00000000 00000001 00003a97
> > > dfe0: 7ec66c70 7ec66c60 00010748 0002e890
> > > Code: 9a000007 e3a03000 e4942000 e3530000 (e5852000)
> > > ---[ end trace 0000000000000000 ]---
> > > ----------------
> > > Code disassembly (best guess):
> > > 0: 9a000007 bls 0x24
> > > 4: e3a03000 mov r3, #0
> > > 8: e4942000 ldr r2, [r4], #0
> > > c: e3530000 cmp r3, #0
> > > * 10: e5852000 str r2, [r5] <-- trapping instruction
> > >
> > >
> > > ---
> > > This report is generated by a bot. It may contain errors.
> > > See https://goo.gl/tpsmEJ for more information about syzbot.
> > > syzbot engineers can be reached at syzkaller@googlegroups.com.
> > >
> > > syzbot will keep track of this issue. See:
> > > https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> > >
> > > If the report is already addressed, let syzbot know by replying with:
> > > #syz fix: exact-commit-title
> > >
> > > If you want syzbot to run the reproducer, reply with:
> > > #syz test: git://repo/address.git branch-or-commit-hash
> > > If you attach or paste a git patch, syzbot will apply it before testing.
> > >
> > > If you want to overwrite report's subsystems, reply with:
> > > #syz set subsystems: new-subsystem
> > > (See the list of subsystem names on the web dashboard)
> > >
> > > If the report is a duplicate of another one, reply with:
> > > #syz dup: exact-subject-of-another-report
> > >
> > > If you want to undo deduplication, reply with:
> > > #syz undup
> >
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] perf: arm_cspmu: Don't touch interrupt registers if no interrupt was assigned
From: Robin Murphy @ 2024-04-05 10:33 UTC (permalink / raw)
To: Ilkka Koskinen, Besar Wicaksono, Suzuki K Poulose, Will Deacon
Cc: Mark Rutland, Raag Jadav, linux-arm-kernel, linux-kernel
In-Reply-To: <20240307193104.58302-1-ilkka@os.amperecomputing.com>
On 2024-03-07 7:31 pm, Ilkka Koskinen wrote:
> The driver enabled and disabled interrupts even if no interrupt was
> assigned to the device.
Why's that a concern - if the interrupt isn't routed anywhere, surely it
makes no difference what happens at the source end?
Thanks,
Robin.
> Signed-off-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
> ---
> drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 50b89b989ce7..2cbdb5dcb6ff 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -795,7 +795,8 @@ static void arm_cspmu_enable_counter(struct arm_cspmu *cspmu, int idx)
> inten_off = PMINTENSET + (4 * reg_id);
> cnten_off = PMCNTENSET + (4 * reg_id);
>
> - writel(BIT(reg_bit), cspmu->base0 + inten_off);
> + if (cspmu->irq)
> + writel(BIT(reg_bit), cspmu->base0 + inten_off);
> writel(BIT(reg_bit), cspmu->base0 + cnten_off);
> }
>
> @@ -810,7 +811,8 @@ static void arm_cspmu_disable_counter(struct arm_cspmu *cspmu, int idx)
> cnten_off = PMCNTENCLR + (4 * reg_id);
>
> writel(BIT(reg_bit), cspmu->base0 + cnten_off);
> - writel(BIT(reg_bit), cspmu->base0 + inten_off);
> + if (cspmu->irq)
> + writel(BIT(reg_bit), cspmu->base0 + inten_off);
> }
>
> static void arm_cspmu_event_update(struct perf_event *event)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [syzbot] [mm?] BUG: unable to handle kernel paging request in copy_from_kernel_nofault (2)
From: Russell King (Oracle) @ 2024-04-05 11:35 UTC (permalink / raw)
To: Mark Rutland
Cc: Alexei Starovoitov, Andrew Morton, linux-arm-kernel, syzbot, LKML,
linux-mm, syzkaller-bugs, bpf
In-Reply-To: <Zg_aTFoC2Pwakyl1@FVFF77S0Q05N>
On Fri, Apr 05, 2024 at 12:02:36PM +0100, Mark Rutland wrote:
> On Thu, Apr 04, 2024 at 03:57:04PM -0700, Alexei Starovoitov wrote:
> > On Wed, Apr 3, 2024 at 6:56 PM Andrew Morton <akpm@linux-foundationorg> wrote:
> > >
> > > On Mon, 01 Apr 2024 22:19:25 -0700 syzbot <syzbot+186522670e6722692d86@syzkaller.appspotmail.com> wrote:
> > >
> > > > Hello,
> > >
> > > Thanks. Cc: bpf@vger.kernel.org
> >
> > I suspect the issue is not on bpf side.
> > Looks like the bug is somewhere in arm32 bits.
> > copy_from_kernel_nofault() is called from lots of places.
> > bpf is just one user that is easy for syzbot to fuzz.
> > Interestingly arm defines copy_from_kernel_nofault_allowed()
> > that should have filtered out user addresses.
> > In this case ffffffe9 is probably a kernel address?
>
> It's at the end of the kernel range, and it's ERR_PTR(-EINVAL).
>
> 0xffffffe9 is -0x16, which is -22, which is -EINVAL.
>
> > But the kernel is doing a write?
> > Which makes no sense, since copy_from_kernel_nofault is probe reading.
>
> It makes perfect sense; the read from 'src' happened, then the kernel tries to
> write the result to 'dst', and that aligns with the disassembly in the report
> below, which I beleive is:
>
> 8: e4942000 ldr r2, [r4], #0 <-- Read of 'src', fault fixup is elsewhere
> c: e3530000 cmp r3, #0
> * 10: e5852000 str r2, [r5] <-- Write to 'dst'
>
> As above, it looks like 'dst' is ERR_PTR(-EINVAL).
>
> Are you certain that BPF is passing a sane value for 'dst'? Where does that
> come from in the first place?
It looks to me like it gets passed in from the BPF program, and the
"type" for the argument is set to ARG_PTR_TO_UNINIT_MEM. What that
means for validation purposes, I've no idea, I'm not a BPF hacker.
Obviously, if BPF is allowing copy_from_kernel_nofault() to be passed
an arbitary destination address, that would be a huge security hole.
So I think BPF folk need to urgently state what checks are done on
the destination value for _any_ function that BPF can call which
writes to memory.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 0/4] KVM, mm: remove the .change_pte() MMU notifier and set_pte_at_notify()
From: Paolo Bonzini @ 2024-04-05 11:58 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Marc Zyngier, Oliver Upton, Tianrui Zhao, Bibo Mao,
Thomas Bogendoerfer, Nicholas Piggin, Anup Patel, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
The .change_pte() MMU notifier callback was intended as an optimization
and for this reason it was initially called without a surrounding
mmu_notifier_invalidate_range_{start,end}() pair. It was only ever
implemented by KVM (which was also the original user of MMU notifiers)
and the rules on when to call set_pte_at_notify() rather than set_pte_at()
have always been pretty obscure.
It may seem a miracle that it has never caused any hard to trigger
bugs, but there's a good reason for that: KVM's implementation has
been nonfunctional for a good part of its existence. Already in
2012, commit 6bdb913f0a70 ("mm: wrap calls to set_pte_at_notify with
invalidate_range_start and invalidate_range_end", 2012-10-09) changed the
.change_pte() callback to occur within an invalidate_range_start/end()
pair; and because KVM unmaps the sPTEs during .invalidate_range_start(),
.change_pte() has no hope of finding a sPTE to change.
Therefore, all the code for .change_pte() can be removed from both KVM
and mm/, and set_pte_at_notify() can be replaced with just set_pte_at().
Please review! Also feel free to take the KVM patches through the mm
tree, as I don't expect any conflicts.
Thanks,
Paolo
Paolo Bonzini (4):
KVM: delete .change_pte MMU notifier callback
KVM: remove unused argument of kvm_handle_hva_range()
mmu_notifier: remove the .change_pte() callback
mm: replace set_pte_at_notify() with just set_pte_at()
arch/arm64/kvm/mmu.c | 34 -----------------
arch/loongarch/include/asm/kvm_host.h | 1 -
arch/loongarch/kvm/mmu.c | 32 ----------------
arch/mips/kvm/mmu.c | 30 ---------------
arch/powerpc/include/asm/kvm_ppc.h | 1 -
arch/powerpc/kvm/book3s.c | 5 ---
arch/powerpc/kvm/book3s.h | 1 -
arch/powerpc/kvm/book3s_64_mmu_hv.c | 12 ------
arch/powerpc/kvm/book3s_hv.c | 1 -
arch/powerpc/kvm/book3s_pr.c | 7 ----
arch/powerpc/kvm/e500_mmu_host.c | 6 ---
arch/riscv/kvm/mmu.c | 20 ----------
arch/x86/kvm/mmu/mmu.c | 54 +--------------------------
arch/x86/kvm/mmu/spte.c | 16 --------
arch/x86/kvm/mmu/spte.h | 2 -
arch/x86/kvm/mmu/tdp_mmu.c | 46 -----------------------
arch/x86/kvm/mmu/tdp_mmu.h | 1 -
include/linux/kvm_host.h | 2 -
include/linux/mmu_notifier.h | 44 ----------------------
include/trace/events/kvm.h | 15 --------
kernel/events/uprobes.c | 5 +--
mm/ksm.c | 4 +-
mm/memory.c | 7 +---
mm/migrate_device.c | 8 +---
mm/mmu_notifier.c | 17 ---------
virt/kvm/kvm_main.c | 50 +------------------------
26 files changed, 10 insertions(+), 411 deletions(-)
--
2.43.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 4/4] mm: replace set_pte_at_notify() with just set_pte_at()
From: Paolo Bonzini @ 2024-04-05 11:58 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Marc Zyngier, Oliver Upton, Tianrui Zhao, Bibo Mao,
Thomas Bogendoerfer, Nicholas Piggin, Anup Patel, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
In-Reply-To: <20240405115815.3226315-1-pbonzini@redhat.com>
With the demise of the .change_pte() MMU notifier callback, there is no
notification happening in set_pte_at_notify(). It is a synonym of
set_pte_at() and can be replaced with it.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/linux/mmu_notifier.h | 2 --
kernel/events/uprobes.c | 5 ++---
mm/ksm.c | 4 ++--
mm/memory.c | 7 +------
mm/migrate_device.c | 8 ++------
5 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h
index 8c72bf651606..d39ebb10caeb 100644
--- a/include/linux/mmu_notifier.h
+++ b/include/linux/mmu_notifier.h
@@ -657,6 +657,4 @@ static inline void mmu_notifier_synchronize(void)
#endif /* CONFIG_MMU_NOTIFIER */
-#define set_pte_at_notify set_pte_at
-
#endif /* _LINUX_MMU_NOTIFIER_H */
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index e4834d23e1d1..f4523b95c945 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -18,7 +18,6 @@
#include <linux/sched/coredump.h>
#include <linux/export.h>
#include <linux/rmap.h> /* anon_vma_prepare */
-#include <linux/mmu_notifier.h> /* set_pte_at_notify */
#include <linux/swap.h> /* folio_free_swap */
#include <linux/ptrace.h> /* user_enable_single_step */
#include <linux/kdebug.h> /* notifier mechanism */
@@ -195,8 +194,8 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
flush_cache_page(vma, addr, pte_pfn(ptep_get(pvmw.pte)));
ptep_clear_flush(vma, addr, pvmw.pte);
if (new_page)
- set_pte_at_notify(mm, addr, pvmw.pte,
- mk_pte(new_page, vma->vm_page_prot));
+ set_pte_at(mm, addr, pvmw.pte,
+ mk_pte(new_page, vma->vm_page_prot));
folio_remove_rmap_pte(old_folio, old_page, vma);
if (!folio_mapped(old_folio))
diff --git a/mm/ksm.c b/mm/ksm.c
index 8c001819cf10..108a4d167824 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1345,7 +1345,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
if (pte_write(entry))
entry = pte_wrprotect(entry);
- set_pte_at_notify(mm, pvmw.address, pvmw.pte, entry);
+ set_pte_at(mm, pvmw.address, pvmw.pte, entry);
}
*orig_pte = entry;
err = 0;
@@ -1447,7 +1447,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
* See Documentation/mm/mmu_notifier.rst
*/
ptep_clear_flush(vma, addr, ptep);
- set_pte_at_notify(mm, addr, ptep, newpte);
+ set_pte_at(mm, addr, ptep, newpte);
folio = page_folio(page);
folio_remove_rmap_pte(folio, page, vma);
diff --git a/mm/memory.c b/mm/memory.c
index f2bc6dd15eb8..9a6f4d8aa379 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3327,13 +3327,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
ptep_clear_flush(vma, vmf->address, vmf->pte);
folio_add_new_anon_rmap(new_folio, vma, vmf->address);
folio_add_lru_vma(new_folio, vma);
- /*
- * We call the notify macro here because, when using secondary
- * mmu page tables (such as kvm shadow page tables), we want the
- * new page to be mapped directly into the secondary page table.
- */
BUG_ON(unshare && pte_write(entry));
- set_pte_at_notify(mm, vmf->address, vmf->pte, entry);
+ set_pte_at(mm, vmf->address, vmf->pte, entry);
update_mmu_cache_range(vmf, vma, vmf->address, vmf->pte, 1);
if (old_folio) {
/*
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index b6c27c76e1a0..66206734b1b9 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -664,13 +664,9 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
if (flush) {
flush_cache_page(vma, addr, pte_pfn(orig_pte));
ptep_clear_flush(vma, addr, ptep);
- set_pte_at_notify(mm, addr, ptep, entry);
- update_mmu_cache(vma, addr, ptep);
- } else {
- /* No need to invalidate - it was non-present before */
- set_pte_at(mm, addr, ptep, entry);
- update_mmu_cache(vma, addr, ptep);
}
+ set_pte_at(mm, addr, ptep, entry);
+ update_mmu_cache(vma, addr, ptep);
pte_unmap_unlock(ptep, ptl);
*src = MIGRATE_PFN_MIGRATE;
--
2.43.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/4] KVM: remove unused argument of kvm_handle_hva_range()
From: Paolo Bonzini @ 2024-04-05 11:58 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Marc Zyngier, Oliver Upton, Tianrui Zhao, Bibo Mao,
Thomas Bogendoerfer, Nicholas Piggin, Anup Patel, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
In-Reply-To: <20240405115815.3226315-1-pbonzini@redhat.com>
The only user was kvm_mmu_notifier_change_pte(), which is now gone.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
virt/kvm/kvm_main.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2fcd9979752a..9701888811ad 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -595,8 +595,6 @@ static void kvm_null_fn(void)
}
#define IS_KVM_NULL_FN(fn) ((fn) == (void *)kvm_null_fn)
-static const union kvm_mmu_notifier_arg KVM_MMU_NOTIFIER_NO_ARG;
-
/* Iterate over each memslot intersecting [start, last] (inclusive) range */
#define kvm_for_each_memslot_in_hva_range(node, slots, start, last) \
for (node = interval_tree_iter_first(&slots->hva_tree, start, last); \
@@ -682,14 +680,12 @@ static __always_inline kvm_mn_ret_t __kvm_handle_hva_range(struct kvm *kvm,
static __always_inline int kvm_handle_hva_range(struct mmu_notifier *mn,
unsigned long start,
unsigned long end,
- union kvm_mmu_notifier_arg arg,
gfn_handler_t handler)
{
struct kvm *kvm = mmu_notifier_to_kvm(mn);
const struct kvm_mmu_notifier_range range = {
.start = start,
.end = end,
- .arg = arg,
.handler = handler,
.on_lock = (void *)kvm_null_fn,
.flush_on_ret = true,
@@ -880,8 +876,7 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
{
trace_kvm_age_hva(start, end);
- return kvm_handle_hva_range(mn, start, end, KVM_MMU_NOTIFIER_NO_ARG,
- kvm_age_gfn);
+ return kvm_handle_hva_range(mn, start, end, kvm_age_gfn);
}
static int kvm_mmu_notifier_clear_young(struct mmu_notifier *mn,
--
2.43.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/4] mmu_notifier: remove the .change_pte() callback
From: Paolo Bonzini @ 2024-04-05 11:58 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Marc Zyngier, Oliver Upton, Tianrui Zhao, Bibo Mao,
Thomas Bogendoerfer, Nicholas Piggin, Anup Patel, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
In-Reply-To: <20240405115815.3226315-1-pbonzini@redhat.com>
The scope of set_pte_at_notify() has reduced more and more through the
years. Initially, it was meant for when the change to the PTE was
not bracketed by mmu_notifier_invalidate_range_{start,end}(). However,
that has not been so for over ten years. During all this period
the only implementation of .change_pte() was KVM and it
had no actual functionality, because it was called after
mmu_notifier_invalidate_range_start() zapped the secondary PTE.
Now that this (nonfunctional) user of the .change_pte() callback is
gone, the whole callback can be removed. For now, leave in place
set_pte_at_notify() even though it is just a synonym for set_pte_at().
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/linux/mmu_notifier.h | 46 ++----------------------------------
mm/mmu_notifier.c | 17 -------------
2 files changed, 2 insertions(+), 61 deletions(-)
diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h
index f349e08a9dfe..8c72bf651606 100644
--- a/include/linux/mmu_notifier.h
+++ b/include/linux/mmu_notifier.h
@@ -122,15 +122,6 @@ struct mmu_notifier_ops {
struct mm_struct *mm,
unsigned long address);
- /*
- * change_pte is called in cases that pte mapping to page is changed:
- * for example, when ksm remaps pte to point to a new shared page.
- */
- void (*change_pte)(struct mmu_notifier *subscription,
- struct mm_struct *mm,
- unsigned long address,
- pte_t pte);
-
/*
* invalidate_range_start() and invalidate_range_end() must be
* paired and are called only when the mmap_lock and/or the
@@ -392,8 +383,6 @@ extern int __mmu_notifier_clear_young(struct mm_struct *mm,
unsigned long end);
extern int __mmu_notifier_test_young(struct mm_struct *mm,
unsigned long address);
-extern void __mmu_notifier_change_pte(struct mm_struct *mm,
- unsigned long address, pte_t pte);
extern int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *r);
extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r);
extern void __mmu_notifier_arch_invalidate_secondary_tlbs(struct mm_struct *mm,
@@ -439,13 +428,6 @@ static inline int mmu_notifier_test_young(struct mm_struct *mm,
return 0;
}
-static inline void mmu_notifier_change_pte(struct mm_struct *mm,
- unsigned long address, pte_t pte)
-{
- if (mm_has_notifiers(mm))
- __mmu_notifier_change_pte(mm, address, pte);
-}
-
static inline void
mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
{
@@ -581,26 +563,6 @@ static inline void mmu_notifier_range_init_owner(
__young; \
})
-/*
- * set_pte_at_notify() sets the pte _after_ running the notifier.
- * This is safe to start by updating the secondary MMUs, because the primary MMU
- * pte invalidate must have already happened with a ptep_clear_flush() before
- * set_pte_at_notify() has been invoked. Updating the secondary MMUs first is
- * required when we change both the protection of the mapping from read-only to
- * read-write and the pfn (like during copy on write page faults). Otherwise the
- * old page would remain mapped readonly in the secondary MMUs after the new
- * page is already writable by some CPU through the primary MMU.
- */
-#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
-({ \
- struct mm_struct *___mm = __mm; \
- unsigned long ___address = __address; \
- pte_t ___pte = __pte; \
- \
- mmu_notifier_change_pte(___mm, ___address, ___pte); \
- set_pte_at(___mm, ___address, __ptep, ___pte); \
-})
-
#else /* CONFIG_MMU_NOTIFIER */
struct mmu_notifier_range {
@@ -650,11 +612,6 @@ static inline int mmu_notifier_test_young(struct mm_struct *mm,
return 0;
}
-static inline void mmu_notifier_change_pte(struct mm_struct *mm,
- unsigned long address, pte_t pte)
-{
-}
-
static inline void
mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
{
@@ -693,7 +650,6 @@ static inline void mmu_notifier_subscriptions_destroy(struct mm_struct *mm)
#define ptep_clear_flush_notify ptep_clear_flush
#define pmdp_huge_clear_flush_notify pmdp_huge_clear_flush
#define pudp_huge_clear_flush_notify pudp_huge_clear_flush
-#define set_pte_at_notify set_pte_at
static inline void mmu_notifier_synchronize(void)
{
@@ -701,4 +657,6 @@ static inline void mmu_notifier_synchronize(void)
#endif /* CONFIG_MMU_NOTIFIER */
+#define set_pte_at_notify set_pte_at
+
#endif /* _LINUX_MMU_NOTIFIER_H */
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index ec3b068cbbe6..8982e6139d07 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -424,23 +424,6 @@ int __mmu_notifier_test_young(struct mm_struct *mm,
return young;
}
-void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address,
- pte_t pte)
-{
- struct mmu_notifier *subscription;
- int id;
-
- id = srcu_read_lock(&srcu);
- hlist_for_each_entry_rcu(subscription,
- &mm->notifier_subscriptions->list, hlist,
- srcu_read_lock_held(&srcu)) {
- if (subscription->ops->change_pte)
- subscription->ops->change_pte(subscription, mm, address,
- pte);
- }
- srcu_read_unlock(&srcu, id);
-}
-
static int mn_itree_invalidate(struct mmu_notifier_subscriptions *subscriptions,
const struct mmu_notifier_range *range)
{
--
2.43.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/4] KVM: delete .change_pte MMU notifier callback
From: Paolo Bonzini @ 2024-04-05 11:58 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Marc Zyngier, Oliver Upton, Tianrui Zhao, Bibo Mao,
Thomas Bogendoerfer, Nicholas Piggin, Anup Patel, Atish Patra,
Sean Christopherson, Andrew Morton, David Hildenbrand,
linux-arm-kernel, kvmarm, loongarch, linux-mips, linuxppc-dev,
kvm-riscv, linux-mm, linux-trace-kernel, linux-perf-users
In-Reply-To: <20240405115815.3226315-1-pbonzini@redhat.com>
The .change_pte() MMU notifier callback was intended as an
optimization. The original point of it was that KSM could tell KVM to flip
its secondary PTE to a new location without having to first zap it. At
the time there was also an .invalidate_page() callback; both of them were
*not* bracketed by calls to mmu_notifier_invalidate_range_{start,end}(),
and .invalidate_page() also doubled as a fallback implementation of
.change_pte().
Later on, however, both callbacks were changed to occur within an
invalidate_range_start/end() block.
In the case of .change_pte(), commit 6bdb913f0a70 ("mm: wrap calls to
set_pte_at_notify with invalidate_range_start and invalidate_range_end",
2012-10-09) did so to remove the fallback from .invalidate_page() to
.change_pte() and allow sleepable .invalidate_page() hooks.
This however made KVM's usage of the .change_pte() callback completely
moot, because KVM unmaps the sPTEs during .invalidate_range_start()
and therefore .change_pte() has no hope of finding a sPTE to change.
Drop the generic KVM code that dispatches to kvm_set_spte_gfn(), as
well as all the architecture specific implementations.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/arm64/kvm/mmu.c | 34 -----------------
arch/loongarch/include/asm/kvm_host.h | 1 -
arch/loongarch/kvm/mmu.c | 32 ----------------
arch/mips/kvm/mmu.c | 30 ---------------
arch/powerpc/include/asm/kvm_ppc.h | 1 -
arch/powerpc/kvm/book3s.c | 5 ---
arch/powerpc/kvm/book3s.h | 1 -
arch/powerpc/kvm/book3s_64_mmu_hv.c | 12 ------
arch/powerpc/kvm/book3s_hv.c | 1 -
arch/powerpc/kvm/book3s_pr.c | 7 ----
arch/powerpc/kvm/e500_mmu_host.c | 6 ---
arch/riscv/kvm/mmu.c | 20 ----------
arch/x86/kvm/mmu/mmu.c | 54 +--------------------------
arch/x86/kvm/mmu/spte.c | 16 --------
arch/x86/kvm/mmu/spte.h | 2 -
arch/x86/kvm/mmu/tdp_mmu.c | 46 -----------------------
arch/x86/kvm/mmu/tdp_mmu.h | 1 -
include/linux/kvm_host.h | 2 -
include/trace/events/kvm.h | 15 --------
virt/kvm/kvm_main.c | 43 ---------------------
20 files changed, 2 insertions(+), 327 deletions(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index dc04bc767865..ff17849be9f4 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1768,40 +1768,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
return false;
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- kvm_pfn_t pfn = pte_pfn(range->arg.pte);
-
- if (!kvm->arch.mmu.pgt)
- return false;
-
- WARN_ON(range->end - range->start != 1);
-
- /*
- * If the page isn't tagged, defer to user_mem_abort() for sanitising
- * the MTE tags. The S2 pte should have been unmapped by
- * mmu_notifier_invalidate_range_end().
- */
- if (kvm_has_mte(kvm) && !page_mte_tagged(pfn_to_page(pfn)))
- return false;
-
- /*
- * We've moved a page around, probably through CoW, so let's treat
- * it just like a translation fault and the map handler will clean
- * the cache to the PoC.
- *
- * The MMU notifiers will have unmapped a huge PMD before calling
- * ->change_pte() (which in turn calls kvm_set_spte_gfn()) and
- * therefore we never need to clear out a huge PMD through this
- * calling path and a memcache is not required.
- */
- kvm_pgtable_stage2_map(kvm->arch.mmu.pgt, range->start << PAGE_SHIFT,
- PAGE_SIZE, __pfn_to_phys(pfn),
- KVM_PGTABLE_PROT_R, NULL, 0);
-
- return false;
-}
-
bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{
u64 size = (range->end - range->start) << PAGE_SHIFT;
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 2d62f7b0d377..69305441f40d 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -203,7 +203,6 @@ void kvm_flush_tlb_all(void);
void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa);
int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long badv, bool write);
-void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end, bool blockable);
int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c
index a556cff35740..98883aa23ab8 100644
--- a/arch/loongarch/kvm/mmu.c
+++ b/arch/loongarch/kvm/mmu.c
@@ -494,38 +494,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
range->end << PAGE_SHIFT, &ctx);
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- unsigned long prot_bits;
- kvm_pte_t *ptep;
- kvm_pfn_t pfn = pte_pfn(range->arg.pte);
- gpa_t gpa = range->start << PAGE_SHIFT;
-
- ptep = kvm_populate_gpa(kvm, NULL, gpa, 0);
- if (!ptep)
- return false;
-
- /* Replacing an absent or old page doesn't need flushes */
- if (!kvm_pte_present(NULL, ptep) || !kvm_pte_young(*ptep)) {
- kvm_set_pte(ptep, 0);
- return false;
- }
-
- /* Fill new pte if write protected or page migrated */
- prot_bits = _PAGE_PRESENT | __READABLE;
- prot_bits |= _CACHE_MASK & pte_val(range->arg.pte);
-
- /*
- * Set _PAGE_WRITE or _PAGE_DIRTY iff old and new pte both support
- * _PAGE_WRITE for map_page_fast if next page write fault
- * _PAGE_DIRTY since gpa has already recorded as dirty page
- */
- prot_bits |= __WRITEABLE & *ptep & pte_val(range->arg.pte);
- kvm_set_pte(ptep, kvm_pfn_pte(pfn, __pgprot(prot_bits)));
-
- return true;
-}
-
bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{
kvm_ptw_ctx ctx;
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 467ee6b95ae1..c17157e700c0 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -444,36 +444,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
return true;
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- gpa_t gpa = range->start << PAGE_SHIFT;
- pte_t hva_pte = range->arg.pte;
- pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
- pte_t old_pte;
-
- if (!gpa_pte)
- return false;
-
- /* Mapping may need adjusting depending on memslot flags */
- old_pte = *gpa_pte;
- if (range->slot->flags & KVM_MEM_LOG_DIRTY_PAGES && !pte_dirty(old_pte))
- hva_pte = pte_mkclean(hva_pte);
- else if (range->slot->flags & KVM_MEM_READONLY)
- hva_pte = pte_wrprotect(hva_pte);
-
- set_pte(gpa_pte, hva_pte);
-
- /* Replacing an absent or old page doesn't need flushes */
- if (!pte_present(old_pte) || !pte_young(old_pte))
- return false;
-
- /* Pages swapped, aged, moved, or cleaned require flushes */
- return !pte_present(hva_pte) ||
- !pte_young(hva_pte) ||
- pte_pfn(old_pte) != pte_pfn(hva_pte) ||
- (pte_dirty(old_pte) && !pte_dirty(hva_pte));
-}
-
bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{
return kvm_mips_mkold_gpa_pt(kvm, range->start, range->end);
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 3281215097cc..ca3829d47ab7 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -287,7 +287,6 @@ struct kvmppc_ops {
bool (*unmap_gfn_range)(struct kvm *kvm, struct kvm_gfn_range *range);
bool (*age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
bool (*test_age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
- bool (*set_spte_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
void (*free_memslot)(struct kvm_memory_slot *slot);
int (*init_vm)(struct kvm *kvm);
void (*destroy_vm)(struct kvm *kvm);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 8acec144120e..0d0624088e6b 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -899,11 +899,6 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
return kvm->arch.kvm_ops->test_age_gfn(kvm, range);
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- return kvm->arch.kvm_ops->set_spte_gfn(kvm, range);
-}
-
int kvmppc_core_init_vm(struct kvm *kvm)
{
diff --git a/arch/powerpc/kvm/book3s.h b/arch/powerpc/kvm/book3s.h
index 58391b4b32ed..4aa2ab89afbc 100644
--- a/arch/powerpc/kvm/book3s.h
+++ b/arch/powerpc/kvm/book3s.h
@@ -12,7 +12,6 @@ extern void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
extern bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range);
extern bool kvm_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
extern bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
-extern bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
extern int kvmppc_mmu_init_pr(struct kvm_vcpu *vcpu);
extern void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu);
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 2b1f0cdd8c18..1b51b1c4713b 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -1010,18 +1010,6 @@ bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
return kvm_test_age_rmapp(kvm, range->slot, range->start);
}
-bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- WARN_ON(range->start + 1 != range->end);
-
- if (kvm_is_radix(kvm))
- kvm_unmap_radix(kvm, range->slot, range->start);
- else
- kvm_unmap_rmapp(kvm, range->slot, range->start);
-
- return false;
-}
-
static int vcpus_running(struct kvm *kvm)
{
return atomic_read(&kvm->arch.vcpus_running) != 0;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 8e86eb577eb8..35cb014a0c51 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -6364,7 +6364,6 @@ static struct kvmppc_ops kvm_ops_hv = {
.unmap_gfn_range = kvm_unmap_gfn_range_hv,
.age_gfn = kvm_age_gfn_hv,
.test_age_gfn = kvm_test_age_gfn_hv,
- .set_spte_gfn = kvm_set_spte_gfn_hv,
.free_memslot = kvmppc_core_free_memslot_hv,
.init_vm = kvmppc_core_init_vm_hv,
.destroy_vm = kvmppc_core_destroy_vm_hv,
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 5b92619a05fd..a7d7137ea0c8 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -461,12 +461,6 @@ static bool kvm_test_age_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
return false;
}
-static bool kvm_set_spte_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- /* The page will get remapped properly on its next fault */
- return do_kvm_unmap_gfn(kvm, range);
-}
-
/*****************************************/
static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
@@ -2071,7 +2065,6 @@ static struct kvmppc_ops kvm_ops_pr = {
.unmap_gfn_range = kvm_unmap_gfn_range_pr,
.age_gfn = kvm_age_gfn_pr,
.test_age_gfn = kvm_test_age_gfn_pr,
- .set_spte_gfn = kvm_set_spte_gfn_pr,
.free_memslot = kvmppc_core_free_memslot_pr,
.init_vm = kvmppc_core_init_vm_pr,
.destroy_vm = kvmppc_core_destroy_vm_pr,
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index ccb8f16ffe41..c664fdec75b1 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -747,12 +747,6 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
return false;
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- /* The page will get remapped properly on its next fault */
- return kvm_e500_mmu_unmap_gfn(kvm, range);
-}
-
/*****************************************/
int e500_mmu_host_init(struct kvmppc_vcpu_e500 *vcpu_e500)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index a9e2fd7245e1..b63650f9b966 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -550,26 +550,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
return false;
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- int ret;
- kvm_pfn_t pfn = pte_pfn(range->arg.pte);
-
- if (!kvm->arch.pgd)
- return false;
-
- WARN_ON(range->end - range->start != 1);
-
- ret = gstage_map_page(kvm, NULL, range->start << PAGE_SHIFT,
- __pfn_to_phys(pfn), PAGE_SIZE, true, true);
- if (ret) {
- kvm_debug("Failed to map G-stage page (error %d)\n", ret);
- return true;
- }
-
- return false;
-}
-
bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{
pte_t *ptep;
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 0049d49aa913..87ba2a9da196 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -432,8 +432,8 @@ static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
* The idea using the light way get the spte on x86_32 guest is from
* gup_get_pte (mm/gup.c).
*
- * An spte tlb flush may be pending, because kvm_set_pte_rmap
- * coalesces them and we are running out of the MMU lock. Therefore
+ * An spte tlb flush may be pending, because they are coalesced and
+ * we are running out of the MMU lock. Therefore
* we need to protect against in-progress updates of the spte.
*
* Reading the spte while an update is in progress may get the old value
@@ -1454,43 +1454,6 @@ static bool kvm_zap_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
return __kvm_zap_rmap(kvm, rmap_head, slot);
}
-static bool kvm_set_pte_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot, gfn_t gfn, int level,
- pte_t pte)
-{
- u64 *sptep;
- struct rmap_iterator iter;
- bool need_flush = false;
- u64 new_spte;
- kvm_pfn_t new_pfn;
-
- WARN_ON_ONCE(pte_huge(pte));
- new_pfn = pte_pfn(pte);
-
-restart:
- for_each_rmap_spte(rmap_head, &iter, sptep) {
- need_flush = true;
-
- if (pte_write(pte)) {
- kvm_zap_one_rmap_spte(kvm, rmap_head, sptep);
- goto restart;
- } else {
- new_spte = kvm_mmu_changed_pte_notifier_make_spte(
- *sptep, new_pfn);
-
- mmu_spte_clear_track_bits(kvm, sptep);
- mmu_spte_set(sptep, new_spte);
- }
- }
-
- if (need_flush && kvm_available_flush_remote_tlbs_range()) {
- kvm_flush_remote_tlbs_gfn(kvm, gfn, level);
- return false;
- }
-
- return need_flush;
-}
-
struct slot_rmap_walk_iterator {
/* input fields. */
const struct kvm_memory_slot *slot;
@@ -1596,19 +1559,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
return flush;
}
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- bool flush = false;
-
- if (kvm_memslots_have_rmaps(kvm))
- flush = kvm_handle_gfn_range(kvm, range, kvm_set_pte_rmap);
-
- if (tdp_mmu_enabled)
- flush |= kvm_tdp_mmu_set_spte_gfn(kvm, range);
-
- return flush;
-}
-
static bool kvm_age_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
struct kvm_memory_slot *slot, gfn_t gfn, int level,
pte_t unused)
diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
index 318135daf685..283af5b90016 100644
--- a/arch/x86/kvm/mmu/spte.c
+++ b/arch/x86/kvm/mmu/spte.c
@@ -322,22 +322,6 @@ u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled)
return spte;
}
-u64 kvm_mmu_changed_pte_notifier_make_spte(u64 old_spte, kvm_pfn_t new_pfn)
-{
- u64 new_spte;
-
- new_spte = old_spte & ~SPTE_BASE_ADDR_MASK;
- new_spte |= (u64)new_pfn << PAGE_SHIFT;
-
- new_spte &= ~PT_WRITABLE_MASK;
- new_spte &= ~shadow_host_writable_mask;
- new_spte &= ~shadow_mmu_writable_mask;
-
- new_spte = mark_spte_for_access_track(new_spte);
-
- return new_spte;
-}
-
u64 mark_spte_for_access_track(u64 spte)
{
if (spte_ad_enabled(spte))
diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
index 1a163aee9ec6..92da4c419171 100644
--- a/arch/x86/kvm/mmu/spte.h
+++ b/arch/x86/kvm/mmu/spte.h
@@ -511,8 +511,6 @@ static inline u64 restore_acc_track_spte(u64 spte)
return spte;
}
-u64 kvm_mmu_changed_pte_notifier_make_spte(u64 old_spte, kvm_pfn_t new_pfn);
-
void __init kvm_mmu_spte_module_init(void);
void kvm_mmu_reset_all_pte_masks(void);
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 3627744fcab6..fbb86932b766 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -1250,52 +1250,6 @@ bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
return kvm_tdp_mmu_handle_gfn(kvm, range, test_age_gfn);
}
-static bool set_spte_gfn(struct kvm *kvm, struct tdp_iter *iter,
- struct kvm_gfn_range *range)
-{
- u64 new_spte;
-
- /* Huge pages aren't expected to be modified without first being zapped. */
- WARN_ON_ONCE(pte_huge(range->arg.pte) || range->start + 1 != range->end);
-
- if (iter->level != PG_LEVEL_4K ||
- !is_shadow_present_pte(iter->old_spte))
- return false;
-
- /*
- * Note, when changing a read-only SPTE, it's not strictly necessary to
- * zero the SPTE before setting the new PFN, but doing so preserves the
- * invariant that the PFN of a present * leaf SPTE can never change.
- * See handle_changed_spte().
- */
- tdp_mmu_iter_set_spte(kvm, iter, SHADOW_NONPRESENT_VALUE);
-
- if (!pte_write(range->arg.pte)) {
- new_spte = kvm_mmu_changed_pte_notifier_make_spte(iter->old_spte,
- pte_pfn(range->arg.pte));
-
- tdp_mmu_iter_set_spte(kvm, iter, new_spte);
- }
-
- return true;
-}
-
-/*
- * Handle the changed_pte MMU notifier for the TDP MMU.
- * data is a pointer to the new pte_t mapping the HVA specified by the MMU
- * notifier.
- * Returns non-zero if a flush is needed before releasing the MMU lock.
- */
-bool kvm_tdp_mmu_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- /*
- * No need to handle the remote TLB flush under RCU protection, the
- * target SPTE _must_ be a leaf SPTE, i.e. cannot result in freeing a
- * shadow page. See the WARN on pfn_changed in handle_changed_spte().
- */
- return kvm_tdp_mmu_handle_gfn(kvm, range, set_spte_gfn);
-}
-
/*
* Remove write access from all SPTEs at or above min_level that map GFNs
* [start, end). Returns true if an SPTE has been changed and the TLBs need to
diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
index 6e1ea04ca885..58b55e61bd33 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.h
+++ b/arch/x86/kvm/mmu/tdp_mmu.h
@@ -31,7 +31,6 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
bool flush);
bool kvm_tdp_mmu_age_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
-bool kvm_tdp_mmu_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
const struct kvm_memory_slot *slot, int min_level);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ab439706ea2f..8dea11701ab2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -259,7 +259,6 @@ int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
#ifdef CONFIG_KVM_GENERIC_MMU_NOTIFIER
union kvm_mmu_notifier_arg {
- pte_t pte;
unsigned long attributes;
};
@@ -273,7 +272,6 @@ struct kvm_gfn_range {
bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
-bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
#endif
enum {
diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
index 011fba6b5552..74e40d5d4af4 100644
--- a/include/trace/events/kvm.h
+++ b/include/trace/events/kvm.h
@@ -456,21 +456,6 @@ TRACE_EVENT(kvm_unmap_hva_range,
__entry->start, __entry->end)
);
-TRACE_EVENT(kvm_set_spte_hva,
- TP_PROTO(unsigned long hva),
- TP_ARGS(hva),
-
- TP_STRUCT__entry(
- __field( unsigned long, hva )
- ),
-
- TP_fast_assign(
- __entry->hva = hva;
- ),
-
- TP_printk("mmu notifier set pte hva: %#016lx", __entry->hva)
-);
-
TRACE_EVENT(kvm_age_hva,
TP_PROTO(unsigned long start, unsigned long end),
TP_ARGS(start, end),
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4eb8afd0b961..2fcd9979752a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -717,48 +717,6 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
return __kvm_handle_hva_range(kvm, &range).ret;
}
-static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
-{
- /*
- * Skipping invalid memslots is correct if and only change_pte() is
- * surrounded by invalidate_range_{start,end}(), which is currently
- * guaranteed by the primary MMU. If that ever changes, KVM needs to
- * unmap the memslot instead of skipping the memslot to ensure that KVM
- * doesn't hold references to the old PFN.
- */
- WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
-
- if (range->slot->flags & KVM_MEMSLOT_INVALID)
- return false;
-
- return kvm_set_spte_gfn(kvm, range);
-}
-
-static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
- struct mm_struct *mm,
- unsigned long address,
- pte_t pte)
-{
- struct kvm *kvm = mmu_notifier_to_kvm(mn);
- const union kvm_mmu_notifier_arg arg = { .pte = pte };
-
- trace_kvm_set_spte_hva(address);
-
- /*
- * .change_pte() must be surrounded by .invalidate_range_{start,end}().
- * If mmu_invalidate_in_progress is zero, then no in-progress
- * invalidations, including this one, found a relevant memslot at
- * start(); rechecking memslots here is unnecessary. Note, a false
- * positive (count elevated by a different invalidation) is sub-optimal
- * but functionally ok.
- */
- WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
- if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
- return;
-
- kvm_handle_hva_range(mn, address, address + 1, arg, kvm_change_spte_gfn);
-}
-
void kvm_mmu_invalidate_begin(struct kvm *kvm)
{
lockdep_assert_held_write(&kvm->mmu_lock);
@@ -976,7 +934,6 @@ static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
.clear_flush_young = kvm_mmu_notifier_clear_flush_young,
.clear_young = kvm_mmu_notifier_clear_young,
.test_young = kvm_mmu_notifier_test_young,
- .change_pte = kvm_mmu_notifier_change_pte,
.release = kvm_mmu_notifier_release,
};
--
2.43.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/4] KVM: arm64: emulation for CTR_EL0
From: Sebastian Ott @ 2024-04-05 12:01 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kernel
Cc: Marc Zyngier, Oliver Upton, James Morse, Suzuki K Poulose,
Catalin Marinas, Will Deacon
Hej folks,
I'm looking into supporting migration between 2 Ampere Altra (Max)
machines (using Neoverse-N1). They are almost identical regarding
their feature id register state except for CTR_EL0.DIC which is set
on one machine but not the other.
CTR_EL0 is currently marked as invariant and migrating a VM between
those 2 machines using qemu fails.
I've send this out as an RFC before [0]. What I've changed here
based on feedback I've got from Marc was:
* store the emulated value per VM and not per VCPU
* allow to change more values than just the DIC bit
* only trap guest access to that reg when needed
* make sure to not present the guest with an inconsistent register set
Patch 2 adds a ctr_el0 member to struct kvm_arch - would it be preferred
to add it into kvm->arch.id_regs[] (this would mean to increase that
array 4x)?
Patch 3 resets CLIDR_EL1 after a write to CTR_EL0 potentially changing
the value for CLIDR_EL1 - would that be ok for userspace?
Thanks,
Sebastian
[0]: https://lore.kernel.org/all/20240318111636.10613-1-sebott@redhat.com/T/
Sebastian Ott (4):
KVM: arm64: change return value in arm64_check_features()
KVM: arm64: maintain per VM value for CTR_EL0
KVM: arm64: add emulation for CTR_EL0 register
KVM: arm64: show writable masks for feature registers
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kvm/sys_regs.c | 131 ++++++++++++++++++++----------
2 files changed, 89 insertions(+), 43 deletions(-)
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/4] KVM: arm64: maintain per VM value for CTR_EL0
From: Sebastian Ott @ 2024-04-05 12:01 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kernel
Cc: Marc Zyngier, Oliver Upton, James Morse, Suzuki K Poulose,
Catalin Marinas, Will Deacon
In-Reply-To: <20240405120108.11844-1-sebott@redhat.com>
In preparation for CTR_EL0 emulation maintain a per VM for this
register and use it where appropriate.
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kvm/sys_regs.c | 22 +++++++++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9e8a496fb284..481216febb46 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -318,6 +318,7 @@ struct kvm_arch {
/* PMCR_EL0.N value for the guest */
u8 pmcr_n;
+ u64 ctr_el0;
/* Iterator for idreg debugfs */
u8 idreg_debugfs_iter;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 131f5b0ca2b9..4d29b1a0842d 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -215,13 +215,21 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
#define CSSELR_MAX 14
+static u64 kvm_get_ctr_el0(struct kvm *kvm)
+{
+ if (kvm->arch.ctr_el0)
+ return kvm->arch.ctr_el0;
+
+ return read_sanitised_ftr_reg(SYS_CTR_EL0);
+}
+
/*
* Returns the minimum line size for the selected cache, expressed as
* Log2(bytes).
*/
-static u8 get_min_cache_line_size(bool icache)
+static u8 get_min_cache_line_size(struct kvm *kvm, bool icache)
{
- u64 ctr = read_sanitised_ftr_reg(SYS_CTR_EL0);
+ u64 ctr = kvm_get_ctr_el0(kvm);
u8 field;
if (icache)
@@ -248,7 +256,7 @@ static u32 get_ccsidr(struct kvm_vcpu *vcpu, u32 csselr)
if (vcpu->arch.ccsidr)
return vcpu->arch.ccsidr[csselr];
- line_size = get_min_cache_line_size(csselr & CSSELR_EL1_InD);
+ line_size = get_min_cache_line_size(vcpu->kvm, csselr & CSSELR_EL1_InD);
/*
* Fabricate a CCSIDR value as the overriding value does not exist.
@@ -283,7 +291,7 @@ static int set_ccsidr(struct kvm_vcpu *vcpu, u32 csselr, u32 val)
u32 i;
if ((val & CCSIDR_EL1_RES0) ||
- line_size < get_min_cache_line_size(csselr & CSSELR_EL1_InD))
+ line_size < get_min_cache_line_size(vcpu->kvm, csselr & CSSELR_EL1_InD))
return -EINVAL;
if (!ccsidr) {
@@ -1862,7 +1870,7 @@ static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
if (p->is_write)
return write_to_read_only(vcpu, p, r);
- p->regval = read_sanitised_ftr_reg(SYS_CTR_EL0);
+ p->regval = kvm_get_ctr_el0(vcpu->kvm);
return true;
}
@@ -1882,7 +1890,7 @@ static bool access_clidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
*/
static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
- u64 ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0);
+ u64 ctr_el0 = kvm_get_ctr_el0(vcpu->kvm);
u64 clidr;
u8 loc;
@@ -1935,7 +1943,7 @@ static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
u64 val)
{
- u64 ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0);
+ u64 ctr_el0 = kvm_get_ctr_el0(vcpu->kvm);
u64 idc = !CLIDR_LOC(val) || (!CLIDR_LOUIS(val) && !CLIDR_LOUU(val));
if ((val & CLIDR_EL1_RES0) || (!(ctr_el0 & CTR_EL0_IDC) && idc))
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 4/4] KVM: arm64: show writable masks for feature registers
From: Sebastian Ott @ 2024-04-05 12:01 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kernel
Cc: Marc Zyngier, Oliver Upton, James Morse, Suzuki K Poulose,
Catalin Marinas, Will Deacon
In-Reply-To: <20240405120108.11844-1-sebott@redhat.com>
Instead of using ~0UL provide the actual writable mask for
non-id feature registers in the output of the
KVM_ARM_GET_REG_WRITABLE_MASKS ioctl.
Explicitely set the mask for CLIDR_EL1 to make sure we present
the same value to userspace than before.
This changes the mask for the CTR_EL0 register in the output
of the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl.
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
arch/arm64/kvm/sys_regs.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index b0ba292259f9..947aa9c0784f 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2505,7 +2505,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
{ SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
- .set_user = set_clidr },
+ .set_user = set_clidr, .val = ~0UL },
{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
@@ -4059,20 +4059,11 @@ int kvm_vm_ioctl_get_reg_writable_masks(struct kvm *kvm, struct reg_mask_range *
if (!is_feature_id_reg(encoding) || !reg->set_user)
continue;
- /*
- * For ID registers, we return the writable mask. Other feature
- * registers return a full 64bit mask. That's not necessary
- * compliant with a given revision of the architecture, but the
- * RES0/RES1 definitions allow us to do that.
- */
- if (is_id_reg(encoding)) {
- if (!reg->val ||
- (is_aa32_id_reg(encoding) && !kvm_supports_32bit_el0()))
- continue;
- val = reg->val;
- } else {
- val = ~0UL;
+ if (!reg->val ||
+ (is_aa32_id_reg(encoding) && !kvm_supports_32bit_el0())) {
+ continue;
}
+ val = reg->val;
if (put_user(val, (masks + KVM_ARM_FEATURE_ID_RANGE_INDEX(encoding))))
return -EFAULT;
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/4] KVM: arm64: add emulation for CTR_EL0 register
From: Sebastian Ott @ 2024-04-05 12:01 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kernel
Cc: Marc Zyngier, Oliver Upton, James Morse, Suzuki K Poulose,
Catalin Marinas, Will Deacon
In-Reply-To: <20240405120108.11844-1-sebott@redhat.com>
CTR_EL0 is currently handled as an invariant register, thus
guests will be presented with the host value of that register.
Add emulation for CTR_EL0 based on a per VM value.
When CTR_EL0 is changed the reset function for CLIDR_EL1 is
called to make sure we present the guest with consistent
register values.
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
arch/arm64/kvm/sys_regs.c | 72 ++++++++++++++++++++++++++++++++++-----
1 file changed, 64 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 4d29b1a0842d..b0ba292259f9 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1874,6 +1874,55 @@ static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
return true;
}
+static u64 reset_ctr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd)
+{
+ vcpu->kvm->arch.ctr_el0 = 0;
+ return kvm_get_ctr_el0(vcpu->kvm);
+}
+
+static int get_ctr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+ u64 *val)
+{
+ *val = kvm_get_ctr_el0(vcpu->kvm);
+ return 0;
+}
+
+static const struct sys_reg_desc *get_sys_reg_desc(u32 encoding);
+
+static int set_ctr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+ u64 val)
+{
+ u64 host_val = read_sanitised_ftr_reg(SYS_CTR_EL0);
+ u64 old_val = kvm_get_ctr_el0(vcpu->kvm);
+ const struct sys_reg_desc *clidr_el1;
+ int ret;
+
+ if (val == old_val)
+ return 0;
+
+ if (kvm_vm_has_ran_once(vcpu->kvm))
+ return -EBUSY;
+
+ mutex_lock(&vcpu->kvm->arch.config_lock);
+ ret = arm64_check_features(vcpu, rd, val);
+ if (ret) {
+ mutex_unlock(&vcpu->kvm->arch.config_lock);
+ return ret;
+ }
+ if (val != host_val)
+ vcpu->kvm->arch.ctr_el0 = val;
+ else
+ vcpu->kvm->arch.ctr_el0 = 0;
+
+ mutex_unlock(&vcpu->kvm->arch.config_lock);
+
+ clidr_el1 = get_sys_reg_desc(SYS_CLIDR_EL1);
+ if (clidr_el1)
+ clidr_el1->reset(vcpu, clidr_el1);
+
+ return 0;
+}
+
static bool access_clidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
@@ -2460,7 +2509,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
- { SYS_DESC(SYS_CTR_EL0), access_ctr },
+ { SYS_DESC(SYS_CTR_EL0), access_ctr, .reset = reset_ctr,
+ .get_user = get_ctr, .set_user = set_ctr, .val = (CTR_EL0_DIC_MASK |
+ CTR_EL0_IDC_MASK |
+ CTR_EL0_DminLine_MASK |
+ CTR_EL0_IminLine_MASK)},
{ SYS_DESC(SYS_SVCR), undef_access },
{ PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr,
@@ -3623,6 +3676,13 @@ static bool index_to_params(u64 id, struct sys_reg_params *params)
}
}
+static const struct sys_reg_desc *get_sys_reg_desc(u32 encoding)
+{
+ struct sys_reg_params params = encoding_to_params(encoding);
+
+ return find_reg(¶ms, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+}
+
const struct sys_reg_desc *get_reg_by_id(u64 id,
const struct sys_reg_desc table[],
unsigned int num)
@@ -3676,18 +3736,11 @@ FUNCTION_INVARIANT(midr_el1)
FUNCTION_INVARIANT(revidr_el1)
FUNCTION_INVARIANT(aidr_el1)
-static u64 get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
-{
- ((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0);
- return ((struct sys_reg_desc *)r)->val;
-}
-
/* ->val is filled in by kvm_sys_reg_table_init() */
static struct sys_reg_desc invariant_sys_regs[] __ro_after_init = {
{ SYS_DESC(SYS_MIDR_EL1), NULL, get_midr_el1 },
{ SYS_DESC(SYS_REVIDR_EL1), NULL, get_revidr_el1 },
{ SYS_DESC(SYS_AIDR_EL1), NULL, get_aidr_el1 },
- { SYS_DESC(SYS_CTR_EL0), NULL, get_ctr_el0 },
};
static int get_invariant_sys_reg(u64 id, u64 __user *uaddr)
@@ -4049,6 +4102,9 @@ void kvm_init_sysreg(struct kvm_vcpu *vcpu)
vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
}
+ if (vcpu->kvm->arch.ctr_el0)
+ vcpu->arch.hcr_el2 |= HCR_TID2;
+
if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
goto out;
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 1/9] drm: xlnx: zynqmp_dpsub: Set layer mode during creation
From: Tomi Valkeinen @ 2024-04-05 12:06 UTC (permalink / raw)
To: Anatoliy Klymenko
Cc: dri-devel, linux-arm-kernel, linux-kernel, devicetree,
linux-media, Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Daniel Vetter, Michal Simek,
Andrzej Hajda, Neil Armstrong, Robert Foss, Jonas Karlman,
Jernej Skrabec, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Mauro Carvalho Chehab
In-Reply-To: <20240321-dp-live-fmt-v3-1-d5090d796b7e@amd.com>
On 21/03/2024 22:43, Anatoliy Klymenko wrote:
> Set layer mode of operation (live or dma-based) during layer creation.
>
> Each DPSUB layer mode of operation is defined by corresponding DT node port
> connection, so it is possible to assign it during layer object creation.
> Previously it was set in layer enable functions, although it is too late
> as setting layer format depends on layer mode, and should be done before
> given layer enabled.
>
> Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/gpu/drm/xlnx/zynqmp_disp.c | 20 ++++++++++++++++----
> drivers/gpu/drm/xlnx/zynqmp_disp.h | 13 +------------
> drivers/gpu/drm/xlnx/zynqmp_dp.c | 2 +-
> drivers/gpu/drm/xlnx/zynqmp_kms.c | 2 +-
> 4 files changed, 19 insertions(+), 18 deletions(-)
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Tomi
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c
> index 8a39b3accce5..e6d26ef60e89 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
> @@ -64,6 +64,16 @@
>
> #define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
>
> +/**
> + * enum zynqmp_dpsub_layer_mode - Layer mode
> + * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
> + * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode
> + */
> +enum zynqmp_dpsub_layer_mode {
> + ZYNQMP_DPSUB_LAYER_NONLIVE,
> + ZYNQMP_DPSUB_LAYER_LIVE,
> +};
> +
> /**
> * struct zynqmp_disp_format - Display subsystem format information
> * @drm_fmt: DRM format (4CC)
> @@ -902,15 +912,12 @@ u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
> /**
> * zynqmp_disp_layer_enable - Enable a layer
> * @layer: The layer
> - * @mode: Operating mode of layer
> *
> * Enable the @layer in the audio/video buffer manager and the blender. DMA
> * channels are started separately by zynqmp_disp_layer_update().
> */
> -void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
> - enum zynqmp_dpsub_layer_mode mode)
> +void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
> {
> - layer->mode = mode;
> zynqmp_disp_avbuf_enable_video(layer->disp, layer);
> zynqmp_disp_blend_layer_enable(layer->disp, layer);
> }
> @@ -1134,6 +1141,11 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
> layer->id = i;
> layer->disp = disp;
> layer->info = &layer_info[i];
> + /* For now assume dpsub works in either live or non-live mode for both layers.
> + * Hybrid mode is not supported yet.
> + */
> + layer->mode = disp->dpsub->dma_enabled ? ZYNQMP_DPSUB_LAYER_NONLIVE
> + : ZYNQMP_DPSUB_LAYER_LIVE;
>
> ret = zynqmp_disp_layer_request_dma(disp, layer);
> if (ret)
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h b/drivers/gpu/drm/xlnx/zynqmp_disp.h
> index 123cffac08be..9b8b202224d9 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
> +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
> @@ -42,16 +42,6 @@ enum zynqmp_dpsub_layer_id {
> ZYNQMP_DPSUB_LAYER_GFX,
> };
>
> -/**
> - * enum zynqmp_dpsub_layer_mode - Layer mode
> - * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
> - * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode
> - */
> -enum zynqmp_dpsub_layer_mode {
> - ZYNQMP_DPSUB_LAYER_NONLIVE,
> - ZYNQMP_DPSUB_LAYER_LIVE,
> -};
> -
> void zynqmp_disp_enable(struct zynqmp_disp *disp);
> void zynqmp_disp_disable(struct zynqmp_disp *disp);
> int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
> @@ -62,8 +52,7 @@ void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
>
> u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
> unsigned int *num_formats);
> -void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
> - enum zynqmp_dpsub_layer_mode mode);
> +void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer);
> void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
> void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
> const struct drm_format_info *info);
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index 1846c4971fd8..04b6bcac3b07 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -1295,7 +1295,7 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
> /* TODO: Make the format configurable. */
> info = drm_format_info(DRM_FORMAT_YUV422);
> zynqmp_disp_layer_set_format(layer, info);
> - zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE);
> + zynqmp_disp_layer_enable(layer);
>
> if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)
> zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255);
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
> index db3bb4afbfc4..43bf416b33d5 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
> @@ -122,7 +122,7 @@ static void zynqmp_dpsub_plane_atomic_update(struct drm_plane *plane,
>
> /* Enable or re-enable the plane if the format has changed. */
> if (format_changed)
> - zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_NONLIVE);
> + zynqmp_disp_layer_enable(layer);
> }
>
> static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = {
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox