public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] drm/bridge: handle gracefully atomic updates during bridge removal
@ 2025-08-08 13:24 Luca Ceresoli
  2025-08-08 13:24 ` [PATCH 1/2] drm/bridge: add drm_bridge_unplug() and drm_bridge_enter/exit() Luca Ceresoli
  2025-08-08 13:24 ` [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug Luca Ceresoli
  0 siblings, 2 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-08-08 13:24 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Hui Pu, Thomas Petazzoni, dri-devel, linux-kernel, Luca Ceresoli,
	Dmitry Baryshkov

This is a first attempt at gracefully handling the case of atomic updates
happening concurrently to physical removal of DRM bridges.

This is part of the work towards removal of bridges from a still existing
DRM pipeline without use-after-free. The grand plan was discussed in [1].
Here's the work breakdown (➜ marks the current series):

 1. ➜ add refcounting to DRM bridges (struct drm_bridge)
    (based on devm_drm_bridge_alloc() [0])
    A. ✔ add new alloc API and refcounting (in v6.16-rc1)
    B. ✔ convert all bridge drivers to new API (now in drm-misc-next)
    C. ✔ kunit tests (now in drm-misc-next)
    D. ✔ add get/put to drm_bridge_add/remove() + attach/detach()
         and warn on old allocation pattern (now in drm-misc-next)
    E. ➜ add get/put on drm_bridge accessors
       1. ✔ drm_bridge_chain_get_first_bridge() + add a cleanup action
       2. ✔ drm_bridge_get_prev_bridge()
       3. … drm_bridge_get_next_bridge()
       4. … drm_for_each_bridge_in_chain()
       5. drm_bridge_connector_init
       6. of_drm_find_bridge
       7. drm_of_find_panel_or_bridge, *_of_get_bridge
    F. debugfs improvements
 2. ➜ handle gracefully atomic updates during bridge removal
 3. … DSI host-device driver interaction
 4. finish the hotplug bridge work, removing the "always-disconnected"
    connector, moving code to the core and potentially removing the
    hotplug-bridge itself (this needs to be clarified as points 1-3 are
    developed)

The idea was proposed by Maxime [0] and is based on the existing
drm_dev_enter/exit() already existing for the DRM device.

This small series implements the core mechanism in drm_bridge.c and uses it
in the ti-sn65dsi83 driver. This prevents usage of device resources by
various code paths that can happen concurrently to unplug of the SN65DSI8x
bridge.

[0] https://lore.kernel.org/all/20250106-vigorous-talented-viper-fa49d9@houat/

Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
Luca Ceresoli (2):
      drm/bridge: add drm_bridge_unplug() and drm_bridge_enter/exit()
      drm/bridge: ti-sn65dsi83: protect device resources on unplug

 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 53 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_bridge.c          | 58 +++++++++++++++++++++++++++++++++++
 include/drm/drm_bridge.h              | 12 ++++++++
 3 files changed, 123 insertions(+)
---
base-commit: d2b48f2b30f25997a1ae1ad0cefac68c25f8c330
change-id: 20250808-drm-bridge-atomic-vs-remove-1d7bb202c8ef

Best regards,
-- 
Luca Ceresoli <luca.ceresoli@bootlin.com>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/2] drm/bridge: add drm_bridge_unplug() and drm_bridge_enter/exit()
  2025-08-08 13:24 [PATCH 0/2] drm/bridge: handle gracefully atomic updates during bridge removal Luca Ceresoli
@ 2025-08-08 13:24 ` Luca Ceresoli
  2025-08-08 13:24 ` [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug Luca Ceresoli
  1 sibling, 0 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-08-08 13:24 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Hui Pu, Thomas Petazzoni, dri-devel, linux-kernel, Luca Ceresoli,
	Dmitry Baryshkov

To allow DRM bridges to be removable, add synchronization functions
allowing to tell when a bridge hardware has been physically unplugged and
to mark a critical section that should not be entered after that.

This is inspired by the drm_dev_unplugged/enter/exit() functions for struct
drm_device.

Suggested-by: Maxime Ripard <mripard@kernel.org>
Link: https://lore.kernel.org/all/20250106-vigorous-talented-viper-fa49d9@houat/
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
 drivers/gpu/drm/drm_bridge.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_bridge.h     | 12 +++++++++
 2 files changed, 70 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index c3bfcd735a3c426a147bf0a7427b3d2cd0df3524..486bc48881c6a05ebe3c911754a40530f0d08e3e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -27,6 +27,7 @@
 #include <linux/media-bus-format.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/srcu.h>
 
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_bridge.h>
@@ -200,6 +201,63 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+DEFINE_STATIC_SRCU(drm_bridge_unplug_srcu);
+
+/**
+ * drm_bridge_enter - Enter DRM bridge critical section
+ * @dev: DRM bridge
+ * @idx: Pointer to index that will be passed to the matching drm_bridge_exit()
+ *
+ * This function marks and protects the beginning of a section that should not
+ * be entered after the bridge has been unplugged. The section end is marked
+ * with drm_bridge_exit(). Calls to this function can be nested.
+ *
+ * Returns:
+ * True if it is OK to enter the section, false otherwise.
+ */
+bool drm_bridge_enter(struct drm_bridge *bridge, int *idx)
+{
+	*idx = srcu_read_lock(&drm_bridge_unplug_srcu);
+
+	if (bridge->unplugged) {
+		srcu_read_unlock(&drm_bridge_unplug_srcu, *idx);
+		return false;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(drm_bridge_enter);
+
+/**
+ * drm_bridge_exit - Exit DRM bridge critical section
+ * @idx: index returned by drm_bridge_enter()
+ *
+ * This function marks the end of a section that should not be entered after
+ * the bridge has been unplugged.
+ */
+void drm_bridge_exit(int idx)
+{
+	srcu_read_unlock(&drm_bridge_unplug_srcu, idx);
+}
+EXPORT_SYMBOL(drm_bridge_exit);
+
+/**
+ * drm_bridge_unplug - unplug a DRM bridge
+ * @dev: DRM bridge
+ *
+ * This tells the bridge has been physically unplugged and no operations on
+ * device resources must be done anymore. Entry-points can use
+ * drm_bridge_enter() and drm_bridge_exit() to protect device resources in
+ * a race free manner.
+ */
+void drm_bridge_unplug(struct drm_bridge *bridge)
+{
+	bridge->unplugged = true;
+
+	synchronize_srcu(&drm_bridge_unplug_srcu);
+}
+EXPORT_SYMBOL(drm_bridge_unplug);
+
 static void __drm_bridge_free(struct kref *kref)
 {
 	struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 620e119cc24c3491c2be5f08efaf51dfa8f708b3..0c6869ebb2be9b89499ee5c42692fd94ca5b3161 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -1095,6 +1095,14 @@ struct drm_bridge {
 	 */
 	struct kref refcount;
 
+	/**
+	 * @unplugged:
+	 *
+	 * Flag to tell if the bridge has been unplugged.
+	 * See drm_bridge_enter() and drm_bridge_unplug().
+	 */
+	bool unplugged;
+
 	/** @driver_private: pointer to the bridge driver's internal context */
 	void *driver_private;
 	/** @ops: bitmask of operations supported by the bridge */
@@ -1226,6 +1234,10 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
 	return container_of(priv, struct drm_bridge, base);
 }
 
+bool drm_bridge_enter(struct drm_bridge *bridge, int *idx);
+void drm_bridge_exit(int idx);
+void drm_bridge_unplug(struct drm_bridge *bridge);
+
 struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge);
 void drm_bridge_put(struct drm_bridge *bridge);
 

-- 
2.50.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-08 13:24 [PATCH 0/2] drm/bridge: handle gracefully atomic updates during bridge removal Luca Ceresoli
  2025-08-08 13:24 ` [PATCH 1/2] drm/bridge: add drm_bridge_unplug() and drm_bridge_enter/exit() Luca Ceresoli
@ 2025-08-08 13:24 ` Luca Ceresoli
  2025-08-19 12:29   ` Maxime Ripard
  1 sibling, 1 reply; 19+ messages in thread
From: Luca Ceresoli @ 2025-08-08 13:24 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Hui Pu, Thomas Petazzoni, dri-devel, linux-kernel, Luca Ceresoli,
	Dmitry Baryshkov

To support hot-unplug of this bridge we need to protect access to device
resources in case sn65dsi83_remove() happens concurrently to other code.

Some care is needed for the case when the unplug happens before
sn65dsi83_atomic_disable() has a chance to enter the critical section
(i.e. a successful drm_bridge_enter() call), which occurs whenever the
hardware is removed while the display is active. When that happens,
sn65dsi83_atomic_disable() in unable to release some resources, thus this
needs to be done in sn65dsi83_remove() after drm_bridge_unplug().

Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 53 +++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 033c44326552ab167d4e8d9b74957c585e4c6fb7..9e4cecf4f7cb056f0c34e87007fcebf50780e49c 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -157,6 +157,7 @@ struct sn65dsi83 {
 	struct drm_bridge		*panel_bridge;
 	struct gpio_desc		*enable_gpio;
 	struct regulator		*vcc;
+	bool				disable_resources_needed;
 	bool				lvds_dual_link;
 	bool				lvds_dual_link_even_odd_swap;
 	int				lvds_vod_swing_conf[2];
@@ -406,6 +407,10 @@ static void sn65dsi83_reset_work(struct work_struct *ws)
 {
 	struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work);
 	int ret;
+	int idx;
+
+	if (!drm_bridge_enter(&ctx->bridge, &idx))
+		return;
 
 	/* Reset the pipe */
 	ret = sn65dsi83_reset_pipe(ctx);
@@ -415,12 +420,18 @@ static void sn65dsi83_reset_work(struct work_struct *ws)
 	}
 	if (ctx->irq)
 		enable_irq(ctx->irq);
+
+	drm_bridge_exit(idx);
 }
 
 static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
 {
 	unsigned int irq_stat;
 	int ret;
+	int idx;
+
+	if (!drm_bridge_enter(&ctx->bridge, &idx))
+		return;
 
 	/*
 	 * Schedule a reset in case of:
@@ -441,6 +452,8 @@ static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
 
 		schedule_work(&ctx->reset_work);
 	}
+
+	drm_bridge_exit(idx);
 }
 
 static void sn65dsi83_monitor_work(struct work_struct *work)
@@ -478,10 +491,15 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
 	__le16 le16val;
 	u16 val;
 	int ret;
+	int idx;
+
+	if (!drm_bridge_enter(bridge, &idx))
+		return;
 
 	ret = regulator_enable(ctx->vcc);
 	if (ret) {
 		dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
+		drm_bridge_exit(idx);
 		return;
 	}
 
@@ -625,6 +643,8 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
 		dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
 		/* On failure, disable PLL again and exit. */
 		regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
+		ctx->disable_resources_needed = true;
+		drm_bridge_exit(idx);
 		return;
 	}
 
@@ -633,6 +653,9 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
 
 	/* Wait for 10ms after soft reset as specified in datasheet */
 	usleep_range(10000, 12000);
+
+	ctx->disable_resources_needed = true;
+	drm_bridge_exit(idx);
 }
 
 static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
@@ -640,6 +663,10 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
 {
 	struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
 	unsigned int pval;
+	int idx;
+
+	if (!drm_bridge_enter(bridge, &idx))
+		return;
 
 	/* Clear all errors that got asserted during initialization. */
 	regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
@@ -659,6 +686,8 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
 		/* Use the polling task */
 		sn65dsi83_monitor_start(ctx);
 	}
+
+	drm_bridge_exit(idx);
 }
 
 static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
@@ -666,6 +695,10 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
 {
 	struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
 	int ret;
+	int idx;
+
+	if (!drm_bridge_enter(bridge, &idx))
+		return;
 
 	if (ctx->irq) {
 		/* Disable irq */
@@ -685,6 +718,9 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
 		dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
 
 	regcache_mark_dirty(ctx->regmap);
+
+	ctx->disable_resources_needed = false;
+	drm_bridge_exit(idx);
 }
 
 static enum drm_mode_status
@@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
 {
 	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
 
+	drm_bridge_unplug(&ctx->bridge);
 	drm_bridge_remove(&ctx->bridge);
+
+	/*
+	 * sn65dsi83_atomic_disable() should release some resources, but it
+	 * cannot if we call drm_bridge_unplug() before it can
+	 * drm_bridge_enter(). If that happens, let's release those
+	 * resources now.
+	 */
+	if (ctx->disable_resources_needed) {
+		if (!ctx->irq)
+			sn65dsi83_monitor_stop(ctx);
+
+		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
+		usleep_range(10000, 11000);
+
+		regulator_disable(ctx->vcc);
+	}
 }
 
 static const struct i2c_device_id sn65dsi83_id[] = {

-- 
2.50.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-08 13:24 ` [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug Luca Ceresoli
@ 2025-08-19 12:29   ` Maxime Ripard
  2025-08-20 11:13     ` Luca Ceresoli
  0 siblings, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-08-19 12:29 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 5657 bytes --]

On Fri, Aug 08, 2025 at 03:24:29PM +0200, Luca Ceresoli wrote:
> To support hot-unplug of this bridge we need to protect access to device
> resources in case sn65dsi83_remove() happens concurrently to other code.
> 
> Some care is needed for the case when the unplug happens before
> sn65dsi83_atomic_disable() has a chance to enter the critical section
> (i.e. a successful drm_bridge_enter() call), which occurs whenever the
> hardware is removed while the display is active. When that happens,
> sn65dsi83_atomic_disable() in unable to release some resources, thus this
> needs to be done in sn65dsi83_remove() after drm_bridge_unplug().
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> ---
>  drivers/gpu/drm/bridge/ti-sn65dsi83.c | 53 +++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
> index 033c44326552ab167d4e8d9b74957c585e4c6fb7..9e4cecf4f7cb056f0c34e87007fcebf50780e49c 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
> @@ -157,6 +157,7 @@ struct sn65dsi83 {
>  	struct drm_bridge		*panel_bridge;
>  	struct gpio_desc		*enable_gpio;
>  	struct regulator		*vcc;
> +	bool				disable_resources_needed;
>  	bool				lvds_dual_link;
>  	bool				lvds_dual_link_even_odd_swap;
>  	int				lvds_vod_swing_conf[2];
> @@ -406,6 +407,10 @@ static void sn65dsi83_reset_work(struct work_struct *ws)
>  {
>  	struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work);
>  	int ret;
> +	int idx;
> +
> +	if (!drm_bridge_enter(&ctx->bridge, &idx))
> +		return;
>  
>  	/* Reset the pipe */
>  	ret = sn65dsi83_reset_pipe(ctx);
> @@ -415,12 +420,18 @@ static void sn65dsi83_reset_work(struct work_struct *ws)
>  	}
>  	if (ctx->irq)
>  		enable_irq(ctx->irq);
> +
> +	drm_bridge_exit(idx);
>  }
>  
>  static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
>  {
>  	unsigned int irq_stat;
>  	int ret;
> +	int idx;
> +
> +	if (!drm_bridge_enter(&ctx->bridge, &idx))
> +		return;
>  
>  	/*
>  	 * Schedule a reset in case of:
> @@ -441,6 +452,8 @@ static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
>  
>  		schedule_work(&ctx->reset_work);
>  	}
> +
> +	drm_bridge_exit(idx);
>  }
>  
>  static void sn65dsi83_monitor_work(struct work_struct *work)
> @@ -478,10 +491,15 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
>  	__le16 le16val;
>  	u16 val;
>  	int ret;
> +	int idx;
> +
> +	if (!drm_bridge_enter(bridge, &idx))
> +		return;
>  
>  	ret = regulator_enable(ctx->vcc);
>  	if (ret) {
>  		dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
> +		drm_bridge_exit(idx);
>  		return;
>  	}
>  
> @@ -625,6 +643,8 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
>  		dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
>  		/* On failure, disable PLL again and exit. */
>  		regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
> +		ctx->disable_resources_needed = true;
> +		drm_bridge_exit(idx);
>  		return;
>  	}
>  
> @@ -633,6 +653,9 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
>  
>  	/* Wait for 10ms after soft reset as specified in datasheet */
>  	usleep_range(10000, 12000);
> +
> +	ctx->disable_resources_needed = true;
> +	drm_bridge_exit(idx);
>  }
>  
>  static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
> @@ -640,6 +663,10 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
>  {
>  	struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
>  	unsigned int pval;
> +	int idx;
> +
> +	if (!drm_bridge_enter(bridge, &idx))
> +		return;
>  
>  	/* Clear all errors that got asserted during initialization. */
>  	regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
> @@ -659,6 +686,8 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
>  		/* Use the polling task */
>  		sn65dsi83_monitor_start(ctx);
>  	}
> +
> +	drm_bridge_exit(idx);
>  }
>  
>  static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
> @@ -666,6 +695,10 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
>  {
>  	struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
>  	int ret;
> +	int idx;
> +
> +	if (!drm_bridge_enter(bridge, &idx))
> +		return;
>  
>  	if (ctx->irq) {
>  		/* Disable irq */
> @@ -685,6 +718,9 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
>  		dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
>  
>  	regcache_mark_dirty(ctx->regmap);
> +
> +	ctx->disable_resources_needed = false;
> +	drm_bridge_exit(idx);
>  }
>  
>  static enum drm_mode_status
> @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
>  {
>  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
>  
> +	drm_bridge_unplug(&ctx->bridge);
>  	drm_bridge_remove(&ctx->bridge);

Shouldn't we merge drm_bridge_unplug with the release part of
devm_drm_bridge_alloc?

> +
> +	/*
> +	 * sn65dsi83_atomic_disable() should release some resources, but it
> +	 * cannot if we call drm_bridge_unplug() before it can
> +	 * drm_bridge_enter(). If that happens, let's release those
> +	 * resources now.
> +	 */
> +	if (ctx->disable_resources_needed) {
> +		if (!ctx->irq)
> +			sn65dsi83_monitor_stop(ctx);
> +
> +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> +		usleep_range(10000, 11000);
> +
> +		regulator_disable(ctx->vcc);
> +	}

I'm not sure you need this. Wouldn't registering a devm action do the
same thing?

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-19 12:29   ` Maxime Ripard
@ 2025-08-20 11:13     ` Luca Ceresoli
  2025-08-27  7:46       ` Maxime Ripard
  2025-09-08 13:49       ` Luca Ceresoli
  0 siblings, 2 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-08-20 11:13 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hello Maxime,

On Tue, 19 Aug 2025 14:29:32 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> >  {
> >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> >  
> > +	drm_bridge_unplug(&ctx->bridge);
> >  	drm_bridge_remove(&ctx->bridge);  
> 
> Shouldn't we merge drm_bridge_unplug with the release part of
> devm_drm_bridge_alloc?

I'm not sure I got what you are suggesting here, sorry.

Do you mean that __devm_drm_bridge_alloc() should add a devres action
to call drm_bridge_unplug(), so the unplug is called implicitly and
does not need to be called explicitly by all drivers?

If that's what you mean, I don't think that would work. Unless I'm
missing something, devres actions are always invoked just after the
driver .remove callback. But we need to call drm_bridge_unplug() at the
beginning (or just before) .remove, at least for drivers that need to do
something in .remove that cannot be done by devm.

In pseudocode:

mybridge_remove()
{
  drm_bridge_unplug(); <-- explicit call as in my patch
  xyz_disable();
  drm_bridge_unplug(); <-- implicitly done by devres
}

We want xyz_disable() to be done after drm_bridge_unplug(), so other
code paths using drm_bridge_enter/exit() won't mess with xyz.

devres actions cannot be added to be executed _before_ .remove, AFAIK.

> > +	/*
> > +	 * sn65dsi83_atomic_disable() should release some resources, but it
> > +	 * cannot if we call drm_bridge_unplug() before it can
> > +	 * drm_bridge_enter(). If that happens, let's release those
> > +	 * resources now.
> > +	 */
> > +	if (ctx->disable_resources_needed) {
> > +		if (!ctx->irq)
> > +			sn65dsi83_monitor_stop(ctx);
> > +
> > +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> > +		usleep_range(10000, 11000);
> > +
> > +		regulator_disable(ctx->vcc);
> > +	}  
> 
> I'm not sure you need this. Wouldn't registering a devm action do the
> same thing?

Good idea, thanks. I'll give it a try.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-20 11:13     ` Luca Ceresoli
@ 2025-08-27  7:46       ` Maxime Ripard
  2025-09-08 13:49         ` Luca Ceresoli
  2025-09-08 13:49       ` Luca Ceresoli
  1 sibling, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-08-27  7:46 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 2114 bytes --]

On Wed, Aug 20, 2025 at 01:13:02PM +0200, Luca Ceresoli wrote:
> Hello Maxime,
> 
> On Tue, 19 Aug 2025 14:29:32 +0200
> Maxime Ripard <mripard@kernel.org> wrote:
> 
> > > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> > >  {
> > >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > >  
> > > +	drm_bridge_unplug(&ctx->bridge);
> > >  	drm_bridge_remove(&ctx->bridge);  
> > 
> > Shouldn't we merge drm_bridge_unplug with the release part of
> > devm_drm_bridge_alloc?
> 
> I'm not sure I got what you are suggesting here, sorry.
> 
> Do you mean that __devm_drm_bridge_alloc() should add a devres action
> to call drm_bridge_unplug(), so the unplug is called implicitly and
> does not need to be called explicitly by all drivers?

Yes

> If that's what you mean, I don't think that would work. Unless I'm
> missing something, devres actions are always invoked just after the
> driver .remove callback.

Yes, they are called in reverse order of registration, after remove.

> But we need to call drm_bridge_unplug() at the beginning (or just
> before) .remove, at least for drivers that need to do something in
> .remove that cannot be done by devm.
> 
> In pseudocode:
> 
> mybridge_remove()
> {
>   drm_bridge_unplug(); <-- explicit call as in my patch
>   xyz_disable();
>   drm_bridge_unplug(); <-- implicitly done by devres
> }
> 
> We want xyz_disable() to be done after drm_bridge_unplug(), so other
> code paths using drm_bridge_enter/exit() won't mess with xyz.

It's not clear to me why doing it before xyz_disable() is important
here? If anything, it would prevent from disabling the hardware for
example, even though you still have your memory mapping, clocks, power
domains, regulators, etc. to properly disable it.

You're still correct that it's a bad idea though because we want to do
it before we start freeing all those, so it needs to execute as the
before the devm actions ...

> devres actions cannot be added to be executed _before_ .remove, AFAIK.

... and we can't do that either.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-20 11:13     ` Luca Ceresoli
  2025-08-27  7:46       ` Maxime Ripard
@ 2025-09-08 13:49       ` Luca Ceresoli
  2025-09-10  7:52         ` Maxime Ripard
  1 sibling, 1 reply; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-08 13:49 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hello Maxime,

On Wed, 20 Aug 2025 13:13:02 +0200
Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:

> > > +	/*
> > > +	 * sn65dsi83_atomic_disable() should release some resources, but it
> > > +	 * cannot if we call drm_bridge_unplug() before it can
> > > +	 * drm_bridge_enter(). If that happens, let's release those
> > > +	 * resources now.
> > > +	 */
> > > +	if (ctx->disable_resources_needed) {
> > > +		if (!ctx->irq)
> > > +			sn65dsi83_monitor_stop(ctx);
> > > +
> > > +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> > > +		usleep_range(10000, 11000);
> > > +
> > > +		regulator_disable(ctx->vcc);
> > > +	}    
> > 
> > I'm not sure you need this. Wouldn't registering a devm action do the
> > same thing?  
> 
> Good idea, thanks. I'll give it a try.

I'm catching up with this series after being busy a few weeks...

I looked at this, but contrary my initial impression I think it would
not be an improvement.

The reason is at least one of these cleanup actions (namely the
regulator_disable()) must be done only if there is a matching enable,
which is in atomic_pre_enable. This is why I introduced a flag in the
first place.

I'm not sure which usage of devres you had in mind, but I see two
options.

Option 1: in probe, add a devres action to call a function like:

sn65dsi83_cleanups()
{
	if (ctx->disable_resources_needed) {
		/* the same cleanups */
	}    
}

But that is just a more indirect way of doing the same thing, and
relies on the same flag.

Option 2: have a function to unconditionally do the cleanups:

sn65dsi83_cleanups()
{
	/* the same cleanups (no if) */
}

And then:
 * in atomic_pre_enable, instead of setting the flag
   add a devres action to call sn65dsi83_cleanups()
 * in atomic_disable, instead of clearing the flag
   remove the devres action

Even this option looks like more complicated and less readable code
to do the same thing.

Do you have in mind a better option that I haven't figured out?

If you don't, I think this part of the patch should stay as is.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-08-27  7:46       ` Maxime Ripard
@ 2025-09-08 13:49         ` Luca Ceresoli
  2025-09-10 10:59           ` Maxime Ripard
  0 siblings, 1 reply; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-08 13:49 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

On Wed, 27 Aug 2025 09:46:03 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> On Wed, Aug 20, 2025 at 01:13:02PM +0200, Luca Ceresoli wrote:
> > Hello Maxime,
> > 
> > On Tue, 19 Aug 2025 14:29:32 +0200
> > Maxime Ripard <mripard@kernel.org> wrote:
> >   
> > > > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> > > >  {
> > > >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > > >  
> > > > +	drm_bridge_unplug(&ctx->bridge);
> > > >  	drm_bridge_remove(&ctx->bridge);    
> > > 
> > > Shouldn't we merge drm_bridge_unplug with the release part of
> > > devm_drm_bridge_alloc?  
> > 
> > I'm not sure I got what you are suggesting here, sorry.
> > 
> > Do you mean that __devm_drm_bridge_alloc() should add a devres action
> > to call drm_bridge_unplug(), so the unplug is called implicitly and
> > does not need to be called explicitly by all drivers?  
> 
> Yes
> 
> > If that's what you mean, I don't think that would work. Unless I'm
> > missing something, devres actions are always invoked just after the
> > driver .remove callback.  
> 
> Yes, they are called in reverse order of registration, after remove.
> 
> > But we need to call drm_bridge_unplug() at the beginning (or just
> > before) .remove, at least for drivers that need to do something in
> > .remove that cannot be done by devm.
> > 
> > In pseudocode:
> > 
> > mybridge_remove()
> > {
> >   drm_bridge_unplug(); <-- explicit call as in my patch
> >   xyz_disable();
> >   drm_bridge_unplug(); <-- implicitly done by devres
> > }
> > 
> > We want xyz_disable() to be done after drm_bridge_unplug(), so other
> > code paths using drm_bridge_enter/exit() won't mess with xyz.  
> 
> It's not clear to me why doing it before xyz_disable() is important
> here? If anything, it would prevent from disabling the hardware for
> example, even though you still have your memory mapping, clocks, power
> domains, regulators, etc. to properly disable it.
> 
> You're still correct that it's a bad idea though because we want to do
> it before we start freeing all those, so it needs to execute as the
> before the devm actions ...
> 
> > devres actions cannot be added to be executed _before_ .remove, AFAIK.  
> 
> ... and we can't do that either.

I understand your words as "the drm_bridge_unplug() is OK where it is,
your patch is OK in this respect". Correct?

So if this is correct, and my reply on the devres cleanups is also
correct (other reply in this thread), that means the whole patch is OK.

Let me know if I'm wrong. :-)

Best regards,
Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-08 13:49       ` Luca Ceresoli
@ 2025-09-10  7:52         ` Maxime Ripard
  2025-09-10 16:34           ` Luca Ceresoli
  0 siblings, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-09-10  7:52 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 2539 bytes --]

On Mon, Sep 08, 2025 at 03:49:01PM +0200, Luca Ceresoli wrote:
> Hello Maxime,
> 
> On Wed, 20 Aug 2025 13:13:02 +0200
> Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
> 
> > > > +	/*
> > > > +	 * sn65dsi83_atomic_disable() should release some resources, but it
> > > > +	 * cannot if we call drm_bridge_unplug() before it can
> > > > +	 * drm_bridge_enter(). If that happens, let's release those
> > > > +	 * resources now.
> > > > +	 */
> > > > +	if (ctx->disable_resources_needed) {
> > > > +		if (!ctx->irq)
> > > > +			sn65dsi83_monitor_stop(ctx);
> > > > +
> > > > +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> > > > +		usleep_range(10000, 11000);
> > > > +
> > > > +		regulator_disable(ctx->vcc);
> > > > +	}    
> > > 
> > > I'm not sure you need this. Wouldn't registering a devm action do the
> > > same thing?  
> > 
> > Good idea, thanks. I'll give it a try.
> 
> I'm catching up with this series after being busy a few weeks...
> 
> I looked at this, but contrary my initial impression I think it would
> not be an improvement.
> 
> The reason is at least one of these cleanup actions (namely the
> regulator_disable()) must be done only if there is a matching enable,
> which is in atomic_pre_enable. This is why I introduced a flag in the
> first place.
> 
> I'm not sure which usage of devres you had in mind, but I see two
> options.
> 
> Option 1: in probe, add a devres action to call a function like:
> 
> sn65dsi83_cleanups()
> {
> 	if (ctx->disable_resources_needed) {
> 		/* the same cleanups */
> 	}    
> }
> 
> But that is just a more indirect way of doing the same thing, and
> relies on the same flag.
> 
> Option 2: have a function to unconditionally do the cleanups:
> 
> sn65dsi83_cleanups()
> {
> 	/* the same cleanups (no if) */
> }
> 
> And then:
>  * in atomic_pre_enable, instead of setting the flag
>    add a devres action to call sn65dsi83_cleanups()
>  * in atomic_disable, instead of clearing the flag
>    remove the devres action
> 
> Even this option looks like more complicated and less readable code
> to do the same thing.
> 
> Do you have in mind a better option that I haven't figured out?

Would using devm_add_action in atomic_pre_enable, and
devm_release_action in atomic_post_disable work?

That way, if you have a typical enable / disable cycle, the action will
get registered and executed properly, and if you only have an enable but
no matching disable, it will be collected after remove.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-08 13:49         ` Luca Ceresoli
@ 2025-09-10 10:59           ` Maxime Ripard
  2025-09-10 16:47             ` Luca Ceresoli
  0 siblings, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-09-10 10:59 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 2921 bytes --]

On Mon, Sep 08, 2025 at 03:49:06PM +0200, Luca Ceresoli wrote:
> Hi Maxime,
> 
> On Wed, 27 Aug 2025 09:46:03 +0200
> Maxime Ripard <mripard@kernel.org> wrote:
> 
> > On Wed, Aug 20, 2025 at 01:13:02PM +0200, Luca Ceresoli wrote:
> > > Hello Maxime,
> > > 
> > > On Tue, 19 Aug 2025 14:29:32 +0200
> > > Maxime Ripard <mripard@kernel.org> wrote:
> > >   
> > > > > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> > > > >  {
> > > > >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > > > >  
> > > > > +	drm_bridge_unplug(&ctx->bridge);
> > > > >  	drm_bridge_remove(&ctx->bridge);    
> > > > 
> > > > Shouldn't we merge drm_bridge_unplug with the release part of
> > > > devm_drm_bridge_alloc?  
> > > 
> > > I'm not sure I got what you are suggesting here, sorry.
> > > 
> > > Do you mean that __devm_drm_bridge_alloc() should add a devres action
> > > to call drm_bridge_unplug(), so the unplug is called implicitly and
> > > does not need to be called explicitly by all drivers?  
> > 
> > Yes
> > 
> > > If that's what you mean, I don't think that would work. Unless I'm
> > > missing something, devres actions are always invoked just after the
> > > driver .remove callback.  
> > 
> > Yes, they are called in reverse order of registration, after remove.
> > 
> > > But we need to call drm_bridge_unplug() at the beginning (or just
> > > before) .remove, at least for drivers that need to do something in
> > > .remove that cannot be done by devm.
> > > 
> > > In pseudocode:
> > > 
> > > mybridge_remove()
> > > {
> > >   drm_bridge_unplug(); <-- explicit call as in my patch
> > >   xyz_disable();
> > >   drm_bridge_unplug(); <-- implicitly done by devres
> > > }
> > > 
> > > We want xyz_disable() to be done after drm_bridge_unplug(), so other
> > > code paths using drm_bridge_enter/exit() won't mess with xyz.  
> > 
> > It's not clear to me why doing it before xyz_disable() is important
> > here? If anything, it would prevent from disabling the hardware for
> > example, even though you still have your memory mapping, clocks, power
> > domains, regulators, etc. to properly disable it.
> > 
> > You're still correct that it's a bad idea though because we want to do
> > it before we start freeing all those, so it needs to execute as the
> > before the devm actions ...
> > 
> > > devres actions cannot be added to be executed _before_ .remove, AFAIK.  
> > 
> > ... and we can't do that either.
> 
> I understand your words as "the drm_bridge_unplug() is OK where it is,
> your patch is OK in this respect". Correct?
> 
> So if this is correct, and my reply on the devres cleanups is also
> correct (other reply in this thread), that means the whole patch is OK.

I'm still confused why it's so important than in your example
xyz_disable must be called after drm_bridge_unplug.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-10  7:52         ` Maxime Ripard
@ 2025-09-10 16:34           ` Luca Ceresoli
  2025-09-11  6:44             ` Maxime Ripard
  0 siblings, 1 reply; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-10 16:34 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

On Wed, 10 Sep 2025 09:52:21 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> On Mon, Sep 08, 2025 at 03:49:01PM +0200, Luca Ceresoli wrote:
> > Hello Maxime,
> > 
> > On Wed, 20 Aug 2025 13:13:02 +0200
> > Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
> >   
> > > > > +	/*
> > > > > +	 * sn65dsi83_atomic_disable() should release some resources, but it
> > > > > +	 * cannot if we call drm_bridge_unplug() before it can
> > > > > +	 * drm_bridge_enter(). If that happens, let's release those
> > > > > +	 * resources now.
> > > > > +	 */
> > > > > +	if (ctx->disable_resources_needed) {
> > > > > +		if (!ctx->irq)
> > > > > +			sn65dsi83_monitor_stop(ctx);
> > > > > +
> > > > > +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> > > > > +		usleep_range(10000, 11000);
> > > > > +
> > > > > +		regulator_disable(ctx->vcc);
> > > > > +	}      
> > > > 
> > > > I'm not sure you need this. Wouldn't registering a devm action do the
> > > > same thing?    
> > > 
> > > Good idea, thanks. I'll give it a try.  
> > 
> > I'm catching up with this series after being busy a few weeks...
> > 
> > I looked at this, but contrary my initial impression I think it would
> > not be an improvement.
> > 
> > The reason is at least one of these cleanup actions (namely the
> > regulator_disable()) must be done only if there is a matching enable,
> > which is in atomic_pre_enable. This is why I introduced a flag in the
> > first place.
> > 
> > I'm not sure which usage of devres you had in mind, but I see two
> > options.
> > 
> > Option 1: in probe, add a devres action to call a function like:
> > 
> > sn65dsi83_cleanups()
> > {
> > 	if (ctx->disable_resources_needed) {
> > 		/* the same cleanups */
> > 	}    
> > }
> > 
> > But that is just a more indirect way of doing the same thing, and
> > relies on the same flag.
> > 
> > Option 2: have a function to unconditionally do the cleanups:
> > 
> > sn65dsi83_cleanups()
> > {
> > 	/* the same cleanups (no if) */
> > }
> > 
> > And then:
> >  * in atomic_pre_enable, instead of setting the flag
> >    add a devres action to call sn65dsi83_cleanups()
> >  * in atomic_disable, instead of clearing the flag
> >    remove the devres action
> > 
> > Even this option looks like more complicated and less readable code
> > to do the same thing.
> > 
> > Do you have in mind a better option that I haven't figured out?  
> 
> Would using devm_add_action in atomic_pre_enable, and
> devm_release_action in atomic_post_disable work?
> 
> That way, if you have a typical enable / disable cycle, the action will
> get registered and executed properly, and if you only have an enable but
> no matching disable, it will be collected after remove.

So you're OK with option 2. I just implemented it, works well and the
resulting code is a bit cleaner. Queued for v2.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-10 10:59           ` Maxime Ripard
@ 2025-09-10 16:47             ` Luca Ceresoli
  2025-09-15 12:03               ` Maxime Ripard
  0 siblings, 1 reply; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-10 16:47 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

On Wed, 10 Sep 2025 12:59:12 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> On Mon, Sep 08, 2025 at 03:49:06PM +0200, Luca Ceresoli wrote:
> > Hi Maxime,
> > 
> > On Wed, 27 Aug 2025 09:46:03 +0200
> > Maxime Ripard <mripard@kernel.org> wrote:
> >   
> > > On Wed, Aug 20, 2025 at 01:13:02PM +0200, Luca Ceresoli wrote:  
> > > > Hello Maxime,
> > > > 
> > > > On Tue, 19 Aug 2025 14:29:32 +0200
> > > > Maxime Ripard <mripard@kernel.org> wrote:
> > > >     
> > > > > > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> > > > > >  {
> > > > > >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > > > > >  
> > > > > > +	drm_bridge_unplug(&ctx->bridge);
> > > > > >  	drm_bridge_remove(&ctx->bridge);      
> > > > > 
> > > > > Shouldn't we merge drm_bridge_unplug with the release part of
> > > > > devm_drm_bridge_alloc?    
> > > > 
> > > > I'm not sure I got what you are suggesting here, sorry.
> > > > 
> > > > Do you mean that __devm_drm_bridge_alloc() should add a devres action
> > > > to call drm_bridge_unplug(), so the unplug is called implicitly and
> > > > does not need to be called explicitly by all drivers?    
> > > 
> > > Yes
> > >   
> > > > If that's what you mean, I don't think that would work. Unless I'm
> > > > missing something, devres actions are always invoked just after the
> > > > driver .remove callback.    
> > > 
> > > Yes, they are called in reverse order of registration, after remove.
> > >   
> > > > But we need to call drm_bridge_unplug() at the beginning (or just
> > > > before) .remove, at least for drivers that need to do something in
> > > > .remove that cannot be done by devm.
> > > > 
> > > > In pseudocode:
> > > > 
> > > > mybridge_remove()
> > > > {
> > > >   drm_bridge_unplug(); <-- explicit call as in my patch
> > > >   xyz_disable();
> > > >   drm_bridge_unplug(); <-- implicitly done by devres
> > > > }
> > > > 
> > > > We want xyz_disable() to be done after drm_bridge_unplug(), so other
> > > > code paths using drm_bridge_enter/exit() won't mess with xyz.    
> > > 
> > > It's not clear to me why doing it before xyz_disable() is important
> > > here? If anything, it would prevent from disabling the hardware for
> > > example, even though you still have your memory mapping, clocks, power
> > > domains, regulators, etc. to properly disable it.
> > > 
> > > You're still correct that it's a bad idea though because we want to do
> > > it before we start freeing all those, so it needs to execute as the
> > > before the devm actions ...
> > >   
> > > > devres actions cannot be added to be executed _before_ .remove, AFAIK.    
> > > 
> > > ... and we can't do that either.  
> > 
> > I understand your words as "the drm_bridge_unplug() is OK where it is,
> > your patch is OK in this respect". Correct?
> > 
> > So if this is correct, and my reply on the devres cleanups is also
> > correct (other reply in this thread), that means the whole patch is OK.  
> 
> I'm still confused why it's so important than in your example
> xyz_disable must be called after drm_bridge_unplug.

Let me clarify with an example.

As I wrote in another reply, I have moved from a flag
(disable_resources_needed) to a devres action as you had suggested, but
the example here is based on the old flag because it is more explicit,
code would be executed in the same order anyway, and, well, because I
had written the example before the devres action conversion.

Take these two functions (stripped versions of the actual ones):

/* Same as proposed, but with _unplug moved at the end */
static void sn65dsi83_remove()
{
	struct sn65dsi83 *ctx = i2c_get_clientdata(client);

	drm_bridge_remove(&ctx->bridge);
	
	/* 
	 * I moved the following code to a devm action, but keeping it
	 * explicit here for the discussion
	 */
	if (ctx->disable_resources_needed) {
		sn65dsi83_monitor_stop(ctx);
		regulator_disable(ctx->vcc);
	}
	
	drm_bridge_unplug(&ctx->bridge);     // At the end!
}

static void sn65dsi83_atomic_disable()
{
	if (!drm_bridge_enter(bridge, &idx))
		return;

	/* These 3 lines will be replaced by devm_release_action() */
	ctx->disable_resources_needed = false;
	sn65dsi83_monitor_stop(ctx);
	regulator_disable(ctx->vcc);

	drm_bridge_exit(idx);
}

Here the xyz_disable() in my pseudocode is the sn65dsi83_monitor_stop()
+ regulator_disable().

If sn65dsi83_remove() and sn65dsi83_atomic_disable() were to happen
concurrently, this sequence of events could happen:

1. atomic_disable:  drm_bridge_enter() -> OK, can go
2. remove:          drm_bridge_remove()
3. remove:          sn65dsi83_monitor_stop()
4. remove:          regulator_disable()
5. remove:          drm_bridge_unplug() -- too late to stop atomic_disable
6. atomic_disable:  ctx->disable_resources_needed = false -- too late to stop .remove
7. atomic_disable:  sn65dsi83_monitor_stop() -- twice, maybe no problem
8. atomic_disable:  regulator_disable() -- Twice, en/disable imbalance!

So there is an excess regulator disable, which is an error. I don't see
how this can be avoided if the drm_bridge_unplug() is called after the
regulator_disable().

Let me know whether this clarifies the need to _unplug at the beginning
of the .remove function.

Best regards,
Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-10 16:34           ` Luca Ceresoli
@ 2025-09-11  6:44             ` Maxime Ripard
  2025-09-11 13:09               ` Luca Ceresoli
  0 siblings, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-09-11  6:44 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 3258 bytes --]

On Wed, Sep 10, 2025 at 06:34:40PM +0200, Luca Ceresoli wrote:
> Hi Maxime,
> 
> On Wed, 10 Sep 2025 09:52:21 +0200
> Maxime Ripard <mripard@kernel.org> wrote:
> 
> > On Mon, Sep 08, 2025 at 03:49:01PM +0200, Luca Ceresoli wrote:
> > > Hello Maxime,
> > > 
> > > On Wed, 20 Aug 2025 13:13:02 +0200
> > > Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
> > >   
> > > > > > +	/*
> > > > > > +	 * sn65dsi83_atomic_disable() should release some resources, but it
> > > > > > +	 * cannot if we call drm_bridge_unplug() before it can
> > > > > > +	 * drm_bridge_enter(). If that happens, let's release those
> > > > > > +	 * resources now.
> > > > > > +	 */
> > > > > > +	if (ctx->disable_resources_needed) {
> > > > > > +		if (!ctx->irq)
> > > > > > +			sn65dsi83_monitor_stop(ctx);
> > > > > > +
> > > > > > +		gpiod_set_value_cansleep(ctx->enable_gpio, 0);
> > > > > > +		usleep_range(10000, 11000);
> > > > > > +
> > > > > > +		regulator_disable(ctx->vcc);
> > > > > > +	}      
> > > > > 
> > > > > I'm not sure you need this. Wouldn't registering a devm action do the
> > > > > same thing?    
> > > > 
> > > > Good idea, thanks. I'll give it a try.  
> > > 
> > > I'm catching up with this series after being busy a few weeks...
> > > 
> > > I looked at this, but contrary my initial impression I think it would
> > > not be an improvement.
> > > 
> > > The reason is at least one of these cleanup actions (namely the
> > > regulator_disable()) must be done only if there is a matching enable,
> > > which is in atomic_pre_enable. This is why I introduced a flag in the
> > > first place.
> > > 
> > > I'm not sure which usage of devres you had in mind, but I see two
> > > options.
> > > 
> > > Option 1: in probe, add a devres action to call a function like:
> > > 
> > > sn65dsi83_cleanups()
> > > {
> > > 	if (ctx->disable_resources_needed) {
> > > 		/* the same cleanups */
> > > 	}    
> > > }
> > > 
> > > But that is just a more indirect way of doing the same thing, and
> > > relies on the same flag.
> > > 
> > > Option 2: have a function to unconditionally do the cleanups:
> > > 
> > > sn65dsi83_cleanups()
> > > {
> > > 	/* the same cleanups (no if) */
> > > }
> > > 
> > > And then:
> > >  * in atomic_pre_enable, instead of setting the flag
> > >    add a devres action to call sn65dsi83_cleanups()
> > >  * in atomic_disable, instead of clearing the flag
> > >    remove the devres action
> > > 
> > > Even this option looks like more complicated and less readable code
> > > to do the same thing.
> > > 
> > > Do you have in mind a better option that I haven't figured out?  
> > 
> > Would using devm_add_action in atomic_pre_enable, and
> > devm_release_action in atomic_post_disable work?
> > 
> > That way, if you have a typical enable / disable cycle, the action will
> > get registered and executed properly, and if you only have an enable but
> > no matching disable, it will be collected after remove.
> 
> So you're OK with option 2. I just implemented it, works well and the
> resulting code is a bit cleaner. Queued for v2.

Kind of, but you shouldn't remove but release it, and it doesn't have to
be a single action / function.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-11  6:44             ` Maxime Ripard
@ 2025-09-11 13:09               ` Luca Ceresoli
  0 siblings, 0 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-11 13:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

On Thu, 11 Sep 2025 08:44:34 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> > > > Option 2: have a function to unconditionally do the cleanups:
> > > > 
> > > > sn65dsi83_cleanups()
> > > > {
> > > > 	/* the same cleanups (no if) */
> > > > }
> > > > 
> > > > And then:
> > > >  * in atomic_pre_enable, instead of setting the flag
> > > >    add a devres action to call sn65dsi83_cleanups()
> > > >  * in atomic_disable, instead of clearing the flag
> > > >    remove the devres action
> > > > 
> > > > Even this option looks like more complicated and less readable code
> > > > to do the same thing.
> > > > 
> > > > Do you have in mind a better option that I haven't figured out?    
> > > 
> > > Would using devm_add_action in atomic_pre_enable, and
> > > devm_release_action in atomic_post_disable work?
> > > 
> > > That way, if you have a typical enable / disable cycle, the action will
> > > get registered and executed properly, and if you only have an enable but
> > > no matching disable, it will be collected after remove.  
> > 
> > So you're OK with option 2. I just implemented it, works well and the
> > resulting code is a bit cleaner. Queued for v2.  
> 
> Kind of, but you shouldn't remove but release it, and it doesn't have to
> be a single action / function.

Released instead of removed: yes.

Doesn't have to be a single function: I currently implemented a single
function with the 3 actions that are currently done in atomic_disable.
I think you propose to add 3 different devres actions, one for each,
but it would be more code and a little more resources used and I don't
see the advantage.

I think it makes sense that I send my current version and we can
continue discussion based on the code. I'm waiting a bit before
sending it, in case you have feedback about the other branch of this
discussion (placement of drm_bridge_unplug()).

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-10 16:47             ` Luca Ceresoli
@ 2025-09-15 12:03               ` Maxime Ripard
  2025-09-15 14:51                 ` Luca Ceresoli
  0 siblings, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-09-15 12:03 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 6368 bytes --]

On Wed, Sep 10, 2025 at 06:47:52PM +0200, Luca Ceresoli wrote:
> On Wed, 10 Sep 2025 12:59:12 +0200
> Maxime Ripard <mripard@kernel.org> wrote:
> 
> > On Mon, Sep 08, 2025 at 03:49:06PM +0200, Luca Ceresoli wrote:
> > > Hi Maxime,
> > > 
> > > On Wed, 27 Aug 2025 09:46:03 +0200
> > > Maxime Ripard <mripard@kernel.org> wrote:
> > >   
> > > > On Wed, Aug 20, 2025 at 01:13:02PM +0200, Luca Ceresoli wrote:  
> > > > > Hello Maxime,
> > > > > 
> > > > > On Tue, 19 Aug 2025 14:29:32 +0200
> > > > > Maxime Ripard <mripard@kernel.org> wrote:
> > > > >     
> > > > > > > @@ -1005,7 +1041,24 @@ static void sn65dsi83_remove(struct i2c_client *client)
> > > > > > >  {
> > > > > > >  	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > > > > > >  
> > > > > > > +	drm_bridge_unplug(&ctx->bridge);
> > > > > > >  	drm_bridge_remove(&ctx->bridge);      
> > > > > > 
> > > > > > Shouldn't we merge drm_bridge_unplug with the release part of
> > > > > > devm_drm_bridge_alloc?    
> > > > > 
> > > > > I'm not sure I got what you are suggesting here, sorry.
> > > > > 
> > > > > Do you mean that __devm_drm_bridge_alloc() should add a devres action
> > > > > to call drm_bridge_unplug(), so the unplug is called implicitly and
> > > > > does not need to be called explicitly by all drivers?    
> > > > 
> > > > Yes
> > > >   
> > > > > If that's what you mean, I don't think that would work. Unless I'm
> > > > > missing something, devres actions are always invoked just after the
> > > > > driver .remove callback.    
> > > > 
> > > > Yes, they are called in reverse order of registration, after remove.
> > > >   
> > > > > But we need to call drm_bridge_unplug() at the beginning (or just
> > > > > before) .remove, at least for drivers that need to do something in
> > > > > .remove that cannot be done by devm.
> > > > > 
> > > > > In pseudocode:
> > > > > 
> > > > > mybridge_remove()
> > > > > {
> > > > >   drm_bridge_unplug(); <-- explicit call as in my patch
> > > > >   xyz_disable();
> > > > >   drm_bridge_unplug(); <-- implicitly done by devres
> > > > > }
> > > > > 
> > > > > We want xyz_disable() to be done after drm_bridge_unplug(), so other
> > > > > code paths using drm_bridge_enter/exit() won't mess with xyz.    
> > > > 
> > > > It's not clear to me why doing it before xyz_disable() is important
> > > > here? If anything, it would prevent from disabling the hardware for
> > > > example, even though you still have your memory mapping, clocks, power
> > > > domains, regulators, etc. to properly disable it.
> > > > 
> > > > You're still correct that it's a bad idea though because we want to do
> > > > it before we start freeing all those, so it needs to execute as the
> > > > before the devm actions ...
> > > >   
> > > > > devres actions cannot be added to be executed _before_ .remove, AFAIK.    
> > > > 
> > > > ... and we can't do that either.  
> > > 
> > > I understand your words as "the drm_bridge_unplug() is OK where it is,
> > > your patch is OK in this respect". Correct?
> > > 
> > > So if this is correct, and my reply on the devres cleanups is also
> > > correct (other reply in this thread), that means the whole patch is OK.  
> > 
> > I'm still confused why it's so important than in your example
> > xyz_disable must be called after drm_bridge_unplug.
> 
> Let me clarify with an example.
> 
> As I wrote in another reply, I have moved from a flag
> (disable_resources_needed) to a devres action as you had suggested, but
> the example here is based on the old flag because it is more explicit,
> code would be executed in the same order anyway, and, well, because I
> had written the example before the devres action conversion.
> 
> Take these two functions (stripped versions of the actual ones):
> 
> /* Same as proposed, but with _unplug moved at the end */
> static void sn65dsi83_remove()
> {
> 	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> 
> 	drm_bridge_remove(&ctx->bridge);
> 	
> 	/* 
> 	 * I moved the following code to a devm action, but keeping it
> 	 * explicit here for the discussion
> 	 */
> 	if (ctx->disable_resources_needed) {
> 		sn65dsi83_monitor_stop(ctx);
> 		regulator_disable(ctx->vcc);
> 	}
> 	
> 	drm_bridge_unplug(&ctx->bridge);     // At the end!
> }

First off, why do we need to have drm_bridge_unplug and
drm_bridge_remove separate?

If we were to mirror drm_dev_enter and drm_dev_unplug, drm_dev_unplug
calls drm_dev_unregister itself, and I can't find a reason where we
might want to split the two.

> static void sn65dsi83_atomic_disable()
> {
> 	if (!drm_bridge_enter(bridge, &idx))
> 		return;
> 
> 	/* These 3 lines will be replaced by devm_release_action() */
> 	ctx->disable_resources_needed = false;
> 	sn65dsi83_monitor_stop(ctx);
> 	regulator_disable(ctx->vcc);
> 
> 	drm_bridge_exit(idx);
> }
> 
> Here the xyz_disable() in my pseudocode is the sn65dsi83_monitor_stop()
> + regulator_disable().
> 
> If sn65dsi83_remove() and sn65dsi83_atomic_disable() were to happen
> concurrently, this sequence of events could happen:
> 
> 1. atomic_disable:  drm_bridge_enter() -> OK, can go
> 2. remove:          drm_bridge_remove()
> 3. remove:          sn65dsi83_monitor_stop()
> 4. remove:          regulator_disable()
> 5. remove:          drm_bridge_unplug() -- too late to stop atomic_disable

drm_dev_unplug would also get delayed until drm_dev_exit is called,
mitigating your issue here.

> 6. atomic_disable:  ctx->disable_resources_needed = false -- too late to stop .remove
> 7. atomic_disable:  sn65dsi83_monitor_stop() -- twice, maybe no problem
> 8. atomic_disable:  regulator_disable() -- Twice, en/disable imbalance!
> 
> So there is an excess regulator disable, which is an error. I don't see
> how this can be avoided if the drm_bridge_unplug() is called after the
> regulator_disable().
> 
> Let me know whether this clarifies the need to _unplug at the beginning
> of the .remove function.

Another thing that just crossed my mind is why we don't call
atomic_disable when we're tearing down the bridge too. We're doing it
for the main DRM devices, it would make sense to me to disable the
encoder -> bridge -> connector (and possibly CRTC) chain if we remove a
bridge automatically.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-15 12:03               ` Maxime Ripard
@ 2025-09-15 14:51                 ` Luca Ceresoli
  2025-09-26 16:37                   ` Luca Ceresoli
  2025-10-07 15:09                   ` Maxime Ripard
  0 siblings, 2 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-15 14:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

thanks for the feedback, this discussion is getting very interesting!

On Mon, 15 Sep 2025 14:03:17 +0200
Maxime Ripard <mripard@kernel.org> wrote:

> > > I'm still confused why it's so important than in your example
> > > xyz_disable must be called after drm_bridge_unplug.  
> > 
> > Let me clarify with an example.
> > 
> > As I wrote in another reply, I have moved from a flag
> > (disable_resources_needed) to a devres action as you had suggested, but
> > the example here is based on the old flag because it is more explicit,
> > code would be executed in the same order anyway, and, well, because I
> > had written the example before the devres action conversion.
> > 
> > Take these two functions (stripped versions of the actual ones):
> > 
> > /* Same as proposed, but with _unplug moved at the end */
> > static void sn65dsi83_remove()
> > {
> > 	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > 
> > 	drm_bridge_remove(&ctx->bridge);
> > 	
> > 	/* 
> > 	 * I moved the following code to a devm action, but keeping it
> > 	 * explicit here for the discussion
> > 	 */
> > 	if (ctx->disable_resources_needed) {
> > 		sn65dsi83_monitor_stop(ctx);
> > 		regulator_disable(ctx->vcc);
> > 	}
> > 	
> > 	drm_bridge_unplug(&ctx->bridge);     // At the end!
> > }  
> 
> First off, why do we need to have drm_bridge_unplug and
> drm_bridge_remove separate?
> 
> If we were to mirror drm_dev_enter and drm_dev_unplug, drm_dev_unplug
> calls drm_dev_unregister itself, and I can't find a reason where we
> might want to split the two.

I think it could make sense and I'm definitely open to it.

After a quick analysis I have mostly one concern. Calls
to drm_bridge_add() and drm_bridge_remove() are balanced in current
code and that's very intuitive. If drm_bridge_unplug() were to call
drm_bridge_remove(), that symmetry would disappear. Some drivers would
still need to call drm_bridge_remove() directly (e.g. the DSI host
drivers which _add/remove() in the DSI attach/detach callbacks), while
other wouldn't because drm_bridge_unplug() would do that.

What do you think about this?

Another concern I initially had is about drivers whose usage of
drm_bridge is more complex than the average. Most simple drivers just
call drm_bridge_remove() in their .remove callback and that's
straightforward. I was suspicious about drivers such as
imx8qxp-pixel-combiner which instantiate multiple bridges, and whether
they need do all the drm_bridge_unplug()s before all the
drm_bridge_remove()s. However I don't think that's a real need because,
except for probe and removal, operations on bridges happen on a
per-bridge basis, so each bridge is independent from others, at least
for the driver I mentioned.

> > static void sn65dsi83_atomic_disable()
> > {
> > 	if (!drm_bridge_enter(bridge, &idx))
> > 		return;
> > 
> > 	/* These 3 lines will be replaced by devm_release_action() */
> > 	ctx->disable_resources_needed = false;
> > 	sn65dsi83_monitor_stop(ctx);
> > 	regulator_disable(ctx->vcc);
> > 
> > 	drm_bridge_exit(idx);
> > }
> > 
> > Here the xyz_disable() in my pseudocode is the sn65dsi83_monitor_stop()
> > + regulator_disable().
> > 
> > If sn65dsi83_remove() and sn65dsi83_atomic_disable() were to happen
> > concurrently, this sequence of events could happen:
> > 
> > 1. atomic_disable:  drm_bridge_enter() -> OK, can go
> > 2. remove:          drm_bridge_remove()
> > 3. remove:          sn65dsi83_monitor_stop()
> > 4. remove:          regulator_disable()
> > 5. remove:          drm_bridge_unplug() -- too late to stop atomic_disable  
> 
> drm_dev_unplug would also get delayed until drm_dev_exit is called,
> mitigating your issue here.

I don't think I got what you mean. With the above code the regulator
would still be subject to an en/disable imbalance.

However I realized the problem does not exist when using devres,
because devres itself takes care of executing each release function only
once, by means of a spinlock.

I think using devres actually solves my concerns about removal during
atomic[_post]_disable, but also for the atomic[_pre]_enable and other
call paths. Also, I think it makes the question of which goes first
(drm_bridge_unplug() or _remove()) way less relevant.

The concern is probably still valid for drivers which don't use devres.
However the concern is irrelevant until there is a need for a bridge to
become hot-pluggable. At that point a driver needs to either move to
devres or take other actions to avoid incurring in the same issue.

I'm going to send soon a v2 with my devres changes so we can continue
this discussion on actual code.

> > 6. atomic_disable:  ctx->disable_resources_needed = false -- too late to stop .remove
> > 7. atomic_disable:  sn65dsi83_monitor_stop() -- twice, maybe no problem
> > 8. atomic_disable:  regulator_disable() -- Twice, en/disable imbalance!
> > 
> > So there is an excess regulator disable, which is an error. I don't see
> > how this can be avoided if the drm_bridge_unplug() is called after the
> > regulator_disable().
> > 
> > Let me know whether this clarifies the need to _unplug at the beginning
> > of the .remove function.  
> 
> Another thing that just crossed my mind is why we don't call
> atomic_disable when we're tearing down the bridge too. We're doing it
> for the main DRM devices, it would make sense to me to disable the
> encoder -> bridge -> connector (and possibly CRTC) chain if we remove a
> bridge automatically.

Uh, interesting idea.

Do you mean something like:

void drm_bridge_unplug(struct drm_bridge *bridge)
{
    bridge->unplugged = true;
    synchronize_srcu(&drm_bridge_unplug_srcu);

    drm_bridge_remove(bridge); // as per discussion above

    drm_atomic_helper_shutdown(bridge->dev);
}

?

I'm not sure which is the right call to tear down the pipeline though.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-15 14:51                 ` Luca Ceresoli
@ 2025-09-26 16:37                   ` Luca Ceresoli
  2025-10-07 15:09                   ` Maxime Ripard
  1 sibling, 0 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-09-26 16:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

On Mon, 15 Sep 2025 16:51:56 +0200
Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:

> I'm going to send soon a v2 with my devres changes so we can continue
> this discussion on actual code.

v2 sent, with the devres changes. Discussion con continue there.

Best regards,
Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-09-15 14:51                 ` Luca Ceresoli
  2025-09-26 16:37                   ` Luca Ceresoli
@ 2025-10-07 15:09                   ` Maxime Ripard
  2025-10-09 14:48                     ` Luca Ceresoli
  1 sibling, 1 reply; 19+ messages in thread
From: Maxime Ripard @ 2025-10-07 15:09 UTC (permalink / raw)
  To: Luca Ceresoli
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

[-- Attachment #1: Type: text/plain, Size: 7900 bytes --]

On Mon, Sep 15, 2025 at 04:51:56PM +0200, Luca Ceresoli wrote:
> Hi Maxime,
> 
> thanks for the feedback, this discussion is getting very interesting!
> 
> On Mon, 15 Sep 2025 14:03:17 +0200
> Maxime Ripard <mripard@kernel.org> wrote:
> 
> > > > I'm still confused why it's so important than in your example
> > > > xyz_disable must be called after drm_bridge_unplug.  
> > > 
> > > Let me clarify with an example.
> > > 
> > > As I wrote in another reply, I have moved from a flag
> > > (disable_resources_needed) to a devres action as you had suggested, but
> > > the example here is based on the old flag because it is more explicit,
> > > code would be executed in the same order anyway, and, well, because I
> > > had written the example before the devres action conversion.
> > > 
> > > Take these two functions (stripped versions of the actual ones):
> > > 
> > > /* Same as proposed, but with _unplug moved at the end */
> > > static void sn65dsi83_remove()
> > > {
> > > 	struct sn65dsi83 *ctx = i2c_get_clientdata(client);
> > > 
> > > 	drm_bridge_remove(&ctx->bridge);
> > > 	
> > > 	/* 
> > > 	 * I moved the following code to a devm action, but keeping it
> > > 	 * explicit here for the discussion
> > > 	 */
> > > 	if (ctx->disable_resources_needed) {
> > > 		sn65dsi83_monitor_stop(ctx);
> > > 		regulator_disable(ctx->vcc);
> > > 	}
> > > 	
> > > 	drm_bridge_unplug(&ctx->bridge);     // At the end!
> > > }  
> > 
> > First off, why do we need to have drm_bridge_unplug and
> > drm_bridge_remove separate?
> > 
> > If we were to mirror drm_dev_enter and drm_dev_unplug, drm_dev_unplug
> > calls drm_dev_unregister itself, and I can't find a reason where we
> > might want to split the two.
> 
> I think it could make sense and I'm definitely open to it.
> 
> After a quick analysis I have mostly one concern. Calls
> to drm_bridge_add() and drm_bridge_remove() are balanced in current
> code and that's very intuitive. If drm_bridge_unplug() were to call
> drm_bridge_remove(), that symmetry would disappear. Some drivers would
> still need to call drm_bridge_remove() directly (e.g. the DSI host
> drivers which _add/remove() in the DSI attach/detach callbacks), while
> other wouldn't because drm_bridge_unplug() would do that.
> 
> What do you think about this?

Which DSI host do you have in mind there? Because it's really not what
we document.

> Another concern I initially had is about drivers whose usage of
> drm_bridge is more complex than the average. Most simple drivers just
> call drm_bridge_remove() in their .remove callback and that's
> straightforward. I was suspicious about drivers such as
> imx8qxp-pixel-combiner which instantiate multiple bridges, and whether
> they need do all the drm_bridge_unplug()s before all the
> drm_bridge_remove()s. However I don't think that's a real need because,
> except for probe and removal, operations on bridges happen on a
> per-bridge basis, so each bridge is independent from others, at least
> for the driver I mentioned.

In this particular case, they would be unplugged all at the same time,
right? In which case, we would disable all the bridges starting from the
one in the chain that just got removed, and then we just have to remove
all of them.

All in all, I think it's ok to somewhat break things here: all this was
broken before. If we want to bring some consistency, we will have to
reduce what bridges are allowed to do. Let's figure out something that
works for all reasonable cases (straightforward, component framework,
DSI device, DSI host, and DSI device on another bus), and the hacky
drivers will move eventually.

That's pretty easy to solve with a documentation update :)

We can just further restrict the order in which

> > > static void sn65dsi83_atomic_disable()
> > > {
> > > 	if (!drm_bridge_enter(bridge, &idx))
> > > 		return;
> > > 
> > > 	/* These 3 lines will be replaced by devm_release_action() */
> > > 	ctx->disable_resources_needed = false;
> > > 	sn65dsi83_monitor_stop(ctx);
> > > 	regulator_disable(ctx->vcc);
> > > 
> > > 	drm_bridge_exit(idx);
> > > }
> > > 
> > > Here the xyz_disable() in my pseudocode is the sn65dsi83_monitor_stop()
> > > + regulator_disable().
> > > 
> > > If sn65dsi83_remove() and sn65dsi83_atomic_disable() were to happen
> > > concurrently, this sequence of events could happen:
> > > 
> > > 1. atomic_disable:  drm_bridge_enter() -> OK, can go
> > > 2. remove:          drm_bridge_remove()
> > > 3. remove:          sn65dsi83_monitor_stop()
> > > 4. remove:          regulator_disable()
> > > 5. remove:          drm_bridge_unplug() -- too late to stop atomic_disable  
> > 
> > drm_dev_unplug would also get delayed until drm_dev_exit is called,
> > mitigating your issue here.
> 
> I don't think I got what you mean. With the above code the regulator
> would still be subject to an en/disable imbalance.

My point was that drm_bridge_remove wouldn't be allowed to execute until
after atomic_disable has called drm_bridge_exit. So we wouldn't have the
sequence of events you described. atomic_disable would disable the
bridge, and then drm_bridge_remove wouln't have anything to disable
anymore by the time it runs.

> However I realized the problem does not exist when using devres,
> because devres itself takes care of executing each release function only
> once, by means of a spinlock.
> 
> I think using devres actually solves my concerns about removal during
> atomic[_post]_disable, but also for the atomic[_pre]_enable and other
> call paths. Also, I think it makes the question of which goes first
> (drm_bridge_unplug() or _remove()) way less relevant.
> 
> The concern is probably still valid for drivers which don't use devres.
> However the concern is irrelevant until there is a need for a bridge to
> become hot-pluggable. At that point a driver needs to either move to
> devres or take other actions to avoid incurring in the same issue.

I disagree with that statement. We never considered !devres as outdated,
and thus we need to support both. Especially if it's about races we know
about in a code path we might never run.

> I'm going to send soon a v2 with my devres changes so we can continue
> this discussion on actual code.
> 
> > > 6. atomic_disable:  ctx->disable_resources_needed = false -- too late to stop .remove
> > > 7. atomic_disable:  sn65dsi83_monitor_stop() -- twice, maybe no problem
> > > 8. atomic_disable:  regulator_disable() -- Twice, en/disable imbalance!
> > > 
> > > So there is an excess regulator disable, which is an error. I don't see
> > > how this can be avoided if the drm_bridge_unplug() is called after the
> > > regulator_disable().
> > > 
> > > Let me know whether this clarifies the need to _unplug at the beginning
> > > of the .remove function.  
> > 
> > Another thing that just crossed my mind is why we don't call
> > atomic_disable when we're tearing down the bridge too. We're doing it
> > for the main DRM devices, it would make sense to me to disable the
> > encoder -> bridge -> connector (and possibly CRTC) chain if we remove a
> > bridge automatically.
> 
> Uh, interesting idea.
> 
> Do you mean something like:
> 
> void drm_bridge_unplug(struct drm_bridge *bridge)
> {
>     bridge->unplugged = true;
>     synchronize_srcu(&drm_bridge_unplug_srcu);
> 
>     drm_bridge_remove(bridge); // as per discussion above
> 
>     drm_atomic_helper_shutdown(bridge->dev);
> }
> 
> ?
> 
> I'm not sure which is the right call to tear down the pipeline though.

No, the shutdown needs to happen before marking the bridge unplugged,
otherwise you'll never run the disable callbacks.

And we probably shouldn't disable the whole device, just everything from
the CRTC that feeds the bridge.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug
  2025-10-07 15:09                   ` Maxime Ripard
@ 2025-10-09 14:48                     ` Luca Ceresoli
  0 siblings, 0 replies; 19+ messages in thread
From: Luca Ceresoli @ 2025-10-09 14:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Thomas Zimmermann, David Airlie, Simona Vetter, Hui Pu,
	Thomas Petazzoni, dri-devel, linux-kernel, Dmitry Baryshkov

Hi Maxime,

On Tue Oct 7, 2025 at 5:09 PM CEST, Maxime Ripard wrote:
>> > First off, why do we need to have drm_bridge_unplug and
>> > drm_bridge_remove separate?
>> >
>> > If we were to mirror drm_dev_enter and drm_dev_unplug, drm_dev_unplug
>> > calls drm_dev_unregister itself, and I can't find a reason where we
>> > might want to split the two.
>>
>> I think it could make sense and I'm definitely open to it.
>>
>> After a quick analysis I have mostly one concern. Calls
>> to drm_bridge_add() and drm_bridge_remove() are balanced in current
>> code and that's very intuitive. If drm_bridge_unplug() were to call
>> drm_bridge_remove(), that symmetry would disappear. Some drivers would
>> still need to call drm_bridge_remove() directly (e.g. the DSI host
>> drivers which _add/remove() in the DSI attach/detach callbacks), while
>> other wouldn't because drm_bridge_unplug() would do that.
>>
>> What do you think about this?
>
> Which DSI host do you have in mind there? Because it's really not what
> we document.

Most DSI host drivers (but not all). I did a classification a few months
ago (~v6.15) and found that the following drivers do the same
(drm_bridge_add in the DSI host attach callback, drm_bridge_remove in the
DSI host detach callback):

     drivers/gpu/drm/bridge/samsung-dsim.c           (see below)
     drivers/gpu/drm/vc4/vc4_dsi.c
     drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
     drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
     drivers/gpu/drm/mediatek/mtk_dsi.c
     drivers/gpu/drm/bridge/tc358768.c
     drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c
     drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
     drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
     drivers/gpu/drm/adp/adp-mipi.c

while these do differently:

   - drm_bridge_add/remove() in driver probe/remove:
       drivers/gpu/drm/omapdrm/dss/dsi.c
       drivers/gpu/drm/bridge/nwl-dsi.c
   - drm_bridge_add/remove() in component_ops.bind/unbind:
       drivers/gpu/drm/mcde/mcde_dsi.c

I had sent a patch to change this in the samsung-dsim driver a while ago:
https://lore.kernel.org/lkml/20250725-drm-bridge-samsung-dsim-add-in-probe-v1-1-b23d29c23fbd@bootlin.com/

However your review to that patch suggested to me that you consider OK what
samsung-dsim and most other DSI host drivers currently do (but it's being
discussed in the above-linked thread, I'd say let's keep it there).

Now I am confused. Do you mean that those drivers' DSI host detach callback
should call drm_bridge_unplug(), which in turn would call
drm_bridge_remove()?

I was assuming drm_bridge_unplug() would always be called in the driver
.remove callback.

>> Another concern I initially had is about drivers whose usage of
>> drm_bridge is more complex than the average. Most simple drivers just
>> call drm_bridge_remove() in their .remove callback and that's
>> straightforward. I was suspicious about drivers such as
>> imx8qxp-pixel-combiner which instantiate multiple bridges, and whether
>> they need do all the drm_bridge_unplug()s before all the
>> drm_bridge_remove()s. However I don't think that's a real need because,
>> except for probe and removal, operations on bridges happen on a
>> per-bridge basis, so each bridge is independent from others, at least
>> for the driver I mentioned.
>
> In this particular case, they would be unplugged all at the same time,
> right? In which case, we would disable all the bridges starting from the
> one in the chain that just got removed, and then we just have to remove
> all of them.
>
> All in all, I think it's ok to somewhat break things here: all this was
> broken before.

...

> If we want to bring some consistency, we will have to
> reduce what bridges are allowed to do. Let's figure out something that
> works for all reasonable cases (straightforward, component framework,
> DSI device, DSI host, and DSI device on another bus), and the hacky
> drivers will move eventually.

I agree with the principle in the quoted lines. But I'm not sure exactly
which "something that works for all reasonable cases" you are suggesting:
moving drm_bridge_remove() inside drm_bridge_unplug()?

> That's pretty easy to solve with a documentation update :)
>
> We can just further restrict the order in which

Oops, unfinished sentence?

>> > > static void sn65dsi83_atomic_disable()
>> > > {
>> > > 	if (!drm_bridge_enter(bridge, &idx))
>> > > 		return;
>> > >
>> > > 	/* These 3 lines will be replaced by devm_release_action() */
>> > > 	ctx->disable_resources_needed = false;
>> > > 	sn65dsi83_monitor_stop(ctx);
>> > > 	regulator_disable(ctx->vcc);
>> > >
>> > > 	drm_bridge_exit(idx);
>> > > }
>> > >
>> > > Here the xyz_disable() in my pseudocode is the sn65dsi83_monitor_stop()
>> > > + regulator_disable().
>> > >
>> > > If sn65dsi83_remove() and sn65dsi83_atomic_disable() were to happen
>> > > concurrently, this sequence of events could happen:
>> > >
>> > > 1. atomic_disable:  drm_bridge_enter() -> OK, can go
>> > > 2. remove:          drm_bridge_remove()
>> > > 3. remove:          sn65dsi83_monitor_stop()
>> > > 4. remove:          regulator_disable()
>> > > 5. remove:          drm_bridge_unplug() -- too late to stop atomic_disable
>> >
>> > drm_dev_unplug would also get delayed until drm_dev_exit is called,
>> > mitigating your issue here.
>>
>> I don't think I got what you mean. With the above code the regulator
>> would still be subject to an en/disable imbalance.
>
> My point was that drm_bridge_remove wouldn't be allowed to execute until
> after atomic_disable has called drm_bridge_exit. So we wouldn't have the
> sequence of events you described. atomic_disable would disable the
> bridge, and then drm_bridge_remove wouln't have anything to disable
> anymore by the time it runs.

Ah, I think you was reasoning about the case with drm_bridge_remove()
called by drm_bridge_unplug(). If that's the case, yes, that's probably
right, e.g. with this drm_bridge_unplug() implementation:

void drm_bridge_unplug(struct drm_bridge *bridge)
{
	bridge->unplugged = true;

	synchronize_srcu(&drm_bridge_unplug_srcu);

	drm_bridge_remove();
}

Oh, wow, this looks suspiciourly similar to drm_dev_unplug(). ;)

>> However I realized the problem does not exist when using devres,
>> because devres itself takes care of executing each release function only
>> once, by means of a spinlock.
>>
>> I think using devres actually solves my concerns about removal during
>> atomic[_post]_disable, but also for the atomic[_pre]_enable and other
>> call paths. Also, I think it makes the question of which goes first
>> (drm_bridge_unplug() or _remove()) way less relevant.
>>
>> The concern is probably still valid for drivers which don't use devres.
>> However the concern is irrelevant until there is a need for a bridge to
>> become hot-pluggable. At that point a driver needs to either move to
>> devres or take other actions to avoid incurring in the same issue.
>
> I disagree with that statement. We never considered !devres as outdated,
> and thus we need to support both. Especially if it's about races we know
> about in a code path we might never run.

I didn't mean that, sorry if I was not clear.

I was meaning: for drivers which don't care about supporting hotplug, this
whole discussion is quite irrelevant. Those which will need to support
hotplug will have to ensure to release device resources exactly once, and
can do that either using devres or by other means.

>> > Another thing that just crossed my mind is why we don't call
>> > atomic_disable when we're tearing down the bridge too. We're doing it
>> > for the main DRM devices, it would make sense to me to disable the
>> > encoder -> bridge -> connector (and possibly CRTC) chain if we remove a
>> > bridge automatically.
>>
>> Uh, interesting idea.
>>
>> Do you mean something like:
>>
>> void drm_bridge_unplug(struct drm_bridge *bridge)
>> {
>>     bridge->unplugged = true;
>>     synchronize_srcu(&drm_bridge_unplug_srcu);
>>
>>     drm_bridge_remove(bridge); // as per discussion above
>>
>>     drm_atomic_helper_shutdown(bridge->dev);
>> }
>>
>> ?
>>
>> I'm not sure which is the right call to tear down the pipeline though.
>
> No, the shutdown needs to happen before marking the bridge unplugged,
> otherwise you'll never run the disable callbacks.

OK.

> And we probably shouldn't disable the whole device, just everything from
> the CRTC that feeds the bridge.

OK, I'll need to figure out how todo that exactly. If you have hints, that
would be great.

Anyway I think it's better to do this in steps: first introduce
drm_bridge_unplug() as discussed, and at a later step augment it to disable
the involved pipeline components on bridge removal. Sounds good?

Best regards,
Luca

--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2025-10-09 14:48 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-08 13:24 [PATCH 0/2] drm/bridge: handle gracefully atomic updates during bridge removal Luca Ceresoli
2025-08-08 13:24 ` [PATCH 1/2] drm/bridge: add drm_bridge_unplug() and drm_bridge_enter/exit() Luca Ceresoli
2025-08-08 13:24 ` [PATCH 2/2] drm/bridge: ti-sn65dsi83: protect device resources on unplug Luca Ceresoli
2025-08-19 12:29   ` Maxime Ripard
2025-08-20 11:13     ` Luca Ceresoli
2025-08-27  7:46       ` Maxime Ripard
2025-09-08 13:49         ` Luca Ceresoli
2025-09-10 10:59           ` Maxime Ripard
2025-09-10 16:47             ` Luca Ceresoli
2025-09-15 12:03               ` Maxime Ripard
2025-09-15 14:51                 ` Luca Ceresoli
2025-09-26 16:37                   ` Luca Ceresoli
2025-10-07 15:09                   ` Maxime Ripard
2025-10-09 14:48                     ` Luca Ceresoli
2025-09-08 13:49       ` Luca Ceresoli
2025-09-10  7:52         ` Maxime Ripard
2025-09-10 16:34           ` Luca Ceresoli
2025-09-11  6:44             ` Maxime Ripard
2025-09-11 13:09               ` Luca Ceresoli

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