public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state
@ 2024-09-17 14:09 Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 1/4] " Tomi Valkeinen
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-17 14:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, Laurent Pinchart
  Cc: linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

Add cleanup macros for the subdev active state. While we could add more
macros to handle state locking in different situations, I believe the
two macros introduced here are the ones most often needed.

A few drivers are changed to use the macros, as an example.

A few thoughts:

The scoped_v4l2_subdev_lock_and_get_active_state() macro will define an
implicitly named 'state' variable inside the scope. This is a bit
similar to scoped_guard(), which defined an implicitly named 'scope'
variable. However, adding the name of the variable as a parameter to the
macro is an easy addition, if needed. Then the usage would be:

    scoped_v4l2_subdev_lock_and_get_active_state(subdev, state) {
    }

Using the CLASS() version does take the name of the variable. The two
macros also look quite different, so I wonder if we should make a helper
macro to hide the CLASS() usage (I don't know what to call it...):

    #define init_v4l2_subdev_lock_and_get_active_state(sd) \
         CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd)

The macro names are quite long, but so is the function name of
'v4l2_subdev_lock_and_get_active_state', which these macros often
replace.

 Tomi

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
Tomi Valkeinen (4):
      media: v4l2-subdev: Add cleanup macros for active state
      media: v4l2-subdev: Use state cleanup macros
      media: renesas: Use state cleanup macros
      media: i2c: ds90ub9xx: Use state cleanup macros

 drivers/media/i2c/ds90ub913.c                      | 11 +++------
 drivers/media/i2c/ds90ub953.c                      | 11 +++------
 drivers/media/i2c/ds90ub960.c                      | 27 +++++++---------------
 drivers/media/platform/renesas/rcar-csi2.c         | 14 ++++-------
 .../media/platform/renesas/rzg2l-cru/rzg2l-csi2.c  |  9 ++++----
 .../media/platform/renesas/rzg2l-cru/rzg2l-ip.c    |  9 ++------
 drivers/media/v4l2-core/v4l2-subdev.c              | 14 +++--------
 include/media/v4l2-subdev.h                        | 10 ++++++++
 8 files changed, 37 insertions(+), 68 deletions(-)
---
base-commit: 98f7e32f20d28ec452afb208f9cffc08448a2652
change-id: 20240917-scoped-state-a995cc0dba33

Best regards,
-- 
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>


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

* [PATCH 1/4] media: v4l2-subdev: Add cleanup macros for active state
  2024-09-17 14:09 [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state Tomi Valkeinen
@ 2024-09-17 14:09 ` Tomi Valkeinen
  2024-09-24 17:17   ` Laurent Pinchart
  2024-09-17 14:09 ` [PATCH 2/4] media: v4l2-subdev: Use state cleanup macros Tomi Valkeinen
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-17 14:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, Laurent Pinchart
  Cc: linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>

Add cleanup macros for active state. These can be used to call
v4l2_subdev_lock_and_get_active_state() and manage the unlocking either
in unscoped or scoped fashion:

This locks the state, gets it to the 'state' variable, and unlocks when
exiting the surrounding scope:

CLASS(v4l2_subdev_lock_and_get_active_state, state)(subdev);

This does the same, but inside the given scope:

scoped_v4l2_subdev_lock_and_get_active_state(subdev) {
}

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
 include/media/v4l2-subdev.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index bd235d325ff9..699007cfffd7 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -8,6 +8,7 @@
 #ifndef _V4L2_SUBDEV_H
 #define _V4L2_SUBDEV_H
 
+#include <linux/cleanup.h>
 #include <linux/types.h>
 #include <linux/v4l2-subdev.h>
 #include <media/media-entity.h>
@@ -1854,6 +1855,15 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
 	return sd->active_state;
 }
 
+DEFINE_CLASS(v4l2_subdev_lock_and_get_active_state, struct v4l2_subdev_state *,
+	     v4l2_subdev_unlock_state(_T),
+	     v4l2_subdev_lock_and_get_active_state(sd), struct v4l2_subdev *sd);
+
+#define scoped_v4l2_subdev_lock_and_get_active_state(sd)              \
+	for (CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd), \
+	     *done = NULL;                                            \
+	     !done; done = (void *)1)
+
 /**
  * v4l2_subdev_init - initializes the sub-device struct
  *

-- 
2.43.0


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

* [PATCH 2/4] media: v4l2-subdev: Use state cleanup macros
  2024-09-17 14:09 [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 1/4] " Tomi Valkeinen
@ 2024-09-17 14:09 ` Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 3/4] media: renesas: " Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 4/4] media: i2c: ds90ub9xx: " Tomi Valkeinen
  3 siblings, 0 replies; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-17 14:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, Laurent Pinchart
  Cc: linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>

Use the new subdev state cleanup macros.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 7c5812d55315..1e701c340d0b 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1478,10 +1478,9 @@ bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct v4l2_subdev_krouting *routing;
-	struct v4l2_subdev_state *state;
 	unsigned int i;
 
-	state = v4l2_subdev_lock_and_get_active_state(sd);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd);
 
 	routing = &state->routing;
 
@@ -1492,14 +1491,10 @@ bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
 			continue;
 
 		if ((route->sink_pad == pad0 && route->source_pad == pad1) ||
-		    (route->source_pad == pad0 && route->sink_pad == pad1)) {
-			v4l2_subdev_unlock_state(state);
+		    (route->source_pad == pad0 && route->sink_pad == pad1))
 			return true;
-		}
 	}
 
-	v4l2_subdev_unlock_state(state);
-
 	return false;
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_has_pad_interdep);
@@ -2393,7 +2388,6 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_disable_streams);
 
 int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)
 {
-	struct v4l2_subdev_state *state;
 	struct v4l2_subdev_route *route;
 	struct media_pad *pad;
 	u64 source_mask = 0;
@@ -2419,12 +2413,10 @@ int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)
 		 * As there's a single source pad, just collect all the source
 		 * streams.
 		 */
-		state = v4l2_subdev_lock_and_get_active_state(sd);
+		CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd);
 
 		for_each_active_route(&state->routing, route)
 			source_mask |= BIT_ULL(route->source_stream);
-
-		v4l2_subdev_unlock_state(state);
 	} else {
 		/*
 		 * For non-streams subdevices, there's a single implicit stream

-- 
2.43.0


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

* [PATCH 3/4] media: renesas: Use state cleanup macros
  2024-09-17 14:09 [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 1/4] " Tomi Valkeinen
  2024-09-17 14:09 ` [PATCH 2/4] media: v4l2-subdev: Use state cleanup macros Tomi Valkeinen
@ 2024-09-17 14:09 ` Tomi Valkeinen
  2024-09-22 10:15   ` Niklas Söderlund
  2024-09-17 14:09 ` [PATCH 4/4] media: i2c: ds90ub9xx: " Tomi Valkeinen
  3 siblings, 1 reply; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-17 14:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, Laurent Pinchart
  Cc: linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>

Use the new subdev state cleanup macros.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
 drivers/media/platform/renesas/rcar-csi2.c            | 14 ++++----------
 drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c |  9 ++++-----
 drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c   |  9 ++-------
 3 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
index c419ddb4c5a2..03ef6566271f 100644
--- a/drivers/media/platform/renesas/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-csi2.c
@@ -1163,27 +1163,24 @@ static void rcsi2_stop(struct rcar_csi2 *priv)
 static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct rcar_csi2 *priv = sd_to_csi2(sd);
-	struct v4l2_subdev_state *state;
 	int ret = 0;
 
 	if (!priv->remote)
 		return -ENODEV;
 
-	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
 
 	if (enable && priv->stream_count == 0) {
 		ret = rcsi2_start(priv, state);
 		if (ret)
-			goto out;
+			return ret;
 	} else if (!enable && priv->stream_count == 1) {
 		rcsi2_stop(priv);
 	}
 
 	priv->stream_count += enable ? 1 : -1;
-out:
-	v4l2_subdev_unlock_state(state);
 
-	return ret;
+	return 0;
 }
 
 static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
@@ -1274,18 +1271,15 @@ static irqreturn_t rcsi2_irq(int irq, void *data)
 
 static irqreturn_t rcsi2_irq_thread(int irq, void *data)
 {
-	struct v4l2_subdev_state *state;
 	struct rcar_csi2 *priv = data;
 
-	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
 
 	rcsi2_stop(priv);
 	usleep_range(1000, 2000);
 	if (rcsi2_start(priv, state))
 		dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
 
-	v4l2_subdev_unlock_state(state);
-
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
index e68fcdaea207..63b846f3e468 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
@@ -238,7 +238,6 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
 	struct v4l2_subdev *source = csi2->remote_source;
 	const struct rzg2l_csi2_format *format;
 	const struct v4l2_mbus_framefmt *fmt;
-	struct v4l2_subdev_state *state;
 	struct v4l2_ctrl *ctrl;
 	u64 mbps;
 
@@ -250,10 +249,10 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
 		return -EINVAL;
 	}
 
-	state = v4l2_subdev_lock_and_get_active_state(&csi2->subdev);
-	fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);
-	format = rzg2l_csi2_code_to_fmt(fmt->code);
-	v4l2_subdev_unlock_state(state);
+	scoped_v4l2_subdev_lock_and_get_active_state(&csi2->subdev) {
+		fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);
+		format = rzg2l_csi2_code_to_fmt(fmt->code);
+	}
 
 	/*
 	 * Calculate hsfreq in Mbps
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
index ac8ebae4ed07..0b9e8a7cf22a 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
@@ -36,14 +36,9 @@ static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int c
 
 struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
 {
-	struct v4l2_subdev_state *state;
-	struct v4l2_mbus_framefmt *fmt;
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&cru->ip.subdev);
 
-	state = v4l2_subdev_lock_and_get_active_state(&cru->ip.subdev);
-	fmt = v4l2_subdev_state_get_format(state, 1);
-	v4l2_subdev_unlock_state(state);
-
-	return fmt;
+	return v4l2_subdev_state_get_format(state, 1);
 }
 
 static int rzg2l_cru_ip_s_stream(struct v4l2_subdev *sd, int enable)

-- 
2.43.0


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

* [PATCH 4/4] media: i2c: ds90ub9xx: Use state cleanup macros
  2024-09-17 14:09 [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state Tomi Valkeinen
                   ` (2 preceding siblings ...)
  2024-09-17 14:09 ` [PATCH 3/4] media: renesas: " Tomi Valkeinen
@ 2024-09-17 14:09 ` Tomi Valkeinen
  3 siblings, 0 replies; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-17 14:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, Laurent Pinchart
  Cc: linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>

Use the new subdev state cleanup macros.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
 drivers/media/i2c/ds90ub913.c | 11 +++--------
 drivers/media/i2c/ds90ub953.c | 11 +++--------
 drivers/media/i2c/ds90ub960.c | 27 ++++++++-------------------
 3 files changed, 14 insertions(+), 35 deletions(-)

diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index ca9bb29dab89..7a53b68db1b4 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -351,7 +351,6 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 	const struct v4l2_subdev_krouting *routing;
 	struct v4l2_mbus_frame_desc source_fd;
 	struct v4l2_subdev_route *route;
-	struct v4l2_subdev_state *state;
 	int ret;
 
 	if (pad != UB913_PAD_SOURCE)
@@ -364,7 +363,7 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 
 	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
 
-	state = v4l2_subdev_lock_and_get_active_state(sd);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd);
 
 	routing = &state->routing;
 
@@ -382,8 +381,7 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		if (i == source_fd.num_entries) {
 			dev_err(&priv->client->dev,
 				"Failed to find stream from source frame desc\n");
-			ret = -EPIPE;
-			goto out_unlock;
+			return -EPIPE;
 		}
 
 		fd->entry[fd->num_entries].stream = route->source_stream;
@@ -395,10 +393,7 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		fd->num_entries++;
 	}
 
-out_unlock:
-	v4l2_subdev_unlock_state(state);
-
-	return ret;
+	return 0;
 }
 
 static int ub913_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 16f88db14981..131b1523c3a5 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -488,7 +488,6 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 	struct ub953_data *priv = sd_to_ub953(sd);
 	struct v4l2_mbus_frame_desc source_fd;
 	struct v4l2_subdev_route *route;
-	struct v4l2_subdev_state *state;
 	int ret;
 
 	if (pad != UB953_PAD_SOURCE)
@@ -501,7 +500,7 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 
 	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
 
-	state = v4l2_subdev_lock_and_get_active_state(sd);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd);
 
 	for_each_active_route(&state->routing, route) {
 		struct v4l2_mbus_frame_desc_entry *source_entry = NULL;
@@ -520,8 +519,7 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		if (!source_entry) {
 			dev_err(&priv->client->dev,
 				"Failed to find stream from source frame desc\n");
-			ret = -EPIPE;
-			goto out_unlock;
+			return -EPIPE;
 		}
 
 		fd->entry[fd->num_entries].stream = route->source_stream;
@@ -536,10 +534,7 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		fd->num_entries++;
 	}
 
-out_unlock:
-	v4l2_subdev_unlock_state(state);
-
-	return ret;
+	return 0;
 }
 
 static int ub953_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index ffe5f25f8647..e873611bf5c7 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -2777,7 +2777,6 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 {
 	struct ub960_data *priv = sd_to_ub960(sd);
 	struct v4l2_subdev_route *route;
-	struct v4l2_subdev_state *state;
 	int ret = 0;
 	struct device *dev = &priv->client->dev;
 	u8 vc_map[UB960_MAX_RX_NPORTS] = {};
@@ -2787,7 +2786,7 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 
 	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
 
-	state = v4l2_subdev_lock_and_get_active_state(&priv->sd);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->sd);
 
 	ub960_get_vc_maps(priv, state, vc_map);
 
@@ -2810,7 +2809,7 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 			dev_err(dev,
 				"Failed to get source frame desc for pad %u\n",
 				route->sink_pad);
-			goto out_unlock;
+			return ret;
 		}
 
 		for (i = 0; i < source_fd.num_entries; i++) {
@@ -2823,8 +2822,7 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		if (!source_entry) {
 			dev_err(dev,
 				"Failed to find stream from source frame desc\n");
-			ret = -EPIPE;
-			goto out_unlock;
+			return -EPIPE;
 		}
 
 		fd->entry[fd->num_entries].stream = route->source_stream;
@@ -2844,16 +2842,13 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 			fmt = v4l2_subdev_state_get_format(state, pad,
 							   route->source_stream);
 
-			if (!fmt) {
-				ret = -EINVAL;
-				goto out_unlock;
-			}
+			if (!fmt)
+				return -EINVAL;
 
 			ub960_fmt = ub960_find_format(fmt->code);
 			if (!ub960_fmt) {
 				dev_err(dev, "Unable to find format\n");
-				ret = -EINVAL;
-				goto out_unlock;
+				return -EINVAL;
 			}
 
 			fd->entry[fd->num_entries].bus.csi2.dt =
@@ -2863,10 +2858,7 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		fd->num_entries++;
 	}
 
-out_unlock:
-	v4l2_subdev_unlock_state(state);
-
-	return ret;
+	return 0;
 }
 
 static int ub960_set_fmt(struct v4l2_subdev *sd,
@@ -2944,14 +2936,13 @@ static int ub960_log_status(struct v4l2_subdev *sd)
 {
 	struct ub960_data *priv = sd_to_ub960(sd);
 	struct device *dev = &priv->client->dev;
-	struct v4l2_subdev_state *state;
 	unsigned int nport;
 	unsigned int i;
 	u16 v16 = 0;
 	u8 v = 0;
 	u8 id[UB960_SR_FPD3_RX_ID_LEN];
 
-	state = v4l2_subdev_lock_and_get_active_state(sd);
+	CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd);
 
 	for (i = 0; i < sizeof(id); i++)
 		ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]);
@@ -3078,8 +3069,6 @@ static int ub960_log_status(struct v4l2_subdev *sd)
 		}
 	}
 
-	v4l2_subdev_unlock_state(state);
-
 	return 0;
 }
 

-- 
2.43.0


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

* Re: [PATCH 3/4] media: renesas: Use state cleanup macros
  2024-09-17 14:09 ` [PATCH 3/4] media: renesas: " Tomi Valkeinen
@ 2024-09-22 10:15   ` Niklas Söderlund
  2024-09-24 17:24     ` Laurent Pinchart
  0 siblings, 1 reply; 11+ messages in thread
From: Niklas Söderlund @ 2024-09-22 10:15 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Hans Verkuil, Sakari Ailus,
	Laurent Pinchart, linux-media, linux-kernel, linux-renesas-soc,
	Tomi Valkeinen

Hi Tomi,

Thanks for your work. I like the scoped management.

On 2024-09-17 17:09:31 +0300, Tomi Valkeinen wrote:
> From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> 
> Use the new subdev state cleanup macros.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/renesas/rcar-csi2.c            | 14 ++++----------
>  drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c |  9 ++++-----
>  drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c   |  9 ++-------
>  3 files changed, 10 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
> index c419ddb4c5a2..03ef6566271f 100644
> --- a/drivers/media/platform/renesas/rcar-csi2.c
> +++ b/drivers/media/platform/renesas/rcar-csi2.c
> @@ -1163,27 +1163,24 @@ static void rcsi2_stop(struct rcar_csi2 *priv)
>  static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable)
>  {
>  	struct rcar_csi2 *priv = sd_to_csi2(sd);
> -	struct v4l2_subdev_state *state;
>  	int ret = 0;
>  
>  	if (!priv->remote)
>  		return -ENODEV;
>  
> -	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
> +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
>  
>  	if (enable && priv->stream_count == 0) {
>  		ret = rcsi2_start(priv, state);
>  		if (ret)
> -			goto out;
> +			return ret;

As ret is now only used in this branch maybe we can move the declaration 
of it here? At least I think you should remove the assignment to 0 above 
as that behavior is not needed anymore but, at lest to me, keeping it 
indicates there is an intent in initializing it.

With that fixed,

Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

>  	} else if (!enable && priv->stream_count == 1) {
>  		rcsi2_stop(priv);
>  	}
>  
>  	priv->stream_count += enable ? 1 : -1;
> -out:
> -	v4l2_subdev_unlock_state(state);
>  
> -	return ret;
> +	return 0;
>  }
>  
>  static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> @@ -1274,18 +1271,15 @@ static irqreturn_t rcsi2_irq(int irq, void *data)
>  
>  static irqreturn_t rcsi2_irq_thread(int irq, void *data)
>  {
> -	struct v4l2_subdev_state *state;
>  	struct rcar_csi2 *priv = data;
>  
> -	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
> +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
>  
>  	rcsi2_stop(priv);
>  	usleep_range(1000, 2000);
>  	if (rcsi2_start(priv, state))
>  		dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
>  
> -	v4l2_subdev_unlock_state(state);
> -
>  	return IRQ_HANDLED;
>  }
>  
> diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> index e68fcdaea207..63b846f3e468 100644
> --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> @@ -238,7 +238,6 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
>  	struct v4l2_subdev *source = csi2->remote_source;
>  	const struct rzg2l_csi2_format *format;
>  	const struct v4l2_mbus_framefmt *fmt;
> -	struct v4l2_subdev_state *state;
>  	struct v4l2_ctrl *ctrl;
>  	u64 mbps;
>  
> @@ -250,10 +249,10 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
>  		return -EINVAL;
>  	}
>  
> -	state = v4l2_subdev_lock_and_get_active_state(&csi2->subdev);
> -	fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);
> -	format = rzg2l_csi2_code_to_fmt(fmt->code);
> -	v4l2_subdev_unlock_state(state);
> +	scoped_v4l2_subdev_lock_and_get_active_state(&csi2->subdev) {
> +		fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);
> +		format = rzg2l_csi2_code_to_fmt(fmt->code);
> +	}
>  
>  	/*
>  	 * Calculate hsfreq in Mbps
> diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> index ac8ebae4ed07..0b9e8a7cf22a 100644
> --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> @@ -36,14 +36,9 @@ static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int c
>  
>  struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
>  {
> -	struct v4l2_subdev_state *state;
> -	struct v4l2_mbus_framefmt *fmt;
> +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&cru->ip.subdev);
>  
> -	state = v4l2_subdev_lock_and_get_active_state(&cru->ip.subdev);
> -	fmt = v4l2_subdev_state_get_format(state, 1);
> -	v4l2_subdev_unlock_state(state);
> -
> -	return fmt;
> +	return v4l2_subdev_state_get_format(state, 1);
>  }
>  
>  static int rzg2l_cru_ip_s_stream(struct v4l2_subdev *sd, int enable)
> 
> -- 
> 2.43.0
> 

-- 
Kind Regards,
Niklas Söderlund

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

* Re: [PATCH 1/4] media: v4l2-subdev: Add cleanup macros for active state
  2024-09-17 14:09 ` [PATCH 1/4] " Tomi Valkeinen
@ 2024-09-24 17:17   ` Laurent Pinchart
  2024-09-24 17:53     ` Tomi Valkeinen
  0 siblings, 1 reply; 11+ messages in thread
From: Laurent Pinchart @ 2024-09-24 17:17 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, linux-media, linux-kernel, linux-renesas-soc,
	Tomi Valkeinen

Hi Tomi,

Thank you for the patch.

On Tue, Sep 17, 2024 at 05:09:29PM +0300, Tomi Valkeinen wrote:
> From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> 
> Add cleanup macros for active state. These can be used to call
> v4l2_subdev_lock_and_get_active_state() and manage the unlocking either
> in unscoped or scoped fashion:
> 
> This locks the state, gets it to the 'state' variable, and unlocks when
> exiting the surrounding scope:
> 
> CLASS(v4l2_subdev_lock_and_get_active_state, state)(subdev);
> 
> This does the same, but inside the given scope:
> 
> scoped_v4l2_subdev_lock_and_get_active_state(subdev) {
> }
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> ---
>  include/media/v4l2-subdev.h | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index bd235d325ff9..699007cfffd7 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -8,6 +8,7 @@
>  #ifndef _V4L2_SUBDEV_H
>  #define _V4L2_SUBDEV_H
>  
> +#include <linux/cleanup.h>
>  #include <linux/types.h>
>  #include <linux/v4l2-subdev.h>
>  #include <media/media-entity.h>
> @@ -1854,6 +1855,15 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
>  	return sd->active_state;
>  }
>  
> +DEFINE_CLASS(v4l2_subdev_lock_and_get_active_state, struct v4l2_subdev_state *,
> +	     v4l2_subdev_unlock_state(_T),
> +	     v4l2_subdev_lock_and_get_active_state(sd), struct v4l2_subdev *sd);
> +
> +#define scoped_v4l2_subdev_lock_and_get_active_state(sd)              \
> +	for (CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd), \
> +	     *done = NULL;                                            \
> +	     !done; done = (void *)1)

That a very long name :-S Could this be done using the scoped_guard()
macro instead ? For instance, with spinlocks you can do

	scoped_guard(spinlock_irqsave, &dev->lock) {
		...
	}

It would be nice to be able to write

	scoped_guard(v4l2_subdev_state, sd) {
		...
	}

This being said, we would then end up with the state variable being
named scope, which wouldn't be great.

This is actually one of my issues with the above macros, and especially
scoped_v4l2_subdev_lock_and_get_active_state(). It creates a local state
variable in the scope, which makes the code less readable in my opinion.

We could keep the class and drop
scoped_v4l2_subdev_lock_and_get_active_state(). I think I would like to
shorten the class name then.

Another option is to use DEFINE_FREE() and __free() instead.

> +
>  /**
>   * v4l2_subdev_init - initializes the sub-device struct
>   *
> 

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 3/4] media: renesas: Use state cleanup macros
  2024-09-22 10:15   ` Niklas Söderlund
@ 2024-09-24 17:24     ` Laurent Pinchart
  0 siblings, 0 replies; 11+ messages in thread
From: Laurent Pinchart @ 2024-09-24 17:24 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Tomi Valkeinen, Mauro Carvalho Chehab, Hans Verkuil, Sakari Ailus,
	linux-media, linux-kernel, linux-renesas-soc, Tomi Valkeinen

On Sun, Sep 22, 2024 at 12:15:19PM +0200, Niklas Söderlund wrote:
> Hi Tomi,
> 
> Thanks for your work. I like the scoped management.
> 
> On 2024-09-17 17:09:31 +0300, Tomi Valkeinen wrote:
> > From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> > 
> > Use the new subdev state cleanup macros.
> > 
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> > ---
> >  drivers/media/platform/renesas/rcar-csi2.c            | 14 ++++----------
> >  drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c |  9 ++++-----
> >  drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c   |  9 ++-------
> >  3 files changed, 10 insertions(+), 22 deletions(-)
> > 
> > diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
> > index c419ddb4c5a2..03ef6566271f 100644
> > --- a/drivers/media/platform/renesas/rcar-csi2.c
> > +++ b/drivers/media/platform/renesas/rcar-csi2.c
> > @@ -1163,27 +1163,24 @@ static void rcsi2_stop(struct rcar_csi2 *priv)
> >  static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable)
> >  {
> >  	struct rcar_csi2 *priv = sd_to_csi2(sd);
> > -	struct v4l2_subdev_state *state;
> >  	int ret = 0;
> >  
> >  	if (!priv->remote)
> >  		return -ENODEV;
> >  
> > -	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
> > +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
> >  
> >  	if (enable && priv->stream_count == 0) {
> >  		ret = rcsi2_start(priv, state);
> >  		if (ret)
> > -			goto out;
> > +			return ret;
> 
> As ret is now only used in this branch maybe we can move the declaration 
> of it here? At least I think you should remove the assignment to 0 above 
> as that behavior is not needed anymore but, at lest to me, keeping it 
> indicates there is an intent in initializing it.
> 
> With that fixed,
> 
> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> 
> >  	} else if (!enable && priv->stream_count == 1) {
> >  		rcsi2_stop(priv);
> >  	}
> >  
> >  	priv->stream_count += enable ? 1 : -1;
> > -out:
> > -	v4l2_subdev_unlock_state(state);
> >  
> > -	return ret;
> > +	return 0;
> >  }
> >  
> >  static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> > @@ -1274,18 +1271,15 @@ static irqreturn_t rcsi2_irq(int irq, void *data)
> >  
> >  static irqreturn_t rcsi2_irq_thread(int irq, void *data)
> >  {
> > -	struct v4l2_subdev_state *state;
> >  	struct rcar_csi2 *priv = data;
> >  
> > -	state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);
> > +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&priv->subdev);
> >  
> >  	rcsi2_stop(priv);
> >  	usleep_range(1000, 2000);
> >  	if (rcsi2_start(priv, state))
> >  		dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
> >  
> > -	v4l2_subdev_unlock_state(state);
> > -
> >  	return IRQ_HANDLED;
> >  }
> >  
> > diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> > index e68fcdaea207..63b846f3e468 100644
> > --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> > +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> > @@ -238,7 +238,6 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
> >  	struct v4l2_subdev *source = csi2->remote_source;
> >  	const struct rzg2l_csi2_format *format;
> >  	const struct v4l2_mbus_framefmt *fmt;
> > -	struct v4l2_subdev_state *state;
> >  	struct v4l2_ctrl *ctrl;
> >  	u64 mbps;
> >  
> > @@ -250,10 +249,10 @@ static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2)
> >  		return -EINVAL;
> >  	}
> >  
> > -	state = v4l2_subdev_lock_and_get_active_state(&csi2->subdev);
> > -	fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);
> > -	format = rzg2l_csi2_code_to_fmt(fmt->code);
> > -	v4l2_subdev_unlock_state(state);
> > +	scoped_v4l2_subdev_lock_and_get_active_state(&csi2->subdev) {
> > +		fmt = v4l2_subdev_state_get_format(state, RZG2L_CSI2_SINK);

fmt could also become a local variable.

Now that I'm looking at this, another issue with
scoped_v4l2_subdev_lock_and_get_active_state() is that it creates a
non-const state variable, while there are use cases for const states.
I'm increasingly thinking we should use __free(), as neither the
scoped_* macro nor CLASS() allow the caller to indicate if the local
variable should be const or not.

> > +		format = rzg2l_csi2_code_to_fmt(fmt->code);
> > +	}
> >  
> >  	/*
> >  	 * Calculate hsfreq in Mbps
> > diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> > index ac8ebae4ed07..0b9e8a7cf22a 100644
> > --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> > +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
> > @@ -36,14 +36,9 @@ static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int c
> >  
> >  struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
> >  {
> > -	struct v4l2_subdev_state *state;
> > -	struct v4l2_mbus_framefmt *fmt;
> > +	CLASS(v4l2_subdev_lock_and_get_active_state, state)(&cru->ip.subdev);
> >  
> > -	state = v4l2_subdev_lock_and_get_active_state(&cru->ip.subdev);
> > -	fmt = v4l2_subdev_state_get_format(state, 1);
> > -	v4l2_subdev_unlock_state(state);
> > -
> > -	return fmt;
> > +	return v4l2_subdev_state_get_format(state, 1);
> >  }
> >  
> >  static int rzg2l_cru_ip_s_stream(struct v4l2_subdev *sd, int enable)
> > 

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 1/4] media: v4l2-subdev: Add cleanup macros for active state
  2024-09-24 17:17   ` Laurent Pinchart
@ 2024-09-24 17:53     ` Tomi Valkeinen
  2024-09-25 16:35       ` Laurent Pinchart
  0 siblings, 1 reply; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-24 17:53 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, linux-media, linux-kernel, linux-renesas-soc,
	Tomi Valkeinen

On 24/09/2024 20:17, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Tue, Sep 17, 2024 at 05:09:29PM +0300, Tomi Valkeinen wrote:
>> From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
>>
>> Add cleanup macros for active state. These can be used to call
>> v4l2_subdev_lock_and_get_active_state() and manage the unlocking either
>> in unscoped or scoped fashion:
>>
>> This locks the state, gets it to the 'state' variable, and unlocks when
>> exiting the surrounding scope:
>>
>> CLASS(v4l2_subdev_lock_and_get_active_state, state)(subdev);
>>
>> This does the same, but inside the given scope:
>>
>> scoped_v4l2_subdev_lock_and_get_active_state(subdev) {
>> }
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
>> ---
>>   include/media/v4l2-subdev.h | 10 ++++++++++
>>   1 file changed, 10 insertions(+)
>>
>> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
>> index bd235d325ff9..699007cfffd7 100644
>> --- a/include/media/v4l2-subdev.h
>> +++ b/include/media/v4l2-subdev.h
>> @@ -8,6 +8,7 @@
>>   #ifndef _V4L2_SUBDEV_H
>>   #define _V4L2_SUBDEV_H
>>   
>> +#include <linux/cleanup.h>
>>   #include <linux/types.h>
>>   #include <linux/v4l2-subdev.h>
>>   #include <media/media-entity.h>
>> @@ -1854,6 +1855,15 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
>>   	return sd->active_state;
>>   }
>>   
>> +DEFINE_CLASS(v4l2_subdev_lock_and_get_active_state, struct v4l2_subdev_state *,
>> +	     v4l2_subdev_unlock_state(_T),
>> +	     v4l2_subdev_lock_and_get_active_state(sd), struct v4l2_subdev *sd);
>> +
>> +#define scoped_v4l2_subdev_lock_and_get_active_state(sd)              \
>> +	for (CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd), \
>> +	     *done = NULL;                                            \
>> +	     !done; done = (void *)1)
> 
> That a very long name :-S Could this be done using the scoped_guard()
> macro instead ? For instance, with spinlocks you can do
> 
> 	scoped_guard(spinlock_irqsave, &dev->lock) {
> 		...
> 	}
> 
> It would be nice to be able to write
> 
> 	scoped_guard(v4l2_subdev_state, sd) {

This can be done but then you need to pass the state to it, not sd. Or 
perhaps it would be possible to implicitly turn the sd into active 
state, but I don't like that at all...

Or maybe:

scoped_guard(v4l2_subdev_state, v4l2_subdev_get_unlocked_active_state(sd))

Not very short either...

> 		...
> 	}
> 
> This being said, we would then end up with the state variable being
> named scope, which wouldn't be great.

No, it wouldn't.

> This is actually one of my issues with the above macros, and especially
> scoped_v4l2_subdev_lock_and_get_active_state(). It creates a local state
> variable in the scope, which makes the code less readable in my opinion.

It's trivial to add a variable name there, as mentioned in the intro letter.

You mentioned the const/non-const state issue in the other email. I 
wonder if some macro-magic could be done for that... Or we can always 
just add "scoped_v4l2_subdev_lock_and_get_active_state_const()"! =)

Also, it's not like we have to use these _everywhere_. So maybe if you 
want a const state, don't use the scoped or the class.

> We could keep the class and drop
> scoped_v4l2_subdev_lock_and_get_active_state(). I think I would like to
> shorten the class name then.
> 
> Another option is to use DEFINE_FREE() and __free() instead.

That can be added too. I had them, but I didn't consider them as useful 
when I already added the class and scoped.

I have to say I don't particularly like the look of either the scoped or 
the class, or even the free. But they're so useful wrt. error handling 
that I don't care if the syntax annoys me =).

Also, I think in theory one should always just use the scoped macro, 
never the class. But as the scoped one adds indentation, in some cases 
using the class keeps the code formatting nicer.

  Tomi


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

* Re: [PATCH 1/4] media: v4l2-subdev: Add cleanup macros for active state
  2024-09-24 17:53     ` Tomi Valkeinen
@ 2024-09-25 16:35       ` Laurent Pinchart
  2024-09-26 15:26         ` Tomi Valkeinen
  0 siblings, 1 reply; 11+ messages in thread
From: Laurent Pinchart @ 2024-09-25 16:35 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, linux-media, linux-kernel, linux-renesas-soc,
	Tomi Valkeinen

Hi Tomi,

On Tue, Sep 24, 2024 at 08:53:38PM +0300, Tomi Valkeinen wrote:
> On 24/09/2024 20:17, Laurent Pinchart wrote:
> > On Tue, Sep 17, 2024 at 05:09:29PM +0300, Tomi Valkeinen wrote:
> >> From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> >>
> >> Add cleanup macros for active state. These can be used to call
> >> v4l2_subdev_lock_and_get_active_state() and manage the unlocking either
> >> in unscoped or scoped fashion:
> >>
> >> This locks the state, gets it to the 'state' variable, and unlocks when
> >> exiting the surrounding scope:
> >>
> >> CLASS(v4l2_subdev_lock_and_get_active_state, state)(subdev);
> >>
> >> This does the same, but inside the given scope:
> >>
> >> scoped_v4l2_subdev_lock_and_get_active_state(subdev) {
> >> }
> >>
> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> >> ---
> >>   include/media/v4l2-subdev.h | 10 ++++++++++
> >>   1 file changed, 10 insertions(+)
> >>
> >> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> >> index bd235d325ff9..699007cfffd7 100644
> >> --- a/include/media/v4l2-subdev.h
> >> +++ b/include/media/v4l2-subdev.h
> >> @@ -8,6 +8,7 @@
> >>   #ifndef _V4L2_SUBDEV_H
> >>   #define _V4L2_SUBDEV_H
> >>   
> >> +#include <linux/cleanup.h>
> >>   #include <linux/types.h>
> >>   #include <linux/v4l2-subdev.h>
> >>   #include <media/media-entity.h>
> >> @@ -1854,6 +1855,15 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
> >>   	return sd->active_state;
> >>   }
> >>   
> >> +DEFINE_CLASS(v4l2_subdev_lock_and_get_active_state, struct v4l2_subdev_state *,
> >> +	     v4l2_subdev_unlock_state(_T),
> >> +	     v4l2_subdev_lock_and_get_active_state(sd), struct v4l2_subdev *sd);
> >> +
> >> +#define scoped_v4l2_subdev_lock_and_get_active_state(sd)              \
> >> +	for (CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd), \
> >> +	     *done = NULL;                                            \
> >> +	     !done; done = (void *)1)
> > 
> > That a very long name :-S Could this be done using the scoped_guard()
> > macro instead ? For instance, with spinlocks you can do
> > 
> > 	scoped_guard(spinlock_irqsave, &dev->lock) {
> > 		...
> > 	}
> > 
> > It would be nice to be able to write
> > 
> > 	scoped_guard(v4l2_subdev_state, sd) {
> 
> This can be done but then you need to pass the state to it, not sd. Or 
> perhaps it would be possible to implicitly turn the sd into active 
> state, but I don't like that at all...
> 
> Or maybe:
> 
> scoped_guard(v4l2_subdev_state, v4l2_subdev_get_unlocked_active_state(sd))
> 
> Not very short either...

That's not very nice. Are there other examples in the kernel of
scoped_*() macros magically creating variables that are then used within
the scope ? I have a feeling we shouldn't do it here.

> > 		...
> > 	}
> > 
> > This being said, we would then end up with the state variable being
> > named scope, which wouldn't be great.
> 
> No, it wouldn't.
> 
> > This is actually one of my issues with the above macros, and especially
> > scoped_v4l2_subdev_lock_and_get_active_state(). It creates a local state
> > variable in the scope, which makes the code less readable in my opinion.
> 
> It's trivial to add a variable name there, as mentioned in the intro letter.
> 
> You mentioned the const/non-const state issue in the other email. I 
> wonder if some macro-magic could be done for that... Or we can always 
> just add "scoped_v4l2_subdev_lock_and_get_active_state_const()"! =)

And that's supposed to be an improvement ? :D

> Also, it's not like we have to use these _everywhere_. So maybe if you 
> want a const state, don't use the scoped or the class.

Looking at the rest of your series there are very few instances of
scoped_v4l2_subdev_lock_and_get_active_state(), so I'm tempted to simply
leave it out. When one writes

	scoped_guard(spinlock_irqsave, &dev->lock) {
	}

It's clear that you're locking the lock for the scope using
spinlock_irqsave. The scoped guard performs a scoped action on an
existing object. The V4L2 subdev active state is different, I don't
think scoped_guard() gives the right semantics.

> > We could keep the class and drop
> > scoped_v4l2_subdev_lock_and_get_active_state(). I think I would like to
> > shorten the class name then.
> > 
> > Another option is to use DEFINE_FREE() and __free() instead.
> 
> That can be added too. I had them, but I didn't consider them as useful 
> when I already added the class and scoped.
> 
> I have to say I don't particularly like the look of either the scoped or 
> the class, or even the free. But they're so useful wrt. error handling 
> that I don't care if the syntax annoys me =).

CLASS() is a bit better once we'll get used to it, as the name of the
variable is explicit. It however doesn't solve the const issue.
Furthermore, its semantics is meant to represent creation of an object
with automatic destruction when it leaves the scope, while with the
subdev active state you're not creating an object. That's why I think
that an explicit variable with a __free() annotation may be the best
option for this.

> Also, I think in theory one should always just use the scoped macro, 
> never the class. But as the scoped one adds indentation, in some cases 
> using the class keeps the code formatting nicer.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 1/4] media: v4l2-subdev: Add cleanup macros for active state
  2024-09-25 16:35       ` Laurent Pinchart
@ 2024-09-26 15:26         ` Tomi Valkeinen
  0 siblings, 0 replies; 11+ messages in thread
From: Tomi Valkeinen @ 2024-09-26 15:26 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sakari Ailus, linux-media, linux-kernel, linux-renesas-soc,
	Tomi Valkeinen

On 25/09/2024 19:35, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Tue, Sep 24, 2024 at 08:53:38PM +0300, Tomi Valkeinen wrote:
>> On 24/09/2024 20:17, Laurent Pinchart wrote:
>>> On Tue, Sep 17, 2024 at 05:09:29PM +0300, Tomi Valkeinen wrote:
>>>> From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
>>>>
>>>> Add cleanup macros for active state. These can be used to call
>>>> v4l2_subdev_lock_and_get_active_state() and manage the unlocking either
>>>> in unscoped or scoped fashion:
>>>>
>>>> This locks the state, gets it to the 'state' variable, and unlocks when
>>>> exiting the surrounding scope:
>>>>
>>>> CLASS(v4l2_subdev_lock_and_get_active_state, state)(subdev);
>>>>
>>>> This does the same, but inside the given scope:
>>>>
>>>> scoped_v4l2_subdev_lock_and_get_active_state(subdev) {
>>>> }
>>>>
>>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
>>>> ---
>>>>    include/media/v4l2-subdev.h | 10 ++++++++++
>>>>    1 file changed, 10 insertions(+)
>>>>
>>>> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
>>>> index bd235d325ff9..699007cfffd7 100644
>>>> --- a/include/media/v4l2-subdev.h
>>>> +++ b/include/media/v4l2-subdev.h
>>>> @@ -8,6 +8,7 @@
>>>>    #ifndef _V4L2_SUBDEV_H
>>>>    #define _V4L2_SUBDEV_H
>>>>    
>>>> +#include <linux/cleanup.h>
>>>>    #include <linux/types.h>
>>>>    #include <linux/v4l2-subdev.h>
>>>>    #include <media/media-entity.h>
>>>> @@ -1854,6 +1855,15 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
>>>>    	return sd->active_state;
>>>>    }
>>>>    
>>>> +DEFINE_CLASS(v4l2_subdev_lock_and_get_active_state, struct v4l2_subdev_state *,
>>>> +	     v4l2_subdev_unlock_state(_T),
>>>> +	     v4l2_subdev_lock_and_get_active_state(sd), struct v4l2_subdev *sd);
>>>> +
>>>> +#define scoped_v4l2_subdev_lock_and_get_active_state(sd)              \
>>>> +	for (CLASS(v4l2_subdev_lock_and_get_active_state, state)(sd), \
>>>> +	     *done = NULL;                                            \
>>>> +	     !done; done = (void *)1)
>>>
>>> That a very long name :-S Could this be done using the scoped_guard()
>>> macro instead ? For instance, with spinlocks you can do
>>>
>>> 	scoped_guard(spinlock_irqsave, &dev->lock) {
>>> 		...
>>> 	}
>>>
>>> It would be nice to be able to write
>>>
>>> 	scoped_guard(v4l2_subdev_state, sd) {
>>
>> This can be done but then you need to pass the state to it, not sd. Or
>> perhaps it would be possible to implicitly turn the sd into active
>> state, but I don't like that at all...
>>
>> Or maybe:
>>
>> scoped_guard(v4l2_subdev_state, v4l2_subdev_get_unlocked_active_state(sd))
>>
>> Not very short either...
> 
> That's not very nice. Are there other examples in the kernel of
> scoped_*() macros magically creating variables that are then used within
> the scope ? I have a feeling we shouldn't do it here.

I'm not aware of any other scoped macros than scoped_guard. Or if there 
are similar macros creating a variable.

I think creating the variable inside the macro is one of the main points 
with scoped_v4l2_subdev_lock_and_get_active_state(), so that not only 
the locking of the state of scoped, also the variable is scoped. It 
hasn't been just once or twice when I have accidentally used a variable 
that was supposed to be only used inside a scope.

>>> 		...
>>> 	}
>>>
>>> This being said, we would then end up with the state variable being
>>> named scope, which wouldn't be great.
>>
>> No, it wouldn't.
>>
>>> This is actually one of my issues with the above macros, and especially
>>> scoped_v4l2_subdev_lock_and_get_active_state(). It creates a local state
>>> variable in the scope, which makes the code less readable in my opinion.
>>
>> It's trivial to add a variable name there, as mentioned in the intro letter.
>>
>> You mentioned the const/non-const state issue in the other email. I
>> wonder if some macro-magic could be done for that... Or we can always
>> just add "scoped_v4l2_subdev_lock_and_get_active_state_const()"! =)
> 
> And that's supposed to be an improvement ? :D
> 
>> Also, it's not like we have to use these _everywhere_. So maybe if you
>> want a const state, don't use the scoped or the class.
> 
> Looking at the rest of your series there are very few instances of
> scoped_v4l2_subdev_lock_and_get_active_state(), so I'm tempted to simply

The changes in this series were just a few examples for a couple of 
drivers I've been working on lately. I didn't do any kind of thorough 
study how many users we have for these.

> leave it out. When one writes
> 
> 	scoped_guard(spinlock_irqsave, &dev->lock) {
> 	}
> 
> It's clear that you're locking the lock for the scope using
> spinlock_irqsave. The scoped guard performs a scoped action on an
> existing object. The V4L2 subdev active state is different, I don't
> think scoped_guard() gives the right semantics.

Hmm so are you here referring specifically to using scoped_guard() for 
the active state locking, or do you refer to the 
scoped_v4l2_subdev_lock_and_get_active_state()?

>>> We could keep the class and drop
>>> scoped_v4l2_subdev_lock_and_get_active_state(). I think I would like to
>>> shorten the class name then.
>>>
>>> Another option is to use DEFINE_FREE() and __free() instead.
>>
>> That can be added too. I had them, but I didn't consider them as useful
>> when I already added the class and scoped.
>>
>> I have to say I don't particularly like the look of either the scoped or
>> the class, or even the free. But they're so useful wrt. error handling
>> that I don't care if the syntax annoys me =).
> 
> CLASS() is a bit better once we'll get used to it, as the name of the
> variable is explicit. It however doesn't solve the const issue.

Again, we can add the variable name to 
scoped_v4l2_subdev_lock_and_get_active_state(), it's a trivial change.

I don't really see the const issue as a major thing. Missing the const 
here never breaks anything. You can pass the non-const state to 
functions that take const state. And you never have to use these 
helpers, you can do it all manually.

Adding const versions is possible. In some way the code has to tell the 
macros that "I want const state", so adding a __const() version of the 
macro sounds fine to me. Except the length of the name quickly becomes a 
problem =).

> Furthermore, its semantics is meant to represent creation of an object
> with automatic destruction when it leaves the scope, while with the
> subdev active state you're not creating an object. That's why I think

The lock guards use CLASS(), and they're not creating any new objects. 
They do hide the use of CLASS, though. But we can do the same by just 
creating our own macro that directly uses CLASS.

> that an explicit variable with a __free() annotation may be the best
> option for this.

But __free() does a different thing. It can, of course, be used in a 
scoped fashion by adding a scope with { }, like:

	{
		struct v4l2_subdev_state *state __free(v4l2_subdev_state_lock) = 
v4l2_subdev_lock_and_get_active_state(sd);

		// use state
	}

but I don't very often see that style used. "__free()" there also makes 
me think the state will be freed... And the line above is definitely not 
short...

If we come up with a suitable short name, this is quite a bit cleaner 
looking:

	hopefully_somewhat_short_name(sd, state) {
		// use state
	}

But all that said, I have to say I don't know if we have enough users 
for these to make these worthwhile. Looking at the single 
scoped_v4l2_subdev_lock_and_get_active_state() use I added to 
rzg2l-csi2.c... That's not really needed, as the original code is not 
right: the rzg2l_csi2_calc_mbps() shouldn't lock the active state, it 
should be passed the (locked) active state.

  Tomi


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

end of thread, other threads:[~2024-09-26 15:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-17 14:09 [PATCH 0/4] media: v4l2-subdev: Add cleanup macros for active state Tomi Valkeinen
2024-09-17 14:09 ` [PATCH 1/4] " Tomi Valkeinen
2024-09-24 17:17   ` Laurent Pinchart
2024-09-24 17:53     ` Tomi Valkeinen
2024-09-25 16:35       ` Laurent Pinchart
2024-09-26 15:26         ` Tomi Valkeinen
2024-09-17 14:09 ` [PATCH 2/4] media: v4l2-subdev: Use state cleanup macros Tomi Valkeinen
2024-09-17 14:09 ` [PATCH 3/4] media: renesas: " Tomi Valkeinen
2024-09-22 10:15   ` Niklas Söderlund
2024-09-24 17:24     ` Laurent Pinchart
2024-09-17 14:09 ` [PATCH 4/4] media: i2c: ds90ub9xx: " Tomi Valkeinen

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