* [PATCH ath-next] wifi: ath9k: owl: remove misleading error message
From: Rosen Penev @ 2026-05-21 23:21 UTC (permalink / raw)
To: linux-wireless
Cc: Toke Høiland-Jørgensen, Andreas Färber,
Manivannan Sadhasivam,
moderated list:ARM/ACTIONS SEMI ARCHITECTURE,
moderated list:ARM/ACTIONS SEMI ARCHITECTURE, open list
The error is about the firmware failing to be requested, not calibration
data. Just return directly anyways.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
index b9ef34709202..4460ee7f44e1 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
+++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
@@ -204,12 +204,8 @@ static int owl_probe(struct pci_dev *pdev,
scnprintf(eeprom_name, sizeof(eeprom_name), "ath9k-eeprom-pci-%s.bin",
dev_name(dev));
- err = request_firmware_nowait(THIS_MODULE, true, eeprom_name,
+ return request_firmware_nowait(THIS_MODULE, true, eeprom_name,
&pdev->dev, GFP_KERNEL, ctx, owl_fw_cb);
- if (err)
- dev_err(&pdev->dev, "failed to request caldata (%d).\n", err);
-
- return err;
}
static void owl_remove(struct pci_dev *pdev)
--
2.54.0
^ permalink raw reply related
* Re: [PATCH RESEND v3 5/6] soc: qcom: pmic-glink-altmode: pass down HPD_IRQ events
From: Bjorn Andersson @ 2026-05-21 23:17 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Heikki Krogerus, Greg Kroah-Hartman, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Adrien Grassein, Jani Nikula, Rodrigo Vivi,
Joonas Lahtinen, Tvrtko Ursulin, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, Tomi Valkeinen,
Konrad Dybcio, Pengyu Luo, Nikita Travkin, Yongxing Mou,
dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno
In-Reply-To: <20260513-hpd-irq-events-v3-5-086857017f16@oss.qualcomm.com>
On Wed, May 13, 2026 at 09:23:25PM +0300, Dmitry Baryshkov wrote:
> Pass IRQ_HPD events to the HPD bridge, letting those to be delivered to
> the DisplayPort driver.
>
Acked-by: Bjorn Andersson <andersson@kernel.org>
Regards,
Bjorn
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/soc/qcom/pmic_glink_altmode.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
> index 619bad2c27ee..946eb20b8f83 100644
> --- a/drivers/soc/qcom/pmic_glink_altmode.c
> +++ b/drivers/soc/qcom/pmic_glink_altmode.c
> @@ -373,7 +373,11 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
> else
> conn_status = connector_status_disconnected;
>
> - drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status);
> + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev,
> + conn_status,
> + alt_port->hpd_irq ?
> + DRM_CONNECTOR_DP_IRQ_HPD :
> + DRM_CONNECTOR_NO_EXTRA_STATUS);
> } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) {
> if (alt_port->svid == USB_TYPEC_TBT_SID)
> pmic_glink_altmode_enable_tbt(altmode, alt_port);
>
> --
> 2.47.3
>
^ permalink raw reply
* Re: [PATCH 4/4] ASoC: meson: aiu: use aiu-formatter-i2s to format I2S output data
From: Mark Brown @ 2026-05-21 23:15 UTC (permalink / raw)
To: Valerio Setti
Cc: Jerome Brunet, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Neil Armstrong, Kevin Hilman, Martin Blumenstingl, linux-kernel,
linux-sound, linux-arm-kernel, linux-amlogic
In-Reply-To: <20260515-reshape-aiu-as-axg-v1-4-53b457784ff3@baylibre.com>
[-- Attachment #1: Type: text/plain, Size: 2732 bytes --]
On Fri, May 15, 2026 at 05:10:40PM +0200, Valerio Setti wrote:
> Create a new DAPM widget for "I2S formatter" and place it on the path
> between FIFO and output DAI interface. Remove I2S output formatting code
> from aiu-encoder-i2s since it's now implemented from aiu-formatter-i2s.
This series, it looks like this specific patch, is breaking pcm-test on
my libretech Le Potato board, the clocking looks to be seriously messed
up. I'm getting:
# selftests: alsa: pcm-test
# TAP version 13
# # Card 0/LIBRETECHCC - LIBRETECH-CC (LIBRETECH-CC)
# # LIBRETECHCC.0 - fe.dai-link-0 (*)
# 1..7
# # default.time1.LIBRETECHCC.0.0.PLAYBACK - 8kHz mono large periods
# ok 1 # SKIP default.time1.LIBRETECHCC.0.0.PLAYBACK
# # snd_pcm_hw_params_set_channels 1: Invalid argument
# # default.time2.LIBRETECHCC.0.0.PLAYBACK - 8kHz stereo large periods
# # default.time2.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.8000.2.8000.32000 sw_params.32000
# not ok 2 default.time2.LIBRETECHCC.0.0.PLAYBACK
# # time mismatch: expected 2000ms got 4425
# # default.time3.LIBRETECHCC.0.0.PLAYBACK - 44.1kHz stereo large periods
# # default.time3.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.44100.2.22528.192000 sw_params.180224
# not ok 3 default.time3.LIBRETECHCC.0.0.PLAYBACK
# # time mismatch: expected 2000ms got 4852
# # default.time4.LIBRETECHCC.0.0.PLAYBACK - 48kHz stereo small periods
# # default.time4.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.48000.2.512.4096 sw_params.4096
# not ok 4 default.time4.LIBRETECHCC.0.0.PLAYBACK
# # expected 48000, wrote 4096
# # default.time5.LIBRETECHCC.0.0.PLAYBACK - 48kHz stereo large periods
# # default.time5.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.48000.2.24000.192000 sw_params.192000
# not ok 5 default.time5.LIBRETECHCC.0.0.PLAYBACK
# # time mismatch: expected 2000ms got 4489
# # default.time6.LIBRETECHCC.0.0.PLAYBACK - 48kHz 6 channel large periods
# # default.time6.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.48000.2.48000.262144 sw_params.240000
# not ok 6 default.time6.LIBRETECHCC.0.0.PLAYBACK
# # time mismatch: expected 2000ms got 6135
# # default.time7.LIBRETECHCC.0.0.PLAYBACK - 96kHz stereo large periods
# # default.time7.LIBRETECHCC.0.0.PLAYBACK hw_params.RW_INTERLEAVED.S16_LE.96000.2.48000.192000 sw_params.192000
# not ok 7 default.time7.LIBRETECHCC.0.0.PLAYBACK
# # time mismatch: expected 2000ms got 2287
# # 1 skipped test(s) detected. Consider enabling relevant config options to improve coverage.
# # Totals: pass:0 fail:6 xfail:0 xpass:0 skip:1 error:0
Full log:
https://lava.sirena.org.uk/scheduler/job/2786342#L1934
The prior patches seem to test fine, it's this one that seems to
introduce the issue.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH RESEND v3 2/6] drm/bridge: pass down IRQ_HPD to the drivers
From: Bjorn Andersson @ 2026-05-21 23:12 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Heikki Krogerus, Greg Kroah-Hartman, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Adrien Grassein, Jani Nikula, Rodrigo Vivi,
Joonas Lahtinen, Tvrtko Ursulin, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, Tomi Valkeinen,
Konrad Dybcio, Pengyu Luo, Nikita Travkin, Yongxing Mou,
dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno
In-Reply-To: <20260513-hpd-irq-events-v3-2-086857017f16@oss.qualcomm.com>
On Wed, May 13, 2026 at 09:23:22PM +0300, Dmitry Baryshkov wrote:
> Pass down the notifications about the IRQ_HPD events down to the
> individual drivers, letting them handle those as required.
>
I think patch 2 through 6 relies on patch 1's commit message to
establish the motivation for each change, but they are scattered across
a variety of drivers/files.
It would be preferable to have the commit message of each patch stand on
its own.
Regards,
Bjorn
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/gpu/drm/bridge/chrontel-ch7033.c | 3 ++-
> drivers/gpu/drm/bridge/lontium-lt8912b.c | 3 ++-
> drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 ++-
> drivers/gpu/drm/bridge/ti-tfp410.c | 4 ++--
> drivers/gpu/drm/display/drm_bridge_connector.c | 22 +++++++++++++---------
> drivers/gpu/drm/drm_bridge.c | 5 +++--
> drivers/gpu/drm/drm_connector.c | 2 +-
> drivers/gpu/drm/i915/display/intel_dp.c | 3 ++-
> drivers/gpu/drm/meson/meson_encoder_hdmi.c | 3 ++-
> drivers/gpu/drm/msm/dp/dp_display.c | 3 ++-
> drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++-
> drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 ++-
> include/drm/drm_bridge.h | 9 ++++++---
> include/drm/drm_connector.h | 3 ++-
> 14 files changed, 43 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c
> index 54d49d4882c8..04e6b4c00a28 100644
> --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c
> +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c
> @@ -259,7 +259,8 @@ static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = {
> .best_encoder = ch7033_connector_best_encoder,
> };
>
> -static void ch7033_hpd_event(void *arg, enum drm_connector_status status)
> +static void ch7033_hpd_event(void *arg, enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct ch7033_priv *priv = arg;
>
> diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> index 8a0b48efca58..b404f0cbf60d 100644
> --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
> +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> @@ -504,7 +504,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
> return 0;
> }
>
> -static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status)
> +static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct lt8912 *lt = data;
>
> diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
> index 11aab07d88df..ca41ebe9f26f 100644
> --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
> +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
> @@ -430,7 +430,8 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid
>
> static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> const struct drm_edid *drm_edid;
>
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index 3b6b0e92cf89..199916662895 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -39,7 +39,6 @@ drm_bridge_to_tfp410(struct drm_bridge *bridge)
> {
> return container_of(bridge, struct tfp410, bridge);
> }
> -
> static inline struct tfp410 *
> drm_connector_to_tfp410(struct drm_connector *connector)
> {
> @@ -110,7 +109,8 @@ static void tfp410_hpd_work_func(struct work_struct *work)
> drm_helper_hpd_irq_event(dvi->bridge.dev);
> }
>
> -static void tfp410_hpd_callback(void *arg, enum drm_connector_status status)
> +static void tfp410_hpd_callback(void *arg, enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct tfp410 *dvi = arg;
>
> diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
> index 39cc18f78eda..5fdb1a231cec 100644
> --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> @@ -141,7 +141,8 @@ struct drm_bridge_connector {
> */
>
> static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct drm_bridge_connector *bridge_connector =
> to_drm_bridge_connector(connector);
> @@ -149,12 +150,13 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
> /* Notify all bridges in the pipeline of hotplug events. */
> drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) {
> if (bridge->funcs->hpd_notify)
> - bridge->funcs->hpd_notify(bridge, connector, status);
> + bridge->funcs->hpd_notify(bridge, connector, status, extra_status);
> }
> }
>
> static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bridge_connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct drm_connector *connector = &drm_bridge_connector->base;
> struct drm_device *dev = connector->dev;
> @@ -163,24 +165,26 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri
> connector->status = status;
> mutex_unlock(&dev->mode_config.mutex);
>
> - drm_bridge_connector_hpd_notify(connector, status);
> + drm_bridge_connector_hpd_notify(connector, status, extra_status);
>
> drm_kms_helper_connector_hotplug_event(connector);
> }
>
> static void drm_bridge_connector_hpd_cb(void *cb_data,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> - drm_bridge_connector_handle_hpd(cb_data, status);
> + drm_bridge_connector_handle_hpd(cb_data, status, extra_status);
> }
>
> static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct drm_bridge_connector *bridge_connector =
> to_drm_bridge_connector(connector);
>
> - drm_bridge_connector_handle_hpd(bridge_connector, status);
> + drm_bridge_connector_handle_hpd(bridge_connector, status, extra_status);
> }
>
> static void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
> @@ -223,7 +227,7 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force)
> if (hdmi)
> drm_atomic_helper_connector_hdmi_hotplug(connector, status);
>
> - drm_bridge_connector_hpd_notify(connector, status);
> + drm_bridge_connector_hpd_notify(connector, status, DRM_CONNECTOR_NO_EXTRA_STATUS);
> } else {
> switch (connector->connector_type) {
> case DRM_MODE_CONNECTOR_DPI:
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index d6f512b73389..c8c3301cd936 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -1444,7 +1444,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
> */
> void drm_bridge_hpd_enable(struct drm_bridge *bridge,
> void (*cb)(void *data,
> - enum drm_connector_status status),
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status),
> void *data)
> {
> if (!(bridge->ops & DRM_BRIDGE_OP_HPD))
> @@ -1509,7 +1510,7 @@ void drm_bridge_hpd_notify(struct drm_bridge *bridge,
> {
> mutex_lock(&bridge->hpd_mutex);
> if (bridge->hpd_cb)
> - bridge->hpd_cb(bridge->hpd_data, status);
> + bridge->hpd_cb(bridge->hpd_data, status, DRM_CONNECTOR_NO_EXTRA_STATUS);
> mutex_unlock(&bridge->hpd_mutex);
> }
> EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify);
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index edee9daccd51..415eb834808c 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -3532,7 +3532,7 @@ void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> return;
>
> if (connector->funcs->oob_hotplug_event)
> - connector->funcs->oob_hotplug_event(connector, status);
> + connector->funcs->oob_hotplug_event(connector, status, extra_status);
>
> drm_connector_put(connector);
> }
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 4955bd8b11d7..98bbcab2067b 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6779,7 +6779,8 @@ static int intel_dp_connector_atomic_check(struct drm_connector *_connector,
> }
>
> static void intel_dp_oob_hotplug_event(struct drm_connector *_connector,
> - enum drm_connector_status hpd_state)
> + enum drm_connector_status hpd_state,
> + enum drm_connector_status_extra extra_status)
> {
> struct intel_connector *connector = to_intel_connector(_connector);
> struct intel_display *display = to_intel_display(connector);
> diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> index 1abb0572bb5f..691b9996c8a4 100644
> --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> @@ -323,7 +323,8 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge,
>
> static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index d2124d625485..7a0623fdbd8e 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1785,7 +1785,8 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge)
>
> void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge);
> struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display;
> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
> index 9eb3431dd93a..74da3ef6b625 100644
> --- a/drivers/gpu/drm/msm/dp/dp_drm.h
> +++ b/drivers/gpu/drm/msm/dp/dp_drm.h
> @@ -41,6 +41,7 @@ void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge);
> void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge);
> void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status);
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status);
>
> #endif /* _DP_DRM_H_ */
> diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
> index 29b2dfb90b5f..a7288791b2a5 100644
> --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
> +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
> @@ -429,7 +429,8 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge,
>
> static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index a8d67bd9ee50..3e4672fbd7a8 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -615,7 +615,8 @@ struct drm_bridge_funcs {
> */
> void (*hpd_notify)(struct drm_bridge *bridge,
> struct drm_connector *connector,
> - enum drm_connector_status status);
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status);
>
> /**
> * @hpd_enable:
> @@ -1260,7 +1261,8 @@ struct drm_bridge {
> * @hpd_cb: Hot plug detection callback, registered with
> * drm_bridge_hpd_enable().
> */
> - void (*hpd_cb)(void *data, enum drm_connector_status status);
> + void (*hpd_cb)(void *data, enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status);
> /**
> * @hpd_data: Private data passed to the Hot plug detection callback
> * @hpd_cb.
> @@ -1550,7 +1552,8 @@ const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
> struct drm_connector *connector);
> void drm_bridge_hpd_enable(struct drm_bridge *bridge,
> void (*cb)(void *data,
> - enum drm_connector_status status),
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status),
> void *data);
> void drm_bridge_hpd_disable(struct drm_bridge *bridge);
> void drm_bridge_hpd_notify(struct drm_bridge *bridge,
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index e05197e970d3..5ac5a64f83d9 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1720,7 +1720,8 @@ struct drm_connector_funcs {
> * has been received from a source outside the display driver / device.
> */
> void (*oob_hotplug_event)(struct drm_connector *connector,
> - enum drm_connector_status status);
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status);
>
> /**
> * @debugfs_init:
>
> --
> 2.47.3
>
^ permalink raw reply
* Re: [PATCH v14 07/44] arm64: RMI: Configure the RMM with the host's page size
From: Suzuki K Poulose @ 2026-05-21 22:36 UTC (permalink / raw)
To: Gavin Shan, Steven Price, kvm, kvmarm
Cc: Catalin Marinas, Marc Zyngier, Will Deacon, James Morse,
Oliver Upton, Zenghui Yu, linux-arm-kernel, linux-kernel,
Joey Gouly, Alexandru Elisei, Christoffer Dall, Fuad Tabba,
linux-coco, Ganapatrao Kulkarni, Shanker Donthineni, Alper Gun,
Aneesh Kumar K . V, Emi Kisanuki, Vishal Annapurve, WeiLin.Chang,
Lorenzo.Pieralisi2
In-Reply-To: <45a953a8-6edc-45c3-b5bd-17f14397ab89@redhat.com>
On 21/05/2026 01:51, Gavin Shan wrote:
> Hi Steven,
>
> On 5/13/26 11:17 PM, Steven Price wrote:
>> RMM v2.0 brings the ability to set the RMM's granule size. Check the
>> feature registers and configure the RMM so that it matches the host's
>> page size. This means that operations can be done with a granulatity
>> equal to PAGE_SIZE.
>>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> ---
>> Changes since v13:
>> * Moved out of KVM.
>> ---
>> arch/arm64/kernel/rmi.c | 42 +++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 42 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/rmi.c b/arch/arm64/kernel/rmi.c
>> index 99c1ccc35c11..a14ead5dedda 100644
>> --- a/arch/arm64/kernel/rmi.c
>> +++ b/arch/arm64/kernel/rmi.c
>> @@ -49,6 +49,45 @@ static int rmi_check_version(void)
>> return 0;
>> }
>> +static int rmi_configure(void)
>> +{
>> + struct rmm_config *config __free(free_page) = NULL;
>> + unsigned long ret;
>> +
>> + config = (struct rmm_config *)get_zeroed_page(GFP_KERNEL);
>> + if (!config)
>> + return -ENOMEM;
>> +
>> + switch (PAGE_SIZE) {
>> + case SZ_4K:
>> + config->rmi_granule_size = RMI_GRANULE_SIZE_4KB;
>> + break;
>> + case SZ_16K:
>> + config->rmi_granule_size = RMI_GRANULE_SIZE_16KB;
>> + break;
>> + case SZ_64K:
>> + config->rmi_granule_size = RMI_GRANULE_SIZE_64KB;
>> + break;
>> + default:
>> + pr_err("Unsupported PAGE_SIZE for RMM\n");
>> + return -EINVAL;
>> + }
>> +
>> + ret = rmi_rmm_config_set(virt_to_phys(config));
>> + if (ret) {
>> + pr_err("RMM config set failed\n");
>> + return -EINVAL;
>> + }
>> +
>
> Looking at branch 'topics/rmm-v2.0-poc_2' of RMM implementation, the
> granule size
> is fixed to be 4KB at present. I'm not sure if I have looked into
> correct RMM
> implementation, but 'topics/rmm-v2.0-poc_2' is recommended one in the cover
> letter.
>
You are right. The tf-RMM only supports 4KB. The policy at the KVM host
is to set the Linux PAGE_SIZE for the GRANULE_SIZE (at least for now).
If the RMM doesn't support the PAGE_SIZE, we don't support the RMM.
> Besides, there has checks in the handler of the RMI command to make sure
> that
> struct rmm_config::tracking_region_size to be 1GB, indicated by zero. It
> maybe
> worthy to set it before call to rmi_rmm_config_set().
>
> config.tracking_region_size = 0; /* 1GB */
Thanks, this explicit initialisation is missing, though in effect the
value is 0'd. Also, we can't really say 1GB here, because the driver
should work for an RMM capable of 64K. So, instead, may be we could :
/* See the definition of RMM_GRANULE_TRACKING_SIZE */
config.tracking_region_size = 0;
Suzuki
> ret = rmi_rmm_config_set(virt_to_phys(config));
>
>
>> + ret = rmi_rmm_activate();
>> + if (ret) {
>> + pr_err("RMM activate failed\n");
>> + return -ENXIO;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static int __init arm64_init_rmi(void)
>> {
>> /* Continue without realm support if we can't agree on a version */
>> @@ -60,6 +99,9 @@ static int __init arm64_init_rmi(void)
>> if (WARN_ON(rmi_features(1, &rmm_feat_reg1)))
>> return 0;
>> + if (rmi_configure())
>> + return 0;
>> +
>> return 0;
>> }
>> subsys_initcall(arm64_init_rmi);
>
> Thanks,
> Gavin
>
^ permalink raw reply
* Re: [PATCH] arm64: mm: call pagetable dtor when freeing hot-removed page tables
From: Andrew Morton @ 2026-05-21 22:31 UTC (permalink / raw)
To: Alistair Popple
Cc: linux-arm-kernel, linux-kernel, linux-mm, catalin.marinas, will,
david
In-Reply-To: <20260521032730.2104017-1-apopple@nvidia.com>
On Thu, 21 May 2026 13:27:30 +1000 Alistair Popple <apopple@nvidia.com> wrote:
> Since 5e8eb9aeeda3 ("arm64: mm: always call PTE/PMD ctor in
> __create_pgd_mapping()") page-table allocation on ARM64 always
> calls pagetable_{pte,pmd,pud,p4d}_ctor(). This sets the page_type
> to PGTY_table, increments NR_PAGETABLE and possible allocates a PTL.
> However the matching pagetable_dtor() calls were never added.
>
> With DEBUG_VM enabled on kernel versions prior to v6.17 without
> 2dfcd1608f3a9 ("mm/page_alloc: let page freeing clear any set page
> type") this leads to the following warning when freeing these pages due
> to page->page_type sharing page->_mapcount:
>
> BUG: Bad page state in process ... pfn:284fbb
> page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x284fbb
> flags: 0x17fffc000000000(node=0|zone=2|lastcpupid=0x1ffff)
> page_type: f2(table)
> page dumped because: nonzero mapcount
> Call trace:
> bad_page+0x13c/0x160
> __free_frozen_pages+0x6cc/0x860
> ___free_pages+0xf4/0x180
> free_pages+0x54/0x80
> free_hotplug_page_range.part.0+0x58/0x90
> free_empty_tables+0x438/0x500
> __remove_pgd_mapping.constprop.0+0x60/0xa8
> arch_remove_memory+0x48/0x80
> try_remove_memory+0x158/0x1d8
> offline_and_remove_memory+0x138/0x180
>
> It can also lead to leaking the ptl allocation if ALLOC_SPLIT_PTLOCKS
> is defined and incorrect NR_PAGETABLE stats. Fix this by calling
> pagetable_dtor() in free_hotplug_pgtable_page() prior to freeing the
> page to undo the effects of calling pagetable_*_ctor().
>
> Fixes: 5e8eb9aeeda3 ("arm64: mm: always call PTE/PMD ctor in __create_pgd_mapping()")
6.16+, so I assume we want cc:stable here.
> arch/arm64/mm/mmu.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 8e1d80a7033e..0c24fe650e95 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1422,6 +1422,7 @@ static void free_hotplug_page_range(struct page *page, size_t size,
>
> static void free_hotplug_pgtable_page(struct page *page)
> {
> + pagetable_dtor(page_ptdesc(page));
> free_hotplug_page_range(page, PAGE_SIZE, NULL);
> }
I'd of course prefer that arm maintainers handle this. But
5e8eb9aeeda3 came via myself so convention kinda-dictates that I get to
fix it.
^ permalink raw reply
* Re: [PATCH v6 1/3] PCI: Add pci_ats_required() for CXL.cache capable devices
From: Nicolin Chen @ 2026-05-21 21:59 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: jgg, will, robin.murphy, joro, bhelgaas, praan, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
linux-cxl, nirmoyd
In-Reply-To: <20260521213123.GA186424@bhelgaas>
On Thu, May 21, 2026 at 04:31:23PM -0500, Bjorn Helgaas wrote:
> On Thu, May 21, 2026 at 02:07:34PM -0700, Nicolin Chen wrote:
> > On Thu, May 21, 2026 at 03:57:23PM -0500, Bjorn Helgaas wrote:
> > > On Thu, May 21, 2026 at 01:34:20PM -0700, Nicolin Chen wrote:
> > > > +bool pci_ats_required(struct pci_dev *pdev)
> > > > +{
> > > > + if (!pci_ats_supported(pdev))
> > > > + return false;
> > > > +
> > > > + /* A VF inherits its PF's requirement for ATS function */
> > > > + if (pdev->is_virtfn)
> > > > + pdev = pci_physfn(pdev);
> > > > +
> > > > + return pci_cxl_ats_required(pdev);
> > >
> > > I acked this before I saw this sashiko feedback, which looks like a
> > > legit issue to me:
> > >
> > > Will this VF inheritance logic ever be reached?
> > >
> > > According to the PCIe SR-IOV specification (section 9.3.3.1), VFs do
> > > not implement the ATS Extended Capability, which means pdev->ats_cap
> > > is always 0 for VFs.
>
> Huh. I wish sashiko would include the spec revision because that sure
> looks wrong. In PCIe r7.0, there is no sec 9.3.3.1. In PCIe r6.0,
> sec 9.3.3.1 is the SR-IOV Extended Capability, which doesn't mention
> ATS. In both, sec 10.5.1 is the ATS Extended Capability and says both
> PFs and VFs can implement it.
I am glad you checked the spec. I should have done the same.
> So I think this is OK as-is:
>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Thanks!
Nicolin
^ permalink raw reply
* Re: [PATCH v11 1/2] kunit: add tests for smp_cond_load_*_timeout()
From: Mark Brown @ 2026-05-21 21:57 UTC (permalink / raw)
To: Andrew Morton
Cc: Ankur Arora, linux-kernel, linux-arch, linux-arm-kernel, linux-pm,
linux-next, bpf, arnd, catalin.marinas, will, peterz,
mark.rutland, harisokn, cl, ast, rafael, daniel.lezcano, memxor,
zhenglifeng1, xueshuai, rdunlap, david.laight.linux,
joao.m.martins, boris.ostrovsky, konrad.wilk, ashok.bhat,
Boqun Feng, Boqun Feng, Christoph Lameter, Ingo Molnar,
Konrad Dybcio
In-Reply-To: <20260521144629.11ee1e2ff88c5387a589f54a@linux-foundation.org>
[-- Attachment #1: Type: text/plain, Size: 367 bytes --]
On Thu, May 21, 2026 at 02:46:29PM -0700, Andrew Morton wrote:
> Anyway, I removed the series "barrier: Add
> smp_cond_load_{relaxed,acquire}_timeout()" from mm.git on May 19 for
> forgotten reasons. So I suggest that the series be respun and resent,
> with these two test patches included.
The tests were failing on arm64 when run on hardware (rather than qemu).
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v11 1/2] kunit: add tests for smp_cond_load_*_timeout()
From: Andrew Morton @ 2026-05-21 21:46 UTC (permalink / raw)
To: Ankur Arora
Cc: linux-kernel, linux-arch, linux-arm-kernel, linux-pm, linux-next,
bpf, arnd, catalin.marinas, will, peterz, mark.rutland, harisokn,
cl, ast, rafael, daniel.lezcano, memxor, zhenglifeng1, xueshuai,
rdunlap, david.laight.linux, joao.m.martins, boris.ostrovsky,
konrad.wilk, ashok.bhat, Boqun Feng, Boqun Feng,
Christoph Lameter, Ingo Molnar, Konrad Dybcio, Mark Brown
In-Reply-To: <20260521083038.134260-1-ankur.a.arora@oracle.com>
On Thu, 21 May 2026 01:30:37 -0700 Ankur Arora <ankur.a.arora@oracle.com> wrote:
> Add success and failure case tests for smp_cond_load_*_timeout().
>
> All of the test cases wait on some state in smp_cond_load_*_timeout().
> In the success case we spawn a kthread that pokes the bit.
>
> Success or failure cases depend on the expected bit being set (or not).
> Additionally in failure cases smp_cond_load_*_timeout() cannot return
> before timeout.
Your title "kunit: ..." implies that this is a kunit patchset. ie, and
to my mind, this implies that the patchset makes changes to kunit
infrastructure. This isn't the case, of course.
>
> ...
>
> +config BARRIER_TIMEOUT_TEST
> + tristate "KUnit tests for smp_cond_load_relaxed_timeout()"
The patchset which attempted to add smp_cond_load_relaxed_timeout() was
titled "barrier: ...", which is a more appropriate identifier for this
patchset.
Anyway, I removed the series "barrier: Add
smp_cond_load_{relaxed,acquire}_timeout()" from mm.git on May 19 for
forgotten reasons. So I suggest that the series be respun and resent,
with these two test patches included.
Again, I'm really not the guy to be handling these patches. But a 4-6%
performance improvement in real world workloads is not to be ignored.
Not by me, anyway.
^ permalink raw reply
* Re: [PATCH v6 1/3] PCI: Add pci_ats_required() for CXL.cache capable devices
From: Bjorn Helgaas @ 2026-05-21 21:31 UTC (permalink / raw)
To: Nicolin Chen
Cc: jgg, will, robin.murphy, joro, bhelgaas, praan, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
linux-cxl, nirmoyd
In-Reply-To: <ag90FlOaljwa0qqU@Asurada-Nvidia>
On Thu, May 21, 2026 at 02:07:34PM -0700, Nicolin Chen wrote:
> On Thu, May 21, 2026 at 03:57:23PM -0500, Bjorn Helgaas wrote:
> > On Thu, May 21, 2026 at 01:34:20PM -0700, Nicolin Chen wrote:
> > > +bool pci_ats_required(struct pci_dev *pdev)
> > > +{
> > > + if (!pci_ats_supported(pdev))
> > > + return false;
> > > +
> > > + /* A VF inherits its PF's requirement for ATS function */
> > > + if (pdev->is_virtfn)
> > > + pdev = pci_physfn(pdev);
> > > +
> > > + return pci_cxl_ats_required(pdev);
> >
> > I acked this before I saw this sashiko feedback, which looks like a
> > legit issue to me:
> >
> > Will this VF inheritance logic ever be reached?
> >
> > According to the PCIe SR-IOV specification (section 9.3.3.1), VFs do
> > not implement the ATS Extended Capability, which means pdev->ats_cap
> > is always 0 for VFs.
Huh. I wish sashiko would include the spec revision because that sure
looks wrong. In PCIe r7.0, there is no sec 9.3.3.1. In PCIe r6.0,
sec 9.3.3.1 is the SR-IOV Extended Capability, which doesn't mention
ATS. In both, sec 10.5.1 is the ATS Extended Capability and says both
PFs and VFs can implement it.
So I think this is OK as-is:
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
^ permalink raw reply
* Re: [PATCH] ARM: rockchip: keep reset control around
From: Heiko Stuebner @ 2026-05-21 21:13 UTC (permalink / raw)
To: Heiko Stuebner
Cc: linux-arm-kernel, linux-rockchip, Philipp Zabel, Steven Price,
Bartosz Golaszewski
In-Reply-To: <20260521210915.2331176-1-heiko@sntech.de>
Am Donnerstag, 21. Mai 2026, 23:09:15 Mitteleuropäische Sommerzeit schrieb Heiko Stuebner:
> Do not put the reset control, retain exclusive control over it.
> After turning on a CPU, the corresponding reset line must stay
> deasserted.
>
> This also avoids calling reset_control_put() before workqueues
> are operational.
>
> Fixes: 78ebbff6d1a0 ("reset: handle removing supplier before consumers")
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Tested-by: Steven Price <steven.price@arm.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Forgot to add Bartosz to the Cc list, sorry
Heiko
> ---
> arch/arm/mach-rockchip/platsmp.c | 16 ++++++++++------
> 1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index f432d22bfed8..f659d894bfae 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -34,6 +34,7 @@ static int ncores;
>
> static struct regmap *pmu;
> static int has_pmu = true;
> +static struct reset_control *cpu_rstc[4];
>
> static int pmu_power_domain_is_on(int pd)
> {
> @@ -64,9 +65,11 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
> static int pmu_set_power_domain(int pd, bool on)
> {
> u32 val = (on) ? 0 : BIT(pd);
> - struct reset_control *rstc = rockchip_get_core_reset(pd);
> + struct reset_control *rstc;
> int ret;
>
> + rstc = pd < ARRAY_SIZE(cpu_rstc) ? cpu_rstc[pd] : ERR_PTR(-EINVAL);
> +
> if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> pr_err("%s: could not get reset control for core %d\n",
> __func__, pd);
> @@ -100,11 +103,8 @@ static int pmu_set_power_domain(int pd, bool on)
> }
> }
>
> - if (!IS_ERR(rstc)) {
> - if (on)
> - reset_control_deassert(rstc);
> - reset_control_put(rstc);
> - }
> + if (!IS_ERR(rstc) && on)
> + reset_control_deassert(rstc);
>
> return 0;
> }
> @@ -312,6 +312,10 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
> ncores = ((l2ctlr >> 24) & 0x3) + 1;
> }
>
> + /* Collect cpu core reset control for each core */
> + for (i = 0; i < ncores; i++)
> + cpu_rstc[i] = rockchip_get_core_reset(i);
> +
> /* Make sure that all cores except the first are really off */
> for (i = 1; i < ncores; i++)
> pmu_set_power_domain(0 + i, false);
>
^ permalink raw reply
* [PATCH] ARM: rockchip: keep reset control around
From: Heiko Stuebner @ 2026-05-21 21:09 UTC (permalink / raw)
To: heiko; +Cc: linux-arm-kernel, linux-rockchip, Philipp Zabel, Steven Price
Do not put the reset control, retain exclusive control over it.
After turning on a CPU, the corresponding reset line must stay
deasserted.
This also avoids calling reset_control_put() before workqueues
are operational.
Fixes: 78ebbff6d1a0 ("reset: handle removing supplier before consumers")
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Tested-by: Steven Price <steven.price@arm.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-rockchip/platsmp.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index f432d22bfed8..f659d894bfae 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -34,6 +34,7 @@ static int ncores;
static struct regmap *pmu;
static int has_pmu = true;
+static struct reset_control *cpu_rstc[4];
static int pmu_power_domain_is_on(int pd)
{
@@ -64,9 +65,11 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
static int pmu_set_power_domain(int pd, bool on)
{
u32 val = (on) ? 0 : BIT(pd);
- struct reset_control *rstc = rockchip_get_core_reset(pd);
+ struct reset_control *rstc;
int ret;
+ rstc = pd < ARRAY_SIZE(cpu_rstc) ? cpu_rstc[pd] : ERR_PTR(-EINVAL);
+
if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
pr_err("%s: could not get reset control for core %d\n",
__func__, pd);
@@ -100,11 +103,8 @@ static int pmu_set_power_domain(int pd, bool on)
}
}
- if (!IS_ERR(rstc)) {
- if (on)
- reset_control_deassert(rstc);
- reset_control_put(rstc);
- }
+ if (!IS_ERR(rstc) && on)
+ reset_control_deassert(rstc);
return 0;
}
@@ -312,6 +312,10 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
ncores = ((l2ctlr >> 24) & 0x3) + 1;
}
+ /* Collect cpu core reset control for each core */
+ for (i = 0; i < ncores; i++)
+ cpu_rstc[i] = rockchip_get_core_reset(i);
+
/* Make sure that all cores except the first are really off */
for (i = 1; i < ncores; i++)
pmu_set_power_domain(0 + i, false);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v6 1/3] PCI: Add pci_ats_required() for CXL.cache capable devices
From: Nicolin Chen @ 2026-05-21 21:07 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: jgg, will, robin.murphy, joro, bhelgaas, praan, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
linux-cxl, nirmoyd
In-Reply-To: <20260521205723.GA184317@bhelgaas>
On Thu, May 21, 2026 at 03:57:23PM -0500, Bjorn Helgaas wrote:
> On Thu, May 21, 2026 at 01:34:20PM -0700, Nicolin Chen wrote:
> > +bool pci_ats_required(struct pci_dev *pdev)
> > +{
> > + if (!pci_ats_supported(pdev))
> > + return false;
> > +
> > + /* A VF inherits its PF's requirement for ATS function */
> > + if (pdev->is_virtfn)
> > + pdev = pci_physfn(pdev);
> > +
> > + return pci_cxl_ats_required(pdev);
>
> I acked this before I saw this sashiko feedback, which looks like a
> legit issue to me:
>
> Will this VF inheritance logic ever be reached?
>
> According to the PCIe SR-IOV specification (section 9.3.3.1), VFs do
> not implement the ATS Extended Capability, which means pdev->ats_cap
> is always 0 for VFs.
>
> Because of this, pci_ats_supported(pdev) will unconditionally return
> false for any VF. This causes the function to return false before it
> can ever reach the pdev->is_virtfn check.
>
> Could this prevent VFs from correctly enabling the ATS always on
> feature and leave them unable to access host memory without
> triggering IOMMU faults?
>
> (From https://sashiko.dev/#/patchset/cover.1779304390.git.nicolinc%40nvidia.com)
>
> I withdraw my ack for now until we figure out if it's a real issue.
I did a bit of research here.
The existing pci_enable_ats() checks:
if (!pci_ats_supported(dev))
return -EINVAL;
at the top, prior to:
if (dev->is_virtfn) {
pdev = pci_physfn(dev);
if (pdev->ats_stu != ps)
return -EINVAL;
So, VF must *support* ATS (its ats_cap must be !0) so as to turn
on ATS, instead of relying on the PF's ats_cap.
IOW, Sashiko's comment "which means pdev->ats_cap is always 0 for
VFs" is wrong.
So, I kept the same order in this new pci_ats_required().
FWIW, I also did an inverted version and asked Sashiko to review:
====================================================================
> @@ -205,6 +205,52 @@ int pci_ats_page_aligned(struct pci_dev *pdev)
[ ... ]
> +bool pci_ats_required(struct pci_dev *pdev)
> +{
> + /* A VF inherits its PF's requirement for ATS function */
> + if (pdev->is_virtfn)
> + pdev = pci_physfn(pdev);
> +
> + if (!pci_ats_supported(pdev))
> + return false;
This isn't a bug, but it looks like these two lines are indented with spaces
instead of tabs.
Also, since pdev is reassigned to pci_physfn(pdev) before checking ATS
support, does this incorrectly check the ATS capability of the PF rather than
the VF?
If a VF has its ATS support explicitly disabled (for example, via PCIe quirks
that set vf->ats_cap = 0), this check might bypass the VF's specific
properties and incorrectly return true based on the PF's capabilities.
Consequently, if a caller attempts to enable ATS on the VF by calling
pci_enable_ats(), it will fail because pci_enable_ats() correctly checks
pci_ats_supported() against the VF.
Would it be better to evaluate pci_ats_supported() on the original pdev
before reassigning it to the PF?
====================================================================
What would you like me to do, Bjorn?
Nicolin
^ permalink raw reply
* Re: [PATCH v6 1/3] PCI: Add pci_ats_required() for CXL.cache capable devices
From: Bjorn Helgaas @ 2026-05-21 20:57 UTC (permalink / raw)
To: Nicolin Chen
Cc: jgg, will, robin.murphy, joro, bhelgaas, praan, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
linux-cxl, nirmoyd
In-Reply-To: <05044d2113e20d81f96677ba53605311662b6b10.1779392420.git.nicolinc@nvidia.com>
On Thu, May 21, 2026 at 01:34:20PM -0700, Nicolin Chen wrote:
> Controlled by IOMMU drivers, ATS can be enabled "on demand", when a given
> PASID on a device is attached to an I/O page table. This is working, even
> when a device has no translation on its RID (i.e., RID is IOMMU bypassed).
>
> However, certain PCIe devices require non-PASID ATS on their RID even when
> the RID is IOMMU bypassed. Call this "ATS always on" in IOMMU term.
>
> For example, CXL spec r4.0 notes in sec 3.2.5.13 Memory Type on CXL.cache:
> "To source requests on CXL.cache, devices need to get the Host Physical
> Address (HPA) from the Host by means of an ATS request on CXL.io."
>
> In other words, the CXL.cache capability requires ATS; otherwise, it can't
> access host physical memory.
>
> Introduce a new pci_ats_required() helper for the IOMMU driver to scan a
> PCI device and shift ATS policies between "on demand" and "always on".
>
> Add the support for CXL.cache devices first. Pre-CXL devices will be added
> in quirks.c file.
>
> Note that pci_ats_required() validates against pci_ats_supported(), so we
> ensure that untrusted devices (e.g. external ports) will not be always on.
> This maintains the existing ATS security policy regarding potential side-
> channel attacks via ATS.
>
> Cc: linux-cxl@vger.kernel.org
> Suggested-by: Vikram Sethi <vsethi@nvidia.com>
> Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Tested-by: Nirmoy Das <nirmoyd@nvidia.com>
> Acked-by: Nirmoy Das <nirmoyd@nvidia.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> ...
> +bool pci_ats_required(struct pci_dev *pdev)
> +{
> + if (!pci_ats_supported(pdev))
> + return false;
> +
> + /* A VF inherits its PF's requirement for ATS function */
> + if (pdev->is_virtfn)
> + pdev = pci_physfn(pdev);
> +
> + return pci_cxl_ats_required(pdev);
I acked this before I saw this sashiko feedback, which looks like a
legit issue to me:
Will this VF inheritance logic ever be reached?
According to the PCIe SR-IOV specification (section 9.3.3.1), VFs do
not implement the ATS Extended Capability, which means pdev->ats_cap
is always 0 for VFs.
Because of this, pci_ats_supported(pdev) will unconditionally return
false for any VF. This causes the function to return false before it
can ever reach the pdev->is_virtfn check.
Could this prevent VFs from correctly enabling the ATS always on
feature and leave them unable to access host memory without
triggering IOMMU faults?
(From https://sashiko.dev/#/patchset/cover.1779304390.git.nicolinc%40nvidia.com)
I withdraw my ack for now until we figure out if it's a real issue.
> +}
> +EXPORT_SYMBOL_GPL(pci_ats_required);
> +
> #ifdef CONFIG_PCI_PRI
> void pci_pri_init(struct pci_dev *pdev)
> {
> --
> 2.43.0
>
^ permalink raw reply
* [PATCH v6 3/3] iommu/arm-smmu-v3: Allow ATS to be always on
From: Nicolin Chen @ 2026-05-21 20:34 UTC (permalink / raw)
To: jgg, will
Cc: robin.murphy, joro, bhelgaas, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
In-Reply-To: <cover.1779392420.git.nicolinc@nvidia.com>
When a device's default substream attaches to an identity domain, the SMMU
driver currently sets the device's STE between two modes:
Mode 1: Cfg=Translate, S1DSS=Bypass, EATS=1
Mode 2: Cfg=bypass (EATS is ignored by HW)
When there is an active PASID (non-default substream), mode 1 is used. And
when there is no PASID support or no active PASID, mode 2 is used.
The driver will also downgrade an STE from mode 1 to mode 2, when the last
active substream becomes inactive.
However, there are PCIe devices that demand ATS to be always on. For these
devices, their STEs have to use the mode 1 as HW ignores EATS with mode 2.
Change the driver accordingly:
- always use the mode 1
- never downgrade to mode 2
- allocate and retain a CD table (see note below)
Note that these devices might not support PASID, i.e. doing non-PASID ATS.
In such a case, the ssid_bits is set to 0. However, s1cdmax must be set to
a !0 value in order to keep the S1DSS field effective. Thus, when a master
requires ats_always_on, set its s1cdmax to at least 1, meaning that the CD
table will have a dummy entry (SSID=1) that will never be used.
Now for these devices, arm_smmu_cdtab_allocated() will always return true,
v.s. false prior to this change. When its default substream is attached to
an IDENTITY domain, its first CD is NULL in the table, which is a totally
valid case. Thus, add "!master->ats_always_on" to the condition.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Tested-by: Nirmoy Das <nirmoyd@nvidia.com>
Acked-by: Nirmoy Das <nirmoyd@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 81 ++++++++++++++++++---
2 files changed, 73 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index ef42df4753ec4..8c3600f4364c5 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -943,6 +943,7 @@ struct arm_smmu_master {
bool ats_enabled : 1;
bool ste_ats_enabled : 1;
bool stall_enabled;
+ bool ats_always_on;
unsigned int ssid_bits;
unsigned int iopf_refcount;
};
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e8d7dbe495f03..4afdb775e0722 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1742,8 +1742,11 @@ void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)
if (!arm_smmu_cdtab_allocated(&master->cd_table))
return;
cdptr = arm_smmu_get_cd_ptr(master, ssid);
- if (WARN_ON(!cdptr))
+ if (!cdptr) {
+ /* Only ats_always_on allows a NULL CD on default substream */
+ WARN_ON(!master->ats_always_on || ssid);
return;
+ }
arm_smmu_write_cd_entry(master, ssid, cdptr, &target);
}
@@ -1756,6 +1759,22 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
cd_table->s1cdmax = master->ssid_bits;
+
+ /*
+ * When a device doesn't support PASID (non default SSID), ssid_bits is
+ * set to 0. This also sets S1CDMAX to 0, which disables the substreams
+ * and ignores the S1DSS field.
+ *
+ * On the other hand, if a device demands ATS to be always on even when
+ * its default substream is IOMMU bypassed, it has to use EATS that is
+ * only effective with an STE (CFG=S1translate, S1DSS=Bypass). For such
+ * use cases, S1CDMAX has to be !0, in order to make use of S1DSS/EATS.
+ *
+ * Set S1CDMAX no lower than 1. This would add a dummy substream in the
+ * CD table but it should never be used by an actual CD.
+ */
+ if (master->ats_always_on)
+ cd_table->s1cdmax = max_t(u8, cd_table->s1cdmax, 1);
max_contexts = 1 << cd_table->s1cdmax;
if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
@@ -3854,9 +3873,12 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,
if (!arm_smmu_ssids_in_use(&master->cd_table)) {
struct iommu_domain *sid_domain =
iommu_driver_get_domain_for_dev(master->dev);
+ bool ats_always_on = master->ats_always_on &&
+ sid_domain->type != IOMMU_DOMAIN_BLOCKED;
+ bool downgrade = sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
+ sid_domain->type == IOMMU_DOMAIN_BLOCKED;
- if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
- sid_domain->type == IOMMU_DOMAIN_BLOCKED)
+ if (!ats_always_on && downgrade)
sid_domain->ops->attach_dev(sid_domain, dev,
sid_domain);
}
@@ -3875,6 +3897,8 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
.old_domain = old_domain,
.ssid = IOMMU_NO_PASID,
};
+ bool ats_always_on = master->ats_always_on &&
+ s1dss != STRTAB_STE_1_S1DSS_TERMINATE;
/*
* Do not allow any ASID to be changed while are working on the STE,
@@ -3886,7 +3910,7 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
* If the CD table is not in use we can use the provided STE, otherwise
* we use a cdtable STE with the provided S1DSS.
*/
- if (arm_smmu_ssids_in_use(&master->cd_table)) {
+ if (ats_always_on || arm_smmu_ssids_in_use(&master->cd_table)) {
/*
* If a CD table has to be present then we need to run with ATS
* on because we have to assume a PASID is using ATS. For
@@ -4215,6 +4239,44 @@ static void arm_smmu_remove_master(struct arm_smmu_master *master)
kfree(master->build_invs);
}
+static int arm_smmu_master_prepare_ats(struct arm_smmu_master *master)
+{
+ bool s1p = master->smmu->features & ARM_SMMU_FEAT_TRANS_S1;
+ unsigned int stu = __ffs(master->smmu->pgsize_bitmap);
+ struct pci_dev *pdev;
+ int ret;
+
+ if (!dev_is_pci(master->dev))
+ return 0;
+ pdev = to_pci_dev(master->dev);
+
+ if (!arm_smmu_ats_supported(master)) {
+ if (pci_ats_required(pdev)) {
+ dev_err_once(master->dev, "SMMU doesn't support ATS\n");
+ return -EOPNOTSUPP;
+ }
+ return 0;
+ }
+
+ ret = pci_prepare_ats(pdev, stu);
+ if (ret || !pci_ats_required(pdev))
+ return ret;
+
+ /*
+ * S1DSS is required for ATS to be always on for identity domain cases.
+ * However, the S1DSS field is ignored if !IDR0_S1P or !IDR1_SSIDSIZE.
+ */
+ if (!s1p || !master->smmu->ssid_bits) {
+ dev_err_once(master->dev,
+ "SMMU doesn't support ATS to be always on\n");
+ return -EOPNOTSUPP;
+ }
+
+ master->ats_always_on = true;
+
+ return arm_smmu_alloc_cd_tables(master);
+}
+
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
{
int ret;
@@ -4263,14 +4325,15 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
master->stall_enabled = true;
- if (dev_is_pci(dev)) {
- unsigned int stu = __ffs(smmu->pgsize_bitmap);
-
- pci_prepare_ats(to_pci_dev(dev), stu);
- }
+ ret = arm_smmu_master_prepare_ats(master);
+ if (ret)
+ goto err_disable_pasid;
return &smmu->iommu;
+err_disable_pasid:
+ arm_smmu_disable_pasid(master);
+ arm_smmu_remove_master(master);
err_free_master:
kfree(master);
return ERR_PTR(ret);
--
2.43.0
^ permalink raw reply related
* [PATCH v6 1/3] PCI: Add pci_ats_required() for CXL.cache capable devices
From: Nicolin Chen @ 2026-05-21 20:34 UTC (permalink / raw)
To: jgg, will
Cc: robin.murphy, joro, bhelgaas, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
In-Reply-To: <cover.1779392420.git.nicolinc@nvidia.com>
Controlled by IOMMU drivers, ATS can be enabled "on demand", when a given
PASID on a device is attached to an I/O page table. This is working, even
when a device has no translation on its RID (i.e., RID is IOMMU bypassed).
However, certain PCIe devices require non-PASID ATS on their RID even when
the RID is IOMMU bypassed. Call this "ATS always on" in IOMMU term.
For example, CXL spec r4.0 notes in sec 3.2.5.13 Memory Type on CXL.cache:
"To source requests on CXL.cache, devices need to get the Host Physical
Address (HPA) from the Host by means of an ATS request on CXL.io."
In other words, the CXL.cache capability requires ATS; otherwise, it can't
access host physical memory.
Introduce a new pci_ats_required() helper for the IOMMU driver to scan a
PCI device and shift ATS policies between "on demand" and "always on".
Add the support for CXL.cache devices first. Pre-CXL devices will be added
in quirks.c file.
Note that pci_ats_required() validates against pci_ats_supported(), so we
ensure that untrusted devices (e.g. external ports) will not be always on.
This maintains the existing ATS security policy regarding potential side-
channel attacks via ATS.
Cc: linux-cxl@vger.kernel.org
Suggested-by: Vikram Sethi <vsethi@nvidia.com>
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Tested-by: Nirmoy Das <nirmoyd@nvidia.com>
Acked-by: Nirmoy Das <nirmoyd@nvidia.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
include/linux/pci-ats.h | 3 +++
include/uapi/linux/pci_regs.h | 1 +
drivers/pci/ats.c | 46 +++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+)
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
index 75c6c86cf09dc..f3723b6861294 100644
--- a/include/linux/pci-ats.h
+++ b/include/linux/pci-ats.h
@@ -12,6 +12,7 @@ int pci_prepare_ats(struct pci_dev *dev, int ps);
void pci_disable_ats(struct pci_dev *dev);
int pci_ats_queue_depth(struct pci_dev *dev);
int pci_ats_page_aligned(struct pci_dev *dev);
+bool pci_ats_required(struct pci_dev *dev);
#else /* CONFIG_PCI_ATS */
static inline bool pci_ats_supported(struct pci_dev *d)
{ return false; }
@@ -24,6 +25,8 @@ static inline int pci_ats_queue_depth(struct pci_dev *d)
{ return -ENODEV; }
static inline int pci_ats_page_aligned(struct pci_dev *dev)
{ return 0; }
+static inline bool pci_ats_required(struct pci_dev *dev)
+{ return false; }
#endif /* CONFIG_PCI_ATS */
#ifdef CONFIG_PCI_PRI
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 14f634ab9350d..6ac45be1008b8 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1349,6 +1349,7 @@
/* CXL r4.0, 8.1.3: PCIe DVSEC for CXL Device */
#define PCI_DVSEC_CXL_DEVICE 0
#define PCI_DVSEC_CXL_CAP 0xA
+#define PCI_DVSEC_CXL_CACHE_CAPABLE _BITUL(0)
#define PCI_DVSEC_CXL_MEM_CAPABLE _BITUL(2)
#define PCI_DVSEC_CXL_HDM_COUNT __GENMASK(5, 4)
#define PCI_DVSEC_CXL_CTRL 0xC
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index ec6c8dbdc5e9c..84cd06d74fc9c 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -205,6 +205,52 @@ int pci_ats_page_aligned(struct pci_dev *pdev)
return 0;
}
+/*
+ * CXL r4.0, sec 3.2.5.13 Memory Type on CXL.cache notes: to source requests on
+ * CXL.cache, devices need to get the Host Physical Address (HPA) from the Host
+ * by means of an ATS request on CXL.io.
+ *
+ * In other words, CXL.cache devices cannot access host physical memory without
+ * ATS.
+ *
+ * Check Cache_Capable instead of Cache_Enable because CXL.cache may be enabled
+ * after the caller uses this to make its ATS decision.
+ */
+static bool pci_cxl_ats_required(struct pci_dev *pdev)
+{
+ int offset;
+ u16 cap;
+
+ offset = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
+ PCI_DVSEC_CXL_DEVICE);
+ if (!offset)
+ return false;
+
+ if (pci_read_config_word(pdev, offset + PCI_DVSEC_CXL_CAP, &cap))
+ return false;
+
+ return cap & PCI_DVSEC_CXL_CACHE_CAPABLE;
+}
+
+/**
+ * pci_ats_required - Whether the PCI device requires ATS
+ * @pdev: the PCI device
+ *
+ * Returns true, if the PCI device requires ATS for basic functional operation.
+ */
+bool pci_ats_required(struct pci_dev *pdev)
+{
+ if (!pci_ats_supported(pdev))
+ return false;
+
+ /* A VF inherits its PF's requirement for ATS function */
+ if (pdev->is_virtfn)
+ pdev = pci_physfn(pdev);
+
+ return pci_cxl_ats_required(pdev);
+}
+EXPORT_SYMBOL_GPL(pci_ats_required);
+
#ifdef CONFIG_PCI_PRI
void pci_pri_init(struct pci_dev *pdev)
{
--
2.43.0
^ permalink raw reply related
* [PATCH v6 2/3] PCI: Allow ATS to be always on for pre-CXL devices
From: Nicolin Chen @ 2026-05-21 20:34 UTC (permalink / raw)
To: jgg, will
Cc: robin.murphy, joro, bhelgaas, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
In-Reply-To: <cover.1779392420.git.nicolinc@nvidia.com>
Some NVIDIA GPU/NIC devices, though they don't implement CXL config space,
have many CXL-like properties. Call this kind "pre-CXL".
Similar to CXL.cache capability, these pre-CXL devices also require the ATS
function even when their RIDs are IOMMU bypassed, i.e. keep ATS "always on"
v.s. "on demand" when a non-zero PASID line gets enabled in SVA use cases.
Introduce pci_dev_specific_ats_required() quirk function to scan a list of
IDs for these devices. Then, include it in pci_ats_required().
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nirmoy Das <nirmoyd@nvidia.com>
Tested-by: Nirmoy Das <nirmoyd@nvidia.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/pci/pci.h | 9 +++++++++
drivers/pci/ats.c | 3 ++-
drivers/pci/quirks.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4a14f88e543a2..e8ad27abb1cfe 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1155,6 +1155,15 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, bool probe)
}
#endif
+#if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_PCI_ATS)
+bool pci_dev_specific_ats_required(struct pci_dev *dev);
+#else
+static inline bool pci_dev_specific_ats_required(struct pci_dev *dev)
+{
+ return false;
+}
+#endif
+
#if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_ARM64)
int acpi_get_rc_resources(struct device *dev, const char *hid, u16 segment,
struct resource *res);
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index 84cd06d74fc9c..96efa00d97433 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -247,7 +247,8 @@ bool pci_ats_required(struct pci_dev *pdev)
if (pdev->is_virtfn)
pdev = pci_physfn(pdev);
- return pci_cxl_ats_required(pdev);
+ return pci_cxl_ats_required(pdev) ||
+ pci_dev_specific_ats_required(pdev);
}
EXPORT_SYMBOL_GPL(pci_ats_required);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index caaed1a01dc02..c0242f3e9f063 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -5715,6 +5715,48 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1457, quirk_intel_e2000_no_ats);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1459, quirk_intel_e2000_no_ats);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145a, quirk_intel_e2000_no_ats);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145c, quirk_intel_e2000_no_ats);
+
+static bool quirk_nvidia_gpu_ats_required(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case 0x2e00 ... 0x2e3f: /* GB20B */
+ return true;
+ }
+ return false;
+}
+
+static const struct pci_dev_ats_required {
+ u16 vendor;
+ u16 device;
+ bool (*ats_required)(struct pci_dev *dev);
+} pci_dev_ats_required[] = {
+ /* NVIDIA GPUs */
+ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, quirk_nvidia_gpu_ats_required },
+ /* NVIDIA CX10 Family NVlink-C2C */
+ { PCI_VENDOR_ID_MELLANOX, 0x2101, NULL },
+ { 0 }
+};
+
+/*
+ * Some NVIDIA devices do not implement CXL config space, but present as PCIe
+ * devices that can issue CXL-like cache operations like CXL.cache. Thus, they
+ * require ATS to obtain host physical addresses, like pci_cxl_ats_required().
+ */
+bool pci_dev_specific_ats_required(struct pci_dev *pdev)
+{
+ const struct pci_dev_ats_required *i;
+
+ for (i = pci_dev_ats_required; i->vendor; i++) {
+ if (i->vendor != pdev->vendor)
+ continue;
+ if (i->ats_required && i->ats_required(pdev))
+ return true;
+ if (!i->ats_required && i->device == pdev->device)
+ return true;
+ }
+
+ return false;
+}
#endif /* CONFIG_PCI_ATS */
/* Freescale PCIe doesn't support MSI in RC mode */
--
2.43.0
^ permalink raw reply related
* [PATCH v6 0/3] Allow ATS to be always on for certain ATS-capable devices
From: Nicolin Chen @ 2026-05-21 20:34 UTC (permalink / raw)
To: jgg, will
Cc: robin.murphy, joro, bhelgaas, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
PCI ATS function is controlled by the IOMMU driver calling pci_enable_ats()
and pci_disable_ats() helpers. Depending on the driver implementation:
- ATS should be enabled when a translation channel is enabled on a PASID
(a typical SVA case).
- ATS should be disabled when the device's RID is IOMMU bypassed and its
PASIDs are not IOMMU-translated for any SVA use case.
However, certain PCIe devices require non-PASID ATS on the RID, even if the
RID is IOMMU bypassed. E.g. CXL.cache capability requires ATS to access the
physical memory; some pre-CXL NVIDIA GPUs also require the ATS to be always
on even when their RIDs are IOMMU bypassed.
Provide a helper function to detect CXL.cache capability and scan through a
pre-CXL device ID list.
As the initial use case, call the helper in ARM SMMUv3 driver and adapt the
driver accordingly with a per-device ats_always_on flag.
This is on Github:
https://github.com/nicolinc/iommufd/commits/pci_ats_always_on-v6
Changelog
v6
* Add Acked-by from Bjorn
* Slightly update commit message (Yi's comments)
* [pci] Drop the redundant pci_ats_disabled() check
* [smmu] Fix mismatched detach path against attach path
* [smmu] Propagate arm_smmu_master_prepare_ats() error code
v5
https://lore.kernel.org/all/cover.1779304390.git.nicolinc@nvidia.com/
* Add Reviewed-by from Dave
* Update comments in pci helpers
* s/pci_ats_always_on/pci_ats_required
* s/pci_cxl_ats_always_on/pci_cxl_ats_required
* s/pci_dev_specific_ats_always_on/pci_dev_specific_ats_required
v4
https://lore.kernel.org/all/cover.1777269009.git.nicolinc@nvidia.com/
* Rebase on v7.1-rc1
* Added Reviewed/Tested/Acked-by lines
* Update commit messages and inline comments
* [pci-quirks] Add range-based scan for NVIDIA GPUs
* [smmu] Add missing arm_smmu_remove_master() in error path
* [pci-ats] Don't init "cap=0"; check pci_read_config_word error
v3
https://lore.kernel.org/all/cover.1772833963.git.nicolinc@nvidia.com/
* Add Reviewed-by from Jonathan
* Update function kdocs of PCI APIs
* Simplify boolean return/variable computations
v2
https://lore.kernel.org/all/cover.1771886695.git.nicolinc@nvidia.com/
* s/non-CXL/pre-CXL
* Rebase on v7.0-rc1
* Update inline comments and commit message
* Add WARN_ON back at !ptr in arm_smmu_clear_cd()
* Add NVIDIA CX10 Family NVlink-C2C to the pre-CXL list
* Do not add boolean parameter to arm_smmu_attach_dev_ste()
v1
https://lore.kernel.org/all/cover.1768624180.git.nicolinc@nvidia.com/
Nicolin Chen (3):
PCI: Add pci_ats_required() for CXL.cache capable devices
PCI: Allow ATS to be always on for pre-CXL devices
iommu/arm-smmu-v3: Allow ATS to be always on
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
drivers/pci/pci.h | 9 +++
include/linux/pci-ats.h | 3 +
include/uapi/linux/pci_regs.h | 1 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 81 ++++++++++++++++++---
drivers/pci/ats.c | 47 ++++++++++++
drivers/pci/quirks.c | 42 +++++++++++
7 files changed, 175 insertions(+), 9 deletions(-)
--
2.43.0
^ permalink raw reply
* Re: [PATCH v4 1/1] dt-bindings: remoteproc: mtk,scp: Allow multiple memory regions for MT8188
From: Conor Dooley @ 2026-05-21 20:26 UTC (permalink / raw)
To: Arnab Layek
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, robh,
krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
andersson, mathieu.poirier, linux-remoteproc,
Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260520112629.3420612-2-arnab.layek@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 3781 bytes --]
On Wed, May 20, 2026 at 07:26:29PM +0800, Arnab Layek wrote:
> The MT8188 SCP can use either one or two reserved memory regions:
> - Required: Main SCP SRAM memory region (mandatory for SCP operation)
> - Optional: SCP L1TCM memory region (Level 1 Tightly Coupled Memory,
> used for performance optimization when available, but not required
> for basic SCP functionality)
>
> Other MediaTek SoCs (MT8183, MT8186, MT8192, MT8195) use only a single
> memory region and must remain restricted to one region for backward
> compatibility.
>
> Update the base schema to allow 1-2 memory regions (minItems: 1,
> maxItems: 2), following the pattern used by other MediaTek dt-bindings
> like mediatek,vcodec-encoder.yaml where the base property defines a
> permissive range accommodating all device variants.
>
> Add two conditionals:
> 1. Explicitly restrict non-MT8188 devices to maxItems: 1
> 2. Document MT8188's two regions with descriptions (minItems: 1 makes
> the L1TCM region optional, allowing boards to specify 1-2 regions
> based on hardware configuration)
>
> This approach maintains backward compatibility while enabling MT8188 to
> specify 1-2 memory regions depending on board design and performance
> requirements.
>
> Signed-off-by: Arnab Layek <arnab.layek@mediatek.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
Cheers,
Conor.
> ---
> .../bindings/remoteproc/mtk,scp.yaml | 45 ++++++++++++++++++-
> 1 file changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> index bdbb12118da4..fca9b0675eae 100644
> --- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> @@ -55,7 +55,8 @@ properties:
> initializing SCP.
>
> memory-region:
> - maxItems: 1
> + minItems: 1
> + maxItems: 2
>
> cros-ec-rpmsg:
> $ref: /schemas/embedded-controller/google,cros-ec.yaml
> @@ -123,7 +124,8 @@ patternProperties:
> initializing sub cores of multi-core SCP.
>
> memory-region:
> - maxItems: 1
> + minItems: 1
> + maxItems: 2
>
> cros-ec-rpmsg:
> $ref: /schemas/embedded-controller/google,cros-ec.yaml
> @@ -205,6 +207,45 @@ allOf:
> items:
> - const: cfg
> - const: l1tcm
> + - if:
> + properties:
> + compatible:
> + enum:
> + - mediatek,mt8183-scp
> + - mediatek,mt8186-scp
> + - mediatek,mt8192-scp
> + - mediatek,mt8195-scp
> + - mediatek,mt8195-scp-dual
> + then:
> + properties:
> + memory-region:
> + maxItems: 1
> + patternProperties:
> + "^scp@[a-f0-9]+$":
> + properties:
> + memory-region:
> + maxItems: 1
> + - if:
> + properties:
> + compatible:
> + enum:
> + - mediatek,mt8188-scp
> + - mediatek,mt8188-scp-dual
> + then:
> + properties:
> + memory-region:
> + minItems: 1
> + items:
> + - description: Main SCP SRAM memory region
> + - description: Optional SCP L1TCM memory region
> + patternProperties:
> + "^scp@[a-f0-9]+$":
> + properties:
> + memory-region:
> + minItems: 1
> + items:
> + - description: Main SCP SRAM memory region
> + - description: Optional SCP L1TCM memory region
>
> additionalProperties: false
>
> --
> 2.45.2
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v7 19/23] drm: bridge: dw_hdmi: Use delayed_work to debounce hotplug event
From: Jonas Karlman @ 2026-05-21 20:13 UTC (permalink / raw)
To: Neil Armstrong
Cc: Andrzej Hajda, Robert Foss, Heiko Stuebner, Laurent Pinchart,
Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Liu Ying,
Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <e584ab2b-677d-4893-95c9-7b68165633c6@linaro.org>
Hi Neil,
On 5/20/2026 11:58 AM, Neil Armstrong wrote:
> Hi,
>
> On 5/18/26 20:01, Jonas Karlman wrote:
>> HDMI Specification Version 1.4b chapter 8.5 mentions:
>>
>> An HDMI Sink shall not assert high voltage level on its Hot Plug
>> Detect pin when the E-EDID is not available for reading.
>>
>> A Source may use a high voltage level Hot Plug Detect signal to
>> initiate the reading of E-EDID data.
>>
>> An HDMI Sink shall indicate any change to the contents of the E-EDID
>> by driving a low voltage level pulse on the Hot Plug Detect pin. This
>> pulse shall be at least 100 msec.
>>
>> Use a delayed work to debounce reacting on HPD events to improve
>> handling of a HPD low voltage level pulse when a sink changes the EDID.
>>
>> The delayed work is only enabled between enable_hpd()/hpd_enable() and
>> disable_hpd()/hpd_disable() calls from core, i.e. enabled after
>> attach/bind/resume and disabled before detach/unbind/suspend.
>>
>> The 1100 msec hotplug debounce timeout was arbitrarily picked to match
>> other drivers using same const, and testing using a Raspberry Pi Monitor
>> seem to use a 200-300 msec pulse when going from standby to power on
>> state.
>
> The logic looks ok, but I'm puzzled by the 1.1 sec debounce, which after
> plugging in a monitor will only send an irq event after 1.1s which is very long.
>
> Since the spec says 100ms and the real worls values are more like 200-300ms,
> I would first reduce this to 500ms.
You are correct, this value was picked based on existing values used by
other drivers:
exynos/exynos_hdmi.c:#define HOTPLUG_DEBOUNCE_MS 1100
bridge/ti-tfp410.c:#define HOTPLUG_DEBOUNCE_MS 1100
amd/display/amdgpu_dm/amdgpu_dm.h:#define AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS 5000
rockchip/dw_hdmi_qp-rockchip.c:#define HOTPLUG_DEBOUNCE_MS 150
150 ms was too short for my test monitor (Raspberry Pi Monitor), it
does a HPD low voltage level pulse when powering on of around 200+ ms.
[82.641903] dw_hdmi_hardirq: EVENT=plugout
[82.841939] dw_hdmi_hardirq: EVENT=plugin
And on my LG OLED 4K TV there was typically a pulse of around 700-900 ms.
So the 1.1 seconds used by other drivers seemed like a good candidate :-)
> But as I understand the code right now, on the first HPD front the irq work
> is programmed to run after the debounce time, but if it's a pulse the irq would
> also trigger on the second HPD front and then delay again the work after the
> debounce time.
Your analysis is correct, any HPD event would keep debouncing adding 1.1
timout from each HPD irq, both plugout and plugin.
The intention was to allow for up to 1.1 seconds to pass between a
plugout and a plugin, before we treated a plugout as a full disconnect
event, and not to delay a possible connected event by 1.1 seconds.
> My understanding of a debounce was that we "ignore" the pulse by only generating
> a single irq event when the pulse is finished.
Correct, as long as the pulse was less than 1.1 seconds.
> The current code does that, we will only have a single irq event and the HPD
> will return as connected state, good. But this delays the irq event 1.1s _after_
> the end of the pulse, which I would expect the event to be send at tht debounce
> time after the start of the pulse.
Good catch and I agree, we should delay/timeout the disconnected state
longer than plugin and react on plugin almost immediately.
> Like, program the work at the beginning of the pulse, if somehow the pulse ends before
> the debounce time, send the irq event immediately, otherwise let the debounce
> work run after the debounce time which will trigger a disconnect event.
>
> But the delay is too high, 1.1s could be a manual unplug/plug or bad connector
> with false contact on the hpd pin.
>
> I would rather reduce this to something more realistic like 500ms or less and
> try to better handle the pulse somehow. But I don't have any idea if the scheme
> I described is doable.
We can configure different delays for plugout and plugin, I am currently
testing something like following:
#define HOTPLUG_CONNECTED_DEBOUNCE_MS 150
#define HOTPLUG_DISCONNECTED_DEBOUNCE_MS 500
delay = status == connector_status_connected ?
HOTPLUG_CONNECTED_DEBOUNCE_MS :
HOTPLUG_DISCONNECTED_DEBOUNCE_MS;
mod_delayed_work(system_percpu_wq, &hdmi->hpd_work,
msecs_to_jiffies(delay));
That would mean:
- at plugout we (re-)start the timer to trigger in 500ms
- at plugin we (re-)start the timer to trigger in 150ms
- whenever the timer triggers the hpd_work is started
- the hpw_work trigger normal detect() handling to determin if
connector status (or EDID) has changed
Example during power on of a Raspberry Pi Monitor:
[82.641903] dw_hdmi_hardirq: EVENT=plugout
[82.648276] dw_hdmi_schedule_hpd_work(status=2)
[82.841939] dw_hdmi_hardirq: EVENT=plugin
[82.848211] dw_hdmi_schedule_hpd_work(status=1)
[83.008573] dw_hdmi_hpd_work(): START
[83.020358] dw_hdmi_bridge_detect()
[83.034958] dw_hdmi_bridge_edid_read()
[83.187102] [drm:update_display_info.part.0] [CONNECTOR:55:HDMI-A-1] CEA VCDB 0x4a
[83.194471] [drm:update_display_info.part.0] [CONNECTOR:55:HDMI-A-1] HDMI: DVI dual 0, max TMDS clock 0 kHz
[83.201755] [drm:update_display_info.part.0] [CONNECTOR:55:HDMI-A-1] ELD monitor RPI MON156
[83.208968] [drm:update_display_info.part.0] [CONNECTOR:55:HDMI-A-1] HDMI: latency present 0 0, video latency 0 0, audio latency 0 0
[83.216588] [drm:update_display_info.part.0] [CONNECTOR:55:HDMI-A-1] ELD size 36, SAD count 1
[83.224445] [drm:check_connector_changed] [CONNECTOR:55:HDMI-A-1] Same epoch counter 2
[83.231553] dw_hdmi_hpd_work(): END
Around 205ms between HPD=0 and HPD=1 and around 160ms from plugin until
delayed hpd_work starts.
And at full plugout the debounce time is around 497 ms:
[95.125105] dw_hdmi_hardirq: EVENT=plugout
[95.147586] dw_hdmi_schedule_hpd_work(status=2)
[95.645277] dw_hdmi_hpd_work(): START
[95.667741] dw_hdmi_bridge_detect()
[95.691523] [drm:drm_edid_connector_update] [CONNECTOR:55:HDMI-A-1] EDID changed, epoch counter 3
[95.709861] [drm:check_connector_changed] [CONNECTOR:55:HDMI-A-1] status updated from connected to disconnected
[95.722674] [drm:check_connector_changed] [CONNECTOR:55:HDMI-A-1] Changed epoch counter 2 => 4
[95.735173] [drm:drm_sysfs_connector_hotplug_event] [CONNECTOR:55:HDMI-A-1] generating connector hotplug event
[95.746326] [drm:drm_fb_helper_hotplug_event]
[95.754871] [drm:drm_client_modeset_probe]
[95.762429] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:55:HDMI-A-1]
[95.769758] dw_hdmi_bridge_detect()
[95.776597] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:55:HDMI-A-1] disconnected
[95.784389] [drm:drm_client_modeset_probe] No connectors reported connected with modes
[95.791865] [drm:drm_client_modeset_probe] [CONNECTOR:55:HDMI-A-1] enabled? no
[95.799426] [drm:drm_client_firmware_config.isra.0] Not using firmware configuration
[95.807140] [drm:drm_client_modeset_probe] picking CRTCs for 1920x1080 config
[95.818422] dw_hdmi_bridge_atomic_disable()
[95.826412] [drm:vop2_plane_atomic_disable] Smart0-win0 disable
[95.868341] [drm:drm_client_hotplug] fbdev: ret=0
[95.878206] dw_hdmi_hpd_work(): END
With a much quicker reaction on plugin event maybe the 1.1 seconds could
stay to avoid having to do a full teardown, disable() + enable() cycle,
at slightly longer HPD pulses.
Or maybe it is time to re-spin an old cec-adapter debounce series [1]
that can allow for some additional time until the CEC phys addr is fully
invalidated at a longer HPD low voltage level pulse.
[1] https://lore.kernel.org/linux-media/HE1PR06MB40115700084D1D875673D60EAC9D0@HE1PR06MB4011.eurprd06.prod.outlook.com/
Regards,
Jonas
>
> Neil
>
>>
>> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
>> ---
>> v7: Change to free irq before mute and clear using IH regs, also include
>> clear of STAT0_RX_SENSE
>> v6: Change back to disable_delayed_work_sync() in hpd disable ops,
>> Ensure HPD interrupt is masked and IRQ handler is disabled early
>> in dw_hdmi_remove() to prevent any irq re-arming of delayed work,
>> Drop use of suspend helper
>> v5: Change to none-sync disable_delayed_work() in hpd disable ops,
>> Change to cancel_delayed_work_sync() in remove,
>> Add cancel_delayed_work_sync() to new suspend helper
>> v4: Disable/mask delayed_work until enable_hpd()/hpd_enable(),
>> Read connector status directly from HW regs in hpd_work
>> v3: New patch
>> ---
>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 80 +++++++++++++++++++++--
>> 1 file changed, 75 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index 8afc9d240121..270db58a0e7c 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -50,6 +50,8 @@
>>
>> #define HDMI14_MAX_TMDSCLK 340000000
>>
>> +#define HOTPLUG_DEBOUNCE_MS 1100
>> +
>> static const u16 csc_coeff_default[3][4] = {
>> { 0x2000, 0x0000, 0x0000, 0x0000 },
>> { 0x0000, 0x2000, 0x0000, 0x0000 },
>> @@ -185,6 +187,7 @@ struct dw_hdmi {
>> hdmi_codec_plugged_cb plugged_cb;
>> struct device *codec_dev;
>> enum drm_connector_status last_connector_result;
>> + struct delayed_work hpd_work;
>> };
>>
>> const struct dw_hdmi_plat_data *dw_hdmi_to_plat_data(struct dw_hdmi *hdmi)
>> @@ -2517,6 +2520,20 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
>> dw_hdmi_connector_status_update(hdmi, connector, connector->status);
>> }
>>
>> +static void dw_hdmi_connector_enable_hpd(struct drm_connector *connector)
>> +{
>> + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>> +
>> + enable_delayed_work(&hdmi->hpd_work);
>> +}
>> +
>> +static void dw_hdmi_connector_disable_hpd(struct drm_connector *connector)
>> +{
>> + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>> +
>> + disable_delayed_work_sync(&hdmi->hpd_work);
>> +}
>> +
>> static void dw_hdmi_connector_destroy(struct drm_connector *connector)
>> {
>> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>> @@ -2538,6 +2555,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
>> static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>> .get_modes = dw_hdmi_connector_get_modes,
>> .atomic_check = dw_hdmi_connector_atomic_check,
>> + .enable_hpd = dw_hdmi_connector_enable_hpd,
>> + .disable_hpd = dw_hdmi_connector_disable_hpd,
>> };
>>
>> static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
>> @@ -2968,6 +2987,20 @@ static const struct drm_edid *dw_hdmi_bridge_edid_read(struct drm_bridge *bridge
>> return dw_hdmi_edid_read(hdmi, connector);
>> }
>>
>> +static void dw_hdmi_bridge_hpd_enable(struct drm_bridge *bridge)
>> +{
>> + struct dw_hdmi *hdmi = bridge->driver_private;
>> +
>> + enable_delayed_work(&hdmi->hpd_work);
>> +}
>> +
>> +static void dw_hdmi_bridge_hpd_disable(struct drm_bridge *bridge)
>> +{
>> + struct dw_hdmi *hdmi = bridge->driver_private;
>> +
>> + disable_delayed_work_sync(&hdmi->hpd_work);
>> +}
>> +
>> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
>> .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>> .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>> @@ -2981,6 +3014,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
>> .mode_valid = dw_hdmi_bridge_mode_valid,
>> .detect = dw_hdmi_bridge_detect,
>> .edid_read = dw_hdmi_bridge_edid_read,
>> + .hpd_enable = dw_hdmi_bridge_hpd_enable,
>> + .hpd_disable = dw_hdmi_bridge_hpd_disable,
>> };
>>
>> /* -----------------------------------------------------------------------------
>> @@ -3101,8 +3136,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
>> status == connector_status_connected ?
>> "plugin" : "plugout");
>>
>> - if (hdmi->bridge.dev)
>> - drm_helper_hpd_irq_event(hdmi->bridge.dev);
>> + mod_delayed_work(system_percpu_wq, &hdmi->hpd_work,
>> + msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
>> }
>>
>> hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
>> @@ -3112,6 +3147,29 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
>> return IRQ_HANDLED;
>> }
>>
>> +static void dw_hdmi_hpd_work(struct work_struct *work)
>> +{
>> + struct dw_hdmi *hdmi = container_of(work, struct dw_hdmi, hpd_work.work);
>> + struct drm_device *dev = hdmi->bridge.dev;
>> +
>> + if (WARN_ON(!dev))
>> + return;
>> +
>> + /*
>> + * Notify the DRM core of the HPD event using drm_helper_hpd_irq_event()
>> + * instead of drm_bridge_hpd_notify(). This will cause the DRM function
>> + * check_connector_changed() to be called, which in turn calls the
>> + * connector detect()/force() funcs to detect any connection status or
>> + * epoch changes. The bridge connector detect() func also ensures that
>> + * any hpd_notify() funcs are called for all bridges in the chain.
>> + *
>> + * drm_bridge_hpd_notify() shares a mutex with drm_bridge_hpd_disable(),
>> + * and can result in a deadlock due to the disable_delayed_work_sync()
>> + * call to wait on work to complete in dw_hdmi_bridge_hpd_disable().
>> + */
>> + drm_helper_hpd_irq_event(dev);
>> +}
>> +
>> static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
>> {
>> .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
>> @@ -3396,6 +3454,9 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
>> goto err_res;
>> }
>>
>> + INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_hpd_work);
>> + disable_delayed_work(&hdmi->hpd_work);
>> +
>> ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
>> dw_hdmi_irq, IRQF_SHARED,
>> dev_name(dev), hdmi);
>> @@ -3532,6 +3593,18 @@ EXPORT_SYMBOL_GPL(dw_hdmi_probe);
>>
>> void dw_hdmi_remove(struct dw_hdmi *hdmi)
>> {
>> + struct platform_device *pdev = to_platform_device(hdmi->dev);
>> + int irq = platform_get_irq(pdev, 0);
>> +
>> + /* Free, mute and clear phy interrupts */
>> + devm_free_irq(hdmi->dev, irq, hdmi);
>> + hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
>> + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
>> + HDMI_IH_PHY_STAT0);
>> +
>> + /* Cancel any pending hot plug work */
>> + cancel_delayed_work_sync(&hdmi->hpd_work);
>> +
>> drm_bridge_remove(&hdmi->bridge);
>>
>> if (hdmi->audio && !IS_ERR(hdmi->audio))
>> @@ -3539,9 +3612,6 @@ void dw_hdmi_remove(struct dw_hdmi *hdmi)
>> if (!IS_ERR(hdmi->cec))
>> platform_device_unregister(hdmi->cec);
>>
>> - /* Disable all interrupts */
>> - hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
>> -
>> if (hdmi->i2c)
>> i2c_del_adapter(&hdmi->i2c->adap);
>> else
>
^ permalink raw reply
* Re: [RFC PATCH 2/2] arm64: mm: add SMCCC-backed cache invalidate provider
From: Dan Williams (nvidia) @ 2026-05-21 20:10 UTC (permalink / raw)
To: Srirangan Madhavan, catalin.marinas, will, mark.rutland,
lpieralisi, sudeep.holla
Cc: conor, jic23, linux-arm-kernel, linux-kernel, vsethi, jevans,
raghupathyk, srikars, nbenech, alwilliamson, Dan Williams,
Srirangan Madhavan
In-Reply-To: <20260521073047.320614-3-smadhavan@nvidia.com>
Srirangan Madhavan wrote:
> Add an arm64 cache maintenance backend that discovers SMCCC cache
> clean+invalidate support, queries attributes, handles transient BUSY and
> RATE_LIMITED responses with bounded retries, and registers with the generic
> cache coherency framework.
>
> Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
> ---
> MAINTAINERS | 1 +
> arch/arm64/mm/Makefile | 1 +
> arch/arm64/mm/cache_maint.c | 180 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 182 insertions(+)
> create mode 100644 arch/arm64/mm/cache_maint.c
[..]
> +static int arm64_smccc_cache_wbinv(struct cache_coherency_ops_inst *cci,
> + struct cc_inval_params *invp)
> +{
> + struct arm64_smccc_cache *cache =
> + container_of(cci, struct arm64_smccc_cache, cci);
> + struct arm_smccc_res res = {};
> + int delay_us = smccc_cache_delay_us(cache);
> + u64 gen = 0;
> + s32 status;
> + int ret;
> + int i;
> +
> + if (!invp->size)
> + return -EINVAL;
> +
> + if (cache->global_op)
> + gen = READ_ONCE(cache->global_flush_gen);
> +
> + guard(mutex)(&cache->lock);
> +
> + /*
> + * If firmware reports a global operation type, a successful operation
> + * covers every request that was already waiting behind it. Skip if the
> + * generation advanced while this request was waiting to enter the
> + * serialized firmware call path.
> + */
> + if (cache->global_op && gen != READ_ONCE(cache->global_flush_gen))
> + return 0;
Hmm, this looks like it could under flush which is worse than over
flushing. The ordering is:
CPU0 CPU1
<dirty>
flush_gen==0
lock
flush_gen==0
flush <dirty>
flush_gen++ flush_gen==0
lock
flush_gen==1
skip
I.e. if CPU1 is racing dirtying while CPU0 is still flushing, then there
is a window for CPU1 to read the updated flush_gen and skip when it
needs to follow on with a new flush cycle. So this either needs a more
sophisticated queue / batch system to track which requests might get
satisfied while waiting for a turn, or just drop the optimization until
it is clear it causes a problem in practice.
I think dropping the optimization is practical for now.
> +
> + for (i = 0; i < SMCCC_CACHE_MAX_RETRIES; i++) {
> + /* Long firmware operations can trigger watchdog checks. */
> + touch_nmi_watchdog();
> +
> + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION,
> + invp->addr, invp->size, 0UL, &res);
> + status = (s32)res.a0;
> + ret = smccc_cache_status_to_errno(status);
> + if (!ret) {
> + if (cache->global_op) {
> + WRITE_ONCE(cache->global_flush_gen,
> + cache->global_flush_gen + 1);
> + }
> + return 0;
> + }
> +
> + if (ret != -EBUSY && ret != -EAGAIN)
> + return ret;
I notice that cxl_region_invalidate_memregion() only expects failures to
find a flush capability, not failures to execute a flush.
Just a note to circle back to this concern.
^ permalink raw reply
* Re: [PATCH v6 01/10] dt-bindings: display: rockchip: analogix-dp: Fix hclk as third clock for RK3588
From: Conor Dooley @ 2026-05-21 19:54 UTC (permalink / raw)
To: Damon Ding
Cc: hjc, heiko, andy.yan, maarten.lankhorst, mripard, tzimmermann,
airlied, simona, robh, krzk+dt, conor+dt, andrzej.hajda,
neil.armstrong, rfoss, Laurent.pinchart, jonas, jernej.skrabec,
nicolas.frattaroli, cristian.ciocaltea, sebastian.reichel,
dmitry.baryshkov, luca.ceresoli, dianders, m.szyprowski,
dri-devel, devicetree, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <20260521080835.1362416-2-damon.ding@rock-chips.com>
[-- Attachment #1: Type: text/plain, Size: 3681 bytes --]
On Thu, May 21, 2026 at 04:08:26PM +0800, Damon Ding wrote:
> RK3588 eDP controller requires HCLK_VO1 to access the VO1 GRF
> registers and enable the video datapath.
>
> Previously, the clock was enabled implicitly via the 'rockchip,vo-grf'
> phandle reference, which allowed the eDP to work without explicitly
> managing the hclk_vo1 clock. However, this is not safe or explicit.
>
> To make the clock dependency explicit, enforce per-SoC clock-names
> requirements:
> - RK3288: 2 clocks (dp, pclk)
> - RK3399: 3 clocks (dp, pclk, grf)
> - RK3588: 3 clocks (dp, pclk, hclk)
>
> Do not reuse the 'grf' clock name for RK3588 because it represents
> a different clock with distinct control logic:
> - The 'grf' clock is only for GRF register access and is toggled
> dynamically during register access.
> - The 'hclk' clock controls both GRF access and video datapath
> gating, and must remain enabled during probe.
>
> Fixes: f855146263b1 ("dt-bindings: display: rockchip: analogix-dp: Add support for RK3588")
> Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
>
> ---
>
> Changes in v4:
> - Modify the commit msg.
>
> Changes in v5:
> - Enforce the correct third clock name on a per-compatible basis.
> - Modify the commit msg simultaneously.
>
> Changes in v6:
> - Expand more detail commit msg about using hclk instead of grf clock.
> ---
> .../rockchip/rockchip,analogix-dp.yaml | 37 +++++++++++++++++--
> 1 file changed, 33 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> index d99b23b88cc5..8001c1facf98 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> @@ -23,10 +23,7 @@ properties:
>
> clock-names:
> minItems: 2
> - items:
> - - const: dp
> - - const: pclk
> - - const: grf
Instead of removing this, you can make it
items:
- const: dp
- const pclk
- enum:
- grf
- hclk
> + maxItems: 3
And delete this.
>
> power-domains:
> maxItems: 1
> @@ -60,6 +57,33 @@ required:
> allOf:
> - $ref: /schemas/display/bridge/analogix,dp.yaml#
>
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - rockchip,rk3288-dp
> + then:
> + properties:
> + clock-names:
> + items:
> + - const: dp
> + - const: pclk
Then this becomes
clock-names:
maxItems: 2
clocks:
maxItems: 2
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - rockchip,rk3399-edp
> + then:
> + properties:
> + clock-names:
> + items:
> + - const: dp
> + - const: pclk
> + - const: grf
maybe this needs a minItems: 3? Depends on if the grf clock is
mandatory. Also probably needs a
clocks:
minItems: 3
if that's the case.
> +
> - if:
> properties:
> compatible:
> @@ -68,6 +92,11 @@ allOf:
> - rockchip,rk3588-edp
> then:
> properties:
> + clock-names:
> + items:
> + - const: dp
> + - const: pclk
> + - const: hclk
And the same here as for the 3399.
Cheers,
Conor.
> resets:
> minItems: 2
> reset-names:
> --
> 2.34.1
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 1/3] dt-bindings: display: bridge: analogix-dp: Add data-lanes support for endpoint
From: Conor Dooley @ 2026-05-21 19:50 UTC (permalink / raw)
To: Damon Ding
Cc: hjc, heiko, andy.yan, maarten.lankhorst, mripard, tzimmermann,
airlied, simona, robh, krzk+dt, conor+dt, andrzej.hajda,
neil.armstrong, rfoss, Laurent.pinchart, jonas, jernej.skrabec,
nicolas.frattaroli, cristian.ciocaltea, sebastian.reichel,
dmitry.baryshkov, luca.ceresoli, dianders, m.szyprowski,
dri-devel, devicetree, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <20260521114459.1394264-2-damon.ding@rock-chips.com>
[-- Attachment #1: Type: text/plain, Size: 2309 bytes --]
On Thu, May 21, 2026 at 07:44:57PM +0800, Damon Ding wrote:
> Add data-lanes property support to the port@1 endpoint for physical
> lane mapping configuration.
>
> Lane mapping is mainly used for below scenarios:
> 1. Correct PCB lane swap and differential line routing crossover
> without hardware changes;
> 2. Adapt mismatched lane pin definitions between SoC and eDP panel;
> 3. Support multiple panel hardware variants on the same board
> by configuring data-lanes in device tree only.
>
> Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Sashiko complaint here looks valid.
pw-bot: changes-requested
Thanks,
Conor.
>
> ---
>
> Changes in v2:
> - Add lane mapping application scenarios in commit message.
> - Remove redundant deprecated property 'data-lanes' for eDP node.
> - Update port@1 $ref to /schemas/graph.yaml#/$defs/port-base.
> ---
> .../bindings/display/bridge/analogix,dp.yaml | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
> index 62f0521b0924..e34fdb21adb4 100644
> --- a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
> @@ -42,13 +42,20 @@ properties:
> properties:
> port@0:
> $ref: /schemas/graph.yaml#/properties/port
> - description:
> - Input node to receive pixel data.
> + description: Input node to receive pixel data.
>
> port@1:
> - $ref: /schemas/graph.yaml#/properties/port
> - description:
> - Port node with one endpoint connected to a dp-connector node.
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + description: Port node with one endpoint connected to sink device node.
> + properties:
> + endpoint:
> + $ref: /schemas/media/video-interfaces.yaml#
> + properties:
> + data-lanes:
> + minItems: 1
> + maxItems: 4
> + items:
> + enum: [ 0, 1, 2, 3 ]
>
> required:
> - port@0
> --
> 2.34.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/3] dt-bindings: rockchip: analogix-dp: Add data-lanes example
From: Conor Dooley @ 2026-05-21 19:47 UTC (permalink / raw)
To: Damon Ding
Cc: hjc, heiko, andy.yan, maarten.lankhorst, mripard, tzimmermann,
airlied, simona, robh, krzk+dt, conor+dt, andrzej.hajda,
neil.armstrong, rfoss, Laurent.pinchart, jonas, jernej.skrabec,
nicolas.frattaroli, cristian.ciocaltea, sebastian.reichel,
dmitry.baryshkov, luca.ceresoli, dianders, m.szyprowski,
dri-devel, devicetree, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <20260521114459.1394264-3-damon.ding@rock-chips.com>
[-- Attachment #1: Type: text/plain, Size: 1034 bytes --]
On Thu, May 21, 2026 at 07:44:58PM +0800, Damon Ding wrote:
> Add data-lanes setting in endpoint example to show actual lane mapping
> usage.
>
> Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Squash this with patch 1.
pw-bot: changes-requested
Thanks,
Conor.
> ---
> .../bindings/display/rockchip/rockchip,analogix-dp.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> index bb75d898a5c5..cf75c926318b 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
> @@ -151,6 +151,7 @@ examples:
> reg = <1>;
>
> edp_out_panel: endpoint {
> + data-lanes = <0 1>;
> remote-endpoint = <&panel_in_edp>;
> };
> };
> --
> 2.34.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v2 1/1] dt-bindings: display: imx: Add television encoder (TVE) for imx53
From: Frank.Li @ 2026-05-21 19:37 UTC (permalink / raw)
To: Philipp Zabel, David Airlie, Simona Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam,
open list:DRM DRIVERS FOR FREESCALE IMX 5/6,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
open list
Cc: imx, Krzysztof Kozlowski
From: Frank Li <Frank.Li@nxp.com>
Add television encoder (TVE) for legacy i.MX53 (over 15 years) to fix below
DTB_CHECK warnings:
arch/arm/boot/dts/nxp/imx/imx53-ard.dtb: /soc/bus@60000000/tve@63ff0000: failed to match any schema with compatible: ['fsl,imx53-tve']
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change in v2
- add Krzysztof Kozlowski's review tag
- move fsl,tve-mode to required list
About cleanup 300 lines warnings for i.MX ARM platformi
---
.../bindings/display/imx/fsl,imx53-tve.yaml | 104 ++++++++++++++++++
1 file changed, 104 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx53-tve.yaml
diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx53-tve.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx53-tve.yaml
new file mode 100644
index 0000000000000..2fcf447459122
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx53-tve.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/imx/fsl,imx53-tve.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX53 Television Encoder (TVE)
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ The Television Encoder (TVE) is a hardware block in the i.MX53 SoC that
+ converts digital video data into analog TV signals (NTSC/PAL).
+
+properties:
+ compatible:
+ const: fsl,imx53-tve
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: TVE gate clock
+ - description: Display interface selector clock
+
+ clock-names:
+ items:
+ - const: tve
+ - const: di_sel
+
+ ddc-i2c-bus:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the I2C bus used for DDC (Display Data Channel) communication
+ to read EDID information from the connected display.
+
+ dac-supply:
+ description:
+ Regulator supply for the TVE DAC (Digital-to-Analog Converter).
+
+ fsl,tve-mode:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ TVE output mode selection.
+ enum:
+ - ntsc
+ - pal
+ - vga
+
+ fsl,hsync-pin:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Pin number for horizontal sync signal in VGA mode.
+ minimum: 0
+ maximum: 8
+
+ fsl,vsync-pin:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Pin number for vertical sync signal in VGA mode.
+ minimum: 0
+ maximum: 8
+
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Port node with one endpoint connected to the IPU display interface.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - fsl,tve-mode
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx5-clock.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ tve@63ff0000 {
+ compatible = "fsl,imx53-tve";
+ reg = <0x63ff0000 0x1000>;
+ interrupts = <92>;
+ clocks = <&clks IMX5_CLK_TVE_GATE>,
+ <&clks IMX5_CLK_IPU_DI1_SEL>;
+ clock-names = "tve", "di_sel";
+ fsl,tve-mode = "vga";
+
+ port {
+ endpoint {
+ remote-endpoint = <&ipu_di1_tve>;
+ };
+ };
+ };
+
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox