linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RESEND PATCH v3 00/32] Separate links and async sub-devices
@ 2023-05-25  9:15 Sakari Ailus
  2023-05-25  9:15 ` [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
                   ` (32 more replies)
  0 siblings, 33 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi all,

(Resending v3, with a wider distribution. This set just touches so many
drivers. It would be nice to have this tested with as much hardware as
possible. I wouldn't mind reviews either.)

This set adds support for multiple downstream links in an async
sub-device, by separating the sub-device registration from the link
creation.

A new concept, V4L2 async connection is added. A connection later on
translates to an MC ancillary or data link. Generally async notifiers have
a number of connections but at that level there is no knowledge of how
many sub-devices they will connect to. The bound and unbound callbacks now
work on connections. For the existing drivers there's only one connection
so I do not expect regressions because of that.

Async sub-device fwnode matching will now take place between the device
(the dev field of struct v4l2_subdev) and a struct v4l2_async_connection
(an endpoint for devices that have endpoints or the device for those that
do not). This is because the graph data structure only describes
point-to-point connections so therefore defining one end of the connection
defines the entire connection.

This set is unlikely to address all needs people have related to the async
framework but I think that beyond what it does, it paves some way for
addressing more of those additional needs.

To be frank, I'd like to get rid of the entire V4L2 async framework, but
it would require allowing much more dynamic driver initialisation,
including sub-devices and device nodes popping up in the system in the
order and extent there is successfully probed hardware. Until that, and
this may well be the entire foreseeable future, we have at least some of
this complexity.

I didn't add the Tested-by: tags I got for v2 as there are significant
changes, albeit only for better I hope. :-) Niklas has also tested this on
rcar-vin + adv746x, it works now while on v2 it did not. So having also
this version validated on i.MX6 would be nice.

The code also can be found in my async-multi branch, on media tree master.

since v2:

- Drop the sub-devices (struct v4l2_async_subdev) earlier re-introduced in
  this patchset. They aren't necessary, instead we can use struct
  v4l2_subdev to store the information. This simplifies the code quite a
  bit, including removal of one of the global lists: only the sub-device
  and notifier lists are left now. The sub-device is assigned to the
  connection at the bound time: information on which sub-devices are
  connected via async connections is only actually available at the time
  of binding.

- Address issues related to sub-device handling in the rcar-vin driver.
  Also other fixes to the rcar-vin driver (bugs introduced in v2).

- Remove sub-device's notifier field, including an omap3isp patch removing
  an unnecessary test.

- Drop support for async sub-device side endpoint matching. Convert
  NXP imx-mipi-csis.

since v1:

- Fixed object relation issues. The set has now been tested on an
  async sub-device with two pads connected by data links to sub-devices on
  a notifier (struct) device. (Multiple notifiers should work, too, but
  has not been tested.)

- Add a function to obtain an async connection based on the sub-device.
  This is useful for drivers for accessing their own link specific data.

- Improved documentation. Include a patch documenting
  v4l2_async_nf_add_fwnode().

- Return endpoint matching and address adv748x driver breakage in v1. It's
  a special case so other drivers can remain simpler.

- Swap notifier initialisation arguments, by making the notifier the first
  argument.

- Remove extra fwnode_handle_put() in max9286_v4l2_unregister().

- Make struct device available before notifier initialisation for
  consistent debug messages.

- Simplify notifier and async sub-device linked lists. Consistent list
  head and list entry naming.

- Drop leftovers from an early experimenation work in rkisp1 and omap3isp
  drivers.

- Simplify xilinx-vipp sub-device binding.

- Use if()s in notifier_dev() of v4l2-async.c.

- Improved debug messages in v4l2-async.c, use v4l2-async prefix and
  generally with notifier device.

- Call match types with macros V4L2_ASYNC_MATCH_TYPE_* (was
  V4L2_ASYNC_MATCH_*).

- Create ancillary links only when the sub-device is registered, not when
  a connection is bound (which can take place more than once for a
  sub-device).

- Rename struct v4l2_async_match as v4l2_async_match_desc.

- Perform list initialisation in notifier init rather than registration.

- Get rid of the "readd" parameter for v4l2_async_nf_unbind_all_subdevs().

- Check async sub-device validity on a notifier only when the notifier is
  registered. This removes extra list traversal and simplifies the code.

- Remove extra list initialisation in v4l2_async_register_subdev().

- Drop v4l2_async_cleanup(). It was no longer useful, called from a single
  place.

- Lots of kerneldoc fixes (mostly changed argument names).

since RFC v1:

- Address missing API usage changes in a lot of drivers.

- Fix compilation problems in intermediate patches.

- Move V4L2 device registration earlier or move notifier initialisation
  and fwnode endpoint parsing past the current V4L2 device registration
  (patches 11--16).

Jacopo Mondi (1):
  media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints()

Sakari Ailus (31):
  media: Documentation: v4l: Document missing async subdev function
  media: xilinx-vipp: Clean up bound async notifier callback
  media: omap3isp: Don't check for the sub-device's notifier
  media: v4l: async: Add some debug prints
  media: v4l: async: Clean up testing for duplicate async subdevs
  media: v4l: async: Drop unneeded list entry initialisation
  media: v4l: async: Don't check whether asd is NULL in validity check
  media: v4l: async: Make V4L2 async match information a struct
  media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_
  media: v4l: async: Only pass match information for async subdev
    validation
  media: v4l: async: Clean up list heads and entries
  media: v4l: async: Simplify async sub-device fwnode matching
  media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection
  media: v4l: async: Clean up error handling in v4l2_async_match_notify
  media: v4l: async: Drop duplicate handling when adding connections
  media: v4l: async: Rework internal lists
  media: v4l: async: Obtain async connection based on sub-device
  media: v4l: async: Allow multiple connections between entities
  media: v4l: async: Try more connections
  media: v4l: async: Support fwnode endpoint list matching for subdevs
  media: adv748x: Return to endpoint matching
  media: pxa_camera: Fix probe error handling
  media: pxa_camera: Register V4L2 device early
  media: marvell: cafe: Register V4L2 device earlier
  media: am437x-vpfe: Register V4L2 device early
  media: omap3isp: Initialise V4L2 async notifier later
  media: xilinx-vipp: Init async notifier after registering V4L2 device
  media: davinci: Init async notifier after registering V4L2 device
  media: qcom: Initialise V4L2 async notifier later
  media: v4l: async: Set v4l2_device in async notifier init
  media: Documentation: v4l: Document sub-device notifiers

 .../driver-api/media/v4l2-subdev.rst          |  28 +-
 drivers/media/i2c/adv748x/adv748x-csi2.c      |  13 +-
 drivers/media/i2c/max9286.c                   |  27 +-
 drivers/media/i2c/rdacm20.c                   |  16 +-
 drivers/media/i2c/rdacm21.c                   |  15 +-
 drivers/media/i2c/st-mipid02.c                |  12 +-
 drivers/media/i2c/tc358746.c                  |  15 +-
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  14 +-
 drivers/media/platform/atmel/atmel-isi.c      |  12 +-
 drivers/media/platform/atmel/atmel-isi.h      |   2 +-
 drivers/media/platform/cadence/cdns-csi2rx.c  |  10 +-
 drivers/media/platform/intel/pxa_camera.c     |  77 +-
 drivers/media/platform/marvell/cafe-driver.c  |  18 +-
 drivers/media/platform/marvell/mcam-core.c    |  12 +-
 drivers/media/platform/marvell/mmp-driver.c   |   6 +-
 .../platform/microchip/microchip-csi2dc.c     |  11 +-
 .../platform/microchip/microchip-isc-base.c   |   4 +-
 .../media/platform/microchip/microchip-isc.h  |   2 +-
 .../microchip/microchip-sama5d2-isc.c         |   9 +-
 .../microchip/microchip-sama7g5-isc.c         |   9 +-
 drivers/media/platform/nxp/imx-mipi-csis.c    |  17 +-
 drivers/media/platform/nxp/imx7-media-csi.c   |  10 +-
 .../platform/nxp/imx8-isi/imx8-isi-core.c     |  12 +-
 drivers/media/platform/qcom/camss/camss.c     |  26 +-
 drivers/media/platform/qcom/camss/camss.h     |   2 +-
 drivers/media/platform/renesas/rcar-isp.c     |  12 +-
 .../platform/renesas/rcar-vin/rcar-core.c     |  52 +-
 .../platform/renesas/rcar-vin/rcar-csi2.c     |  20 +-
 .../platform/renesas/rcar-vin/rcar-vin.h      |   8 +-
 drivers/media/platform/renesas/rcar_drif.c    |  12 +-
 drivers/media/platform/renesas/renesas-ceu.c  |  10 +-
 .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  14 +-
 .../platform/renesas/rzg2l-cru/rzg2l-cru.h    |   2 +-
 .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |  12 +-
 .../platform/rockchip/rkisp1/rkisp1-common.h  |   2 +-
 .../platform/rockchip/rkisp1/rkisp1-csi.c     |   7 +-
 .../platform/rockchip/rkisp1/rkisp1-dev.c     |  12 +-
 .../platform/rockchip/rkisp1/rkisp1-isp.c     |   8 +-
 .../platform/samsung/exynos4-is/media-dev.c   |  11 +-
 .../platform/samsung/exynos4-is/media-dev.h   |   2 +-
 drivers/media/platform/st/stm32/stm32-dcmi.c  |  12 +-
 .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  10 +-
 .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |   8 +-
 .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   2 +-
 .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |  10 +-
 .../sun8i_a83t_mipi_csi2.c                    |  10 +-
 .../media/platform/ti/am437x/am437x-vpfe.c    |  36 +-
 .../media/platform/ti/am437x/am437x-vpfe.h    |   2 +-
 drivers/media/platform/ti/cal/cal.c           |  10 +-
 .../media/platform/ti/davinci/vpif_capture.c  |  33 +-
 drivers/media/platform/ti/omap3isp/isp.c      |  29 +-
 drivers/media/platform/ti/omap3isp/isp.h      |  15 +-
 drivers/media/platform/ti/omap3isp/ispccdc.c  |  13 +-
 drivers/media/platform/ti/omap3isp/ispccp2.c  |   2 +
 drivers/media/platform/ti/omap3isp/ispcsi2.c  |   2 +
 .../media/platform/ti/omap3isp/ispcsiphy.c    |  15 +-
 drivers/media/platform/video-mux.c            |  10 +-
 drivers/media/platform/xilinx/xilinx-vipp.c   |  55 +-
 drivers/media/v4l2-core/v4l2-async.c          | 685 ++++++++++--------
 drivers/media/v4l2-core/v4l2-fwnode.c         | 109 +--
 drivers/media/v4l2-core/v4l2-subdev.c         |  13 +
 .../media/deprecated/atmel/atmel-isc-base.c   |   4 +-
 .../media/deprecated/atmel/atmel-isc.h        |   2 +-
 .../deprecated/atmel/atmel-sama5d2-isc.c      |   9 +-
 .../deprecated/atmel/atmel-sama7g5-isc.c      |   9 +-
 drivers/staging/media/imx/imx-media-csi.c     |  10 +-
 .../staging/media/imx/imx-media-dev-common.c  |   6 +-
 drivers/staging/media/imx/imx-media-dev.c     |   2 +-
 drivers/staging/media/imx/imx-media-of.c      |   4 +-
 drivers/staging/media/imx/imx6-mipi-csi2.c    |  12 +-
 drivers/staging/media/imx/imx8mq-mipi-csi2.c  |  10 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |   6 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.h    |   2 +-
 drivers/staging/media/tegra-video/vi.c        |  18 +-
 drivers/staging/media/tegra-video/vi.h        |   2 +-
 include/media/davinci/vpif_types.h            |   2 +-
 include/media/v4l2-async.h                    | 218 +++---
 include/media/v4l2-fwnode.h                   |  68 +-
 include/media/v4l2-subdev.h                   |  17 +-
 79 files changed, 973 insertions(+), 1072 deletions(-)

-- 
2.30.2


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

* [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints()
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:13   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function Sakari Ailus
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

The v4l2_async_nf_parse_fwnode_endpoints() function, part of
v4l2-fwnode.c, was a helper meant to register one async sub-dev for each
fwnode endpoint of a device.

The function is marked as deprecated in the documentation and is actually
not used anywhere anymore. Drop it and remove the helper function
v4l2_async_nf_fwnode_parse_endpoint() from v4l2-fwnode.c.

This change allows to make the helper function
__v4l2_async_nf_add_connection() visibility private to v4l2-async.c so
that there is no risk drivers can mistakenly use it.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
[Sakari Ailus: Small fixups on top.]
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c  |  6 +-
 drivers/media/v4l2-core/v4l2-fwnode.c | 97 ---------------------------
 include/media/v4l2-async.h            | 34 ++--------
 include/media/v4l2-fwnode.h           | 66 ------------------
 4 files changed, 7 insertions(+), 196 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index b16b5f4cb91e2..7831bc8792904 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -662,8 +662,9 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
 
-int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
-			       struct v4l2_async_subdev *asd)
+
+static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
+				      struct v4l2_async_subdev *asd)
 {
 	int ret;
 
@@ -679,7 +680,6 @@ int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
 	mutex_unlock(&list_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_subdev);
 
 struct v4l2_async_subdev *
 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 049c2f2001eaa..b71561957b9fb 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -798,103 +798,6 @@ int v4l2_fwnode_device_parse(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
 
-static int
-v4l2_async_nf_fwnode_parse_endpoint(struct device *dev,
-				    struct v4l2_async_notifier *notifier,
-				    struct fwnode_handle *endpoint,
-				    unsigned int asd_struct_size,
-				    parse_endpoint_func parse_endpoint)
-{
-	struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
-	struct v4l2_async_subdev *asd;
-	int ret;
-
-	asd = kzalloc(asd_struct_size, GFP_KERNEL);
-	if (!asd)
-		return -ENOMEM;
-
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode =
-		fwnode_graph_get_remote_port_parent(endpoint);
-	if (!asd->match.fwnode) {
-		dev_dbg(dev, "no remote endpoint found\n");
-		ret = -ENOTCONN;
-		goto out_err;
-	}
-
-	ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep);
-	if (ret) {
-		dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
-			 ret);
-		goto out_err;
-	}
-
-	ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0;
-	if (ret == -ENOTCONN)
-		dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port,
-			vep.base.id);
-	else if (ret < 0)
-		dev_warn(dev,
-			 "driver could not parse port@%u/endpoint@%u (%d)\n",
-			 vep.base.port, vep.base.id, ret);
-	v4l2_fwnode_endpoint_free(&vep);
-	if (ret < 0)
-		goto out_err;
-
-	ret = __v4l2_async_nf_add_subdev(notifier, asd);
-	if (ret < 0) {
-		/* not an error if asd already exists */
-		if (ret == -EEXIST)
-			ret = 0;
-		goto out_err;
-	}
-
-	return 0;
-
-out_err:
-	fwnode_handle_put(asd->match.fwnode);
-	kfree(asd);
-
-	return ret == -ENOTCONN ? 0 : ret;
-}
-
-int
-v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
-				     struct v4l2_async_notifier *notifier,
-				     size_t asd_struct_size,
-				     parse_endpoint_func parse_endpoint)
-{
-	struct fwnode_handle *fwnode;
-	int ret = 0;
-
-	if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
-		return -EINVAL;
-
-	fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) {
-		struct fwnode_handle *dev_fwnode;
-		bool is_available;
-
-		dev_fwnode = fwnode_graph_get_port_parent(fwnode);
-		is_available = fwnode_device_is_available(dev_fwnode);
-		fwnode_handle_put(dev_fwnode);
-		if (!is_available)
-			continue;
-
-
-		ret = v4l2_async_nf_fwnode_parse_endpoint(dev, notifier,
-							  fwnode,
-							  asd_struct_size,
-							  parse_endpoint);
-		if (ret < 0)
-			break;
-	}
-
-	fwnode_handle_put(fwnode);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(v4l2_async_nf_parse_fwnode_endpoints);
-
 /*
  * v4l2_fwnode_reference_parse - parse references for async sub-devices
  * @dev: the device node the properties of which are parsed for references
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 25eb1d138c069..2c9baa3c9266a 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -131,32 +131,10 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
  *
  * This function initializes the notifier @asd_list. It must be called
  * before adding a subdevice to a notifier, using one of:
- * v4l2_async_nf_add_fwnode_remote(),
- * v4l2_async_nf_add_fwnode(),
- * v4l2_async_nf_add_i2c(),
- * __v4l2_async_nf_add_subdev() or
- * v4l2_async_nf_parse_fwnode_endpoints().
- */
-void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
-
-/**
- * __v4l2_async_nf_add_subdev - Add an async subdev to the
- *				notifier's master asd list.
- *
- * @notifier: pointer to &struct v4l2_async_notifier
- * @asd: pointer to &struct v4l2_async_subdev
- *
- * \warning: Drivers should avoid using this function and instead use one of:
- * v4l2_async_nf_add_fwnode(),
- * v4l2_async_nf_add_fwnode_remote() or
+ * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
  * v4l2_async_nf_add_i2c().
- *
- * Call this function before registering a notifier to link the provided @asd to
- * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
- * it will be freed by the framework when the notifier is destroyed.
  */
-int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
-			       struct v4l2_async_subdev *asd);
+void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
 
 struct v4l2_async_subdev *
 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
@@ -263,12 +241,8 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier);
  * Release memory resources related to a notifier, including the async
  * sub-devices allocated for the purposes of the notifier but not the notifier
  * itself. The user is responsible for calling this function to clean up the
- * notifier after calling
- * v4l2_async_nf_add_fwnode_remote(),
- * v4l2_async_nf_add_fwnode(),
- * v4l2_async_nf_add_i2c(),
- * __v4l2_async_nf_add_subdev() or
- * v4l2_async_nf_parse_fwnode_endpoints().
+ * notifier after calling v4l2_async_nf_add_fwnode_remote(),
+ * v4l2_async_nf_add_fwnode() or v4l2_async_nf_add_i2c().
  *
  * There is no harm from calling v4l2_async_nf_cleanup() in other
  * cases as long as its memory has been zeroed after it has been
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 394d798f3dfa4..855dae84b751d 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -393,72 +393,6 @@ int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode,
 int v4l2_fwnode_device_parse(struct device *dev,
 			     struct v4l2_fwnode_device_properties *props);
 
-/**
- * typedef parse_endpoint_func - Driver's callback function to be called on
- *	each V4L2 fwnode endpoint.
- *
- * @dev: pointer to &struct device
- * @vep: pointer to &struct v4l2_fwnode_endpoint
- * @asd: pointer to &struct v4l2_async_subdev
- *
- * Return:
- * * %0 on success
- * * %-ENOTCONN if the endpoint is to be skipped but this
- *   should not be considered as an error
- * * %-EINVAL if the endpoint configuration is invalid
- */
-typedef int (*parse_endpoint_func)(struct device *dev,
-				  struct v4l2_fwnode_endpoint *vep,
-				  struct v4l2_async_subdev *asd);
-
-/**
- * v4l2_async_nf_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
- *						device node
- * @dev: the device the endpoints of which are to be parsed
- * @notifier: notifier for @dev
- * @asd_struct_size: size of the driver's async sub-device struct, including
- *		     sizeof(struct v4l2_async_subdev). The &struct
- *		     v4l2_async_subdev shall be the first member of
- *		     the driver's async sub-device struct, i.e. both
- *		     begin at the same memory address.
- * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
- *		    endpoint. Optional.
- *
- * DEPRECATED! This function is deprecated. Don't use it in new drivers.
- * Instead see an example in cio2_parse_firmware() function in
- * drivers/media/pci/intel/ipu3/ipu3-cio2.c .
- *
- * Parse the fwnode endpoints of the @dev device and populate the async sub-
- * devices list in the notifier. The @parse_endpoint callback function is
- * called for each endpoint with the corresponding async sub-device pointer to
- * let the caller initialize the driver-specific part of the async sub-device
- * structure.
- *
- * The notifier memory shall be zeroed before this function is called on the
- * notifier.
- *
- * This function may not be called on a registered notifier and may be called on
- * a notifier only once.
- *
- * The &struct v4l2_fwnode_endpoint passed to the callback function
- * @parse_endpoint is released once the function is finished. If there is a need
- * to retain that configuration, the user needs to allocate memory for it.
- *
- * Any notifier populated using this function must be released with a call to
- * v4l2_async_nf_cleanup() after it has been unregistered and the async
- * sub-devices are no longer in use, even if the function returned an error.
- *
- * Return: %0 on success, including when no async sub-devices are found
- *	   %-ENOMEM if memory allocation failed
- *	   %-EINVAL if graph or endpoint parsing failed
- *	   Other error codes as returned by @parse_endpoint
- */
-int
-v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
-				     struct v4l2_async_notifier *notifier,
-				     size_t asd_struct_size,
-				     parse_endpoint_func parse_endpoint);
-
 /* Helper macros to access the connector links. */
 
 /** v4l2_connector_last_link - Helper macro to get the first
-- 
2.30.2


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

* [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
  2023-05-25  9:15 ` [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:14   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
                   ` (30 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Also v4l2_async_nf_add_fwnode() may be used to add an async sub-device
descriptor to a notifier. Document this.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 Documentation/driver-api/media/v4l2-subdev.rst | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
index 602dadaa81d86..ce8e9d0a332bc 100644
--- a/Documentation/driver-api/media/v4l2-subdev.rst
+++ b/Documentation/driver-api/media/v4l2-subdev.rst
@@ -204,9 +204,9 @@ that the bridge device needs for its operation. Several functions are available
 to add subdevice descriptors to a notifier, depending on the type of device and
 the needs of the driver.
 
-:c:func:`v4l2_async_nf_add_fwnode_remote` and
-:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
-registering their async sub-devices with the notifier.
+:c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
+:c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
+:c:with the notifier.
 
 :c:func:`v4l2_async_register_subdev_sensor` is a helper function for
 sensor drivers registering their own async sub-device, but it also registers a
-- 
2.30.2


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

* [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
  2023-05-25  9:15 ` [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
  2023-05-25  9:15 ` [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:20   ` Laurent Pinchart
  2023-05-30  2:21   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier Sakari Ailus
                   ` (29 subsequent siblings)
  32 siblings, 2 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The async notifier bound callback does a lot of checks that have probably
been always unnecessary. Remove the lookup of the async subev that we
already have, as well as the debug print that is already printed by the
framework.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/xilinx/xilinx-vipp.c | 32 ++++-----------------
 1 file changed, 5 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 3123216b3f70e..b309af0c83749 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -312,36 +312,14 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
 
 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *unused)
+				   struct v4l2_async_subdev *asd)
 {
-	struct xvip_composite_device *xdev =
-		container_of(notifier, struct xvip_composite_device, notifier);
-	struct xvip_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct xvip_graph_entity *entity = to_xvip_entity(asd);
 
-	/* Locate the entity corresponding to the bound subdev and store the
-	 * subdev pointer.
-	 */
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
-		entity = to_xvip_entity(asd);
+	entity->entity = &subdev->entity;
+	entity->subdev = subdev;
 
-		if (entity->asd.match.fwnode != subdev->fwnode)
-			continue;
-
-		if (entity->subdev) {
-			dev_err(xdev->dev, "duplicate subdev for node %p\n",
-				entity->asd.match.fwnode);
-			return -EINVAL;
-		}
-
-		dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name);
-		entity->entity = &subdev->entity;
-		entity->subdev = subdev;
-		return 0;
-	}
-
-	dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name);
-	return -EINVAL;
+	return 0;
 }
 
 static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = {
-- 
2.30.2


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

* [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (2 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:23   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints Sakari Ailus
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

There's no need to check for a sub-device's notifier as we only register
one notifier (and one V4L2 device). Remove this check and prepare for
removing this field in struct v4l2_subdev.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/ti/omap3isp/isp.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
index f3aaa9e76492e..c2b222f7df892 100644
--- a/drivers/media/platform/ti/omap3isp/isp.c
+++ b/drivers/media/platform/ti/omap3isp/isp.c
@@ -2039,9 +2039,6 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 	}
 
 	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
-		if (sd->notifier != &isp->notifier)
-			continue;
-
 		ret = isp_link_entity(isp, &sd->entity,
 				      v4l2_subdev_to_bus_cfg(sd)->interface);
 		if (ret < 0) {
-- 
2.30.2


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

* [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (3 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:34   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs Sakari Ailus
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Just add some debug prints for V4L2 async sub-device matching process.
These might come useful in figuring out why things don't work as expected.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 71 ++++++++++++++++++++++++----
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 7831bc8792904..c5781124337af 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -77,6 +77,17 @@ static bool match_i2c(struct v4l2_async_notifier *notifier,
 #endif
 }
 
+static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
+{
+	if (notifier->sd)
+		return notifier->sd->dev;
+
+	if (notifier->v4l2_dev)
+		return notifier->v4l2_dev->dev;
+
+	return NULL;
+}
+
 static bool
 match_fwnode_one(struct v4l2_async_notifier *notifier,
 		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
@@ -88,13 +99,20 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 	bool sd_fwnode_is_ep;
 	struct device *dev;
 
+	dev_dbg(notifier_dev(notifier),
+		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
+		sd_fwnode, asd->match.fwnode);
+
 	/*
 	 * Both the subdev and the async subdev can provide either an endpoint
 	 * fwnode or a device fwnode. Start with the simple case of direct
 	 * fwnode matching.
 	 */
-	if (sd_fwnode == asd->match.fwnode)
+	if (sd_fwnode == asd->match.fwnode) {
+		dev_dbg(notifier_dev(notifier),
+			"v4l2-async: direct match found\n");
 		return true;
+	}
 
 	/*
 	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
@@ -107,8 +125,11 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
 	asd_fwnode_is_ep = fwnode_graph_is_endpoint(asd->match.fwnode);
 
-	if (sd_fwnode_is_ep == asd_fwnode_is_ep)
+	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
+		dev_dbg(notifier_dev(notifier),
+			"v4l2-async: direct match not found\n");
 		return false;
+	}
 
 	/*
 	 * The sd and asd fwnodes are of different types. Get the device fwnode
@@ -122,10 +143,17 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 		other_fwnode = sd_fwnode;
 	}
 
+	dev_dbg(notifier_dev(notifier),
+		"v4l2-async: fwnode compat match: need %pfw, trying %pfw\n",
+		dev_fwnode, other_fwnode);
+
 	fwnode_handle_put(dev_fwnode);
 
-	if (dev_fwnode != other_fwnode)
+	if (dev_fwnode != other_fwnode) {
+		dev_dbg(notifier_dev(notifier),
+			"v4l2-async: compat match not found\n");
 		return false;
+	}
 
 	/*
 	 * We have a heterogeneous match. Retrieve the struct device of the side
@@ -145,12 +173,18 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 			   dev->driver->name);
 	}
 
+	dev_dbg(notifier_dev(notifier), "v4l2-async: compat match found\n");
+
 	return true;
 }
 
 static bool match_fwnode(struct v4l2_async_notifier *notifier,
 			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
 {
+	dev_dbg(notifier_dev(notifier),
+		"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
+		dev_fwnode(notifier_dev(notifier)), sd->fwnode);
+
 	if (match_fwnode_one(notifier, sd, sd->fwnode, asd))
 		return true;
 
@@ -158,6 +192,9 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 	if (IS_ERR_OR_NULL(sd->fwnode->secondary))
 		return false;
 
+	dev_dbg(notifier_dev(notifier),
+		"v4l2-async: trying secondary fwnode match\n");
+
 	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd);
 }
 
@@ -271,22 +308,33 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
 static int
 v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
 {
+	struct v4l2_async_notifier *__notifier = notifier;
+
 	/* Quick check whether there are still more sub-devices here. */
 	if (!list_empty(&notifier->waiting))
 		return 0;
 
+	if (notifier->sd)
+		dev_dbg(notifier_dev(notifier),
+			"v4l2-async: trying to complete\n");
+
 	/* Check the entire notifier tree; find the root notifier first. */
 	while (notifier->parent)
 		notifier = notifier->parent;
 
 	/* This is root if it has v4l2_dev. */
-	if (!notifier->v4l2_dev)
+	if (!notifier->v4l2_dev) {
+		dev_dbg(notifier_dev(__notifier),
+			"v4l2-async: V4L2 device not available\n");
 		return 0;
+	}
 
 	/* Is everything ready? */
 	if (!v4l2_async_nf_can_complete(notifier))
 		return 0;
 
+	dev_dbg(notifier_dev(__notifier), "v4l2-async: complete\n");
+
 	return v4l2_async_nf_call_complete(notifier);
 }
 
@@ -350,6 +398,9 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	/* Move from the global subdevice list to notifier's done */
 	list_move(&sd->async_list, &notifier->done);
 
+	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
+		dev_name(sd->dev), ret);
+
 	/*
 	 * See if the sub-device has a notifier. If not, return here.
 	 */
@@ -378,6 +429,8 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
 	if (!v4l2_dev)
 		return 0;
 
+	dev_dbg(notifier_dev(notifier), "v4l2-async: trying all sub-devices\n");
+
 again:
 	list_for_each_entry(sd, &subdev_list, async_list) {
 		struct v4l2_async_subdev *asd;
@@ -387,6 +440,9 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
 		if (!asd)
 			continue;
 
+		dev_dbg(notifier_dev(notifier),
+			"v4l2-async: match found, subdev %s\n", sd->name);
+
 		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
 		if (ret < 0)
 			return ret;
@@ -496,8 +552,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd,
 				   int this_index)
 {
-	struct device *dev =
-		notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
+	struct device *dev = notifier_dev(notifier);
 
 	if (!asd)
 		return -EINVAL;
@@ -506,12 +561,12 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 	case V4L2_ASYNC_MATCH_I2C:
 	case V4L2_ASYNC_MATCH_FWNODE:
 		if (v4l2_async_nf_has_async_subdev(notifier, asd, this_index)) {
-			dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n");
+			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
 			return -EEXIST;
 		}
 		break;
 	default:
-		dev_err(dev, "Invalid match type %u on %p\n",
+		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
 			asd->match_type, asd);
 		return -EINVAL;
 	}
-- 
2.30.2


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

* [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (4 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:42   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation Sakari Ailus
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

There's a need to verify that a single async sub-device isn't being added
multiple times, this would be an error. This takes place at the time of
adding the async sub-device to the notifier's list as well as when the
notifier is added to the global notifier's list.

Use the pointer to the sub-device for testing this instead of an index to
an array that is long gone. (There was an array of async sub-devices in
the notifier before it was converted to a linked list by commit
66beb323e4a0 ("media: v4l2: async: Remove notifier subdevs array").

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index c5781124337af..320fe5cbaaf41 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -520,21 +520,19 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
 
 /*
  * Find out whether an async sub-device was set up already or
- * whether it exists in a given notifier before @this_index.
- * If @this_index < 0, search the notifier's entire @asd_list.
+ * whether it exists in a given notifier.
  */
 static bool
 v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
-			       struct v4l2_async_subdev *asd, int this_index)
+			       struct v4l2_async_subdev *asd, bool skip_self)
 {
 	struct v4l2_async_subdev *asd_y;
-	int j = 0;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
 	list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
-		if (this_index >= 0 && j++ >= this_index)
+		if (skip_self && asd == asd_y)
 			break;
 		if (asd_equal(asd, asd_y))
 			return true;
@@ -550,7 +548,7 @@ v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
 
 static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd,
-				   int this_index)
+				   bool skip_self)
 {
 	struct device *dev = notifier_dev(notifier);
 
@@ -560,7 +558,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 	switch (asd->match_type) {
 	case V4L2_ASYNC_MATCH_I2C:
 	case V4L2_ASYNC_MATCH_FWNODE:
-		if (v4l2_async_nf_has_async_subdev(notifier, asd, this_index)) {
+		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
 			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
 			return -EEXIST;
 		}
@@ -583,7 +581,7 @@ EXPORT_SYMBOL(v4l2_async_nf_init);
 static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_subdev *asd;
-	int ret, i = 0;
+	int ret;
 
 	INIT_LIST_HEAD(&notifier->waiting);
 	INIT_LIST_HEAD(&notifier->done);
@@ -591,7 +589,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
-		ret = v4l2_async_nf_asd_valid(notifier, asd, i++);
+		ret = v4l2_async_nf_asd_valid(notifier, asd, true);
 		if (ret)
 			goto err_unlock;
 
@@ -725,7 +723,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
 
 	mutex_lock(&list_lock);
 
-	ret = v4l2_async_nf_asd_valid(notifier, asd, -1);
+	ret = v4l2_async_nf_asd_valid(notifier, asd, false);
 	if (ret)
 		goto unlock;
 
-- 
2.30.2


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

* [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (5 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:46   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check Sakari Ailus
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The list entry is initialised as a head in v4l2_async_register_subdev()
just before being added to the list. This isn't needed, drop the
initialisation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 320fe5cbaaf41..aef9a16e892ef 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -823,8 +823,6 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 
 	mutex_lock(&list_lock);
 
-	INIT_LIST_HEAD(&sd->async_list);
-
 	list_for_each_entry(notifier, &notifier_list, list) {
 		struct v4l2_device *v4l2_dev =
 			v4l2_async_nf_find_v4l2_dev(notifier);
-- 
2.30.2


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

* [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (6 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:48   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct Sakari Ailus
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The callers do pass a non-NULL asd to v4l2_async_nf_asd_valid() already.
There's no need for the NULL check here.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index aef9a16e892ef..7c924faac4c10 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -552,9 +552,6 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 {
 	struct device *dev = notifier_dev(notifier);
 
-	if (!asd)
-		return -EINVAL;
-
 	switch (asd->match_type) {
 	case V4L2_ASYNC_MATCH_I2C:
 	case V4L2_ASYNC_MATCH_FWNODE:
-- 
2.30.2


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

* [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (7 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:52   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ Sakari Ailus
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Make V4L2 async match information a struct, making it easier to use it
elsewhere outside the scope of struct v4l2_async_subdev.

Also remove an obsolete comment --- none of these fields are supposed to
be touched by drivers.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 20 +++++++-------
 include/media/v4l2-async.h           | 41 ++++++++++++++++------------
 2 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 7c924faac4c10..7f56648e40c44 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -212,7 +212,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 
 	list_for_each_entry(asd, &notifier->waiting, list) {
 		/* bus_type has been verified valid before */
-		switch (asd->match_type) {
+		switch (asd->match.type) {
 		case V4L2_ASYNC_MATCH_I2C:
 			match = match_i2c;
 			break;
@@ -237,10 +237,10 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 static bool asd_equal(struct v4l2_async_subdev *asd_x,
 		      struct v4l2_async_subdev *asd_y)
 {
-	if (asd_x->match_type != asd_y->match_type)
+	if (asd_x->match.type != asd_y->match.type)
 		return false;
 
-	switch (asd_x->match_type) {
+	switch (asd_x->match.type) {
 	case V4L2_ASYNC_MATCH_I2C:
 		return asd_x->match.i2c.adapter_id ==
 			asd_y->match.i2c.adapter_id &&
@@ -552,7 +552,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 {
 	struct device *dev = notifier_dev(notifier);
 
-	switch (asd->match_type) {
+	switch (asd->match.type) {
 	case V4L2_ASYNC_MATCH_I2C:
 	case V4L2_ASYNC_MATCH_FWNODE:
 		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
@@ -561,8 +561,8 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 		}
 		break;
 	default:
-		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
-			asd->match_type, asd);
+		dev_err(dev, "v4l2-asymc: Invalid match type %u on %p\n",
+			asd->match.type, asd);
 		return -EINVAL;
 	}
 
@@ -688,7 +688,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 		return;
 
 	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
-		switch (asd->match_type) {
+		switch (asd->match.type) {
 		case V4L2_ASYNC_MATCH_FWNODE:
 			fwnode_handle_put(asd->match.fwnode);
 			break;
@@ -743,7 +743,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 	if (!asd)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+	asd->match.type = V4L2_ASYNC_MATCH_FWNODE;
 	asd->match.fwnode = fwnode_handle_get(fwnode);
 
 	ret = __v4l2_async_nf_add_subdev(notifier, asd);
@@ -790,7 +790,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 	if (!asd)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match_type = V4L2_ASYNC_MATCH_I2C;
+	asd->match.type = V4L2_ASYNC_MATCH_I2C;
 	asd->match.i2c.adapter_id = adapter_id;
 	asd->match.i2c.address = address;
 
@@ -901,7 +901,7 @@ EXPORT_SYMBOL(v4l2_async_unregister_subdev);
 static void print_waiting_subdev(struct seq_file *s,
 				 struct v4l2_async_subdev *asd)
 {
-	switch (asd->match_type) {
+	switch (asd->match.type) {
 	case V4L2_ASYNC_MATCH_I2C:
 		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
 			   asd->match.i2c.address);
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 2c9baa3c9266a..d347ef32f4ecb 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -34,23 +34,37 @@ enum v4l2_async_match_type {
 };
 
 /**
- * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
+ * struct v4l2_async_match_desc - async sub-device match information
  *
- * @match_type:	type of match that will be used
- * @match:	union of per-bus type matching data sets
- * @match.fwnode:
- *		pointer to &struct fwnode_handle to be matched.
+ * @type:	type of match that will be used
+ * @fwnode:	pointer to &struct fwnode_handle to be matched.
  *		Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
- * @match.i2c:	embedded struct with I2C parameters to be matched.
+ * @i2c:	embedded struct with I2C parameters to be matched.
  *		Both @match.i2c.adapter_id and @match.i2c.address
  *		should be matched.
  *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
- * @match.i2c.adapter_id:
+ * @i2c.adapter_id:
  *		I2C adapter ID to be matched.
  *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
- * @match.i2c.address:
+ * @i2c.address:
  *		I2C address to be matched.
  *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
+ */
+struct v4l2_async_match_desc {
+	enum v4l2_async_match_type type;
+	union {
+		struct fwnode_handle *fwnode;
+		struct {
+			int adapter_id;
+			unsigned short address;
+		} i2c;
+	};
+};
+
+/**
+ * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
+ *
+ * @match:	struct of match type and per-bus type matching data sets
  * @asd_list:	used to add struct v4l2_async_subdev objects to the
  *		master notifier @asd_list
  * @list:	used to link struct v4l2_async_subdev objects, waiting to be
@@ -61,16 +75,7 @@ enum v4l2_async_match_type {
  * v4l2_async_subdev as its first member.
  */
 struct v4l2_async_subdev {
-	enum v4l2_async_match_type match_type;
-	union {
-		struct fwnode_handle *fwnode;
-		struct {
-			int adapter_id;
-			unsigned short address;
-		} i2c;
-	} match;
-
-	/* v4l2-async core private: not to be used by drivers */
+	struct v4l2_async_match_desc match;
 	struct list_head list;
 	struct list_head asd_list;
 };
-- 
2.30.2


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

* [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (8 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  2:55   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation Sakari Ailus
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The async match type is a struct field now, rename V4L2_ASYNC_MATCH_*
macros as V4L2_ASYNC_MATCH_TYPE_* instead.

This patch has been produced by:

git grep -l V4L2_ASYNC_MATCH_ -- drivers/media/ drivers/staging/media/ \
	include/ Documentation/|xargs perl -i -pe \
	's/V4L2_ASYNC_MATCH_\K/TYPE_/g'

so it must be correct.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 22 +++++++++++-----------
 include/media/v4l2-async.h           | 16 ++++++++--------
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 7f56648e40c44..93234c316aa6e 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -213,10 +213,10 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 	list_for_each_entry(asd, &notifier->waiting, list) {
 		/* bus_type has been verified valid before */
 		switch (asd->match.type) {
-		case V4L2_ASYNC_MATCH_I2C:
+		case V4L2_ASYNC_MATCH_TYPE_I2C:
 			match = match_i2c;
 			break;
-		case V4L2_ASYNC_MATCH_FWNODE:
+		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 			match = match_fwnode;
 			break;
 		default:
@@ -241,12 +241,12 @@ static bool asd_equal(struct v4l2_async_subdev *asd_x,
 		return false;
 
 	switch (asd_x->match.type) {
-	case V4L2_ASYNC_MATCH_I2C:
+	case V4L2_ASYNC_MATCH_TYPE_I2C:
 		return asd_x->match.i2c.adapter_id ==
 			asd_y->match.i2c.adapter_id &&
 			asd_x->match.i2c.address ==
 			asd_y->match.i2c.address;
-	case V4L2_ASYNC_MATCH_FWNODE:
+	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 		return asd_x->match.fwnode == asd_y->match.fwnode;
 	default:
 		break;
@@ -553,8 +553,8 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
 	struct device *dev = notifier_dev(notifier);
 
 	switch (asd->match.type) {
-	case V4L2_ASYNC_MATCH_I2C:
-	case V4L2_ASYNC_MATCH_FWNODE:
+	case V4L2_ASYNC_MATCH_TYPE_I2C:
+	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
 			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
 			return -EEXIST;
@@ -689,7 +689,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 
 	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
 		switch (asd->match.type) {
-		case V4L2_ASYNC_MATCH_FWNODE:
+		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 			fwnode_handle_put(asd->match.fwnode);
 			break;
 		default:
@@ -743,7 +743,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 	if (!asd)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match.type = V4L2_ASYNC_MATCH_FWNODE;
+	asd->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
 	asd->match.fwnode = fwnode_handle_get(fwnode);
 
 	ret = __v4l2_async_nf_add_subdev(notifier, asd);
@@ -790,7 +790,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 	if (!asd)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match.type = V4L2_ASYNC_MATCH_I2C;
+	asd->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
 	asd->match.i2c.adapter_id = adapter_id;
 	asd->match.i2c.address = address;
 
@@ -902,11 +902,11 @@ static void print_waiting_subdev(struct seq_file *s,
 				 struct v4l2_async_subdev *asd)
 {
 	switch (asd->match.type) {
-	case V4L2_ASYNC_MATCH_I2C:
+	case V4L2_ASYNC_MATCH_TYPE_I2C:
 		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
 			   asd->match.i2c.address);
 		break;
-	case V4L2_ASYNC_MATCH_FWNODE: {
+	case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
 		struct fwnode_handle *devnode, *fwnode = asd->match.fwnode;
 
 		devnode = fwnode_graph_is_endpoint(fwnode) ?
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index d347ef32f4ecb..8d1506a9755c3 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -22,15 +22,15 @@ struct v4l2_async_notifier;
  * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
  *	in order to identify a match
  *
- * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address
- * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node
+ * @V4L2_ASYNC_MATCH_TYPE_I2C: Match will check for I2C adapter ID and address
+ * @V4L2_ASYNC_MATCH_TYPE_FWNODE: Match will use firmware node
  *
  * This enum is used by the asynchronous sub-device logic to define the
  * algorithm that will be used to match an asynchronous device.
  */
 enum v4l2_async_match_type {
-	V4L2_ASYNC_MATCH_I2C,
-	V4L2_ASYNC_MATCH_FWNODE,
+	V4L2_ASYNC_MATCH_TYPE_I2C,
+	V4L2_ASYNC_MATCH_TYPE_FWNODE,
 };
 
 /**
@@ -38,17 +38,17 @@ enum v4l2_async_match_type {
  *
  * @type:	type of match that will be used
  * @fwnode:	pointer to &struct fwnode_handle to be matched.
- *		Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
+ *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_FWNODE.
  * @i2c:	embedded struct with I2C parameters to be matched.
  *		Both @match.i2c.adapter_id and @match.i2c.address
  *		should be matched.
- *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
+ *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
  * @i2c.adapter_id:
  *		I2C adapter ID to be matched.
- *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
+ *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
  * @i2c.address:
  *		I2C address to be matched.
- *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
+ *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
  */
 struct v4l2_async_match_desc {
 	enum v4l2_async_match_type type;
-- 
2.30.2


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

* [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (9 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  3:02   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries Sakari Ailus
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Pass only information required for sub-device matching to functions
checking whether the async sub-device already exists. Do the same for
debug message printing. This makes further changes to other aspects of
async sub-devices easier.

Accordingly, also perform further renames:

	asd_equal as v4l2_async_match_equal,
	v4l2_async_nf_has_async_subdev as v4l2_async_nf_has_async_match,
	__v4l2_async_nf_has_async_subdev as
		v4l2_async_nf_has_async_subdev_entry and
	v4l2_async_nf_asd_valid as v4l2_async_nf_match_valid.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 109 ++++++++++++++-------------
 1 file changed, 56 insertions(+), 53 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 93234c316aa6e..5eb9850f1c6c4 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -64,14 +64,15 @@ static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n,
 }
 
 static bool match_i2c(struct v4l2_async_notifier *notifier,
-		      struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
+		      struct v4l2_subdev *sd,
+		      struct v4l2_async_match_desc *match)
 {
 #if IS_ENABLED(CONFIG_I2C)
 	struct i2c_client *client = i2c_verify_client(sd->dev);
 
 	return client &&
-		asd->match.i2c.adapter_id == client->adapter->nr &&
-		asd->match.i2c.address == client->addr;
+		match->i2c.adapter_id == client->adapter->nr &&
+		match->i2c.address == client->addr;
 #else
 	return false;
 #endif
@@ -91,7 +92,7 @@ static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
 static bool
 match_fwnode_one(struct v4l2_async_notifier *notifier,
 		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
-		 struct v4l2_async_subdev *asd)
+		 struct v4l2_async_match_desc *match)
 {
 	struct fwnode_handle *other_fwnode;
 	struct fwnode_handle *dev_fwnode;
@@ -101,14 +102,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 
 	dev_dbg(notifier_dev(notifier),
 		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
-		sd_fwnode, asd->match.fwnode);
+		sd_fwnode, match->fwnode);
 
 	/*
 	 * Both the subdev and the async subdev can provide either an endpoint
 	 * fwnode or a device fwnode. Start with the simple case of direct
 	 * fwnode matching.
 	 */
-	if (sd_fwnode == asd->match.fwnode) {
+	if (sd_fwnode == match->fwnode) {
 		dev_dbg(notifier_dev(notifier),
 			"v4l2-async: direct match found\n");
 		return true;
@@ -123,7 +124,7 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 	 * match unconnected endpoints.
 	 */
 	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
-	asd_fwnode_is_ep = fwnode_graph_is_endpoint(asd->match.fwnode);
+	asd_fwnode_is_ep = fwnode_graph_is_endpoint(match->fwnode);
 
 	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
 		dev_dbg(notifier_dev(notifier),
@@ -137,9 +138,9 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 	 */
 	if (sd_fwnode_is_ep) {
 		dev_fwnode = fwnode_graph_get_port_parent(sd_fwnode);
-		other_fwnode = asd->match.fwnode;
+		other_fwnode = match->fwnode;
 	} else {
-		dev_fwnode = fwnode_graph_get_port_parent(asd->match.fwnode);
+		dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
 		other_fwnode = sd_fwnode;
 	}
 
@@ -179,13 +180,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 }
 
 static bool match_fwnode(struct v4l2_async_notifier *notifier,
-			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
+			 struct v4l2_subdev *sd,
+			 struct v4l2_async_match_desc *match)
 {
 	dev_dbg(notifier_dev(notifier),
 		"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
 		dev_fwnode(notifier_dev(notifier)), sd->fwnode);
 
-	if (match_fwnode_one(notifier, sd, sd->fwnode, asd))
+	if (match_fwnode_one(notifier, sd, sd->fwnode, match))
 		return true;
 
 	/* Also check the secondary fwnode. */
@@ -195,7 +197,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 	dev_dbg(notifier_dev(notifier),
 		"v4l2-async: trying secondary fwnode match\n");
 
-	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd);
+	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, match);
 }
 
 static LIST_HEAD(subdev_list);
@@ -207,7 +209,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		      struct v4l2_subdev *sd)
 {
 	bool (*match)(struct v4l2_async_notifier *notifier,
-		      struct v4l2_subdev *sd, struct v4l2_async_subdev *asd);
+		      struct v4l2_subdev *sd,
+		      struct v4l2_async_match_desc *match);
 	struct v4l2_async_subdev *asd;
 
 	list_for_each_entry(asd, &notifier->waiting, list) {
@@ -226,7 +229,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		}
 
 		/* match cannot be NULL here */
-		if (match(notifier, sd, asd))
+		if (match(notifier, sd, &asd->match))
 			return asd;
 	}
 
@@ -234,20 +237,18 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 }
 
 /* Compare two async sub-device descriptors for equivalence */
-static bool asd_equal(struct v4l2_async_subdev *asd_x,
-		      struct v4l2_async_subdev *asd_y)
+static bool v4l2_async_match_equal(struct v4l2_async_match_desc *match1,
+				   struct v4l2_async_match_desc *match2)
 {
-	if (asd_x->match.type != asd_y->match.type)
+	if (match1->type != match2->type)
 		return false;
 
-	switch (asd_x->match.type) {
+	switch (match1->type) {
 	case V4L2_ASYNC_MATCH_TYPE_I2C:
-		return asd_x->match.i2c.adapter_id ==
-			asd_y->match.i2c.adapter_id &&
-			asd_x->match.i2c.address ==
-			asd_y->match.i2c.address;
+		return match1->i2c.adapter_id == match2->i2c.adapter_id &&
+			match1->i2c.address == match2->i2c.address;
 	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
-		return asd_x->match.fwnode == asd_y->match.fwnode;
+		return match1->fwnode == match2->fwnode;
 	default:
 		break;
 	}
@@ -497,21 +498,21 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
 
 /* See if an async sub-device can be found in a notifier's lists. */
 static bool
-__v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
-				 struct v4l2_async_subdev *asd)
+v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
+				    struct v4l2_async_match_desc *match)
 {
-	struct v4l2_async_subdev *asd_y;
+	struct v4l2_async_subdev *asd;
 	struct v4l2_subdev *sd;
 
-	list_for_each_entry(asd_y, &notifier->waiting, list)
-		if (asd_equal(asd, asd_y))
+	list_for_each_entry(asd, &notifier->waiting, list)
+		if (v4l2_async_match_equal(&asd->match, match))
 			return true;
 
 	list_for_each_entry(sd, &notifier->done, async_list) {
 		if (WARN_ON(!sd->asd))
 			continue;
 
-		if (asd_equal(asd, sd->asd))
+		if (v4l2_async_match_equal(&sd->asd->match, match))
 			return true;
 	}
 
@@ -523,46 +524,48 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
  * whether it exists in a given notifier.
  */
 static bool
-v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
-			       struct v4l2_async_subdev *asd, bool skip_self)
+v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
+			      struct v4l2_async_match_desc *match,
+			      bool skip_self)
 {
-	struct v4l2_async_subdev *asd_y;
+	struct v4l2_async_subdev *asd;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
-		if (skip_self && asd == asd_y)
+	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+		if (skip_self && &asd->match == match)
 			break;
-		if (asd_equal(asd, asd_y))
+		if (v4l2_async_match_equal(&asd->match, match))
 			return true;
 	}
 
 	/* Check that an asd does not exist in other notifiers. */
 	list_for_each_entry(notifier, &notifier_list, list)
-		if (__v4l2_async_nf_has_async_subdev(notifier, asd))
+		if (v4l2_async_nf_has_async_match_entry(notifier, match))
 			return true;
 
 	return false;
 }
 
-static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
-				   struct v4l2_async_subdev *asd,
-				   bool skip_self)
+static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
+				     struct v4l2_async_match_desc *match,
+				     bool skip_self)
 {
 	struct device *dev = notifier_dev(notifier);
 
-	switch (asd->match.type) {
+	switch (match->type) {
 	case V4L2_ASYNC_MATCH_TYPE_I2C:
 	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
-		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
-			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
+		if (v4l2_async_nf_has_async_match(notifier, match,
+						  skip_self)) {
+			dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
 			return -EEXIST;
 		}
 		break;
 	default:
-		dev_err(dev, "v4l2-asymc: Invalid match type %u on %p\n",
-			asd->match.type, asd);
+		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
+			match->type, match);
 		return -EINVAL;
 	}
 
@@ -586,7 +589,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
-		ret = v4l2_async_nf_asd_valid(notifier, asd, true);
+		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
 		if (ret)
 			goto err_unlock;
 
@@ -720,7 +723,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
 
 	mutex_lock(&list_lock);
 
-	ret = v4l2_async_nf_asd_valid(notifier, asd, false);
+	ret = v4l2_async_nf_match_valid(notifier, &asd->match, false);
 	if (ret)
 		goto unlock;
 
@@ -898,16 +901,16 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 }
 EXPORT_SYMBOL(v4l2_async_unregister_subdev);
 
-static void print_waiting_subdev(struct seq_file *s,
-				 struct v4l2_async_subdev *asd)
+static void print_waiting_match(struct seq_file *s,
+				struct v4l2_async_match_desc *match)
 {
-	switch (asd->match.type) {
+	switch (match->type) {
 	case V4L2_ASYNC_MATCH_TYPE_I2C:
-		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
-			   asd->match.i2c.address);
+		seq_printf(s, " [i2c] dev=%d-%04x\n", match->i2c.adapter_id,
+			   match->i2c.address);
 		break;
 	case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
-		struct fwnode_handle *devnode, *fwnode = asd->match.fwnode;
+		struct fwnode_handle *devnode, *fwnode = match->fwnode;
 
 		devnode = fwnode_graph_is_endpoint(fwnode) ?
 			  fwnode_graph_get_port_parent(fwnode) :
@@ -944,7 +947,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
 	list_for_each_entry(notif, &notifier_list, list) {
 		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
 		list_for_each_entry(asd, &notif->waiting, list)
-			print_waiting_subdev(s, asd);
+			print_waiting_match(s, &asd->match);
 	}
 
 	mutex_unlock(&list_lock);
-- 
2.30.2


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

* [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (10 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  3:09   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching Sakari Ailus
                   ` (20 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The naming of list heads and list entries is confusing as they're named
similarly. Use _list for list head and _entry for list entries.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  2 +-
 drivers/media/platform/xilinx/xilinx-vipp.c   |  6 +--
 drivers/media/v4l2-core/v4l2-async.c          | 54 +++++++++----------
 drivers/staging/media/tegra-video/vi.c        |  4 +-
 include/media/v4l2-async.h                    | 36 ++++++-------
 include/media/v4l2-subdev.h                   |  2 +-
 6 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 3c84cb1216320..9231d6a65f4ec 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
 	unsigned int pad;
 	int ret;
 
-	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) {
 		s_asd = to_sensor_asd(asd);
 		q = &cio2->queue[s_asd->csi2.port];
 
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index b309af0c83749..52c5a7decf284 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
 	struct xvip_graph_entity *entity;
 	struct v4l2_async_subdev *asd;
 
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
 		entity = to_xvip_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
 
 	/* Create links for every entity. */
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_build_one(xdev, entity);
 		if (ret < 0)
@@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
 	if (ret < 0)
 		return 0;
 
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
 		if (ret < 0) {
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 5eb9850f1c6c4..06b1e1a1a5f87 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -213,7 +213,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		      struct v4l2_async_match_desc *match);
 	struct v4l2_async_subdev *asd;
 
-	list_for_each_entry(asd, &notifier->waiting, list) {
+	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry) {
 		/* bus_type has been verified valid before */
 		switch (asd->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_I2C:
@@ -262,7 +262,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *n;
 
-	list_for_each_entry(n, &notifier_list, list)
+	list_for_each_entry(n, &notifier_list, notifier_entry)
 		if (n->sd == sd)
 			return n;
 
@@ -287,10 +287,10 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_subdev *sd;
 
-	if (!list_empty(&notifier->waiting))
+	if (!list_empty(&notifier->waiting_list))
 		return false;
 
-	list_for_each_entry(sd, &notifier->done, async_list) {
+	list_for_each_entry(sd, &notifier->done_list, async_list) {
 		struct v4l2_async_notifier *subdev_notifier =
 			v4l2_async_find_subdev_notifier(sd);
 
@@ -312,7 +312,7 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
 	struct v4l2_async_notifier *__notifier = notifier;
 
 	/* Quick check whether there are still more sub-devices here. */
-	if (!list_empty(&notifier->waiting))
+	if (!list_empty(&notifier->waiting_list))
 		return 0;
 
 	if (notifier->sd)
@@ -391,13 +391,12 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 		return ret;
 	}
 
-	/* Remove from the waiting list */
-	list_del(&asd->list);
+	list_del(&asd->waiting_entry);
 	sd->asd = asd;
 	sd->notifier = notifier;
 
 	/* Move from the global subdevice list to notifier's done */
-	list_move(&sd->async_list, &notifier->done);
+	list_move(&sd->async_list, &notifier->done_list);
 
 	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
 		dev_name(sd->dev), ret);
@@ -478,7 +477,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
 {
 	struct v4l2_subdev *sd, *tmp;
 
-	list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
+	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
 		struct v4l2_async_notifier *subdev_notifier =
 			v4l2_async_find_subdev_notifier(sd);
 
@@ -487,7 +486,8 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
 
 		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
 		if (readd)
-			list_add_tail(&sd->asd->list, &notifier->waiting);
+			list_add_tail(&sd->asd->waiting_entry,
+				      &notifier->waiting_list);
 		v4l2_async_cleanup(sd);
 
 		list_move(&sd->async_list, &subdev_list);
@@ -504,11 +504,11 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
 	struct v4l2_async_subdev *asd;
 	struct v4l2_subdev *sd;
 
-	list_for_each_entry(asd, &notifier->waiting, list)
+	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry)
 		if (v4l2_async_match_equal(&asd->match, match))
 			return true;
 
-	list_for_each_entry(sd, &notifier->done, async_list) {
+	list_for_each_entry(sd, &notifier->done_list, async_list) {
 		if (WARN_ON(!sd->asd))
 			continue;
 
@@ -533,7 +533,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
 		if (skip_self && &asd->match == match)
 			break;
 		if (v4l2_async_match_equal(&asd->match, match))
@@ -541,7 +541,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 	}
 
 	/* Check that an asd does not exist in other notifiers. */
-	list_for_each_entry(notifier, &notifier_list, list)
+	list_for_each_entry(notifier, &notifier_list, notifier_entry)
 		if (v4l2_async_nf_has_async_match_entry(notifier, match))
 			return true;
 
@@ -583,17 +583,17 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	struct v4l2_async_subdev *asd;
 	int ret;
 
-	INIT_LIST_HEAD(&notifier->waiting);
-	INIT_LIST_HEAD(&notifier->done);
+	INIT_LIST_HEAD(&notifier->waiting_list);
+	INIT_LIST_HEAD(&notifier->done_list);
 
 	mutex_lock(&list_lock);
 
-	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
 		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
 		if (ret)
 			goto err_unlock;
 
-		list_add_tail(&asd->list, &notifier->waiting);
+		list_add_tail(&asd->waiting_entry, &notifier->waiting_list);
 	}
 
 	ret = v4l2_async_nf_try_all_subdevs(notifier);
@@ -605,7 +605,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 		goto err_unbind;
 
 	/* Keep also completed notifiers on the list */
-	list_add(&notifier->list, &notifier_list);
+	list_add(&notifier->notifier_entry, &notifier_list);
 
 	mutex_unlock(&list_lock);
 
@@ -670,7 +670,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
 	notifier->sd = NULL;
 	notifier->v4l2_dev = NULL;
 
-	list_del(&notifier->list);
+	list_del(&notifier->notifier_entry);
 }
 
 void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
@@ -690,7 +690,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 	if (!notifier || !notifier->asd_list.next)
 		return;
 
-	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
+	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_entry) {
 		switch (asd->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 			fwnode_handle_put(asd->match.fwnode);
@@ -699,7 +699,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 			break;
 		}
 
-		list_del(&asd->asd_list);
+		list_del(&asd->asd_entry);
 		v4l2_async_nf_call_destroy(notifier, asd);
 		kfree(asd);
 	}
@@ -727,7 +727,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
 	if (ret)
 		goto unlock;
 
-	list_add_tail(&asd->asd_list, &notifier->asd_list);
+	list_add_tail(&asd->asd_entry, &notifier->asd_list);
 
 unlock:
 	mutex_unlock(&list_lock);
@@ -823,7 +823,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 
 	mutex_lock(&list_lock);
 
-	list_for_each_entry(notifier, &notifier_list, list) {
+	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
 		struct v4l2_device *v4l2_dev =
 			v4l2_async_nf_find_v4l2_dev(notifier);
 		struct v4l2_async_subdev *asd;
@@ -890,7 +890,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 	if (sd->asd) {
 		struct v4l2_async_notifier *notifier = sd->notifier;
 
-		list_add(&sd->asd->list, &notifier->waiting);
+		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
 
 		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
 	}
@@ -944,9 +944,9 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
 
 	mutex_lock(&list_lock);
 
-	list_for_each_entry(notif, &notifier_list, list) {
+	list_for_each_entry(notif, &notifier_list, notifier_entry) {
 		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
-		list_for_each_entry(asd, &notif->waiting, list)
+		list_for_each_entry(asd, &notif->waiting_list, waiting_entry)
 			print_waiting_match(s, &asd->match);
 	}
 
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 2f1aff7e87170..350871f34f7cc 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
 	struct tegra_vi_graph_entity *entity;
 	struct v4l2_async_subdev *asd;
 
-	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	}
 
 	/* create links between the entities */
-	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
+	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		ret = tegra_vi_graph_build(chan, entity);
 		if (ret < 0)
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 8d1506a9755c3..54f9f45ed3d8e 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -65,10 +65,10 @@ struct v4l2_async_match_desc {
  * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
  *
  * @match:	struct of match type and per-bus type matching data sets
- * @asd_list:	used to add struct v4l2_async_subdev objects to the
- *		master notifier @asd_list
- * @list:	used to link struct v4l2_async_subdev objects, waiting to be
- *		probed, to a notifier->waiting list
+ * @asd_entry:	used to add struct v4l2_async_subdev objects to the
+ *		master notifier @asd_entry
+ * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
+ *		probed, to a notifier->waiting_list list
  *
  * When this struct is used as a member in a driver specific struct,
  * the driver specific struct shall contain the &struct
@@ -76,8 +76,8 @@ struct v4l2_async_match_desc {
  */
 struct v4l2_async_subdev {
 	struct v4l2_async_match_desc match;
-	struct list_head list;
-	struct list_head asd_list;
+	struct list_head asd_entry;
+	struct list_head waiting_entry;
 };
 
 /**
@@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations {
  * @sd:		sub-device that registered the notifier, NULL otherwise
  * @parent:	parent notifier
  * @asd_list:	master list of struct v4l2_async_subdev
- * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
- * @done:	list of struct v4l2_subdev, already probed
- * @list:	member in a global list of notifiers
+ * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
+ * @done_list:	list of struct v4l2_subdev, already probed
+ * @notifier_entry: member in a global list of notifiers
  */
 struct v4l2_async_notifier {
 	const struct v4l2_async_notifier_operations *ops;
@@ -117,9 +117,9 @@ struct v4l2_async_notifier {
 	struct v4l2_subdev *sd;
 	struct v4l2_async_notifier *parent;
 	struct list_head asd_list;
-	struct list_head waiting;
-	struct list_head done;
-	struct list_head list;
+	struct list_head waiting_list;
+	struct list_head done_list;
+	struct list_head notifier_entry;
 };
 
 /**
@@ -134,7 +134,7 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  *
- * This function initializes the notifier @asd_list. It must be called
+ * This function initializes the notifier @asd_entry. It must be called
  * before adding a subdevice to a notifier, using one of:
  * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
  * v4l2_async_nf_add_i2c().
@@ -147,7 +147,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 			   unsigned int asd_struct_size);
 /**
  * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
- *				subdev to the notifier's master asd_list.
+ *				subdev to the notifier's master asd_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @fwnode: fwnode handle of the sub-device to be matched, pointer to
@@ -157,7 +157,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
  *	  sub-device struct, i.e. both begin at the same memory address.
  *
  * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
- * notifiers @asd_list. The function also gets a reference of the fwnode which
+ * notifiers @asd_entry. The function also gets a reference of the fwnode which
  * is released later at notifier cleanup time.
  */
 #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
@@ -170,7 +170,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
 /**
  * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
  *						  remote async subdev to the
- *						  notifier's master asd_list.
+ *						  notifier's master asd_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @ep: local endpoint pointing to the remote sub-device to be matched,
@@ -180,7 +180,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
  *	  sub-device struct, i.e. both begin at the same memory address.
  *
  * Gets the remote endpoint of a given local endpoint, set it up for fwnode
- * matching and adds the async sub-device to the notifier's @asd_list. The
+ * matching and adds the async sub-device to the notifier's @asd_entry. The
  * function also gets a reference of the fwnode which is released later at
  * notifier cleanup time.
  *
@@ -196,7 +196,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
 			unsigned int asd_struct_size);
 /**
  * v4l2_async_nf_add_i2c - Allocate and add an i2c async
- *				subdev to the notifier's master asd_list.
+ *				subdev to the notifier's master asd_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @adapter: I2C adapter ID to be matched
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index cfd19e72d0fc4..82e4cf3dd2e05 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1020,7 +1020,7 @@ struct v4l2_subdev_platform_data {
  * @dev: pointer to the physical device, if any
  * @fwnode: The fwnode_handle of the subdev, usually the same as
  *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
- * @async_list: Links this subdev to a global subdev_list or @notifier->done
+ * @async_list: Links this subdev to a global subdev_entry or @notifier->done
  *	list.
  * @asd: Pointer to respective &struct v4l2_async_subdev.
  * @notifier: Pointer to the managing notifier.
-- 
2.30.2


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

* [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (11 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  5:08   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection Sakari Ailus
                   ` (19 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

V4L2 async sub-device matching originally used the device nodes only.
Endpoint nodes were taken into use instead as using the device nodes was
problematic for it was in some cases ambiguous which link might have been
in question.

There is however no need to use endpoint nodes on both sides, as the async
sub-device's fwnode can always be trivially obtained using
fwnode_graph_get_remote_endpoint() when needed while what counts is
whether or not the link is between two device nodes, i.e. the device nodes
match.

This will briefly break the adv748x driver but it will be fixed later in
the set, by patch "media: adv748x: Return to endpoint matching".

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/adv748x/adv748x-csi2.c   |  5 +-
 drivers/media/i2c/max9286.c                | 14 +---
 drivers/media/i2c/rdacm20.c                | 16 +---
 drivers/media/i2c/rdacm21.c                | 15 +---
 drivers/media/i2c/tc358746.c               |  5 --
 drivers/media/platform/nxp/imx-mipi-csis.c |  7 --
 drivers/media/v4l2-core/v4l2-async.c       | 88 ++++++----------------
 7 files changed, 26 insertions(+), 124 deletions(-)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
index bd4f3fe0e3096..b6f93c1db3d2a 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -296,13 +296,12 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
 	if (!is_tx_enabled(tx))
 		return 0;
 
+	/* FIXME: Do endpoint matching again! */
+
 	adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
 			    MEDIA_ENT_F_VID_IF_BRIDGE,
 			    is_txa(tx) ? "txa" : "txb");
 
-	/* Ensure that matching is based upon the endpoint fwnodes */
-	tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]);
-
 	/* Register internal ops for incremental subdev registration */
 	tx->sd.internal_ops = &adv748x_csi2_internal_ops;
 
diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 13a986b885889..64f5c49cae776 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -1051,7 +1051,6 @@ static const struct v4l2_ctrl_ops max9286_ctrl_ops = {
 static int max9286_v4l2_register(struct max9286_priv *priv)
 {
 	struct device *dev = &priv->client->dev;
-	struct fwnode_handle *ep;
 	int ret;
 	int i;
 
@@ -1093,25 +1092,14 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
 	if (ret)
 		goto err_async;
 
-	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), MAX9286_SRC_PAD,
-					     0, 0);
-	if (!ep) {
-		dev_err(dev, "Unable to retrieve endpoint on \"port@4\"\n");
-		ret = -ENOENT;
-		goto err_async;
-	}
-	priv->sd.fwnode = ep;
-
 	ret = v4l2_async_register_subdev(&priv->sd);
 	if (ret < 0) {
 		dev_err(dev, "Unable to register subdevice\n");
-		goto err_put_node;
+		goto err_async;
 	}
 
 	return 0;
 
-err_put_node:
-	fwnode_handle_put(ep);
 err_async:
 	v4l2_ctrl_handler_free(&priv->ctrls);
 	max9286_v4l2_notifier_unregister(priv);
diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index a2263fa825b59..9d8a8f9efd835 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -567,7 +567,6 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
 static int rdacm20_probe(struct i2c_client *client)
 {
 	struct rdacm20_device *dev;
-	struct fwnode_handle *ep;
 	int ret;
 
 	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
@@ -616,24 +615,12 @@ static int rdacm20_probe(struct i2c_client *client)
 	if (ret < 0)
 		goto error_free_ctrls;
 
-	ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
-	if (!ep) {
-		dev_err(&client->dev,
-			"Unable to get endpoint in node %pOF\n",
-			client->dev.of_node);
-		ret = -ENOENT;
-		goto error_free_ctrls;
-	}
-	dev->sd.fwnode = ep;
-
 	ret = v4l2_async_register_subdev(&dev->sd);
 	if (ret)
-		goto error_put_node;
+		goto error_free_ctrls;
 
 	return 0;
 
-error_put_node:
-	fwnode_handle_put(ep);
 error_free_ctrls:
 	v4l2_ctrl_handler_free(&dev->ctrls);
 error:
@@ -650,7 +637,6 @@ static void rdacm20_remove(struct i2c_client *client)
 {
 	struct rdacm20_device *dev = i2c_to_rdacm20(client);
 
-	fwnode_handle_put(dev->sd.fwnode);
 	v4l2_async_unregister_subdev(&dev->sd);
 	v4l2_ctrl_handler_free(&dev->ctrls);
 	media_entity_cleanup(&dev->sd.entity);
diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 9ccc56c30d3b0..d67cfcb2e05a4 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -543,7 +543,6 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
 static int rdacm21_probe(struct i2c_client *client)
 {
 	struct rdacm21_device *dev;
-	struct fwnode_handle *ep;
 	int ret;
 
 	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
@@ -588,24 +587,12 @@ static int rdacm21_probe(struct i2c_client *client)
 	if (ret < 0)
 		goto error_free_ctrls;
 
-	ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
-	if (!ep) {
-		dev_err(&client->dev,
-			"Unable to get endpoint in node %pOF\n",
-			client->dev.of_node);
-		ret = -ENOENT;
-		goto error_free_ctrls;
-	}
-	dev->sd.fwnode = ep;
-
 	ret = v4l2_async_register_subdev(&dev->sd);
 	if (ret)
-		goto error_put_node;
+		goto error_free_ctrls;
 
 	return 0;
 
-error_put_node:
-	fwnode_handle_put(dev->sd.fwnode);
 error_free_ctrls:
 	v4l2_ctrl_handler_free(&dev->ctrls);
 error:
diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
index ec1a193ba161a..b37a9ff73f6ad 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -1476,9 +1476,6 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 	if (err)
 		goto err_cleanup;
 
-	tc358746->sd.fwnode = fwnode_graph_get_endpoint_by_id(
-		dev_fwnode(tc358746->sd.dev), TC358746_SOURCE, 0, 0);
-
 	err = v4l2_async_register_subdev(&tc358746->sd);
 	if (err)
 		goto err_unregister;
@@ -1486,7 +1483,6 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 	return 0;
 
 err_unregister:
-	fwnode_handle_put(tc358746->sd.fwnode);
 	v4l2_async_nf_unregister(&tc358746->notifier);
 err_cleanup:
 	v4l2_async_nf_cleanup(&tc358746->notifier);
@@ -1605,7 +1601,6 @@ static void tc358746_remove(struct i2c_client *client)
 	v4l2_fwnode_endpoint_free(&tc358746->csi_vep);
 	v4l2_async_nf_unregister(&tc358746->notifier);
 	v4l2_async_nf_cleanup(&tc358746->notifier);
-	fwnode_handle_put(sd->fwnode);
 	v4l2_async_unregister_subdev(sd);
 	media_entity_cleanup(&sd->entity);
 
diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
index 05d52762e7926..d0dc30187775d 100644
--- a/drivers/media/platform/nxp/imx-mipi-csis.c
+++ b/drivers/media/platform/nxp/imx-mipi-csis.c
@@ -1365,13 +1365,6 @@ static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
 
 	sd->dev = csis->dev;
 
-	sd->fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev),
-						     1, 0, 0);
-	if (!sd->fwnode) {
-		dev_err(csis->dev, "Unable to retrieve endpoint for port@1\n");
-		return -ENOENT;
-	}
-
 	csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
 					 | MEDIA_PAD_FL_MUST_CONNECT;
 	csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 06b1e1a1a5f87..335597889f365 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -94,89 +94,36 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
 		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
 		 struct v4l2_async_match_desc *match)
 {
-	struct fwnode_handle *other_fwnode;
-	struct fwnode_handle *dev_fwnode;
-	bool asd_fwnode_is_ep;
-	bool sd_fwnode_is_ep;
-	struct device *dev;
+	struct fwnode_handle *asd_dev_fwnode;
+	bool ret;
 
 	dev_dbg(notifier_dev(notifier),
 		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
 		sd_fwnode, match->fwnode);
 
-	/*
-	 * Both the subdev and the async subdev can provide either an endpoint
-	 * fwnode or a device fwnode. Start with the simple case of direct
-	 * fwnode matching.
-	 */
 	if (sd_fwnode == match->fwnode) {
 		dev_dbg(notifier_dev(notifier),
 			"v4l2-async: direct match found\n");
 		return true;
 	}
 
-	/*
-	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
-	 * endpoint or a device. If they're of the same type, there's no match.
-	 * Technically speaking this checks if the nodes refer to a connected
-	 * endpoint, which is the simplest check that works for both OF and
-	 * ACPI. This won't make a difference, as drivers should not try to
-	 * match unconnected endpoints.
-	 */
-	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
-	asd_fwnode_is_ep = fwnode_graph_is_endpoint(match->fwnode);
-
-	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
+	if (!fwnode_graph_is_endpoint(match->fwnode)) {
 		dev_dbg(notifier_dev(notifier),
 			"v4l2-async: direct match not found\n");
 		return false;
 	}
 
-	/*
-	 * The sd and asd fwnodes are of different types. Get the device fwnode
-	 * parent of the endpoint fwnode, and compare it with the other fwnode.
-	 */
-	if (sd_fwnode_is_ep) {
-		dev_fwnode = fwnode_graph_get_port_parent(sd_fwnode);
-		other_fwnode = match->fwnode;
-	} else {
-		dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
-		other_fwnode = sd_fwnode;
-	}
+	asd_dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
 
-	dev_dbg(notifier_dev(notifier),
-		"v4l2-async: fwnode compat match: need %pfw, trying %pfw\n",
-		dev_fwnode, other_fwnode);
+	ret = sd_fwnode == asd_dev_fwnode;
 
-	fwnode_handle_put(dev_fwnode);
+	fwnode_handle_put(asd_dev_fwnode);
 
-	if (dev_fwnode != other_fwnode) {
-		dev_dbg(notifier_dev(notifier),
-			"v4l2-async: compat match not found\n");
-		return false;
-	}
-
-	/*
-	 * We have a heterogeneous match. Retrieve the struct device of the side
-	 * that matched on a device fwnode to print its driver name.
-	 */
-	if (sd_fwnode_is_ep)
-		dev = notifier->v4l2_dev ? notifier->v4l2_dev->dev
-		    : notifier->sd->dev;
-	else
-		dev = sd->dev;
-
-	if (dev && dev->driver) {
-		if (sd_fwnode_is_ep)
-			dev_warn(dev, "Driver %s uses device fwnode, incorrect match may occur\n",
-				 dev->driver->name);
-		dev_notice(dev, "Consider updating driver %s to match on endpoints\n",
-			   dev->driver->name);
-	}
-
-	dev_dbg(notifier_dev(notifier), "v4l2-async: compat match found\n");
+	dev_dbg(notifier_dev(notifier),
+		"v4l2-async: device--endpoint match %sfound\n",
+		ret ? "" : "not ");
 
-	return true;
+	return ret;
 }
 
 static bool match_fwnode(struct v4l2_async_notifier *notifier,
@@ -814,12 +761,19 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	int ret;
 
 	/*
-	 * No reference taken. The reference is held by the device
-	 * (struct v4l2_subdev.dev), and async sub-device does not
-	 * exist independently of the device at any point of time.
+	 * No reference taken. The reference is held by the device (struct
+	 * v4l2_subdev.dev), and async sub-device does not exist independently
+	 * of the device at any point of time.
+	 *
+	 * The async sub-device shall always be registered for its device node,
+	 * not the endpoint node.
 	 */
-	if (!sd->fwnode && sd->dev)
+	if (!sd->fwnode && sd->dev) {
 		sd->fwnode = dev_fwnode(sd->dev);
+	} else if (fwnode_graph_is_endpoint(sd->fwnode)) {
+		dev_warn(sd->dev, "sub-device fwnode is an endpoint!\n");
+		return -EINVAL;
+	}
 
 	mutex_lock(&list_lock);
 
-- 
2.30.2


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

* [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (12 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  5:50   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify Sakari Ailus
                   ` (18 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Rename v4l2_async_subdev as v4l2_async_connection, in order to
differentiate between the sub-devices and their connections: one
sub-device can have many connections but the V4L2 async framework has so
far allowed just a single one. Connections in this context will later
translate into either MC ancillary or data links.

This patch prepares changing that relation by changing existing users of
v4l2_async_subdev to switch to v4l2_async_connection. Async sub-devices
themselves will not be needed anymore

Additionally, __v4l2_async_nf_add_subdev() has been renamed as
__v4l2_async_nf_add_connection().

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../driver-api/media/v4l2-subdev.rst          |  12 +-
 drivers/media/i2c/max9286.c                   |   9 +-
 drivers/media/i2c/st-mipid02.c                |   8 +-
 drivers/media/i2c/tc358746.c                  |   6 +-
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  10 +-
 drivers/media/platform/atmel/atmel-isi.c      |   8 +-
 drivers/media/platform/atmel/atmel-isi.h      |   2 +-
 drivers/media/platform/cadence/cdns-csi2rx.c  |   6 +-
 drivers/media/platform/intel/pxa_camera.c     |  12 +-
 drivers/media/platform/marvell/cafe-driver.c  |   5 +-
 drivers/media/platform/marvell/mcam-core.c    |   4 +-
 drivers/media/platform/marvell/mmp-driver.c   |   4 +-
 .../platform/microchip/microchip-csi2dc.c     |   6 +-
 .../platform/microchip/microchip-isc-base.c   |   4 +-
 .../media/platform/microchip/microchip-isc.h  |   2 +-
 .../microchip/microchip-sama5d2-isc.c         |   4 +-
 .../microchip/microchip-sama7g5-isc.c         |   4 +-
 drivers/media/platform/nxp/imx-mipi-csis.c    |   6 +-
 drivers/media/platform/nxp/imx7-media-csi.c   |   6 +-
 .../platform/nxp/imx8-isi/imx8-isi-core.c     |   8 +-
 drivers/media/platform/qcom/camss/camss.c     |   2 +-
 drivers/media/platform/qcom/camss/camss.h     |   2 +-
 drivers/media/platform/renesas/rcar-isp.c     |   8 +-
 .../platform/renesas/rcar-vin/rcar-core.c     |  44 ++---
 .../platform/renesas/rcar-vin/rcar-csi2.c     |  16 +-
 .../platform/renesas/rcar-vin/rcar-vin.h      |   8 +-
 drivers/media/platform/renesas/rcar_drif.c    |   8 +-
 drivers/media/platform/renesas/renesas-ceu.c  |   6 +-
 .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  10 +-
 .../platform/renesas/rzg2l-cru/rzg2l-cru.h    |   2 +-
 .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |   8 +-
 .../platform/rockchip/rkisp1/rkisp1-common.h  |   2 +-
 .../platform/rockchip/rkisp1/rkisp1-dev.c     |   8 +-
 .../platform/samsung/exynos4-is/media-dev.c   |   6 +-
 .../platform/samsung/exynos4-is/media-dev.h   |   2 +-
 drivers/media/platform/st/stm32/stm32-dcmi.c  |   8 +-
 .../platform/sunxi/sun4i-csi/sun4i_csi.c      |   6 +-
 .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |   2 +-
 .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   2 +-
 .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |   6 +-
 .../sun8i_a83t_mipi_csi2.c                    |   6 +-
 .../media/platform/ti/am437x/am437x-vpfe.c    |   5 +-
 .../media/platform/ti/am437x/am437x-vpfe.h    |   2 +-
 drivers/media/platform/ti/cal/cal.c           |   6 +-
 .../media/platform/ti/davinci/vpif_capture.c  |   7 +-
 drivers/media/platform/ti/omap3isp/isp.h      |   2 +-
 drivers/media/platform/video-mux.c            |   6 +-
 drivers/media/platform/xilinx/xilinx-vipp.c   |  22 +--
 drivers/media/v4l2-core/v4l2-async.c          | 159 +++++++++---------
 drivers/media/v4l2-core/v4l2-fwnode.c         |   8 +-
 .../media/deprecated/atmel/atmel-isc-base.c   |   4 +-
 .../media/deprecated/atmel/atmel-isc.h        |   2 +-
 .../deprecated/atmel/atmel-sama5d2-isc.c      |   4 +-
 .../deprecated/atmel/atmel-sama7g5-isc.c      |   4 +-
 drivers/staging/media/imx/imx-media-csi.c     |   6 +-
 .../staging/media/imx/imx-media-dev-common.c  |   2 +-
 drivers/staging/media/imx/imx-media-dev.c     |   2 +-
 drivers/staging/media/imx/imx-media-of.c      |   4 +-
 drivers/staging/media/imx/imx6-mipi-csi2.c    |   8 +-
 drivers/staging/media/imx/imx8mq-mipi-csi2.c  |   6 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |   2 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.h    |   2 +-
 drivers/staging/media/tegra-video/vi.c        |  14 +-
 drivers/staging/media/tegra-video/vi.h        |   2 +-
 include/media/davinci/vpif_types.h            |   2 +-
 include/media/v4l2-async.h                    |  66 ++++----
 include/media/v4l2-fwnode.h                   |   2 +-
 include/media/v4l2-subdev.h                   |   5 +-
 68 files changed, 320 insertions(+), 322 deletions(-)

diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
index ce8e9d0a332bc..83d3d29608136 100644
--- a/Documentation/driver-api/media/v4l2-subdev.rst
+++ b/Documentation/driver-api/media/v4l2-subdev.rst
@@ -214,14 +214,14 @@ notifier and further registers async sub-devices for lens and flash devices
 found in firmware. The notifier for the sub-device is unregistered with the
 async sub-device.
 
-These functions allocate an async sub-device descriptor which is of type struct
-:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct
-:c:type:`v4l2_async_subdev` shall be the first member of this struct:
+These functions allocate an async connection descriptor which is of type struct
+:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct
+:c:type:`v4l2_async_connection` shall be the first member of this struct:
 
 .. code-block:: c
 
 	struct my_async_subdev {
-		struct v4l2_async_subdev asd;
+		struct v4l2_async_connection asd;
 		...
 	};
 
@@ -244,10 +244,10 @@ notifier callback is called. After all subdevices have been located the
 system the .unbind() method is called. All three callbacks are optional.
 
 Drivers can store any type of custom data in their driver-specific
-:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special
+:c:type:`v4l2_async_connection` wrapper. If any of that data requires special
 handling when the structure is freed, drivers must implement the ``.destroy()``
 notifier callback. The framework will call it right before freeing the
-:c:type:`v4l2_async_subdev`.
+:c:type:`v4l2_async_connection`.
 
 Calling subdev operations
 ~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 64f5c49cae776..44def5e3ba5d1 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -161,11 +161,12 @@ struct max9286_source {
 };
 
 struct max9286_asd {
-	struct v4l2_async_subdev base;
+	struct v4l2_async_connection base;
 	struct max9286_source *source;
 };
 
-static inline struct max9286_asd *to_max9286_asd(struct v4l2_async_subdev *asd)
+static inline struct max9286_asd *
+to_max9286_asd(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct max9286_asd, base);
 }
@@ -659,7 +660,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
 
 static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
 				struct v4l2_subdev *subdev,
-				struct v4l2_async_subdev *asd)
+				struct v4l2_async_connection *asd)
 {
 	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
 	struct max9286_source *source = to_max9286_asd(asd)->source;
@@ -721,7 +722,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
 
 static void max9286_notify_unbind(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *subdev,
-				  struct v4l2_async_subdev *asd)
+				  struct v4l2_async_connection *asd)
 {
 	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
 	struct max9286_source *source = to_max9286_asd(asd)->source;
diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index 31b89aff0e86a..daea4cb29ec83 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -820,7 +820,7 @@ static const struct media_entity_operations mipid02_subdev_entity_ops = {
 
 static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *s_subdev,
-			       struct v4l2_async_subdev *asd)
+			       struct v4l2_async_connection *asd)
 {
 	struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd);
 	struct i2c_client *client = bridge->i2c_client;
@@ -854,7 +854,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
 
 static void mipid02_async_unbind(struct v4l2_async_notifier *notifier,
 				 struct v4l2_subdev *s_subdev,
-				 struct v4l2_async_subdev *asd)
+				 struct v4l2_async_connection *asd)
 {
 	struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd);
 
@@ -870,7 +870,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 {
 	struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
 	struct i2c_client *client = bridge->i2c_client;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct device_node *ep_node;
 	int ret;
 
@@ -905,7 +905,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 	v4l2_async_nf_init(&bridge->notifier);
 	asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
 					      of_fwnode_handle(ep_node),
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	of_node_put(ep_node);
 
 	if (IS_ERR(asd)) {
diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
index b37a9ff73f6ad..a455848d60c15 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -1426,7 +1426,7 @@ static int tc358746_init_controls(struct tc358746 *tc358746)
 
 static int tc358746_notify_bound(struct v4l2_async_notifier *notifier,
 				 struct v4l2_subdev *sd,
-				 struct v4l2_async_subdev *asd)
+				 struct v4l2_async_connection *asd)
 {
 	struct tc358746 *tc358746 =
 		container_of(notifier, struct tc358746, notifier);
@@ -1445,7 +1445,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_PARALLEL,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	int err;
 
@@ -1462,7 +1462,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 
 	v4l2_async_nf_init(&tc358746->notifier);
 	asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	fwnode_handle_put(ep);
 
 	if (IS_ERR(asd)) {
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 9231d6a65f4ec..1893d1ff4f169 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1371,7 +1371,7 @@ static const struct v4l2_subdev_ops cio2_subdev_ops = {
 /******* V4L2 sub-device asynchronous registration callbacks***********/
 
 struct sensor_async_subdev {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	struct csi2_bus_info csi2;
 };
 
@@ -1380,7 +1380,7 @@ struct sensor_async_subdev {
 /* The .bound() notifier callback when a match is found */
 static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *sd,
-			       struct v4l2_async_subdev *asd)
+			       struct v4l2_async_connection *asd)
 {
 	struct cio2_device *cio2 = to_cio2_device(notifier);
 	struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
@@ -1401,7 +1401,7 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
 /* The .unbind callback */
 static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
 				 struct v4l2_subdev *sd,
-				 struct v4l2_async_subdev *asd)
+				 struct v4l2_async_connection *asd)
 {
 	struct cio2_device *cio2 = to_cio2_device(notifier);
 	struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
@@ -1415,12 +1415,12 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
 	struct cio2_device *cio2 = to_cio2_device(notifier);
 	struct device *dev = &cio2->pci_dev->dev;
 	struct sensor_async_subdev *s_asd;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct cio2_queue *q;
 	unsigned int pad;
 	int ret;
 
-	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &cio2->notifier.asc_list, asc_entry) {
 		s_asd = to_sensor_asd(asd);
 		q = &cio2->queue[s_asd->csi2.port];
 
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index c29e04864445c..7dbad99d4e45e 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -1120,7 +1120,7 @@ static int isi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 
 static void isi_graph_notify_unbind(struct v4l2_async_notifier *notifier,
 				     struct v4l2_subdev *sd,
-				     struct v4l2_async_subdev *asd)
+				     struct v4l2_async_connection *asd)
 {
 	struct atmel_isi *isi = notifier_to_isi(notifier);
 
@@ -1132,7 +1132,7 @@ static void isi_graph_notify_unbind(struct v4l2_async_notifier *notifier,
 
 static int isi_graph_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asd)
 {
 	struct atmel_isi *isi = notifier_to_isi(notifier);
 
@@ -1151,7 +1151,7 @@ static const struct v4l2_async_notifier_operations isi_graph_notify_ops = {
 
 static int isi_graph_init(struct atmel_isi *isi)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct device_node *ep;
 	int ret;
 
@@ -1163,7 +1163,7 @@ static int isi_graph_init(struct atmel_isi *isi)
 
 	asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier,
 					      of_fwnode_handle(ep),
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	of_node_put(ep);
 
 	if (IS_ERR(asd))
diff --git a/drivers/media/platform/atmel/atmel-isi.h b/drivers/media/platform/atmel/atmel-isi.h
index 7ad3895a2c87e..58ce900ca4c90 100644
--- a/drivers/media/platform/atmel/atmel-isi.h
+++ b/drivers/media/platform/atmel/atmel-isi.h
@@ -121,7 +121,7 @@
 #define ISI_DATAWIDTH_8				0x01
 #define ISI_DATAWIDTH_10			0x02
 
-struct v4l2_async_subdev;
+struct v4l2_async_connection;
 
 struct isi_platform_data {
 	u8 has_emb_sync;
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 9755d1c8ceb9b..b0731c07eace0 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -246,7 +246,7 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
 
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *s_subdev,
-			      struct v4l2_async_subdev *asd)
+			      struct v4l2_async_connection *asd)
 {
 	struct v4l2_subdev *subdev = notifier->sd;
 	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
@@ -365,7 +365,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx,
 static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 {
 	struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *fwh;
 	struct device_node *ep;
 	int ret;
@@ -402,7 +402,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 	v4l2_async_nf_init(&csi2rx->notifier);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	of_node_put(ep);
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index 9ed3c2e063de0..f0d316d5fe27c 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -2044,7 +2044,7 @@ static const struct video_device pxa_camera_videodev_template = {
 
 static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier,
 		     struct v4l2_subdev *subdev,
-		     struct v4l2_async_subdev *asd)
+		     struct v4l2_async_connection *asd)
 {
 	int err;
 	struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
@@ -2123,7 +2123,7 @@ static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier,
 
 static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier,
 		     struct v4l2_subdev *subdev,
-		     struct v4l2_async_subdev *asd)
+		     struct v4l2_async_connection *asd)
 {
 	struct pxa_camera_dev *pcdev = v4l2_dev_to_pcdev(notifier->v4l2_dev);
 
@@ -2197,7 +2197,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
 				    struct pxa_camera_dev *pcdev)
 {
 	u32 mclk_rate;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct device_node *np = dev->of_node;
 	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
 	int err = of_property_read_u32(np, "clock-frequency",
@@ -2252,7 +2252,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
 
 	asd = v4l2_async_nf_add_fwnode_remote(&pcdev->notifier,
 					      of_fwnode_handle(np),
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	if (IS_ERR(asd))
 		err = PTR_ERR(asd);
 out:
@@ -2293,14 +2293,14 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pcdev->res = res;
 	pcdev->pdata = pdev->dev.platform_data;
 	if (pcdev->pdata) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 
 		pcdev->platform_flags = pcdev->pdata->flags;
 		pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
 		asd = v4l2_async_nf_add_i2c(&pcdev->notifier,
 					    pcdev->pdata->sensor_i2c_adapter_id,
 					    pcdev->pdata->sensor_i2c_address,
-					    struct v4l2_async_subdev);
+					    struct v4l2_async_connection);
 		if (IS_ERR(asd))
 			err = PTR_ERR(asd);
 	} else if (pdev->dev.of_node) {
diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
index ae97ce4ead988..dd1bba70bd791 100644
--- a/drivers/media/platform/marvell/cafe-driver.c
+++ b/drivers/media/platform/marvell/cafe-driver.c
@@ -478,7 +478,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 	int ret;
 	struct cafe_camera *cam;
 	struct mcam_camera *mcam;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct i2c_client *i2c_dev;
 
 	/*
@@ -540,7 +540,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 
 	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
 				    i2c_adapter_id(cam->i2c_adapter),
-				    ov7670_info.addr, struct v4l2_async_subdev);
+				    ov7670_info.addr,
+				    struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		goto out_smbus_shutdown;
diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
index 154bdcb3f2cc5..3cee6d6b83fa9 100644
--- a/drivers/media/platform/marvell/mcam-core.c
+++ b/drivers/media/platform/marvell/mcam-core.c
@@ -1756,7 +1756,7 @@ EXPORT_SYMBOL_GPL(mccic_irq);
  */
 
 static int mccic_notify_bound(struct v4l2_async_notifier *notifier,
-	struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd)
+	struct v4l2_subdev *subdev, struct v4l2_async_connection *asd)
 {
 	struct mcam_camera *cam = notifier_to_mcam(notifier);
 	int ret;
@@ -1801,7 +1801,7 @@ static int mccic_notify_bound(struct v4l2_async_notifier *notifier,
 }
 
 static void mccic_notify_unbind(struct v4l2_async_notifier *notifier,
-	struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd)
+	struct v4l2_subdev *subdev, struct v4l2_async_connection *asd)
 {
 	struct mcam_camera *cam = notifier_to_mcam(notifier);
 
diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c
index e93feefb447b4..dbc1368b91210 100644
--- a/drivers/media/platform/marvell/mmp-driver.c
+++ b/drivers/media/platform/marvell/mmp-driver.c
@@ -180,7 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct fwnode_handle *ep;
 	struct mmp_camera_platform_data *pdata;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret;
 
 	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
@@ -242,7 +242,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	v4l2_async_nf_init(&mcam->notifier);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	fwnode_handle_put(ep);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c
index bfb3edcf018a8..d631c3880c536 100644
--- a/drivers/media/platform/microchip/microchip-csi2dc.c
+++ b/drivers/media/platform/microchip/microchip-csi2dc.c
@@ -476,7 +476,7 @@ static const struct v4l2_subdev_ops csi2dc_subdev_ops = {
 
 static int csi2dc_async_bound(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *subdev,
-			      struct v4l2_async_subdev *asd)
+			      struct v4l2_async_connection *asd)
 {
 	struct csi2dc_device *csi2dc = container_of(notifier,
 						struct csi2dc_device, notifier);
@@ -520,14 +520,14 @@ static const struct v4l2_async_notifier_operations csi2dc_async_ops = {
 static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc,
 				   struct fwnode_handle *input_fwnode)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret = 0;
 
 	v4l2_async_nf_init(&csi2dc->notifier);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2dc->notifier,
 					      input_fwnode,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 
 	fwnode_handle_put(input_fwnode);
 
diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c
index 4e657fad33d04..8dbf7bc1e863b 100644
--- a/drivers/media/platform/microchip/microchip-isc-base.c
+++ b/drivers/media/platform/microchip/microchip-isc-base.c
@@ -1712,7 +1712,7 @@ static int isc_ctrl_init(struct isc_device *isc)
 
 static int isc_async_bound(struct v4l2_async_notifier *notifier,
 			   struct v4l2_subdev *subdev,
-			   struct v4l2_async_subdev *asd)
+			   struct v4l2_async_connection *asd)
 {
 	struct isc_device *isc = container_of(notifier->v4l2_dev,
 					      struct isc_device, v4l2_dev);
@@ -1741,7 +1741,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier,
 
 static void isc_async_unbind(struct v4l2_async_notifier *notifier,
 			     struct v4l2_subdev *subdev,
-			     struct v4l2_async_subdev *asd)
+			     struct v4l2_async_connection *asd)
 {
 	struct isc_device *isc = container_of(notifier->v4l2_dev,
 					      struct isc_device, v4l2_dev);
diff --git a/drivers/media/platform/microchip/microchip-isc.h b/drivers/media/platform/microchip/microchip-isc.h
index e3a6c7367e70a..ad4e98a1dd8fc 100644
--- a/drivers/media/platform/microchip/microchip-isc.h
+++ b/drivers/media/platform/microchip/microchip-isc.h
@@ -44,7 +44,7 @@ struct isc_buffer {
 
 struct isc_subdev_entity {
 	struct v4l2_subdev		*sd;
-	struct v4l2_async_subdev	*asd;
+	struct v4l2_async_connection	*asd;
 	struct device_node		*epn;
 	struct v4l2_async_notifier      notifier;
 
diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
index 746f4a2fa9f6e..10e6cebf629e6 100644
--- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
@@ -525,7 +525,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
 	}
 
 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
@@ -533,7 +533,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		of_node_put(subdev_entity->epn);
 		subdev_entity->epn = NULL;
diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
index 79ae696764d08..324810dbdc3af 100644
--- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
@@ -515,7 +515,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 	}
 
 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
@@ -523,7 +523,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		of_node_put(subdev_entity->epn);
 		subdev_entity->epn = NULL;
diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
index d0dc30187775d..390834ce482bd 100644
--- a/drivers/media/platform/nxp/imx-mipi-csis.c
+++ b/drivers/media/platform/nxp/imx-mipi-csis.c
@@ -1230,7 +1230,7 @@ mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
 
 static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *sd,
-				  struct v4l2_async_subdev *asd)
+				  struct v4l2_async_connection *asd)
 {
 	struct mipi_csis_device *csis = mipi_notifier_to_csis_state(notifier);
 	struct media_pad *sink = &csis->sd.entity.pads[CSIS_PAD_SINK];
@@ -1247,7 +1247,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	unsigned int i;
 	int ret;
@@ -1278,7 +1278,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
 	dev_dbg(csis->dev, "flags: 0x%08x\n", csis->bus.flags);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csis->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		goto err_parse;
diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
index b701e823436a8..75b7ad65a1141 100644
--- a/drivers/media/platform/nxp/imx7-media-csi.c
+++ b/drivers/media/platform/nxp/imx7-media-csi.c
@@ -2078,7 +2078,7 @@ static const struct media_entity_operations imx7_csi_entity_ops = {
 
 static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier,
 				 struct v4l2_subdev *sd,
-				 struct v4l2_async_subdev *asd)
+				 struct v4l2_async_connection *asd)
 {
 	struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier);
 	struct media_pad *sink = &csi->sd.entity.pads[IMX7_CSI_PAD_SINK];
@@ -2103,7 +2103,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
 
 static int imx7_csi_async_register(struct imx7_csi *csi)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -2118,7 +2118,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
 	}
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 
 	fwnode_handle_put(ep);
 
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
index 253e77189b69f..a09f416a64c4f 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
@@ -30,12 +30,12 @@
  */
 
 struct mxc_isi_async_subdev {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	unsigned int port;
 };
 
 static inline struct mxc_isi_async_subdev *
-asd_to_mxc_isi_async_subdev(struct v4l2_async_subdev *asd)
+asd_to_mxc_isi_async_subdev(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct mxc_isi_async_subdev, asd);
 };
@@ -48,12 +48,12 @@ notifier_to_mxc_isi_dev(struct v4l2_async_notifier *n)
 
 static int mxc_isi_async_notifier_bound(struct v4l2_async_notifier *notifier,
 					struct v4l2_subdev *sd,
-					struct v4l2_async_subdev *asd)
+					struct v4l2_async_connection *asc)
 {
 	const unsigned int link_flags = MEDIA_LNK_FL_IMMUTABLE
 				      | MEDIA_LNK_FL_ENABLED;
 	struct mxc_isi_dev *isi = notifier_to_mxc_isi_dev(notifier);
-	struct mxc_isi_async_subdev *masd = asd_to_mxc_isi_async_subdev(asd);
+	struct mxc_isi_async_subdev *masd = asd_to_mxc_isi_async_subdev(asc);
 	struct media_pad *pad = &isi->crossbar.pads[masd->port];
 	struct device_link *link;
 
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 1ef26aea3eae6..006855bf076b7 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -1383,7 +1383,7 @@ static void camss_unregister_entities(struct camss *camss)
 
 static int camss_subdev_notifier_bound(struct v4l2_async_notifier *async,
 				       struct v4l2_subdev *subdev,
-				       struct v4l2_async_subdev *asd)
+				       struct v4l2_async_connection *asd)
 {
 	struct camss *camss = container_of(async, struct camss, notifier);
 	struct camss_async_subdev *csd =
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 3acd2b3403e8c..f6c326cb853b8 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -113,7 +113,7 @@ struct camss_camera_interface {
 };
 
 struct camss_async_subdev {
-	struct v4l2_async_subdev asd; /* must be first */
+	struct v4l2_async_connection asd; /* must be first */
 	struct camss_camera_interface interface;
 };
 
diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c
index f666b621338d0..5d6d9ffb5201d 100644
--- a/drivers/media/platform/renesas/rcar-isp.c
+++ b/drivers/media/platform/renesas/rcar-isp.c
@@ -326,7 +326,7 @@ static const struct v4l2_subdev_ops rcar_isp_subdev_ops = {
 
 static int risp_notify_bound(struct v4l2_async_notifier *notifier,
 			     struct v4l2_subdev *subdev,
-			     struct v4l2_async_subdev *asd)
+			     struct v4l2_async_connection *asd)
 {
 	struct rcar_isp *isp = notifier_to_isp(notifier);
 	int pad;
@@ -350,7 +350,7 @@ static int risp_notify_bound(struct v4l2_async_notifier *notifier,
 
 static void risp_notify_unbind(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *subdev,
-			       struct v4l2_async_subdev *asd)
+			       struct v4l2_async_connection *asd)
 {
 	struct rcar_isp *isp = notifier_to_isp(notifier);
 
@@ -366,7 +366,7 @@ static const struct v4l2_async_notifier_operations risp_notify_ops = {
 
 static int risp_parse_dt(struct rcar_isp *isp)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *fwnode;
 	struct fwnode_handle *ep;
 	unsigned int id;
@@ -396,7 +396,7 @@ static int risp_parse_dt(struct rcar_isp *isp)
 	isp->notifier.ops = &risp_notify_ops;
 
 	asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode,
-				       struct v4l2_async_subdev);
+				       struct v4l2_async_connection);
 	fwnode_handle_put(fwnode);
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
index ff4bde9cc0e30..b0f76477b54c7 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
@@ -252,7 +252,7 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
 
 static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
 				     struct v4l2_subdev *subdev,
-				     struct v4l2_async_subdev *asd)
+				     struct v4l2_async_connection *asc)
 {
 	struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 	unsigned int i;
@@ -264,7 +264,7 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
 	mutex_lock(&vin->group->lock);
 
 	for (i = 0; i < RVIN_CSI_MAX; i++) {
-		if (vin->group->remotes[i].asd != asd)
+		if (vin->group->remotes[i].asc != asc)
 			continue;
 		vin->group->remotes[i].subdev = NULL;
 		vin_dbg(vin, "Unbind %s from slot %u\n", subdev->name, i);
@@ -278,7 +278,7 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
 
 static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asc)
 {
 	struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 	unsigned int i;
@@ -286,7 +286,7 @@ static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
 	mutex_lock(&vin->group->lock);
 
 	for (i = 0; i < RVIN_CSI_MAX; i++) {
-		if (vin->group->remotes[i].asd != asd)
+		if (vin->group->remotes[i].asc != asc)
 			continue;
 		vin->group->remotes[i].subdev = subdev;
 		vin_dbg(vin, "Bound %s to slot %u\n", subdev->name, i);
@@ -311,7 +311,7 @@ static int rvin_group_parse_of(struct rvin_dev *vin, unsigned int port,
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	int ret;
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), port, id, 0);
@@ -327,14 +327,14 @@ static int rvin_group_parse_of(struct rvin_dev *vin, unsigned int port,
 		goto out;
 	}
 
-	asd = v4l2_async_nf_add_fwnode(&vin->group->notifier, fwnode,
-				       struct v4l2_async_subdev);
-	if (IS_ERR(asd)) {
-		ret = PTR_ERR(asd);
+	asc = v4l2_async_nf_add_fwnode(&vin->group->notifier, fwnode,
+				       struct v4l2_async_connection);
+	if (IS_ERR(asc)) {
+		ret = PTR_ERR(asc);
 		goto out;
 	}
 
-	vin->group->remotes[vep.base.id].asd = asd;
+	vin->group->remotes[vep.base.id].asc = asc;
 
 	vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
 		to_of_node(fwnode), vep.base.id);
@@ -387,7 +387,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
 			continue;
 
 		for (id = 0; id < max_id; id++) {
-			if (vin->group->remotes[id].asd)
+			if (vin->group->remotes[id].asc)
 				continue;
 
 			ret = rvin_group_parse_of(vin->group->vin[i], port, id);
@@ -396,7 +396,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
 		}
 	}
 
-	if (list_empty(&vin->group->notifier.asd_list))
+	if (list_empty(&vin->group->notifier.asc_list))
 		return 0;
 
 	vin->group->notifier.ops = &rvin_group_notify_ops;
@@ -611,7 +611,7 @@ static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier)
 
 static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier,
 					struct v4l2_subdev *subdev,
-					struct v4l2_async_subdev *asd)
+					struct v4l2_async_connection *asc)
 {
 	struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 
@@ -624,7 +624,7 @@ static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier,
 
 static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier,
 				      struct v4l2_subdev *subdev,
-				      struct v4l2_async_subdev *asd)
+				      struct v4l2_async_connection *asc)
 {
 	struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 	int ret;
@@ -656,7 +656,7 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_UNKNOWN,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	int ret;
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 0, 0, 0);
@@ -687,14 +687,14 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin)
 		goto out;
 	}
 
-	asd = v4l2_async_nf_add_fwnode(&vin->notifier, fwnode,
-				       struct v4l2_async_subdev);
-	if (IS_ERR(asd)) {
-		ret = PTR_ERR(asd);
+	asc = v4l2_async_nf_add_fwnode(&vin->notifier, fwnode,
+				       struct v4l2_async_connection);
+	if (IS_ERR(asc)) {
+		ret = PTR_ERR(asc);
 		goto out;
 	}
 
-	vin->parallel.asd = asd;
+	vin->parallel.asc = asc;
 
 	vin_dbg(vin, "Add parallel OF device %pOF\n", to_of_node(fwnode));
 out:
@@ -719,11 +719,11 @@ static int rvin_parallel_init(struct rvin_dev *vin)
 	if (ret)
 		return ret;
 
-	if (!vin->parallel.asd)
+	if (!vin->parallel.asc)
 		return -ENODEV;
 
 	vin_dbg(vin, "Found parallel subdevice %pOF\n",
-		to_of_node(vin->parallel.asd->match.fwnode));
+		to_of_node(vin->parallel.asc->match.fwnode));
 
 	vin->notifier.ops = &rvin_parallel_notify_ops;
 	ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
index e34060c2b0395..de7b479df3a9d 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
@@ -968,12 +968,12 @@ static irqreturn_t rcsi2_irq_thread(int irq, void *data)
 
 static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *subdev,
-			      struct v4l2_async_subdev *asd)
+			      struct v4l2_async_connection *asc)
 {
 	struct rcar_csi2 *priv = notifier_to_csi2(notifier);
 	int pad;
 
-	pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode,
+	pad = media_entity_get_fwnode_pad(&subdev->entity, asc->match.fwnode,
 					  MEDIA_PAD_FL_SOURCE);
 	if (pad < 0) {
 		dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name);
@@ -993,7 +993,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier,
 
 static void rcsi2_notify_unbind(struct v4l2_async_notifier *notifier,
 				struct v4l2_subdev *subdev,
-				struct v4l2_async_subdev *asd)
+				struct v4l2_async_connection *asc)
 {
 	struct rcar_csi2 *priv = notifier_to_csi2(notifier);
 
@@ -1044,7 +1044,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,
 
 static int rcsi2_parse_dt(struct rcar_csi2 *priv)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	struct fwnode_handle *fwnode;
 	struct fwnode_handle *ep;
 	struct v4l2_fwnode_endpoint v4l2_ep = {
@@ -1079,11 +1079,11 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
 	v4l2_async_nf_init(&priv->notifier);
 	priv->notifier.ops = &rcar_csi2_notify_ops;
 
-	asd = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,
-				       struct v4l2_async_subdev);
+	asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,
+				       struct v4l2_async_connection);
 	fwnode_handle_put(fwnode);
-	if (IS_ERR(asd))
-		return PTR_ERR(asd);
+	if (IS_ERR(asc))
+		return PTR_ERR(asc);
 
 	ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier);
 	if (ret)
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
index cb206d3976ddf..c99d64e1cb01f 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
@@ -106,7 +106,7 @@ struct rvin_video_format {
 
 /**
  * struct rvin_parallel_entity - Parallel video input endpoint descriptor
- * @asd:	sub-device descriptor for async framework
+ * @asc:	sub-device descriptor for async framework
  * @subdev:	subdevice matched using async framework
  * @mbus_type:	media bus type
  * @bus:	media bus parallel configuration
@@ -115,7 +115,7 @@ struct rvin_video_format {
  *
  */
 struct rvin_parallel_entity {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	struct v4l2_subdev *subdev;
 
 	enum v4l2_mbus_type mbus_type;
@@ -275,7 +275,7 @@ struct rvin_dev {
  * @notifier:		group notifier for CSI-2 async subdevices
  * @vin:		VIN instances which are part of the group
  * @link_setup:		Callback to create all links for the media graph
- * @remotes:		array of pairs of fwnode and subdev pointers
+ * @remotes:		array of pairs of async connection and subdev pointers
  *			to all remote subdevices.
  */
 struct rvin_group {
@@ -291,7 +291,7 @@ struct rvin_group {
 	int (*link_setup)(struct rvin_dev *vin);
 
 	struct {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asc;
 		struct v4l2_subdev *subdev;
 	} remotes[RVIN_REMOTES_MAX];
 };
diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c
index 3a92f4535c18b..90fda730030d7 100644
--- a/drivers/media/platform/renesas/rcar_drif.c
+++ b/drivers/media/platform/renesas/rcar_drif.c
@@ -1097,7 +1097,7 @@ static void rcar_drif_sdr_unregister(struct rcar_drif_sdr *sdr)
 /* Sub-device bound callback */
 static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asd)
 {
 	struct rcar_drif_sdr *sdr =
 		container_of(notifier, struct rcar_drif_sdr, notifier);
@@ -1112,7 +1112,7 @@ static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier,
 /* Sub-device unbind callback */
 static void rcar_drif_notify_unbind(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asd)
 {
 	struct rcar_drif_sdr *sdr =
 		container_of(notifier, struct rcar_drif_sdr, notifier);
@@ -1205,7 +1205,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
 {
 	struct v4l2_async_notifier *notifier = &sdr->notifier;
 	struct fwnode_handle *fwnode, *ep;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 
 	v4l2_async_nf_init(notifier);
 
@@ -1225,7 +1225,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
 	}
 
 	asd = v4l2_async_nf_add_fwnode(notifier, fwnode,
-				       struct v4l2_async_subdev);
+				       struct v4l2_async_connection);
 	fwnode_handle_put(fwnode);
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c
index 56b9c59cfda82..be6140c93fc0c 100644
--- a/drivers/media/platform/renesas/renesas-ceu.c
+++ b/drivers/media/platform/renesas/renesas-ceu.c
@@ -152,7 +152,7 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
  * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
  */
 struct ceu_subdev {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	struct v4l2_subdev *v4l2_sd;
 
 	/* per-subdevice mbus configuration options */
@@ -160,7 +160,7 @@ struct ceu_subdev {
 	struct ceu_mbus_fmt mbus_fmt;
 };
 
-static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_subdev *asd)
+static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct ceu_subdev, asd);
 }
@@ -1384,7 +1384,7 @@ static void ceu_vdev_release(struct video_device *vdev)
 
 static int ceu_notify_bound(struct v4l2_async_notifier *notifier,
 			    struct v4l2_subdev *v4l2_sd,
-			    struct v4l2_async_subdev *asd)
+			    struct v4l2_async_connection *asd)
 {
 	struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
 	struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
index 7a71370fcc32c..2d1093997db52 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
@@ -93,7 +93,7 @@ static int rzg2l_cru_group_notify_complete(struct v4l2_async_notifier *notifier)
 
 static void rzg2l_cru_group_notify_unbind(struct v4l2_async_notifier *notifier,
 					  struct v4l2_subdev *subdev,
-					  struct v4l2_async_subdev *asd)
+					  struct v4l2_async_connection *asd)
 {
 	struct rzg2l_cru_dev *cru = notifier_to_cru(notifier);
 
@@ -111,7 +111,7 @@ static void rzg2l_cru_group_notify_unbind(struct v4l2_async_notifier *notifier,
 
 static int rzg2l_cru_group_notify_bound(struct v4l2_async_notifier *notifier,
 					struct v4l2_subdev *subdev,
-					struct v4l2_async_subdev *asd)
+					struct v4l2_async_connection *asd)
 {
 	struct rzg2l_cru_dev *cru = notifier_to_cru(notifier);
 
@@ -139,7 +139,7 @@ static int rzg2l_cru_mc_parse_of(struct rzg2l_cru_dev *cru)
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
 	struct fwnode_handle *ep, *fwnode;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret;
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(cru->dev), 1, 0, 0);
@@ -163,7 +163,7 @@ static int rzg2l_cru_mc_parse_of(struct rzg2l_cru_dev *cru)
 	}
 
 	asd = v4l2_async_nf_add_fwnode(&cru->notifier, fwnode,
-				       struct v4l2_async_subdev);
+				       struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		goto out;
@@ -191,7 +191,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
 
 	cru->notifier.ops = &rzg2l_cru_async_ops;
 
-	if (list_empty(&cru->notifier.asd_list))
+	if (list_empty(&cru->notifier.asc_list))
 		return 0;
 
 	ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier);
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
index 0b682cbae3eb5..811603f18af09 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
@@ -45,7 +45,7 @@ enum rzg2l_cru_dma_state {
 };
 
 struct rzg2l_cru_csi {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct v4l2_subdev *subdev;
 	u32 channel;
 };
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
index 30dad7383654c..f6bf4cdff28c2 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
@@ -600,7 +600,7 @@ static const struct v4l2_subdev_ops rzg2l_csi2_subdev_ops = {
 
 static int rzg2l_csi2_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asd)
 {
 	struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier);
 
@@ -616,7 +616,7 @@ static int rzg2l_csi2_notify_bound(struct v4l2_async_notifier *notifier,
 
 static void rzg2l_csi2_notify_unbind(struct v4l2_async_notifier *notifier,
 				     struct v4l2_subdev *subdev,
-				     struct v4l2_async_subdev *asd)
+				     struct v4l2_async_connection *asd)
 {
 	struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier);
 
@@ -647,7 +647,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
 	struct v4l2_fwnode_endpoint v4l2_ep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *fwnode;
 	struct fwnode_handle *ep;
 	int ret;
@@ -678,7 +678,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
 	csi2->notifier.ops = &rzg2l_csi2_notify_ops;
 
 	asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode,
-				       struct v4l2_async_subdev);
+				       struct v4l2_async_connection);
 	fwnode_handle_put(fwnode);
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index a1293c45aae11..d30f0ecb1bfd8 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -148,7 +148,7 @@ struct rkisp1_info {
  * @port:		port number (0: MIPI, 1: Parallel)
  */
 struct rkisp1_sensor_async {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	unsigned int index;
 	struct fwnode_handle *source_ep;
 	unsigned int lanes;
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index 4762cb32353de..eb88494c2a427 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -122,12 +122,12 @@ struct rkisp1_isr_data {
 
 static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,
 					struct v4l2_subdev *sd,
-					struct v4l2_async_subdev *asd)
+					struct v4l2_async_connection *asc)
 {
 	struct rkisp1_device *rkisp1 =
 		container_of(notifier, struct rkisp1_device, notifier);
 	struct rkisp1_sensor_async *s_asd =
-		container_of(asd, struct rkisp1_sensor_async, asd);
+		container_of(asc, struct rkisp1_sensor_async, asd);
 	int source_pad;
 	int ret;
 
@@ -165,10 +165,10 @@ static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier)
 	return v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev);
 }
 
-static void rkisp1_subdev_notifier_destroy(struct v4l2_async_subdev *asd)
+static void rkisp1_subdev_notifier_destroy(struct v4l2_async_connection *asc)
 {
 	struct rkisp1_sensor_async *rk_asd =
-		container_of(asd, struct rkisp1_sensor_async, asd);
+		container_of(asc, struct rkisp1_sensor_async, asd);
 
 	fwnode_handle_put(rk_asd->source_ep);
 }
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c
index c9cb9a216fae1..59070616cb1bd 100644
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.c
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c
@@ -401,7 +401,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 	int index = fmd->num_sensors;
 	struct fimc_source_info *pd = &fmd->sensor[index].pdata;
 	struct device_node *rem, *np;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
 	int ret;
 
@@ -466,7 +466,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 
 	asd = v4l2_async_nf_add_fwnode_remote(&fmd->subdev_notifier,
 					      of_fwnode_handle(ep),
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 
 	of_node_put(ep);
 
@@ -1372,7 +1372,7 @@ static int fimc_md_register_clk_provider(struct fimc_md *fmd)
 
 static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
 				 struct v4l2_subdev *subdev,
-				 struct v4l2_async_subdev *asd)
+				 struct v4l2_async_connection *asd)
 {
 	struct fimc_md *fmd = notifier_to_fimc_md(notifier);
 	struct fimc_sensor_info *si = NULL;
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.h b/drivers/media/platform/samsung/exynos4-is/media-dev.h
index 079105d88bab7..786264cf79dc1 100644
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.h
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.h
@@ -82,7 +82,7 @@ struct fimc_camclk_info {
  */
 struct fimc_sensor_info {
 	struct fimc_source_info pdata;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct v4l2_subdev *subdev;
 	struct fimc_dev *host;
 };
diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
index dad6e22e4ce42..6d1197d4464e2 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -1837,7 +1837,7 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 
 static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier,
 				     struct v4l2_subdev *sd,
-				     struct v4l2_async_subdev *asd)
+				     struct v4l2_async_connection *asd)
 {
 	struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier);
 
@@ -1849,7 +1849,7 @@ static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier,
 
 static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asd)
 {
 	struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier);
 	unsigned int ret;
@@ -1887,7 +1887,7 @@ static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = {
 
 static int dcmi_graph_init(struct stm32_dcmi *dcmi)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct device_node *ep;
 	int ret;
 
@@ -1901,7 +1901,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
 
 	asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier,
 					      of_fwnode_handle(ep),
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 
 	of_node_put(ep);
 
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index d6e7d1b360836..38ca534842100 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -42,7 +42,7 @@ static const struct media_entity_operations sun4i_csi_video_entity_ops = {
 
 static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *subdev,
-				  struct v4l2_async_subdev *asd)
+				  struct v4l2_async_connection *asd)
 {
 	struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi,
 					     notifier);
@@ -118,7 +118,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_PARALLEL,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -136,7 +136,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
 	csi->bus = vep.bus.parallel;
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		goto out;
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index 4db950973ce2a..ebb725fc11ba5 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -642,7 +642,7 @@ static int sun6i_csi_bridge_link(struct sun6i_csi_device *csi_dev,
 static int
 sun6i_csi_bridge_notifier_bound(struct v4l2_async_notifier *notifier,
 				struct v4l2_subdev *remote_subdev,
-				struct v4l2_async_subdev *async_subdev)
+				struct v4l2_async_connection *async_subdev)
 {
 	struct sun6i_csi_device *csi_dev =
 		container_of(notifier, struct sun6i_csi_device,
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
index ee592a14b9c5d..44653b38f7221 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
@@ -34,7 +34,7 @@ struct sun6i_csi_bridge_source {
 };
 
 struct sun6i_csi_bridge_async_subdev {
-	struct v4l2_async_subdev	async_subdev;
+	struct v4l2_async_connection	async_subdev;
 	struct sun6i_csi_bridge_source	*source;
 };
 
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
index dce130b4c9f6f..a78900dd0b7a6 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
@@ -408,7 +408,7 @@ static const struct media_entity_operations sun6i_mipi_csi2_entity_ops = {
 static int
 sun6i_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *remote_subdev,
-			       struct v4l2_async_subdev *async_subdev)
+			       struct v4l2_async_connection *async_subdev)
 {
 	struct v4l2_subdev *subdev = notifier->sd;
 	struct sun6i_mipi_csi2_device *csi2_dev =
@@ -462,7 +462,7 @@ sun6i_mipi_csi2_bridge_source_setup(struct sun6i_mipi_csi2_device *csi2_dev)
 {
 	struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier;
 	struct v4l2_fwnode_endpoint *endpoint = &csi2_dev->bridge.endpoint;
-	struct v4l2_async_subdev *subdev_async;
+	struct v4l2_async_connection *subdev_async;
 	struct fwnode_handle *handle;
 	struct device *dev = csi2_dev->dev;
 	int ret;
@@ -480,7 +480,7 @@ sun6i_mipi_csi2_bridge_source_setup(struct sun6i_mipi_csi2_device *csi2_dev)
 
 	subdev_async =
 		v4l2_async_nf_add_fwnode_remote(notifier, handle,
-						struct v4l2_async_subdev);
+						struct v4l2_async_connection);
 	if (IS_ERR(subdev_async))
 		ret = PTR_ERR(subdev_async);
 
diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
index 23d32e198aaae..909aaef200989 100644
--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
@@ -445,7 +445,7 @@ static const struct media_entity_operations sun8i_a83t_mipi_csi2_entity_ops = {
 static int
 sun8i_a83t_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier,
 				    struct v4l2_subdev *remote_subdev,
-				    struct v4l2_async_subdev *async_subdev)
+				    struct v4l2_async_connection *async_subdev)
 {
 	struct v4l2_subdev *subdev = notifier->sd;
 	struct sun8i_a83t_mipi_csi2_device *csi2_dev =
@@ -499,7 +499,7 @@ sun8i_a83t_mipi_csi2_bridge_source_setup(struct sun8i_a83t_mipi_csi2_device *csi
 {
 	struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier;
 	struct v4l2_fwnode_endpoint *endpoint = &csi2_dev->bridge.endpoint;
-	struct v4l2_async_subdev *subdev_async;
+	struct v4l2_async_connection *subdev_async;
 	struct fwnode_handle *handle;
 	struct device *dev = csi2_dev->dev;
 	int ret;
@@ -517,7 +517,7 @@ sun8i_a83t_mipi_csi2_bridge_source_setup(struct sun8i_a83t_mipi_csi2_device *csi
 
 	subdev_async =
 		v4l2_async_nf_add_fwnode_remote(notifier, handle,
-						struct v4l2_async_subdev);
+						struct v4l2_async_connection);
 	if (IS_ERR(subdev_async))
 		ret = PTR_ERR(subdev_async);
 
diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c
index ffe1887cc429b..a1e01ef5ebddb 100644
--- a/drivers/media/platform/ti/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c
@@ -2144,7 +2144,7 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
 static int
 vpfe_async_bound(struct v4l2_async_notifier *notifier,
 		 struct v4l2_subdev *subdev,
-		 struct v4l2_async_subdev *asd)
+		 struct v4l2_async_connection *asd)
 {
 	struct vpfe_device *vpfe = container_of(notifier->v4l2_dev,
 					       struct vpfe_device, v4l2_dev);
@@ -2370,8 +2370,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
 
 		pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpfe->notifier,
 							 of_fwnode_handle(rem),
-							 struct
-							 v4l2_async_subdev);
+							 struct v4l2_async_connection);
 		of_node_put(rem);
 		if (IS_ERR(pdata->asd[i]))
 			goto cleanup;
diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.h b/drivers/media/platform/ti/am437x/am437x-vpfe.h
index f8b4e917b91a3..50c3c793b3708 100644
--- a/drivers/media/platform/ti/am437x/am437x-vpfe.h
+++ b/drivers/media/platform/ti/am437x/am437x-vpfe.h
@@ -84,7 +84,7 @@ struct vpfe_config {
 	/* information about each subdev */
 	struct vpfe_subdev_info sub_devs[VPFE_MAX_SUBDEV];
 	/* Flat array, arranged in groups */
-	struct v4l2_async_subdev *asd[VPFE_MAX_SUBDEV];
+	struct v4l2_async_connection *asd[VPFE_MAX_SUBDEV];
 };
 
 struct vpfe_cap_buffer {
diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c
index 9c5105223d6bf..bf7a985168c7b 100644
--- a/drivers/media/platform/ti/cal/cal.c
+++ b/drivers/media/platform/ti/cal/cal.c
@@ -804,19 +804,19 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
  */
 
 struct cal_v4l2_async_subdev {
-	struct v4l2_async_subdev asd; /* Must be first */
+	struct v4l2_async_connection asd; /* Must be first */
 	struct cal_camerarx *phy;
 };
 
 static inline struct cal_v4l2_async_subdev *
-to_cal_asd(struct v4l2_async_subdev *asd)
+to_cal_asd(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct cal_v4l2_async_subdev, asd);
 }
 
 static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 				    struct v4l2_subdev *subdev,
-				    struct v4l2_async_subdev *asd)
+				    struct v4l2_async_connection *asd)
 {
 	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
 	int pad;
diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c
index 44d269d6038c5..a63c9e51dac41 100644
--- a/drivers/media/platform/ti/davinci/vpif_capture.c
+++ b/drivers/media/platform/ti/davinci/vpif_capture.c
@@ -1363,12 +1363,12 @@ static inline void free_vpif_objs(void)
 
 static int vpif_async_bound(struct v4l2_async_notifier *notifier,
 			    struct v4l2_subdev *subdev,
-			    struct v4l2_async_subdev *asd)
+			    struct v4l2_async_connection *asd)
 {
 	int i;
 
 	for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) {
-		struct v4l2_async_subdev *_asd = vpif_obj.config->asd[i];
+		struct v4l2_async_connection *_asd = vpif_obj.config->asd[i];
 		const struct fwnode_handle *fwnode = _asd->match.fwnode;
 
 		if (fwnode == subdev->fwnode) {
@@ -1570,8 +1570,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
 
 		pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpif_obj.notifier,
 							 of_fwnode_handle(rem),
-							 struct
-							 v4l2_async_subdev);
+							 struct v4l2_async_connection);
 		if (IS_ERR(pdata->asd[i]))
 			goto err_cleanup;
 
diff --git a/drivers/media/platform/ti/omap3isp/isp.h b/drivers/media/platform/ti/omap3isp/isp.h
index a9d760fbf3493..32ea70c8d2f9b 100644
--- a/drivers/media/platform/ti/omap3isp/isp.h
+++ b/drivers/media/platform/ti/omap3isp/isp.h
@@ -220,7 +220,7 @@ struct isp_device {
 };
 
 struct isp_async_subdev {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	struct isp_bus_cfg bus;
 };
 
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index 1d9f32e5a9171..e1dd798764312 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -343,7 +343,7 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = {
 
 static int video_mux_notify_bound(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *sd,
-				  struct v4l2_async_subdev *asd)
+				  struct v4l2_async_connection *asd)
 {
 	struct video_mux *vmux = notifier_to_video_mux(notifier);
 
@@ -363,7 +363,7 @@ static int video_mux_async_register(struct video_mux *vmux,
 	v4l2_async_nf_init(&vmux->notifier);
 
 	for (i = 0; i < num_input_pads; i++) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 		struct fwnode_handle *ep, *remote_ep;
 
 		ep = fwnode_graph_get_endpoint_by_id(
@@ -381,7 +381,7 @@ static int video_mux_async_register(struct video_mux *vmux,
 		fwnode_handle_put(remote_ep);
 
 		asd = v4l2_async_nf_add_fwnode_remote(&vmux->notifier, ep,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		fwnode_handle_put(ep);
 
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 52c5a7decf284..96fbbc55eb12c 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -34,13 +34,13 @@
  * @subdev: V4L2 subdev
  */
 struct xvip_graph_entity {
-	struct v4l2_async_subdev asd; /* must be first */
+	struct v4l2_async_connection asd; /* must be first */
 	struct media_entity *entity;
 	struct v4l2_subdev *subdev;
 };
 
 static inline struct xvip_graph_entity *
-to_xvip_entity(struct v4l2_async_subdev *asd)
+to_xvip_entity(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct xvip_graph_entity, asd);
 }
@@ -54,9 +54,9 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
 		       const struct fwnode_handle *fwnode)
 {
 	struct xvip_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -285,13 +285,13 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	struct xvip_composite_device *xdev =
 		container_of(notifier, struct xvip_composite_device, notifier);
 	struct xvip_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret;
 
 	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
 
 	/* Create links for every entity. */
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_build_one(xdev, entity);
 		if (ret < 0)
@@ -312,9 +312,9 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
 
 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
 				   struct v4l2_subdev *subdev,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asc)
 {
-	struct xvip_graph_entity *entity = to_xvip_entity(asd);
+	struct xvip_graph_entity *entity = to_xvip_entity(asc);
 
 	entity->entity = &subdev->entity;
 	entity->subdev = subdev;
@@ -380,7 +380,7 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
 static int xvip_graph_parse(struct xvip_composite_device *xdev)
 {
 	struct xvip_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret;
 
 	/*
@@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
 	if (ret < 0)
 		return 0;
 
-	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
 		if (ret < 0) {
@@ -501,7 +501,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
 		goto done;
 	}
 
-	if (list_empty(&xdev->notifier.asd_list)) {
+	if (list_empty(&xdev->notifier.asc_list)) {
 		dev_err(xdev->dev, "no subdev found in graph\n");
 		ret = -ENOENT;
 		goto done;
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 335597889f365..b1025dfc27a92 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -28,22 +28,22 @@
 
 static int v4l2_async_nf_call_bound(struct v4l2_async_notifier *n,
 				    struct v4l2_subdev *subdev,
-				    struct v4l2_async_subdev *asd)
+				    struct v4l2_async_connection *asc)
 {
 	if (!n->ops || !n->ops->bound)
 		return 0;
 
-	return n->ops->bound(n, subdev, asd);
+	return n->ops->bound(n, subdev, asc);
 }
 
 static void v4l2_async_nf_call_unbind(struct v4l2_async_notifier *n,
 				      struct v4l2_subdev *subdev,
-				      struct v4l2_async_subdev *asd)
+				      struct v4l2_async_connection *asc)
 {
 	if (!n->ops || !n->ops->unbind)
 		return;
 
-	n->ops->unbind(n, subdev, asd);
+	n->ops->unbind(n, subdev, asc);
 }
 
 static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n)
@@ -55,12 +55,12 @@ static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n)
 }
 
 static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n,
-				       struct v4l2_async_subdev *asd)
+				       struct v4l2_async_connection *asc)
 {
 	if (!n->ops || !n->ops->destroy)
 		return;
 
-	n->ops->destroy(asd);
+	n->ops->destroy(asc);
 }
 
 static bool match_i2c(struct v4l2_async_notifier *notifier,
@@ -151,18 +151,18 @@ static LIST_HEAD(subdev_list);
 static LIST_HEAD(notifier_list);
 static DEFINE_MUTEX(list_lock);
 
-static struct v4l2_async_subdev *
+static struct v4l2_async_connection *
 v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		      struct v4l2_subdev *sd)
 {
 	bool (*match)(struct v4l2_async_notifier *notifier,
 		      struct v4l2_subdev *sd,
 		      struct v4l2_async_match_desc *match);
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 
-	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry) {
+	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry) {
 		/* bus_type has been verified valid before */
-		switch (asd->match.type) {
+		switch (asc->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_I2C:
 			match = match_i2c;
 			break;
@@ -176,8 +176,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		}
 
 		/* match cannot be NULL here */
-		if (match(notifier, sd, &asd->match))
-			return asd;
+		if (match(notifier, sd, &asc->match))
+			return asc;
 	}
 
 	return NULL;
@@ -310,7 +310,7 @@ static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n,
 static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 				   struct v4l2_device *v4l2_dev,
 				   struct v4l2_subdev *sd,
-				   struct v4l2_async_subdev *asd)
+				   struct v4l2_async_connection *asc)
 {
 	struct v4l2_async_notifier *subdev_notifier;
 	int ret;
@@ -319,7 +319,7 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	if (ret < 0)
 		return ret;
 
-	ret = v4l2_async_nf_call_bound(notifier, sd, asd);
+	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
 	if (ret < 0) {
 		v4l2_device_unregister_subdev(sd);
 		return ret;
@@ -333,13 +333,13 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	 */
 	ret = v4l2_async_create_ancillary_links(notifier, sd);
 	if (ret) {
-		v4l2_async_nf_call_unbind(notifier, sd, asd);
+		v4l2_async_nf_call_unbind(notifier, sd, asc);
 		v4l2_device_unregister_subdev(sd);
 		return ret;
 	}
 
-	list_del(&asd->waiting_entry);
-	sd->asd = asd;
+	list_del(&asc->waiting_entry);
+	sd->asd = asc;
 	sd->notifier = notifier;
 
 	/* Move from the global subdevice list to notifier's done */
@@ -380,17 +380,17 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
 
 again:
 	list_for_each_entry(sd, &subdev_list, async_list) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asc;
 		int ret;
 
-		asd = v4l2_async_find_match(notifier, sd);
-		if (!asd)
+		asc = v4l2_async_find_match(notifier, sd);
+		if (!asc)
 			continue;
 
 		dev_dbg(notifier_dev(notifier),
 			"v4l2-async: match found, subdev %s\n", sd->name);
 
-		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
+		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc);
 		if (ret < 0)
 			return ret;
 
@@ -448,11 +448,11 @@ static bool
 v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
 				    struct v4l2_async_match_desc *match)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	struct v4l2_subdev *sd;
 
-	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry)
-		if (v4l2_async_match_equal(&asd->match, match))
+	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry)
+		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
 
 	list_for_each_entry(sd, &notifier->done_list, async_list) {
@@ -475,19 +475,19 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 			      struct v4l2_async_match_desc *match,
 			      bool skip_self)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
-		if (skip_self && &asd->match == match)
+	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
+		if (skip_self && &asc->match == match)
 			break;
-		if (v4l2_async_match_equal(&asd->match, match))
+		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
 	}
 
-	/* Check that an asd does not exist in other notifiers. */
+	/* Check that an asc does not exist in other notifiers. */
 	list_for_each_entry(notifier, &notifier_list, notifier_entry)
 		if (v4l2_async_nf_has_async_match_entry(notifier, match))
 			return true;
@@ -521,13 +521,13 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
 
 void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
 {
-	INIT_LIST_HEAD(&notifier->asd_list);
+	INIT_LIST_HEAD(&notifier->asc_list);
 }
 EXPORT_SYMBOL(v4l2_async_nf_init);
 
 static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	int ret;
 
 	INIT_LIST_HEAD(&notifier->waiting_list);
@@ -535,12 +535,12 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 
 	mutex_lock(&list_lock);
 
-	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
-		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
+	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
+		ret = v4l2_async_nf_match_valid(notifier, &asc->match, true);
 		if (ret)
 			goto err_unlock;
 
-		list_add_tail(&asd->waiting_entry, &notifier->waiting_list);
+		list_add_tail(&asc->waiting_entry, &notifier->waiting_list);
 	}
 
 	ret = v4l2_async_nf_try_all_subdevs(notifier);
@@ -632,23 +632,23 @@ EXPORT_SYMBOL(v4l2_async_nf_unregister);
 
 static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_async_subdev *asd, *tmp;
+	struct v4l2_async_connection *asc, *tmp;
 
-	if (!notifier || !notifier->asd_list.next)
+	if (!notifier || !notifier->asc_list.next)
 		return;
 
-	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_entry) {
-		switch (asd->match.type) {
+	list_for_each_entry_safe(asc, tmp, &notifier->asc_list, asc_entry) {
+		switch (asc->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
-			fwnode_handle_put(asd->match.fwnode);
+			fwnode_handle_put(asc->match.fwnode);
 			break;
 		default:
 			break;
 		}
 
-		list_del(&asd->asd_entry);
-		v4l2_async_nf_call_destroy(notifier, asd);
-		kfree(asd);
+		list_del(&asc->asc_entry);
+		v4l2_async_nf_call_destroy(notifier, asc);
+		kfree(asc);
 	}
 }
 
@@ -662,95 +662,94 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
 
-
-static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
-				      struct v4l2_async_subdev *asd)
+static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
+					  struct v4l2_async_connection *asc)
 {
 	int ret;
 
 	mutex_lock(&list_lock);
 
-	ret = v4l2_async_nf_match_valid(notifier, &asd->match, false);
+	ret = v4l2_async_nf_match_valid(notifier, &asc->match, false);
 	if (ret)
 		goto unlock;
 
-	list_add_tail(&asd->asd_entry, &notifier->asd_list);
+	list_add_tail(&asc->asc_entry, &notifier->asc_list);
 
 unlock:
 	mutex_unlock(&list_lock);
 	return ret;
 }
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 			   struct fwnode_handle *fwnode,
-			   unsigned int asd_struct_size)
+			   unsigned int asc_struct_size)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	int ret;
 
-	asd = kzalloc(asd_struct_size, GFP_KERNEL);
-	if (!asd)
+	asc = kzalloc(asc_struct_size, GFP_KERNEL);
+	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
-	asd->match.fwnode = fwnode_handle_get(fwnode);
+	asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
+	asc->match.fwnode = fwnode_handle_get(fwnode);
 
-	ret = __v4l2_async_nf_add_subdev(notifier, asd);
+	ret = __v4l2_async_nf_add_connection(notifier, asc);
 	if (ret) {
 		fwnode_handle_put(fwnode);
-		kfree(asd);
+		kfree(asc);
 		return ERR_PTR(ret);
 	}
 
-	return asd;
+	return asc;
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode);
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
 				  struct fwnode_handle *endpoint,
-				  unsigned int asd_struct_size)
+				  unsigned int asc_struct_size)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	struct fwnode_handle *remote;
 
 	remote = fwnode_graph_get_remote_endpoint(endpoint);
 	if (!remote)
 		return ERR_PTR(-ENOTCONN);
 
-	asd = __v4l2_async_nf_add_fwnode(notif, remote, asd_struct_size);
+	asc = __v4l2_async_nf_add_fwnode(notif, remote, asc_struct_size);
 	/*
 	 * Calling __v4l2_async_nf_add_fwnode grabs a refcount,
 	 * so drop the one we got in fwnode_graph_get_remote_port_parent.
 	 */
 	fwnode_handle_put(remote);
-	return asd;
+	return asc;
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode_remote);
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
-			unsigned short address, unsigned int asd_struct_size)
+			unsigned short address, unsigned int asc_struct_size)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 	int ret;
 
-	asd = kzalloc(asd_struct_size, GFP_KERNEL);
-	if (!asd)
+	asc = kzalloc(asc_struct_size, GFP_KERNEL);
+	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
-	asd->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
-	asd->match.i2c.adapter_id = adapter_id;
-	asd->match.i2c.address = address;
+	asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
+	asc->match.i2c.adapter_id = adapter_id;
+	asc->match.i2c.address = address;
 
-	ret = __v4l2_async_nf_add_subdev(notifier, asd);
+	ret = __v4l2_async_nf_add_connection(notifier, asc);
 	if (ret) {
-		kfree(asd);
+		kfree(asc);
 		return ERR_PTR(ret);
 	}
 
-	return asd;
+	return asc;
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 
@@ -780,16 +779,16 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
 		struct v4l2_device *v4l2_dev =
 			v4l2_async_nf_find_v4l2_dev(notifier);
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asc;
 
 		if (!v4l2_dev)
 			continue;
 
-		asd = v4l2_async_find_match(notifier, sd);
-		if (!asd)
+		asc = v4l2_async_find_match(notifier, sd);
+		if (!asc)
 			continue;
 
-		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
+		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc);
 		if (ret)
 			goto err_unbind;
 
@@ -894,14 +893,14 @@ v4l2_async_nf_name(struct v4l2_async_notifier *notifier)
 static int pending_subdevs_show(struct seq_file *s, void *data)
 {
 	struct v4l2_async_notifier *notif;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asc;
 
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(notif, &notifier_list, notifier_entry) {
 		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
-		list_for_each_entry(asd, &notif->waiting_list, waiting_entry)
-			print_waiting_match(s, &asd->match);
+		list_for_each_entry(asc, &notif->waiting_list, waiting_entry)
+			print_waiting_match(s, &asc->match);
 	}
 
 	mutex_unlock(&list_lock);
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index b71561957b9fb..7c3e1648a0f49 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -821,10 +821,10 @@ static int v4l2_fwnode_reference_parse(struct device *dev,
 	     !(ret = fwnode_property_get_reference_args(dev_fwnode(dev), prop,
 							NULL, 0, index, &args));
 	     index++) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 
 		asd = v4l2_async_nf_add_fwnode(notifier, args.fwnode,
-					       struct v4l2_async_subdev);
+					       struct v4l2_async_connection);
 		fwnode_handle_put(args.fwnode);
 		if (IS_ERR(asd)) {
 			/* not an error if asd already exists */
@@ -1126,10 +1126,10 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
 								  props,
 								  nprops)));
 	     index++) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 
 		asd = v4l2_async_nf_add_fwnode(notifier, fwnode,
-					       struct v4l2_async_subdev);
+					       struct v4l2_async_connection);
 		fwnode_handle_put(fwnode);
 		if (IS_ERR(asd)) {
 			ret = PTR_ERR(asd);
diff --git a/drivers/staging/media/deprecated/atmel/atmel-isc-base.c b/drivers/staging/media/deprecated/atmel/atmel-isc-base.c
index 61c5afa581424..f5d963904201f 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-isc-base.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-isc-base.c
@@ -1727,7 +1727,7 @@ static int isc_ctrl_init(struct isc_device *isc)
 
 static int isc_async_bound(struct v4l2_async_notifier *notifier,
 			    struct v4l2_subdev *subdev,
-			    struct v4l2_async_subdev *asd)
+			    struct v4l2_async_connection *asd)
 {
 	struct isc_device *isc = container_of(notifier->v4l2_dev,
 					      struct isc_device, v4l2_dev);
@@ -1746,7 +1746,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier,
 
 static void isc_async_unbind(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *subdev,
-			      struct v4l2_async_subdev *asd)
+			      struct v4l2_async_connection *asd)
 {
 	struct isc_device *isc = container_of(notifier->v4l2_dev,
 					      struct isc_device, v4l2_dev);
diff --git a/drivers/staging/media/deprecated/atmel/atmel-isc.h b/drivers/staging/media/deprecated/atmel/atmel-isc.h
index dfc030b5a08f0..31767ea74be62 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-isc.h
+++ b/drivers/staging/media/deprecated/atmel/atmel-isc.h
@@ -44,7 +44,7 @@ struct isc_buffer {
 
 struct isc_subdev_entity {
 	struct v4l2_subdev		*sd;
-	struct v4l2_async_subdev	*asd;
+	struct v4l2_async_connection	*asd;
 	struct device_node		*epn;
 	struct v4l2_async_notifier      notifier;
 
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
index cc86ebcc76af5..58c8c7813e0f9 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
@@ -503,7 +503,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
 	}
 
 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
@@ -511,7 +511,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		of_node_put(subdev_entity->epn);
 		subdev_entity->epn = NULL;
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
index 68ef3374d25e6..f10ddee0949e1 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
@@ -493,7 +493,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 	}
 
 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
-		struct v4l2_async_subdev *asd;
+		struct v4l2_async_connection *asd;
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
@@ -501,7 +501,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		of_node_put(subdev_entity->epn);
 		subdev_entity->epn = NULL;
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 097171bb930d3..09b8b396022e0 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1892,7 +1892,7 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = {
 
 static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier,
 				struct v4l2_subdev *sd,
-				struct v4l2_async_subdev *asd)
+				struct v4l2_async_connection *asd)
 {
 	struct csi_priv *priv = notifier_to_dev(notifier);
 	struct media_pad *sink = &priv->sd.entity.pads[CSI_SINK_PAD];
@@ -1913,7 +1913,7 @@ static const struct v4l2_async_notifier_operations csi_notify_ops = {
 
 static int imx_csi_async_register(struct csi_priv *priv)
 {
-	struct v4l2_async_subdev *asd = NULL;
+	struct v4l2_async_connection *asd = NULL;
 	struct fwnode_handle *ep;
 	unsigned int port;
 	int ret;
@@ -1930,7 +1930,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
 	if (ep) {
 		asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep,
-						      struct v4l2_async_subdev);
+						      struct v4l2_async_connection);
 
 		fwnode_handle_put(ep);
 
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
index 991820a8500fb..c1216b4557b69 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -384,7 +384,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
 	int ret;
 
 	/* no subdevs? just bail */
-	if (list_empty(&imxmd->notifier.asd_list)) {
+	if (list_empty(&imxmd->notifier.asc_list)) {
 		v4l2_err(&imxmd->v4l2_dev, "no subdevs\n");
 		return -ENODEV;
 	}
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index c80113905069b..be54dca11465d 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -20,7 +20,7 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
 /* async subdev bound notifier */
 static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *sd,
-				  struct v4l2_async_subdev *asd)
+				  struct v4l2_async_connection *asd)
 {
 	struct imx_media_dev *imxmd = notifier2dev(notifier);
 	int ret;
diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
index 92a99010c1505..118bff988bc7e 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -19,7 +19,7 @@
 static int imx_media_of_add_csi(struct imx_media_dev *imxmd,
 				struct device_node *csi_np)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	int ret = 0;
 
 	if (!of_device_is_available(csi_np)) {
@@ -31,7 +31,7 @@ static int imx_media_of_add_csi(struct imx_media_dev *imxmd,
 	/* add CSI fwnode to async notifier */
 	asd = v4l2_async_nf_add_fwnode(&imxmd->notifier,
 				       of_fwnode_handle(csi_np),
-				       struct v4l2_async_subdev);
+				       struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		if (ret == -EEXIST)
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index c07994ea6e962..2e86f82ad70cd 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -591,7 +591,7 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
 
 static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
 			     struct v4l2_subdev *sd,
-			     struct v4l2_async_subdev *asd)
+			     struct v4l2_async_connection *asd)
 {
 	struct csi2_dev *csi2 = notifier_to_dev(notifier);
 	struct media_pad *sink = &csi2->sd.entity.pads[CSI2_SINK_PAD];
@@ -614,7 +614,7 @@ static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
 
 static void csi2_notify_unbind(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *sd,
-			       struct v4l2_async_subdev *asd)
+			       struct v4l2_async_connection *asd)
 {
 	struct csi2_dev *csi2 = notifier_to_dev(notifier);
 
@@ -631,7 +631,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -652,7 +652,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	fwnode_handle_put(ep);
 
 	if (IS_ERR(asd))
diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
index 32700cb8bc4d5..2f723ad34c2c5 100644
--- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
@@ -567,7 +567,7 @@ mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n)
 
 static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier,
 					struct v4l2_subdev *sd,
-					struct v4l2_async_subdev *asd)
+					struct v4l2_async_connection *asd)
 {
 	struct csi_state *state = mipi_notifier_to_csi2_state(notifier);
 	struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
@@ -587,7 +587,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct fwnode_handle *ep;
 	unsigned int i;
 	int ret;
@@ -619,7 +619,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
 		state->bus.flags);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
-					      struct v4l2_async_subdev);
+					      struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
 		goto err_parse;
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
index 1ca4673df2b3a..dd7dfecb9ef33 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
@@ -395,7 +395,7 @@ static int sun6i_isp_proc_link(struct sun6i_isp_device *isp_dev,
 
 static int sun6i_isp_proc_notifier_bound(struct v4l2_async_notifier *notifier,
 					 struct v4l2_subdev *remote_subdev,
-					 struct v4l2_async_subdev *async_subdev)
+					 struct v4l2_async_connection *async_subdev)
 {
 	struct sun6i_isp_device *isp_dev =
 		container_of(notifier, struct sun6i_isp_device, proc.notifier);
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
index c5c274e21ad55..db6738a39147b 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
@@ -34,7 +34,7 @@ struct sun6i_isp_proc_source {
 };
 
 struct sun6i_isp_proc_async_subdev {
-	struct v4l2_async_subdev	async_subdev;
+	struct v4l2_async_connection	async_subdev;
 	struct sun6i_isp_proc_source	*source;
 };
 
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 350871f34f7cc..c93e5ac9dbf0c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -54,7 +54,7 @@ to_tegra_channel_buffer(struct vb2_v4l2_buffer *vb)
 }
 
 static inline struct tegra_vi_graph_entity *
-to_tegra_vi_graph_entity(struct v4l2_async_subdev *asd)
+to_tegra_vi_graph_entity(struct v4l2_async_connection *asd)
 {
 	return container_of(asd, struct tegra_vi_graph_entity, asd);
 }
@@ -1563,9 +1563,9 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
 			   const struct fwnode_handle *fwnode)
 {
 	struct tegra_vi_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 
-	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -1679,7 +1679,7 @@ static int tegra_vi_graph_build(struct tegra_vi_channel *chan,
 static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 {
 	struct tegra_vi_graph_entity *entity;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct v4l2_subdev *subdev;
 	struct tegra_vi_channel *chan;
 	struct tegra_vi *vi;
@@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	}
 
 	/* create links between the entities */
-	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
+	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		ret = tegra_vi_graph_build(chan, entity);
 		if (ret < 0)
@@ -1752,7 +1752,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 
 static int tegra_vi_graph_notify_bound(struct v4l2_async_notifier *notifier,
 				       struct v4l2_subdev *subdev,
-				       struct v4l2_async_subdev *asd)
+				       struct v4l2_async_connection *asd)
 {
 	struct tegra_vi_graph_entity *entity;
 	struct tegra_vi *vi;
@@ -1876,7 +1876,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
 
 		ret = tegra_vi_graph_parse_one(chan, remote);
 		fwnode_handle_put(remote);
-		if (ret < 0 || list_empty(&chan->notifier.asd_list))
+		if (ret < 0 || list_empty(&chan->notifier.asc_list))
 			continue;
 
 		chan->notifier.ops = &tegra_vi_async_ops;
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index a68e2c02c7b02..ae49eff7536a8 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -106,7 +106,7 @@ struct tegra_vi {
  * @subdev: V4L2 subdev
  */
 struct tegra_vi_graph_entity {
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_connection asd;
 	struct media_entity *entity;
 	struct v4l2_subdev *subdev;
 };
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index d03e5c54347ad..6cce1f09c721b 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -72,7 +72,7 @@ struct vpif_capture_config {
 	int i2c_adapter_id;
 	const char *card_name;
 
-	struct v4l2_async_subdev *asd[VPIF_CAPTURE_MAX_CHANNELS];
+	struct v4l2_async_connection *asd[VPIF_CAPTURE_MAX_CHANNELS];
 	int asd_sizes[VPIF_CAPTURE_MAX_CHANNELS];
 };
 #endif /* _VPIF_TYPES_H */
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 54f9f45ed3d8e..38d9d097fdb52 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -34,7 +34,7 @@ enum v4l2_async_match_type {
 };
 
 /**
- * struct v4l2_async_match_desc - async sub-device match information
+ * struct v4l2_async_match_desc - async connection match information
  *
  * @type:	type of match that will be used
  * @fwnode:	pointer to &struct fwnode_handle to be matched.
@@ -62,21 +62,21 @@ struct v4l2_async_match_desc {
 };
 
 /**
- * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
+ * struct v4l2_async_connection - connection descriptor, as known to a bridge
  *
  * @match:	struct of match type and per-bus type matching data sets
- * @asd_entry:	used to add struct v4l2_async_subdev objects to the
- *		master notifier @asd_entry
- * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
- *		probed, to a notifier->waiting_list list
+ * @asc_entry:	used to add struct v4l2_async_connection objects to the
+ *		master notifier @asc_list
+ * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to
+ *		be probed, to a notifier->waiting_list list
  *
  * When this struct is used as a member in a driver specific struct,
  * the driver specific struct shall contain the &struct
- * v4l2_async_subdev as its first member.
+ * v4l2_async_connection as its first member.
  */
-struct v4l2_async_subdev {
+struct v4l2_async_connection {
 	struct v4l2_async_match_desc match;
-	struct list_head asd_entry;
+	struct list_head asc_entry;
 	struct list_head waiting_entry;
 };
 
@@ -86,17 +86,17 @@ struct v4l2_async_subdev {
  * @complete:	All subdevices have been probed successfully. The complete
  *		callback is only executed for the root notifier.
  * @unbind:	a subdevice is leaving
- * @destroy:	the asd is about to be freed
+ * @destroy:	the asc is about to be freed
  */
 struct v4l2_async_notifier_operations {
 	int (*bound)(struct v4l2_async_notifier *notifier,
 		     struct v4l2_subdev *subdev,
-		     struct v4l2_async_subdev *asd);
+		     struct v4l2_async_connection *asc);
 	int (*complete)(struct v4l2_async_notifier *notifier);
 	void (*unbind)(struct v4l2_async_notifier *notifier,
 		       struct v4l2_subdev *subdev,
-		       struct v4l2_async_subdev *asd);
-	void (*destroy)(struct v4l2_async_subdev *asd);
+		       struct v4l2_async_connection *asc);
+	void (*destroy)(struct v4l2_async_connection *asc);
 };
 
 /**
@@ -106,7 +106,7 @@ struct v4l2_async_notifier_operations {
  * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
  * @sd:		sub-device that registered the notifier, NULL otherwise
  * @parent:	parent notifier
- * @asd_list:	master list of struct v4l2_async_subdev
+ * @asc_list:	master list of struct v4l2_async_subdev
  * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
  * @done_list:	list of struct v4l2_subdev, already probed
  * @notifier_entry: member in a global list of notifiers
@@ -116,7 +116,7 @@ struct v4l2_async_notifier {
 	struct v4l2_device *v4l2_dev;
 	struct v4l2_subdev *sd;
 	struct v4l2_async_notifier *parent;
-	struct list_head asd_list;
+	struct list_head asc_list;
 	struct list_head waiting_list;
 	struct list_head done_list;
 	struct list_head notifier_entry;
@@ -134,53 +134,53 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  *
- * This function initializes the notifier @asd_entry. It must be called
+ * This function initializes the notifier @asc_entry. It must be called
  * before adding a subdevice to a notifier, using one of:
  * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
  * v4l2_async_nf_add_i2c().
  */
 void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 			   struct fwnode_handle *fwnode,
-			   unsigned int asd_struct_size);
+			   unsigned int asc_struct_size);
 /**
  * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
- *				subdev to the notifier's master asd_entry.
+ *				subdev to the notifier's master asc_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @fwnode: fwnode handle of the sub-device to be matched, pointer to
  *	    &struct fwnode_handle
- * @type: Type of the driver's async sub-device struct. The &struct
- *	  v4l2_async_subdev shall be the first member of the driver's async
- *	  sub-device struct, i.e. both begin at the same memory address.
+ * @type: Type of the driver's async sub-device or connection struct. The
+ *	  &struct v4l2_async_connection shall be the first member of the
+ *	  driver's async struct, i.e. both begin at the same memory address.
  *
- * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
- * notifiers @asd_entry. The function also gets a reference of the fwnode which
+ * Allocate a fwnode-matched asc of size asc_struct_size, and add it to the
+ * notifiers @asc_entry. The function also gets a reference of the fwnode which
  * is released later at notifier cleanup time.
  */
 #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
 	((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type)))
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
 				  struct fwnode_handle *endpoint,
-				  unsigned int asd_struct_size);
+				  unsigned int asc_struct_size);
 /**
  * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
  *						  remote async subdev to the
- *						  notifier's master asd_entry.
+ *						  notifier's master asc_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @ep: local endpoint pointing to the remote sub-device to be matched,
  *	pointer to &struct fwnode_handle
  * @type: Type of the driver's async sub-device struct. The &struct
- *	  v4l2_async_subdev shall be the first member of the driver's async
+ *	  v4l2_async_connection shall be the first member of the driver's async
  *	  sub-device struct, i.e. both begin at the same memory address.
  *
  * Gets the remote endpoint of a given local endpoint, set it up for fwnode
- * matching and adds the async sub-device to the notifier's @asd_entry. The
+ * matching and adds the async connection to the notifier's @asc_entry. The
  * function also gets a reference of the fwnode which is released later at
  * notifier cleanup time.
  *
@@ -190,19 +190,19 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
 #define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \
 	((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type)))
 
-struct v4l2_async_subdev *
+struct v4l2_async_connection *
 __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
 			int adapter_id, unsigned short address,
-			unsigned int asd_struct_size);
+			unsigned int asc_struct_size);
 /**
  * v4l2_async_nf_add_i2c - Allocate and add an i2c async
- *				subdev to the notifier's master asd_entry.
+ *				subdev to the notifier's master asc_entry.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
  * @adapter: I2C adapter ID to be matched
  * @address: I2C address of sub-device to be matched
  * @type: Type of the driver's async sub-device struct. The &struct
- *	  v4l2_async_subdev shall be the first member of the driver's async
+ *	  v4l2_async_connection shall be the first member of the driver's async
  *	  sub-device struct, i.e. both begin at the same memory address.
  *
  * Same as v4l2_async_nf_add_fwnode() but for I2C matched
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 855dae84b751d..4e4a6cf83097a 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -23,7 +23,7 @@
 
 struct fwnode_handle;
 struct v4l2_async_notifier;
-struct v4l2_async_subdev;
+struct v4l2_async_connection;
 
 /**
  * struct v4l2_fwnode_endpoint - the endpoint data structure
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 82e4cf3dd2e05..215fc8af87614 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1022,8 +1022,7 @@ struct v4l2_subdev_platform_data {
  *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
  * @async_list: Links this subdev to a global subdev_entry or @notifier->done
  *	list.
- * @asd: Pointer to respective &struct v4l2_async_subdev.
- * @notifier: Pointer to the managing notifier.
+ * @asd: Pointer to respective &struct v4l2_async_connection.
  * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
  *		     device using v4l2_async_register_subdev_sensor().
  * @pdata: common part of subdevice platform data
@@ -1065,7 +1064,7 @@ struct v4l2_subdev {
 	struct device *dev;
 	struct fwnode_handle *fwnode;
 	struct list_head async_list;
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_connection *asd;
 	struct v4l2_async_notifier *notifier;
 	struct v4l2_async_notifier *subdev_notifier;
 	struct v4l2_subdev_platform_data *pdata;
-- 
2.30.2


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

* [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (13 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  5:52   ` Laurent Pinchart
  2023-05-25  9:15 ` [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections Sakari Ailus
                   ` (17 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Add labels for error handling instead of doing it all in individual cases.
Prepare for more functionality in this function.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index b1025dfc27a92..f51f0c37210c9 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -320,10 +320,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 		return ret;
 
 	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
-	if (ret < 0) {
-		v4l2_device_unregister_subdev(sd);
-		return ret;
-	}
+	if (ret < 0)
+		goto err_unregister_subdev;
 
 	/*
 	 * Depending of the function of the entities involved, we may want to
@@ -332,11 +330,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	 * pad).
 	 */
 	ret = v4l2_async_create_ancillary_links(notifier, sd);
-	if (ret) {
-		v4l2_async_nf_call_unbind(notifier, sd, asc);
-		v4l2_device_unregister_subdev(sd);
-		return ret;
-	}
+	if (ret)
+		goto err_call_unbind;
 
 	list_del(&asc->waiting_entry);
 	sd->asd = asc;
@@ -363,6 +358,14 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	subdev_notifier->parent = notifier;
 
 	return v4l2_async_nf_try_all_subdevs(subdev_notifier);
+
+err_call_unbind:
+	v4l2_async_nf_call_unbind(notifier, sd, asc);
+
+err_unregister_subdev:
+	v4l2_device_unregister_subdev(sd);
+
+	return ret;
 }
 
 /* Test all async sub-devices in a notifier for a match. */
-- 
2.30.2


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

* [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (14 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify Sakari Ailus
@ 2023-05-25  9:15 ` Sakari Ailus
  2023-05-30  6:01   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists Sakari Ailus
                   ` (16 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:15 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

The connections are checked for duplicates already when the notifier is
registered. This is effectively a sanity check for driver (and possibly
obscure firmware) bugs. Don't do this when adding the connection.

Retain the int return type for now. It'll be needed very soon again.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index f51f0c37210c9..5dfc6d5f6a7c3 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -475,8 +475,7 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
  */
 static bool
 v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
-			      struct v4l2_async_match_desc *match,
-			      bool skip_self)
+			      struct v4l2_async_match_desc *match)
 {
 	struct v4l2_async_connection *asc;
 
@@ -484,7 +483,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 
 	/* Check that an asd is not being added more than once. */
 	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
-		if (skip_self && &asc->match == match)
+		if (&asc->match == match)
 			break;
 		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
@@ -499,16 +498,14 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 }
 
 static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
-				     struct v4l2_async_match_desc *match,
-				     bool skip_self)
+				     struct v4l2_async_match_desc *match)
 {
 	struct device *dev = notifier_dev(notifier);
 
 	switch (match->type) {
 	case V4L2_ASYNC_MATCH_TYPE_I2C:
 	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
-		if (v4l2_async_nf_has_async_match(notifier, match,
-						  skip_self)) {
+		if (v4l2_async_nf_has_async_match(notifier, match)) {
 			dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
 			return -EEXIST;
 		}
@@ -539,7 +536,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
-		ret = v4l2_async_nf_match_valid(notifier, &asc->match, true);
+		ret = v4l2_async_nf_match_valid(notifier, &asc->match);
 		if (ret)
 			goto err_unlock;
 
@@ -668,19 +665,13 @@ EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
 static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
 					  struct v4l2_async_connection *asc)
 {
-	int ret;
-
 	mutex_lock(&list_lock);
 
-	ret = v4l2_async_nf_match_valid(notifier, &asc->match, false);
-	if (ret)
-		goto unlock;
-
 	list_add_tail(&asc->asc_entry, &notifier->asc_list);
 
-unlock:
 	mutex_unlock(&list_lock);
-	return ret;
+
+	return 0;
 }
 
 struct v4l2_async_connection *
-- 
2.30.2


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

* [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (15 preceding siblings ...)
  2023-05-25  9:15 ` [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  6:11   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 18/32] media: v4l: async: Obtain async connection based on sub-device Sakari Ailus
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

This patch re-arranges internal V4L2 async lists for preparation of
supporting multiple connections per sub-device as well as cleaning up used
lists.

The list of unbound V4L2 sub-devices is maintained for the purpose of
listing those sub-devices only, not for their binding status. Also, the
V4L2 async connections have a single list entry in the notifier's list, be
that either waiting or done lists, while the notifier's asc_list is
removed.

The one-to-one relation between a sub-device and a connection is still
maintained in this patch.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |   2 +-
 .../platform/renesas/rcar-vin/rcar-core.c     |   2 +-
 .../platform/renesas/rzg2l-cru/rzg2l-core.c   |   2 +-
 drivers/media/platform/xilinx/xilinx-vipp.c   |   8 +-
 drivers/media/v4l2-core/v4l2-async.c          | 102 +++++++++---------
 .../staging/media/imx/imx-media-dev-common.c  |   2 +-
 drivers/staging/media/tegra-video/vi.c        |   6 +-
 include/media/v4l2-async.h                    |   9 +-
 8 files changed, 68 insertions(+), 65 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 1893d1ff4f169..0f43b5e10f187 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
 	unsigned int pad;
 	int ret;
 
-	list_for_each_entry(asd, &cio2->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &cio2->notifier.done_list, asc_entry) {
 		s_asd = to_sensor_asd(asd);
 		q = &cio2->queue[s_asd->csi2.port];
 
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
index b0f76477b54c7..498778eb9892b 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
@@ -396,7 +396,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
 		}
 	}
 
-	if (list_empty(&vin->group->notifier.asc_list))
+	if (list_empty(&vin->group->notifier.waiting_list))
 		return 0;
 
 	vin->group->notifier.ops = &rvin_group_notify_ops;
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
index 2d1093997db52..e026ed5337513 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
@@ -191,7 +191,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
 
 	cru->notifier.ops = &rzg2l_cru_async_ops;
 
-	if (list_empty(&cru->notifier.asc_list))
+	if (list_empty(&cru->notifier.waiting_list))
 		return 0;
 
 	ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier);
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 96fbbc55eb12c..a535a7584da0f 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
 	struct xvip_graph_entity *entity;
 	struct v4l2_async_connection *asd;
 
-	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
 
 	/* Create links for every entity. */
-	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_build_one(xdev, entity);
 		if (ret < 0)
@@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
 	if (ret < 0)
 		return 0;
 
-	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &xdev->notifier.waiting_list, asc_entry) {
 		entity = to_xvip_entity(asd);
 		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
 		if (ret < 0) {
@@ -501,7 +501,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
 		goto done;
 	}
 
-	if (list_empty(&xdev->notifier.asc_list)) {
+	if (list_empty(&xdev->notifier.waiting_list)) {
 		dev_err(xdev->dev, "no subdev found in graph\n");
 		ret = -ENOENT;
 		goto done;
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 5dfc6d5f6a7c3..d8de9ff3249d4 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -160,7 +160,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
 		      struct v4l2_async_match_desc *match);
 	struct v4l2_async_connection *asc;
 
-	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry) {
+	list_for_each_entry(asc, &notifier->waiting_list, asc_entry) {
 		/* bus_type has been verified valid before */
 		switch (asc->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_I2C:
@@ -232,14 +232,14 @@ v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier *notifier)
 static bool
 v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_subdev *sd;
+	struct v4l2_async_connection *asc;
 
 	if (!list_empty(&notifier->waiting_list))
 		return false;
 
-	list_for_each_entry(sd, &notifier->done_list, async_list) {
+	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
 		struct v4l2_async_notifier *subdev_notifier =
-			v4l2_async_find_subdev_notifier(sd);
+			v4l2_async_find_subdev_notifier(asc->sd);
 
 		if (subdev_notifier &&
 		    !v4l2_async_nf_can_complete(subdev_notifier))
@@ -333,12 +333,13 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 	if (ret)
 		goto err_call_unbind;
 
-	list_del(&asc->waiting_entry);
 	sd->asd = asc;
 	sd->notifier = notifier;
 
-	/* Move from the global subdevice list to notifier's done */
-	list_move(&sd->async_list, &notifier->done_list);
+	asc->sd = sd;
+
+	/* Move from the waiting list to notifier's done */
+	list_move(&asc->asc_entry, &notifier->done_list);
 
 	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
 		dev_name(sd->dev), ret);
@@ -422,25 +423,23 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
 
 /* Unbind all sub-devices in the notifier tree. */
 static void
-v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
-				 bool readd)
+v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_subdev *sd, *tmp;
+	struct v4l2_async_connection *asc, *asc_tmp;
 
-	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
+	list_for_each_entry_safe(asc, asc_tmp, &notifier->done_list,
+				 asc_entry) {
 		struct v4l2_async_notifier *subdev_notifier =
-			v4l2_async_find_subdev_notifier(sd);
+			v4l2_async_find_subdev_notifier(asc->sd);
 
 		if (subdev_notifier)
-			v4l2_async_nf_unbind_all_subdevs(subdev_notifier, true);
+			v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
-		if (readd)
-			list_add_tail(&sd->asd->waiting_entry,
-				      &notifier->waiting_list);
-		v4l2_async_cleanup(sd);
-
-		list_move(&sd->async_list, &subdev_list);
+		v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
+		v4l2_async_cleanup(asc->sd);
+		list_move_tail(&asc->asc_entry, &notifier->waiting_list);
+		list_move(&asc->sd->async_list, &subdev_list);
+		asc->sd = NULL;
 	}
 
 	notifier->parent = NULL;
@@ -452,17 +451,16 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
 				    struct v4l2_async_match_desc *match)
 {
 	struct v4l2_async_connection *asc;
-	struct v4l2_subdev *sd;
 
-	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry)
+	list_for_each_entry(asc, &notifier->waiting_list, asc_entry)
 		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
 
-	list_for_each_entry(sd, &notifier->done_list, async_list) {
-		if (WARN_ON(!sd->asd))
+	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
+		if (WARN_ON(!asc->sd->asd))
 			continue;
 
-		if (v4l2_async_match_equal(&sd->asd->match, match))
+		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
 	}
 
@@ -477,16 +475,24 @@ static bool
 v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
 			      struct v4l2_async_match_desc *match)
 {
-	struct v4l2_async_connection *asc;
+	struct list_head *heads[] = {
+		&notifier->waiting_list,
+		&notifier->done_list,
+	};
+	unsigned int i;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
-		if (&asc->match == match)
-			break;
-		if (v4l2_async_match_equal(&asc->match, match))
-			return true;
+	for (i = 0; i < ARRAY_SIZE(heads); i++) {
+		struct v4l2_async_connection *asc;
+
+		list_for_each_entry(asc, heads[i], asc_entry) {
+			if (&asc->match == match)
+				break;
+			if (v4l2_async_match_equal(&asc->match, match))
+				return true;
+		}
 	}
 
 	/* Check that an asc does not exist in other notifiers. */
@@ -521,7 +527,8 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
 
 void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
 {
-	INIT_LIST_HEAD(&notifier->asc_list);
+	INIT_LIST_HEAD(&notifier->waiting_list);
+	INIT_LIST_HEAD(&notifier->done_list);
 }
 EXPORT_SYMBOL(v4l2_async_nf_init);
 
@@ -530,17 +537,12 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	struct v4l2_async_connection *asc;
 	int ret;
 
-	INIT_LIST_HEAD(&notifier->waiting_list);
-	INIT_LIST_HEAD(&notifier->done_list);
-
 	mutex_lock(&list_lock);
 
-	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
+	list_for_each_entry(asc, &notifier->waiting_list, asc_entry) {
 		ret = v4l2_async_nf_match_valid(notifier, &asc->match);
 		if (ret)
 			goto err_unlock;
-
-		list_add_tail(&asc->waiting_entry, &notifier->waiting_list);
 	}
 
 	ret = v4l2_async_nf_try_all_subdevs(notifier);
@@ -562,7 +564,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	/*
 	 * On failure, unbind all sub-devices registered through this notifier.
 	 */
-	v4l2_async_nf_unbind_all_subdevs(notifier, false);
+	v4l2_async_nf_unbind_all_subdevs(notifier);
 
 err_unlock:
 	mutex_unlock(&list_lock);
@@ -612,7 +614,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
 	if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
 		return;
 
-	v4l2_async_nf_unbind_all_subdevs(notifier, false);
+	v4l2_async_nf_unbind_all_subdevs(notifier);
 
 	notifier->sd = NULL;
 	notifier->v4l2_dev = NULL;
@@ -634,10 +636,12 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_connection *asc, *tmp;
 
-	if (!notifier || !notifier->asc_list.next)
+	if (!notifier || !notifier->waiting_list.next)
 		return;
 
-	list_for_each_entry_safe(asc, tmp, &notifier->asc_list, asc_entry) {
+	WARN_ON(!list_empty(&notifier->done_list));
+
+	list_for_each_entry_safe(asc, tmp, &notifier->waiting_list, asc_entry) {
 		switch (asc->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
 			fwnode_handle_put(asc->match.fwnode);
@@ -667,7 +671,7 @@ static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
 {
 	mutex_lock(&list_lock);
 
-	list_add_tail(&asc->asc_entry, &notifier->asc_list);
+	list_add_tail(&asc->asc_entry, &notifier->waiting_list);
 
 	mutex_unlock(&list_lock);
 
@@ -808,10 +812,12 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	 */
 	subdev_notifier = v4l2_async_find_subdev_notifier(sd);
 	if (subdev_notifier)
-		v4l2_async_nf_unbind_all_subdevs(subdev_notifier, false);
+		v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-	if (sd->asd)
+	if (sd->asd) {
 		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+		sd->asd->sd = NULL;
+	}
 	v4l2_async_cleanup(sd);
 
 	mutex_unlock(&list_lock);
@@ -837,9 +843,9 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 	if (sd->asd) {
 		struct v4l2_async_notifier *notifier = sd->notifier;
 
-		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
-
+		list_move(&sd->asd->asc_entry, &notifier->waiting_list);
 		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+		sd->asd->sd = NULL;
 	}
 
 	v4l2_async_cleanup(sd);
@@ -893,7 +899,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
 
 	list_for_each_entry(notif, &notifier_list, notifier_entry) {
 		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
-		list_for_each_entry(asc, &notif->waiting_list, waiting_entry)
+		list_for_each_entry(asc, &notif->waiting_list, asc_entry)
 			print_waiting_match(s, &asc->match);
 	}
 
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
index c1216b4557b69..67c1b16db6558 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -384,7 +384,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
 	int ret;
 
 	/* no subdevs? just bail */
-	if (list_empty(&imxmd->notifier.asc_list)) {
+	if (list_empty(&imxmd->notifier.waiting_list)) {
 		v4l2_err(&imxmd->v4l2_dev, "no subdevs\n");
 		return -ENODEV;
 	}
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index c93e5ac9dbf0c..146b4fd3c8b52 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
 	struct tegra_vi_graph_entity *entity;
 	struct v4l2_async_connection *asd;
 
-	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		if (entity->asd.match.fwnode == fwnode)
 			return entity;
@@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	}
 
 	/* create links between the entities */
-	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
+	list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) {
 		entity = to_tegra_vi_graph_entity(asd);
 		ret = tegra_vi_graph_build(chan, entity);
 		if (ret < 0)
@@ -1876,7 +1876,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
 
 		ret = tegra_vi_graph_parse_one(chan, remote);
 		fwnode_handle_put(remote);
-		if (ret < 0 || list_empty(&chan->notifier.asc_list))
+		if (ret < 0 || list_empty(&chan->notifier.waiting_list))
 			continue;
 
 		chan->notifier.ops = &tegra_vi_async_ops;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 38d9d097fdb52..56b7238e2cbe2 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -66,9 +66,8 @@ struct v4l2_async_match_desc {
  *
  * @match:	struct of match type and per-bus type matching data sets
  * @asc_entry:	used to add struct v4l2_async_connection objects to the
- *		master notifier @asc_list
- * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to
- *		be probed, to a notifier->waiting_list list
+ *		notifier @waiting_list or @done_list
+ * @sd:		the related sub-device
  *
  * When this struct is used as a member in a driver specific struct,
  * the driver specific struct shall contain the &struct
@@ -77,7 +76,7 @@ struct v4l2_async_match_desc {
 struct v4l2_async_connection {
 	struct v4l2_async_match_desc match;
 	struct list_head asc_entry;
-	struct list_head waiting_entry;
+	struct v4l2_subdev *sd;
 };
 
 /**
@@ -106,7 +105,6 @@ struct v4l2_async_notifier_operations {
  * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
  * @sd:		sub-device that registered the notifier, NULL otherwise
  * @parent:	parent notifier
- * @asc_list:	master list of struct v4l2_async_subdev
  * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
  * @done_list:	list of struct v4l2_subdev, already probed
  * @notifier_entry: member in a global list of notifiers
@@ -116,7 +114,6 @@ struct v4l2_async_notifier {
 	struct v4l2_device *v4l2_dev;
 	struct v4l2_subdev *sd;
 	struct v4l2_async_notifier *parent;
-	struct list_head asc_list;
 	struct list_head waiting_list;
 	struct list_head done_list;
 	struct list_head notifier_entry;
-- 
2.30.2


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

* [RESEND PATCH v3 18/32] media: v4l: async: Obtain async connection based on sub-device
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (16 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 19/32] media: v4l: async: Allow multiple connections between entities Sakari Ailus
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Add v4l2_async_connection_unique() function for obtaining a struct
v4l2_async_connection, typically allocated by drivers together with their
own information on an external sub-device.

The relation between connections and sub-devices still remains 1:1 but
this code becomes more complex when the relation soon changes.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/platform/rockchip/rkisp1/rkisp1-csi.c   |  7 ++++++-
 .../media/platform/rockchip/rkisp1/rkisp1-isp.c   |  8 ++++++--
 drivers/media/platform/ti/omap3isp/isp.c          | 11 +++++++++--
 drivers/media/platform/ti/omap3isp/isp.h          | 13 +++++++++++--
 drivers/media/platform/ti/omap3isp/ispccdc.c      | 13 +++++++++++--
 drivers/media/platform/ti/omap3isp/ispccp2.c      |  2 ++
 drivers/media/platform/ti/omap3isp/ispcsi2.c      |  2 ++
 drivers/media/platform/ti/omap3isp/ispcsiphy.c    | 15 ++++++++++++---
 drivers/media/v4l2-core/v4l2-async.c              |  7 +++++++
 include/media/v4l2-async.h                        | 11 +++++++++++
 10 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
index d7acc94e10f8d..fdff3d0da4e50 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
@@ -381,6 +381,7 @@ static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
 	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
 	struct rkisp1_device *rkisp1 = csi->rkisp1;
 	struct rkisp1_sensor_async *source_asd;
+	struct v4l2_async_connection *asc;
 	struct media_pad *source_pad;
 	struct v4l2_subdev *source;
 	int ret;
@@ -406,7 +407,11 @@ static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
 		return -EPIPE;
 	}
 
-	source_asd = container_of(source->asd, struct rkisp1_sensor_async, asd);
+	asc = v4l2_async_connection_unique(source);
+	if (!asc)
+		return -EPIPE;
+
+	source_asd = container_of(asc, struct rkisp1_sensor_async, asd);
 	if (source_asd->mbus_type != V4L2_MBUS_CSI2_DPHY)
 		return -EINVAL;
 
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
index 585cf3f534692..07fbb77ce2349 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
@@ -868,9 +868,13 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
 		mbus_flags = 0;
 	} else {
 		const struct rkisp1_sensor_async *asd;
+		struct v4l2_async_connection *asc;
 
-		asd = container_of(rkisp1->source->asd,
-				   struct rkisp1_sensor_async, asd);
+		asc = v4l2_async_connection_unique(rkisp1->source);
+		if (!asc)
+			return -EPIPE;
+
+		asd = container_of(asc, struct rkisp1_sensor_async, asd);
 
 		mbus_type = asd->mbus_type;
 		mbus_flags = asd->mbus_flags;
diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
index c2b222f7df892..aa4ec1c8f637f 100644
--- a/drivers/media/platform/ti/omap3isp/isp.c
+++ b/drivers/media/platform/ti/omap3isp/isp.c
@@ -2039,8 +2039,15 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 	}
 
 	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
-		ret = isp_link_entity(isp, &sd->entity,
-				      v4l2_subdev_to_bus_cfg(sd)->interface);
+		struct isp_bus_cfg *bus_cfg;
+
+		bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+		if (!bus_cfg) {
+			mutex_unlock(&isp->media_dev.graph_mutex);
+			return -EINVAL;
+		}
+
+		ret = isp_link_entity(isp, &sd->entity, bus_cfg->interface);
 		if (ret < 0) {
 			mutex_unlock(&isp->media_dev.graph_mutex);
 			return ret;
diff --git a/drivers/media/platform/ti/omap3isp/isp.h b/drivers/media/platform/ti/omap3isp/isp.h
index 32ea70c8d2f9b..b4793631ad975 100644
--- a/drivers/media/platform/ti/omap3isp/isp.h
+++ b/drivers/media/platform/ti/omap3isp/isp.h
@@ -224,8 +224,17 @@ struct isp_async_subdev {
 	struct isp_bus_cfg bus;
 };
 
-#define v4l2_subdev_to_bus_cfg(sd) \
-	(&container_of((sd)->asd, struct isp_async_subdev, asd)->bus)
+static inline struct isp_bus_cfg *
+v4l2_subdev_to_bus_cfg(struct v4l2_subdev *sd)
+{
+	struct v4l2_async_connection *asc;
+
+	asc = v4l2_async_connection_unique(sd);
+	if (!asc)
+		return NULL;
+
+	return &container_of(asc, struct isp_async_subdev, asd)->bus;
+}
 
 #define v4l2_dev_to_isp_device(dev) \
 	container_of(dev, struct isp_device, v4l2_dev)
diff --git a/drivers/media/platform/ti/omap3isp/ispccdc.c b/drivers/media/platform/ti/omap3isp/ispccdc.c
index fdcdffe5fecb5..2fe42aa918004 100644
--- a/drivers/media/platform/ti/omap3isp/ispccdc.c
+++ b/drivers/media/platform/ti/omap3isp/ispccdc.c
@@ -1140,8 +1140,13 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
 	if (ccdc->input == CCDC_INPUT_PARALLEL) {
 		struct v4l2_subdev *sd =
 			to_isp_pipeline(&ccdc->subdev.entity)->external;
+		struct isp_bus_cfg *bus_cfg;
 
-		parcfg = &v4l2_subdev_to_bus_cfg(sd)->bus.parallel;
+		bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+		if (WARN_ON(!bus_cfg))
+			return;
+
+		parcfg = &bus_cfg->bus.parallel;
 		ccdc->bt656 = parcfg->bt656;
 	}
 
@@ -2436,7 +2441,11 @@ static int ccdc_link_validate(struct v4l2_subdev *sd,
 	if (ccdc->input == CCDC_INPUT_PARALLEL) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(link->source->entity);
-		struct isp_bus_cfg *bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+		struct isp_bus_cfg *bus_cfg;
+
+		bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+		if (WARN_ON(!bus_cfg))
+			return -EPIPE;
 
 		parallel_shift = bus_cfg->bus.parallel.data_lane_shift;
 	} else {
diff --git a/drivers/media/platform/ti/omap3isp/ispccp2.c b/drivers/media/platform/ti/omap3isp/ispccp2.c
index fc90ff88464fd..da5f0176ec789 100644
--- a/drivers/media/platform/ti/omap3isp/ispccp2.c
+++ b/drivers/media/platform/ti/omap3isp/ispccp2.c
@@ -360,6 +360,8 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
 	pad = media_pad_remote_pad_first(&ccp2->pads[CCP2_PAD_SINK]);
 	sensor = media_entity_to_v4l2_subdev(pad->entity);
 	buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+	if (WARN_ON(!buscfg))
+		return -EPIPE;
 
 	ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);
 	if (ret < 0)
diff --git a/drivers/media/platform/ti/omap3isp/ispcsi2.c b/drivers/media/platform/ti/omap3isp/ispcsi2.c
index 6870980a2fa9e..0f9a54b11f983 100644
--- a/drivers/media/platform/ti/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/ti/omap3isp/ispcsi2.c
@@ -564,6 +564,8 @@ static int csi2_configure(struct isp_csi2_device *csi2)
 	pad = media_pad_remote_pad_first(&csi2->pads[CSI2_PAD_SINK]);
 	sensor = media_entity_to_v4l2_subdev(pad->entity);
 	buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+	if (WARN_ON(!buscfg))
+		return -EPIPE;
 
 	csi2->frame_skip = 0;
 	v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
diff --git a/drivers/media/platform/ti/omap3isp/ispcsiphy.c b/drivers/media/platform/ti/omap3isp/ispcsiphy.c
index 1bde76c0adbee..29a84d8ca0df1 100644
--- a/drivers/media/platform/ti/omap3isp/ispcsiphy.c
+++ b/drivers/media/platform/ti/omap3isp/ispcsiphy.c
@@ -163,13 +163,17 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
 static int omap3isp_csiphy_config(struct isp_csiphy *phy)
 {
 	struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
-	struct isp_bus_cfg *buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+	struct isp_bus_cfg *buscfg;
 	struct isp_csiphy_lanes_cfg *lanes;
 	int csi2_ddrclk_khz;
 	unsigned int num_data_lanes, used_lanes = 0;
 	unsigned int i;
 	u32 reg;
 
+	buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+	if (WARN_ON(!buscfg))
+		return -EPIPE;
+
 	if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1
 	    || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2) {
 		lanes = &buscfg->bus.ccp2.lanecfg;
@@ -306,8 +310,13 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy)
 	mutex_lock(&phy->mutex);
 	if (phy->entity) {
 		struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
-		struct isp_bus_cfg *buscfg =
-			v4l2_subdev_to_bus_cfg(pipe->external);
+		struct isp_bus_cfg *buscfg;
+
+		buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+		if (WARN_ON(!buscfg)) {
+			mutex_unlock(&phy->mutex);
+			return;
+		}
 
 		csiphy_routing_cfg(phy, buscfg->interface, false,
 				   buscfg->bus.ccp2.phy_layer);
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index d8de9ff3249d4..fbc98c194a92a 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -751,6 +751,13 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 
+struct v4l2_async_connection *
+v4l2_async_connection_unique(struct v4l2_subdev *sd)
+{
+	return sd->asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
+
 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *subdev_notifier;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 56b7238e2cbe2..6e0f9a4965aa5 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -209,6 +209,17 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
 	((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \
 					 sizeof(type)))
 
+/**
+ * v4l2_async_connection_unique - return a unique &struct v4l2_async_connection
+ *				  for a sub-device
+ * @sd: the sub-device
+ *
+ * Return an async connection for a sub-device, when there is a single
+ * one only.
+ */
+struct v4l2_async_connection *
+v4l2_async_connection_unique(struct v4l2_subdev *sd);
+
 /**
  * v4l2_async_nf_register - registers a subdevice asynchronous notifier
  *
-- 
2.30.2


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

* [RESEND PATCH v3 19/32] media: v4l: async: Allow multiple connections between entities
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (17 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 18/32] media: v4l: async: Obtain async connection based on sub-device Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 20/32] media: v4l: async: Try more connections Sakari Ailus
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

When the v4l2-async framework was introduced, the use case for it was to
connect a camera sensor with a parallel receiver. Both tended to be rather
simple devices with a single connection between them.

The framework has been since improved in multiple ways but there are
limitations that have remained, for instance the assumption an async
sub-device is connected towards a single notifier and via a single link
only.

This patch enables connecting a sub-device to one or more notifiers
simultaneously, with one or more connections per notifier. The notifier
information is moved from the sub-device to the connection and the
connections in sub-device are no longer a pointer but a linked list.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 149 ++++++++++++++-------------
 include/media/v4l2-async.h           |  17 +--
 include/media/v4l2-subdev.h          |   6 +-
 3 files changed, 90 insertions(+), 82 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index fbc98c194a92a..e6d9109049cc4 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -313,29 +313,43 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_connection *asc)
 {
 	struct v4l2_async_notifier *subdev_notifier;
+	bool registered = false;
 	int ret;
 
-	ret = v4l2_device_register_subdev(v4l2_dev, sd);
-	if (ret < 0)
-		return ret;
+	if (list_empty(&sd->asc_list)) {
+		ret = v4l2_device_register_subdev(v4l2_dev, sd);
+		if (ret < 0)
+			return ret;
+		registered = true;
+	}
 
 	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
-	if (ret < 0)
+	if (ret < 0) {
+		if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
+			dev_dbg(notifier_dev(notifier),
+				"failed binding %pfw (%d)\n",
+				asc->match.fwnode, ret);
 		goto err_unregister_subdev;
+	}
 
-	/*
-	 * Depending of the function of the entities involved, we may want to
-	 * create links between them (for example between a sensor and its lens
-	 * or between a sensor's source pad and the connected device's sink
-	 * pad).
-	 */
-	ret = v4l2_async_create_ancillary_links(notifier, sd);
-	if (ret)
-		goto err_call_unbind;
-
-	sd->asd = asc;
-	sd->notifier = notifier;
+	if (registered) {
+		/*
+		 * Depending of the function of the entities involved, we may
+		 * want to create links between them (for example between a
+		 * sensor and its lens or between a sensor's source pad and the
+		 * connected device's sink pad).
+		 */
+		ret = v4l2_async_create_ancillary_links(notifier, sd);
+		if (ret) {
+			if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
+				dev_dbg(notifier_dev(notifier),
+					"failed creating links for %pfw (%d)\n",
+					asc->match.fwnode, ret);
+			goto err_call_unbind;
+		}
+	}
 
+	list_add(&asc->asc_subdev_entry, &sd->asc_list);
 	asc->sd = sd;
 
 	/* Move from the waiting list to notifier's done */
@@ -362,9 +376,11 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 
 err_call_unbind:
 	v4l2_async_nf_call_unbind(notifier, sd, asc);
+	list_del(&asc->asc_subdev_entry);
 
 err_unregister_subdev:
-	v4l2_device_unregister_subdev(sd);
+	if (registered)
+		v4l2_device_unregister_subdev(sd);
 
 	return ret;
 }
@@ -410,15 +426,16 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
 	return 0;
 }
 
-static void v4l2_async_cleanup(struct v4l2_subdev *sd)
+static void v4l2_async_unbind_subdev_one(struct v4l2_async_notifier *notifier,
+					 struct v4l2_async_connection *asc)
 {
-	v4l2_device_unregister_subdev(sd);
-	/*
-	 * Subdevice driver will reprobe and put the subdev back
-	 * onto the list
-	 */
-	list_del_init(&sd->async_list);
-	sd->asd = NULL;
+	list_move_tail(&asc->asc_entry, &notifier->waiting_list);
+	if (list_is_singular(&asc->asc_subdev_entry)) {
+		v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
+		v4l2_device_unregister_subdev(asc->sd);
+		asc->sd = NULL;
+	}
+	list_del(&asc->asc_subdev_entry);
 }
 
 /* Unbind all sub-devices in the notifier tree. */
@@ -435,11 +452,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
 		if (subdev_notifier)
 			v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-		v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
-		v4l2_async_cleanup(asc->sd);
-		list_move_tail(&asc->asc_entry, &notifier->waiting_list);
-		list_move(&asc->sd->async_list, &subdev_list);
-		asc->sd = NULL;
+		v4l2_async_unbind_subdev_one(notifier, asc);
 	}
 
 	notifier->parent = NULL;
@@ -456,13 +469,9 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
 		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
 
-	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
-		if (WARN_ON(!asc->sd->asd))
-			continue;
-
+	list_for_each_entry(asc, &notifier->done_list, asc_entry)
 		if (v4l2_async_match_equal(&asc->match, match))
 			return true;
-	}
 
 	return false;
 }
@@ -642,16 +651,12 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 	WARN_ON(!list_empty(&notifier->done_list));
 
 	list_for_each_entry_safe(asc, tmp, &notifier->waiting_list, asc_entry) {
-		switch (asc->match.type) {
-		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
-			fwnode_handle_put(asc->match.fwnode);
-			break;
-		default:
-			break;
-		}
-
 		list_del(&asc->asc_entry);
 		v4l2_async_nf_call_destroy(notifier, asc);
+
+		if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
+			fwnode_handle_put(asc->match.fwnode);
+
 		kfree(asc);
 	}
 }
@@ -666,16 +671,14 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
 
-static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
-					  struct v4l2_async_connection *asc)
+static void __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
+					   struct v4l2_async_connection *asc)
 {
 	mutex_lock(&list_lock);
 
 	list_add_tail(&asc->asc_entry, &notifier->waiting_list);
 
 	mutex_unlock(&list_lock);
-
-	return 0;
 }
 
 struct v4l2_async_connection *
@@ -684,21 +687,16 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 			   unsigned int asc_struct_size)
 {
 	struct v4l2_async_connection *asc;
-	int ret;
 
 	asc = kzalloc(asc_struct_size, GFP_KERNEL);
 	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
+	asc->notifier = notifier;
 	asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
 	asc->match.fwnode = fwnode_handle_get(fwnode);
 
-	ret = __v4l2_async_nf_add_connection(notifier, asc);
-	if (ret) {
-		fwnode_handle_put(fwnode);
-		kfree(asc);
-		return ERR_PTR(ret);
-	}
+	__v4l2_async_nf_add_connection(notifier, asc);
 
 	return asc;
 }
@@ -731,21 +729,17 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 			unsigned short address, unsigned int asc_struct_size)
 {
 	struct v4l2_async_connection *asc;
-	int ret;
 
 	asc = kzalloc(asc_struct_size, GFP_KERNEL);
 	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
+	asc->notifier = notifier;
 	asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
 	asc->match.i2c.adapter_id = adapter_id;
 	asc->match.i2c.address = address;
 
-	ret = __v4l2_async_nf_add_connection(notifier, asc);
-	if (ret) {
-		kfree(asc);
-		return ERR_PTR(ret);
-	}
+	__v4l2_async_nf_add_connection(notifier, asc);
 
 	return asc;
 }
@@ -754,7 +748,11 @@ EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 struct v4l2_async_connection *
 v4l2_async_connection_unique(struct v4l2_subdev *sd)
 {
-	return sd->asd;
+	if (!list_is_singular(&sd->asc_list))
+		return NULL;
+
+	return list_first_entry(&sd->asc_list,
+				struct v4l2_async_connection, asc_subdev_entry);
 }
 EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
 
@@ -762,8 +760,11 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *subdev_notifier;
 	struct v4l2_async_notifier *notifier;
+	struct v4l2_async_connection *asc;
 	int ret;
 
+	INIT_LIST_HEAD(&sd->asc_list);
+
 	/*
 	 * No reference taken. The reference is held by the device (struct
 	 * v4l2_subdev.dev), and async sub-device does not exist independently
@@ -784,7 +785,6 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
 		struct v4l2_device *v4l2_dev =
 			v4l2_async_nf_find_v4l2_dev(notifier);
-		struct v4l2_async_connection *asc;
 
 		if (!v4l2_dev)
 			continue;
@@ -821,11 +821,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	if (subdev_notifier)
 		v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-	if (sd->asd) {
-		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
-		sd->asd->sd = NULL;
-	}
-	v4l2_async_cleanup(sd);
+	if (asc)
+		v4l2_async_unbind_subdev_one(notifier, asc);
 
 	mutex_unlock(&list_lock);
 
@@ -835,6 +832,8 @@ EXPORT_SYMBOL(v4l2_async_register_subdev);
 
 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 {
+	struct v4l2_async_connection *asc, *asc_tmp;
+
 	if (!sd->async_list.next)
 		return;
 
@@ -847,15 +846,19 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 	kfree(sd->subdev_notifier);
 	sd->subdev_notifier = NULL;
 
-	if (sd->asd) {
-		struct v4l2_async_notifier *notifier = sd->notifier;
+	if (sd->asc_list.next) {
+		list_for_each_entry_safe(asc, asc_tmp, &sd->asc_list,
+					 asc_subdev_entry) {
+			list_move(&asc->asc_entry,
+				  &asc->notifier->waiting_list);
 
-		list_move(&sd->asd->asc_entry, &notifier->waiting_list);
-		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
-		sd->asd->sd = NULL;
+			v4l2_async_unbind_subdev_one(asc->notifier, asc);
+			list_del(&asc->asc_subdev_entry);
+		}
 	}
 
-	v4l2_async_cleanup(sd);
+	list_del(&sd->async_list);
+	sd->async_list.next = NULL;
 
 	mutex_unlock(&list_lock);
 }
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 6e0f9a4965aa5..4c311f9b66bab 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -62,27 +62,32 @@ struct v4l2_async_match_desc {
 };
 
 /**
- * struct v4l2_async_connection - connection descriptor, as known to a bridge
+ * struct v4l2_async_connection - sub-device connection descriptor, as known to
+ *				  a bridge
  *
  * @match:	struct of match type and per-bus type matching data sets
+ * @notifier:	the async notifier the connection is related to
  * @asc_entry:	used to add struct v4l2_async_connection objects to the
  *		notifier @waiting_list or @done_list
+ * @asc_subdev_entry:	entry in struct v4l2_async_subdev.asc_list list
  * @sd:		the related sub-device
  *
- * When this struct is used as a member in a driver specific struct,
- * the driver specific struct shall contain the &struct
- * v4l2_async_connection as its first member.
+ * When this struct is used as a member in a driver specific struct, the driver
+ * specific struct shall contain the &struct v4l2_async_connection as its first
+ * member.
  */
 struct v4l2_async_connection {
 	struct v4l2_async_match_desc match;
+	struct v4l2_async_notifier *notifier;
 	struct list_head asc_entry;
+	struct list_head asc_subdev_entry;
 	struct v4l2_subdev *sd;
 };
 
 /**
  * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations
- * @bound:	a subdevice driver has successfully probed one of the subdevices
- * @complete:	All subdevices have been probed successfully. The complete
+ * @bound:	a sub-device has been bound by the given connection
+ * @complete:	All connections have been bound successfully. The complete
  *		callback is only executed for the root notifier.
  * @unbind:	a subdevice is leaving
  * @destroy:	the asc is about to be freed
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 215fc8af87614..cc22c10540286 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1022,9 +1022,10 @@ struct v4l2_subdev_platform_data {
  *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
  * @async_list: Links this subdev to a global subdev_entry or @notifier->done
  *	list.
- * @asd: Pointer to respective &struct v4l2_async_connection.
  * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
  *		     device using v4l2_async_register_subdev_sensor().
+ * @asc_list: Async connection list, of &struct
+ *	      v4l2_async_connection.subdev_entry.
  * @pdata: common part of subdevice platform data
  * @state_lock: A pointer to a lock used for all the subdev's states, set by the
  *		driver. This is	optional. If NULL, each state instance will get
@@ -1064,9 +1065,8 @@ struct v4l2_subdev {
 	struct device *dev;
 	struct fwnode_handle *fwnode;
 	struct list_head async_list;
-	struct v4l2_async_connection *asd;
-	struct v4l2_async_notifier *notifier;
 	struct v4l2_async_notifier *subdev_notifier;
+	struct list_head asc_list;
 	struct v4l2_subdev_platform_data *pdata;
 	struct mutex *state_lock;
 
-- 
2.30.2


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

* [RESEND PATCH v3 20/32] media: v4l: async: Try more connections
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (18 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 19/32] media: v4l: async: Allow multiple connections between entities Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 21/32] media: v4l: async: Support fwnode endpoint list matching for subdevs Sakari Ailus
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

When an async sub-device is registered, it used to be that the first one
of its connections were matched when found. Continue looking for matches
until a notifier no longer has any.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index e6d9109049cc4..740f2a0de78ff 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -789,6 +789,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 		if (!v4l2_dev)
 			continue;
 
+again:
 		asc = v4l2_async_find_match(notifier, sd);
 		if (!asc)
 			continue;
@@ -801,13 +802,12 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 		if (ret)
 			goto err_unbind;
 
-		goto out_unlock;
+		goto again;
 	}
 
 	/* None matched, wait for hot-plugging */
 	list_add(&sd->async_list, &subdev_list);
 
-out_unlock:
 	mutex_unlock(&list_lock);
 
 	return 0;
-- 
2.30.2


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

* [RESEND PATCH v3 21/32] media: v4l: async: Support fwnode endpoint list matching for subdevs
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (19 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 20/32] media: v4l: async: Try more connections Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 22/32] media: adv748x: Return to endpoint matching Sakari Ailus
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Support matching V4L2 async sub-devices based on particular fwnode
endpoint. This makes it possible to instantiate multiple V4L2 sub-devices
based on given fwnode endpoints from a single device, based on driver
needs.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c  | 41 +++++++++++++++++++++++++++
 drivers/media/v4l2-core/v4l2-subdev.c | 13 +++++++++
 include/media/v4l2-async.h            | 29 +++++++++++++++++++
 include/media/v4l2-subdev.h           |  8 ++++--
 4 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 740f2a0de78ff..12b465a16ec1c 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -134,6 +134,30 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 		"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
 		dev_fwnode(notifier_dev(notifier)), sd->fwnode);
 
+	if (!list_empty(&sd->async_subdev_endpoint_list)) {
+		struct v4l2_async_subdev_endpoint *ase;
+
+		dev_dbg(sd->dev,
+			"v4l2-async: endpoint fwnode list available, looking for %pfw\n",
+			match->fwnode);
+
+		list_for_each_entry(ase, &sd->async_subdev_endpoint_list,
+				    async_subdev_endpoint_entry) {
+			bool matched = ase->endpoint == match->fwnode;
+
+			dev_dbg(sd->dev,
+				"v4l2-async: endpoint-endpoint match %sfound with %pfw\n",
+				matched ? "" : "not ", ase->endpoint);
+
+			if (matched)
+				return true;
+		}
+
+		dev_dbg(sd->dev, "async: no endpoint matched\n");
+
+		return false;
+	}
+
 	if (match_fwnode_one(notifier, sd, sd->fwnode, match))
 		return true;
 
@@ -745,6 +769,23 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 
+int v4l2_async_subdev_endpoint_add(struct v4l2_subdev *sd,
+				   struct fwnode_handle *fwnode)
+{
+	struct v4l2_async_subdev_endpoint *ase;
+
+	ase = kmalloc(sizeof(*ase), GFP_KERNEL);
+	if (!ase)
+		return -ENOMEM;
+
+	ase->endpoint = fwnode;
+	list_add(&ase->async_subdev_endpoint_entry,
+		 &sd->async_subdev_endpoint_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_subdev_endpoint_add);
+
 struct v4l2_async_connection *
 v4l2_async_connection_unique(struct v4l2_subdev *sd)
 {
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 2ec179cd12643..217b8019fb9b6 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1467,8 +1467,20 @@ EXPORT_SYMBOL_GPL(__v4l2_subdev_init_finalize);
 
 void v4l2_subdev_cleanup(struct v4l2_subdev *sd)
 {
+	struct v4l2_async_subdev_endpoint *ase, *ase_tmp;
+
 	__v4l2_subdev_state_free(sd->active_state);
 	sd->active_state = NULL;
+
+	if (list_empty(&sd->async_subdev_endpoint_list))
+		return;
+
+	list_for_each_entry_safe(ase, ase_tmp, &sd->async_subdev_endpoint_list,
+				 async_subdev_endpoint_entry) {
+		list_del(&ase->async_subdev_endpoint_entry);
+
+		kfree(ase);
+	}
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_cleanup);
 
@@ -2182,6 +2194,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
 	sd->dev_priv = NULL;
 	sd->host_priv = NULL;
 	sd->privacy_led = NULL;
+	INIT_LIST_HEAD(&sd->async_subdev_endpoint_list);
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	sd->entity.name = sd->name;
 	sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 4c311f9b66bab..d0bef6626e043 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -124,6 +124,17 @@ struct v4l2_async_notifier {
 	struct list_head notifier_entry;
 };
 
+/**
+ * struct v4l2_async_subdev_endpoint - Entry in sub-device's fwnode list
+ *
+ * @entry: An entry in async_subdev_endpoint_list of &struct v4l2_subdev
+ * @endpoint: Endpoint fwnode agains which to match the sub-device
+ */
+struct v4l2_async_subdev_endpoint {
+	struct list_head async_subdev_endpoint_entry;
+	struct fwnode_handle *endpoint;
+};
+
 /**
  * v4l2_async_debug_init - Initialize debugging tools.
  *
@@ -214,6 +225,24 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
 	((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \
 					 sizeof(type)))
 
+/**
+ * v4l2_async_subdev_endpoint_add - Add an endpoint fwnode to async sub-device
+ *				    matching list
+ *
+ * @sd: the sub-device
+ * @fwnode: the endpoint fwnode to match
+ *
+ * Add a fwnode to the async sub-device's matching list. This allows registering
+ * multiple async sub-devices from a single device.
+ *
+ * Note that calling v4l2_subdev_cleanup() as part of the sub-device's cleanup
+ * if endpoints have been added to the sub-device's fwnode matching list.
+ *
+ * Returns an error on failure, 0 on success.
+ */
+int v4l2_async_subdev_endpoint_add(struct v4l2_subdev *sd,
+				   struct fwnode_handle *fwnode);
+
 /**
  * v4l2_async_connection_unique - return a unique &struct v4l2_async_connection
  *				  for a sub-device
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index cc22c10540286..9b94847fb6072 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1022,6 +1022,8 @@ struct v4l2_subdev_platform_data {
  *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
  * @async_list: Links this subdev to a global subdev_entry or @notifier->done
  *	list.
+ * @async_subdev_endpoint_entry: List entry in async_ep_list of
+ *				 &struct v4l2_async_subdev_endpoint
  * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
  *		     device using v4l2_async_register_subdev_sensor().
  * @asc_list: Async connection list, of &struct
@@ -1065,6 +1067,7 @@ struct v4l2_subdev {
 	struct device *dev;
 	struct fwnode_handle *fwnode;
 	struct list_head async_list;
+	struct list_head async_subdev_endpoint_list;
 	struct v4l2_async_notifier *subdev_notifier;
 	struct list_head asc_list;
 	struct v4l2_subdev_platform_data *pdata;
@@ -1381,8 +1384,9 @@ int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name,
  * v4l2_subdev_cleanup() - Releases the resources allocated by the subdevice
  * @sd: The subdevice
  *
- * This function will release the resources allocated in
- * v4l2_subdev_init_finalize.
+ * Clean up a V4L2 async sub-device. Must be called for a sub-device as part of
+ * its release if resources have been associated with it using
+ * v4l2_async_subdev_endpoint_add() or v4l2_subdev_init_finalize().
  */
 void v4l2_subdev_cleanup(struct v4l2_subdev *sd);
 
-- 
2.30.2


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

* [RESEND PATCH v3 22/32] media: adv748x: Return to endpoint matching
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (20 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 21/32] media: v4l: async: Support fwnode endpoint list matching for subdevs Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling Sakari Ailus
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Return the two CSI-2 transmitters of adv748x to endpoint matching. This
should make the driver work again as expected.

Fixes: ("media: v4l: async: Simplify async sub-device fwnode matching")
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/adv748x/adv748x-csi2.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
index b6f93c1db3d2a..a5a7cb228896b 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -296,8 +296,6 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
 	if (!is_tx_enabled(tx))
 		return 0;
 
-	/* FIXME: Do endpoint matching again! */
-
 	adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
 			    MEDIA_ENT_F_VID_IF_BRIDGE,
 			    is_txa(tx) ? "txa" : "txb");
@@ -313,10 +311,15 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
 	if (ret)
 		return ret;
 
-	ret = adv748x_csi2_init_controls(tx);
+	ret = v4l2_async_subdev_endpoint_add(&tx->sd,
+					     of_fwnode_handle(state->endpoints[tx->port]));
 	if (ret)
 		goto err_free_media;
 
+	ret = adv748x_csi2_init_controls(tx);
+	if (ret)
+		goto err_cleanup_subdev;
+
 	ret = v4l2_async_register_subdev(&tx->sd);
 	if (ret)
 		goto err_free_ctrl;
@@ -325,6 +328,8 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
 
 err_free_ctrl:
 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
+err_cleanup_subdev:
+	v4l2_subdev_cleanup(&tx->sd);
 err_free_media:
 	media_entity_cleanup(&tx->sd.entity);
 
@@ -339,4 +344,5 @@ void adv748x_csi2_cleanup(struct adv748x_csi2 *tx)
 	v4l2_async_unregister_subdev(&tx->sd);
 	media_entity_cleanup(&tx->sd.entity);
 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
+	v4l2_subdev_cleanup(&tx->sd);
 }
-- 
2.30.2


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

* [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (21 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 22/32] media: adv748x: Return to endpoint matching Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  4:51   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early Sakari Ailus
                   ` (9 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Fix and simplify error handling in pxa_camera probe, by moving devm_*()
functions early in the probe function and then tearing down what was set
up on error patch.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/intel/pxa_camera.c | 48 ++++++++++++-----------
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index f0d316d5fe27c..dad5e8d97683e 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -2289,6 +2289,24 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	if (IS_ERR(pcdev->clk))
 		return PTR_ERR(pcdev->clk);
 
+	/*
+	 * Request the regions.
+	 */
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	pcdev->irq = irq;
+	pcdev->base = base;
+
+	/* request irq */
+	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
+			       PXA_CAM_DRV_NAME, pcdev);
+	if (err) {
+		dev_err(&pdev->dev, "Camera interrupt register failed\n");
+		return err;
+	}
+
 	v4l2_async_nf_init(&pcdev->notifier);
 	pcdev->res = res;
 	pcdev->pdata = pdev->dev.platform_data;
@@ -2338,21 +2356,12 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	spin_lock_init(&pcdev->lock);
 	mutex_init(&pcdev->mlock);
 
-	/*
-	 * Request the regions.
-	 */
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	pcdev->irq = irq;
-	pcdev->base = base;
-
 	/* request dma */
 	pcdev->dma_chans[0] = dma_request_chan(&pdev->dev, "CI_Y");
 	if (IS_ERR(pcdev->dma_chans[0])) {
 		dev_err(&pdev->dev, "Can't request DMA for Y\n");
-		return PTR_ERR(pcdev->dma_chans[0]);
+		err = PTR_ERR(pcdev->dma_chans[0]);
+		goto exit_notifier_cleanup;
 	}
 
 	pcdev->dma_chans[1] = dma_request_chan(&pdev->dev, "CI_U");
@@ -2379,14 +2388,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* request irq */
-	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
-			       PXA_CAM_DRV_NAME, pcdev);
-	if (err) {
-		dev_err(&pdev->dev, "Camera interrupt register failed\n");
-		goto exit_free_dma;
-	}
-
 	tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
 
 	pxa_camera_activate(pcdev);
@@ -2398,16 +2399,15 @@ static int pxa_camera_probe(struct platform_device *pdev)
 
 	err = pxa_camera_init_videobuf2(pcdev);
 	if (err)
-		goto exit_notifier_cleanup;
+		goto exit_v4l2_device_unregister;
 
 	pcdev->notifier.ops = &pxa_camera_sensor_ops;
 	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
 	if (err)
-		goto exit_notifier_cleanup;
+		goto exit_v4l2_device_unregister;
 
 	return 0;
-exit_notifier_cleanup:
-	v4l2_async_nf_cleanup(&pcdev->notifier);
+exit_v4l2_device_unregister:
 	v4l2_device_unregister(&pcdev->v4l2_dev);
 exit_deactivate:
 	pxa_camera_deactivate(pcdev);
@@ -2418,6 +2418,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	dma_release_channel(pcdev->dma_chans[1]);
 exit_free_dma_y:
 	dma_release_channel(pcdev->dma_chans[0]);
+exit_notifier_cleanup:
+	v4l2_async_nf_cleanup(&pcdev->notifier);
 	return err;
 }
 
-- 
2.30.2


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

* [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (22 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  4:54   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier Sakari Ailus
                   ` (8 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Register V4L2 device before initialising the notifier. This way the device
is available to the notifier from the beginning which makes it possible to
use it for debug prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/intel/pxa_camera.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index dad5e8d97683e..5df93fd4ff04b 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -2307,6 +2307,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
+	if (err)
+		return err;
+
 	v4l2_async_nf_init(&pcdev->notifier);
 	pcdev->res = res;
 	pcdev->pdata = pdev->dev.platform_data;
@@ -2324,10 +2328,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	} else if (pdev->dev.of_node) {
 		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
 	} else {
-		return -ENODEV;
+		err = -ENODEV;
 	}
 	if (err < 0)
-		return err;
+		goto exit_v4l2_device_unregister;
 
 	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
 			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
@@ -2393,22 +2397,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pxa_camera_activate(pcdev);
 
 	platform_set_drvdata(pdev, pcdev);
-	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
-	if (err)
-		goto exit_deactivate;
 
 	err = pxa_camera_init_videobuf2(pcdev);
 	if (err)
-		goto exit_v4l2_device_unregister;
+		goto exit_deactivate;
 
 	pcdev->notifier.ops = &pxa_camera_sensor_ops;
 	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
 	if (err)
-		goto exit_v4l2_device_unregister;
+		goto exit_deactivate;
 
 	return 0;
-exit_v4l2_device_unregister:
-	v4l2_device_unregister(&pcdev->v4l2_dev);
 exit_deactivate:
 	pxa_camera_deactivate(pcdev);
 	tasklet_kill(&pcdev->task_eof);
@@ -2420,6 +2419,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	dma_release_channel(pcdev->dma_chans[0]);
 exit_notifier_cleanup:
 	v4l2_async_nf_cleanup(&pcdev->notifier);
+exit_v4l2_device_unregister:
+	v4l2_device_unregister(&pcdev->v4l2_dev);
 	return err;
 }
 
-- 
2.30.2


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

* [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (23 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  5:00   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 26/32] media: am437x-vpfe: Register V4L2 device early Sakari Ailus
                   ` (7 subsequent siblings)
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Register V4L2 device before the async notifier so the struct device will
be available for the notifier which makes it possible to use it for debug
prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/marvell/cafe-driver.c | 11 +++++++++--
 drivers/media/platform/marvell/mcam-core.c   |  6 ------
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
index dd1bba70bd791..fbfbb9f67ddfc 100644
--- a/drivers/media/platform/marvell/cafe-driver.c
+++ b/drivers/media/platform/marvell/cafe-driver.c
@@ -536,6 +536,10 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto out_pdown;
 
+	ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev);
+	if (ret)
+		goto out_smbus_shutdown;
+
 	v4l2_async_nf_init(&mcam->notifier);
 
 	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
@@ -544,12 +548,12 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 				    struct v4l2_async_connection);
 	if (IS_ERR(asd)) {
 		ret = PTR_ERR(asd);
-		goto out_smbus_shutdown;
+		goto out_v4l2_device_unregister;
 	}
 
 	ret = mccic_register(mcam);
 	if (ret)
-		goto out_smbus_shutdown;
+		goto out_v4l2_device_unregister;
 
 	clkdev_create(mcam->mclk, "xclk", "%d-%04x",
 		i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
@@ -565,6 +569,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 
 out_mccic_shutdown:
 	mccic_shutdown(mcam);
+out_v4l2_device_unregister:
+	v4l2_device_unregister(&mcam->v4l2_dev);
 out_smbus_shutdown:
 	cafe_smbus_shutdown(cam);
 out_pdown:
@@ -587,6 +593,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 static void cafe_shutdown(struct cafe_camera *cam)
 {
 	mccic_shutdown(&cam->mcam);
+	v4l2_device_unregister(&cam->mcam.v4l2_dev);
 	cafe_smbus_shutdown(cam);
 	free_irq(cam->pdev->irq, cam);
 	pci_iounmap(cam->pdev, cam->mcam.regs);
diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
index 3cee6d6b83fa9..bcfcecdb03ea2 100644
--- a/drivers/media/platform/marvell/mcam-core.c
+++ b/drivers/media/platform/marvell/mcam-core.c
@@ -1866,10 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
 	/*
 	 * Register with V4L
 	 */
-	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
-	if (ret)
-		goto out;
-
 	mutex_init(&cam->s_mutex);
 	cam->state = S_NOTREADY;
 	mcam_set_config_needed(cam, 1);
@@ -1915,7 +1911,6 @@ int mccic_register(struct mcam_camera *cam)
 
 out:
 	v4l2_async_nf_unregister(&cam->notifier);
-	v4l2_device_unregister(&cam->v4l2_dev);
 	v4l2_async_nf_cleanup(&cam->notifier);
 	return ret;
 }
@@ -1937,7 +1932,6 @@ void mccic_shutdown(struct mcam_camera *cam)
 		mcam_free_dma_bufs(cam);
 	v4l2_ctrl_handler_free(&cam->ctrl_handler);
 	v4l2_async_nf_unregister(&cam->notifier);
-	v4l2_device_unregister(&cam->v4l2_dev);
 	v4l2_async_nf_cleanup(&cam->notifier);
 }
 EXPORT_SYMBOL_GPL(mccic_shutdown);
-- 
2.30.2


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

* [RESEND PATCH v3 26/32] media: am437x-vpfe: Register V4L2 device early
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (24 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 27/32] media: omap3isp: Initialise V4L2 async notifier later Sakari Ailus
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Register V4L2 device before the async notifier so the struct device will
be available for the notifier which makes it possible to use it for debug
prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/platform/ti/am437x/am437x-vpfe.c    | 27 +++++++++----------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c
index a1e01ef5ebddb..1457a188fea12 100644
--- a/drivers/media/platform/ti/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c
@@ -2403,10 +2403,17 @@ static int vpfe_probe(struct platform_device *pdev)
 
 	vpfe->pdev = &pdev->dev;
 
+	ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev);
+	if (ret) {
+		vpfe_err(vpfe, "Unable to register v4l2 device.\n");
+		return ret;
+	}
+
 	vpfe_cfg = vpfe_get_pdata(vpfe);
 	if (!vpfe_cfg) {
 		dev_err(&pdev->dev, "No platform data\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto probe_out_cleanup;
 	}
 
 	vpfe->cfg = vpfe_cfg;
@@ -2433,13 +2440,6 @@ static int vpfe_probe(struct platform_device *pdev)
 		goto probe_out_cleanup;
 	}
 
-	ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev);
-	if (ret) {
-		vpfe_err(vpfe,
-			"Unable to register v4l2 device.\n");
-		goto probe_out_cleanup;
-	}
-
 	/* set the driver data in platform device */
 	platform_set_drvdata(pdev, vpfe);
 	/* Enabling module functional clock */
@@ -2449,7 +2449,7 @@ static int vpfe_probe(struct platform_device *pdev)
 	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0) {
 		vpfe_err(vpfe, "Unable to resume device.\n");
-		goto probe_out_v4l2_unregister;
+		goto probe_out_cleanup;
 	}
 
 	vpfe_ccdc_config_defaults(ccdc);
@@ -2462,7 +2462,7 @@ static int vpfe_probe(struct platform_device *pdev)
 				GFP_KERNEL);
 	if (!vpfe->sd) {
 		ret = -ENOMEM;
-		goto probe_out_v4l2_unregister;
+		goto probe_out_cleanup;
 	}
 
 	vpfe->notifier.ops = &vpfe_async_ops;
@@ -2470,15 +2470,14 @@ static int vpfe_probe(struct platform_device *pdev)
 	if (ret) {
 		vpfe_err(vpfe, "Error registering async notifier\n");
 		ret = -EINVAL;
-		goto probe_out_v4l2_unregister;
+		goto probe_out_cleanup;
 	}
 
 	return 0;
 
-probe_out_v4l2_unregister:
-	v4l2_device_unregister(&vpfe->v4l2_dev);
 probe_out_cleanup:
 	v4l2_async_nf_cleanup(&vpfe->notifier);
+	v4l2_device_unregister(&vpfe->v4l2_dev);
 	return ret;
 }
 
@@ -2493,8 +2492,8 @@ static void vpfe_remove(struct platform_device *pdev)
 
 	v4l2_async_nf_unregister(&vpfe->notifier);
 	v4l2_async_nf_cleanup(&vpfe->notifier);
-	v4l2_device_unregister(&vpfe->v4l2_dev);
 	video_unregister_device(&vpfe->video_dev);
+	v4l2_device_unregister(&vpfe->v4l2_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
-- 
2.30.2


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

* [RESEND PATCH v3 27/32] media: omap3isp: Initialise V4L2 async notifier later
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (25 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 26/32] media: am437x-vpfe: Register V4L2 device early Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 28/32] media: xilinx-vipp: Init async notifier after registering V4L2 device Sakari Ailus
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Initialise V4L2 async notifier and parse DT for async sub-devices later,
just before registering the notifier. This way the V4L2 device has been
registered before initialising the notifier which makes it possible to
use it for debug prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/ti/omap3isp/isp.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
index aa4ec1c8f637f..5b3266b214874 100644
--- a/drivers/media/platform/ti/omap3isp/isp.c
+++ b/drivers/media/platform/ti/omap3isp/isp.c
@@ -2002,6 +2002,7 @@ static void isp_remove(struct platform_device *pdev)
 	struct isp_device *isp = platform_get_drvdata(pdev);
 
 	v4l2_async_nf_unregister(&isp->notifier);
+	v4l2_async_nf_cleanup(&isp->notifier);
 	isp_unregister_entities(isp);
 	isp_cleanup_modules(isp);
 	isp_xclk_cleanup(isp);
@@ -2011,7 +2012,6 @@ static void isp_remove(struct platform_device *pdev)
 	__omap3isp_put(isp, false);
 
 	media_entity_enum_cleanup(&isp->crashed);
-	v4l2_async_nf_cleanup(&isp->notifier);
 
 	kfree(isp);
 }
@@ -2292,13 +2292,8 @@ static int isp_probe(struct platform_device *pdev)
 
 	mutex_init(&isp->isp_mutex);
 	spin_lock_init(&isp->stat_lock);
-	v4l2_async_nf_init(&isp->notifier);
 	isp->dev = &pdev->dev;
 
-	ret = isp_parse_of_endpoints(isp);
-	if (ret < 0)
-		goto error;
-
 	isp->ref_count = 0;
 
 	ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32));
@@ -2430,6 +2425,12 @@ static int isp_probe(struct platform_device *pdev)
 
 	isp->notifier.ops = &isp_subdev_notifier_ops;
 
+	v4l2_async_nf_init(&isp->notifier);
+
+	ret = isp_parse_of_endpoints(isp);
+	if (ret < 0)
+		goto error_register_entities;
+
 	ret = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier);
 	if (ret)
 		goto error_register_entities;
@@ -2440,6 +2441,7 @@ static int isp_probe(struct platform_device *pdev)
 	return 0;
 
 error_register_entities:
+	v4l2_async_nf_cleanup(&isp->notifier);
 	isp_unregister_entities(isp);
 error_modules:
 	isp_cleanup_modules(isp);
@@ -2449,7 +2451,6 @@ static int isp_probe(struct platform_device *pdev)
 	isp_xclk_cleanup(isp);
 	__omap3isp_put(isp, false);
 error:
-	v4l2_async_nf_cleanup(&isp->notifier);
 	mutex_destroy(&isp->isp_mutex);
 error_release_isp:
 	kfree(isp);
-- 
2.30.2


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

* [RESEND PATCH v3 28/32] media: xilinx-vipp: Init async notifier after registering V4L2 device
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (26 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 27/32] media: omap3isp: Initialise V4L2 async notifier later Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 29/32] media: davinci: " Sakari Ailus
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Initialise the V4L2 async notifier after registering the V4L2 device, just
before parsing DT for async sub-devices. This way struct device is
available to the notifier right from the beginning which makes it possible
to use it for debug prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/xilinx/xilinx-vipp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index a535a7584da0f..6bb426a25fe90 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -494,6 +494,8 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
 		goto done;
 	}
 
+	v4l2_async_nf_init(&xdev->notifier);
+
 	/* Parse the graph to extract a list of subdevice DT nodes. */
 	ret = xvip_graph_parse(xdev);
 	if (ret < 0) {
@@ -574,7 +576,6 @@ static int xvip_composite_probe(struct platform_device *pdev)
 
 	xdev->dev = &pdev->dev;
 	INIT_LIST_HEAD(&xdev->dmas);
-	v4l2_async_nf_init(&xdev->notifier);
 
 	ret = xvip_composite_v4l2_init(xdev);
 	if (ret < 0)
-- 
2.30.2


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

* [RESEND PATCH v3 29/32] media: davinci: Init async notifier after registering V4L2 device
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (27 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 28/32] media: xilinx-vipp: Init async notifier after registering V4L2 device Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 30/32] media: qcom: Initialise V4L2 async notifier later Sakari Ailus
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Initialise the V4L2 async notifier after registering the V4L2 device, just
before parsing DT for async sub-devices. This way struct device is
available to the notifier right from the beginning which makes it possible
to use it for debug prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/platform/ti/davinci/vpif_capture.c    | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c
index a63c9e51dac41..9b97e26be0892 100644
--- a/drivers/media/platform/ti/davinci/vpif_capture.c
+++ b/drivers/media/platform/ti/davinci/vpif_capture.c
@@ -1608,18 +1608,12 @@ static __init int vpif_probe(struct platform_device *pdev)
 	int res_idx = 0;
 	int i, err;
 
-	pdev->dev.platform_data = vpif_capture_get_pdata(pdev);
-	if (!pdev->dev.platform_data) {
-		dev_warn(&pdev->dev, "Missing platform data.  Giving up.\n");
-		return -EINVAL;
-	}
-
 	vpif_dev = &pdev->dev;
 
 	err = initialize_vpif();
 	if (err) {
 		v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
-		goto cleanup;
+		return err;
 	}
 
 	err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
@@ -1655,6 +1649,12 @@ static __init int vpif_probe(struct platform_device *pdev)
 		goto vpif_unregister;
 	}
 
+	pdev->dev.platform_data = vpif_capture_get_pdata(pdev);
+	if (!pdev->dev.platform_data) {
+		dev_warn(&pdev->dev, "Missing platform data.  Giving up.\n");
+		goto probe_subdev_out;
+	}
+
 	if (!vpif_obj.config->asd_sizes[0]) {
 		int i2c_id = vpif_obj.config->i2c_adapter_id;
 
@@ -1695,14 +1695,13 @@ static __init int vpif_probe(struct platform_device *pdev)
 	return 0;
 
 probe_subdev_out:
+	v4l2_async_nf_cleanup(&vpif_obj.notifier);
 	/* free sub devices memory */
 	kfree(vpif_obj.sd);
 vpif_unregister:
 	v4l2_device_unregister(&vpif_obj.v4l2_dev);
 vpif_free:
 	free_vpif_objs();
-cleanup:
-	v4l2_async_nf_cleanup(&vpif_obj.notifier);
 
 	return err;
 }
-- 
2.30.2


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

* [RESEND PATCH v3 30/32] media: qcom: Initialise V4L2 async notifier later
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (28 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 29/32] media: davinci: " Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-25  9:16 ` [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init Sakari Ailus
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Initialise V4L2 async notifier and parse DT for async sub-devices later,
just before registering the notifier. This way the V4L2 device has been
registered before initialising the notifier which makes it possible to
use it for debug prints.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/platform/qcom/camss/camss.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 006855bf076b7..b89e2bb5b505e 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -1615,14 +1615,6 @@ static int camss_probe(struct platform_device *pdev)
 	if (!camss->vfe)
 		return -ENOMEM;
 
-	v4l2_async_nf_init(&camss->notifier);
-
-	num_subdevs = camss_of_parse_ports(camss);
-	if (num_subdevs < 0) {
-		ret = num_subdevs;
-		goto err_cleanup;
-	}
-
 	ret = camss_icc_get(camss);
 	if (ret < 0)
 		goto err_cleanup;
@@ -1648,9 +1640,17 @@ static int camss_probe(struct platform_device *pdev)
 		goto err_cleanup;
 	}
 
+	v4l2_async_nf_init(&camss->notifier);
+
+	num_subdevs = camss_of_parse_ports(camss);
+	if (num_subdevs < 0) {
+		ret = num_subdevs;
+		goto err_cleanup;
+	}
+
 	ret = camss_register_entities(camss);
 	if (ret < 0)
-		goto err_register_entities;
+		goto err_cleanup;
 
 	if (num_subdevs) {
 		camss->notifier.ops = &camss_subdev_notifier_ops;
@@ -1691,9 +1691,8 @@ static int camss_probe(struct platform_device *pdev)
 
 err_register_subdevs:
 	camss_unregister_entities(camss);
-err_register_entities:
-	v4l2_device_unregister(&camss->v4l2_dev);
 err_cleanup:
+	v4l2_device_unregister(&camss->v4l2_dev);
 	v4l2_async_nf_cleanup(&camss->notifier);
 
 	return ret;
-- 
2.30.2


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

* [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (29 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 30/32] media: qcom: Initialise V4L2 async notifier later Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  6:22   ` Laurent Pinchart
  2023-05-25  9:16 ` [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
  2023-05-25  9:22 ` [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
  32 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Set the v4l2_device already in async notifier init, so struct device
related to it will be available before the notifier is registered.

This is done in order to make struct device available earlier, during
construction of the async connections, for sensible debug prints.

This patch has been mostly generated using the following two commands:

git grep -l v4l2_async_nf_init -- drivers/media/ drivers/staging/media/ |
	while read i; do perl -e '
	@a=<>; unlink("'$i'"); open(F, "> '$i'");
	for $f ({i=>"v4l2_async_nf_init", r=>"v4l2_async_nf_register"},
		{i=>"v4l2_async_subdev_nf_init",
		 r=>"v4l2_async_subdev_nf_register"} ) {
	my $b; @a = map { $b = "$1, $2" if
	s/$f->{r}\(([^,]*),\s*([^\)]*)\)/v4l2_async_nf_register\($2\)/;
	$_; } @a; @a = map { if (defined $b) {
	s/v4l2_async_nf_init\([^\)]*\)/$f->{i}\($b\)/;
	s/$f->{r}\(\K[^,]*,\s*//; }; $_; } @a; }; print F @a; close F;'
	< $i; done

git grep -lP 'v4l2_async_(subdev_|)nf_init' | xargs perl -i -pe \
	's/v4l2_async_(subdev_|)nf_init\(\K([^,]*),\s*([^,]*)\)/$3, $2\)/'

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/max9286.c                   |  4 +-
 drivers/media/i2c/st-mipid02.c                |  4 +-
 drivers/media/i2c/tc358746.c                  |  4 +-
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  4 +-
 drivers/media/platform/atmel/atmel-isi.c      |  4 +-
 drivers/media/platform/cadence/cdns-csi2rx.c  |  4 +-
 drivers/media/platform/intel/pxa_camera.c     |  4 +-
 drivers/media/platform/marvell/cafe-driver.c  |  2 +-
 drivers/media/platform/marvell/mcam-core.c    |  2 +-
 drivers/media/platform/marvell/mmp-driver.c   |  2 +-
 .../platform/microchip/microchip-csi2dc.c     |  5 +--
 .../microchip/microchip-sama5d2-isc.c         |  5 +--
 .../microchip/microchip-sama7g5-isc.c         |  5 +--
 drivers/media/platform/nxp/imx-mipi-csis.c    |  4 +-
 drivers/media/platform/nxp/imx7-media-csi.c   |  4 +-
 .../platform/nxp/imx8-isi/imx8-isi-core.c     |  4 +-
 drivers/media/platform/qcom/camss/camss.c     |  5 +--
 drivers/media/platform/renesas/rcar-isp.c     |  4 +-
 .../platform/renesas/rcar-vin/rcar-core.c     |  8 ++--
 .../platform/renesas/rcar-vin/rcar-csi2.c     |  4 +-
 drivers/media/platform/renesas/rcar_drif.c    |  4 +-
 drivers/media/platform/renesas/renesas-ceu.c  |  4 +-
 .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  4 +-
 .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |  4 +-
 .../platform/rockchip/rkisp1/rkisp1-dev.c     |  4 +-
 .../platform/samsung/exynos4-is/media-dev.c   |  5 +--
 drivers/media/platform/st/stm32/stm32-dcmi.c  |  4 +-
 .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  4 +-
 .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |  6 +--
 .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |  4 +-
 .../sun8i_a83t_mipi_csi2.c                    |  4 +-
 .../media/platform/ti/am437x/am437x-vpfe.c    |  4 +-
 drivers/media/platform/ti/cal/cal.c           |  4 +-
 .../media/platform/ti/davinci/vpif_capture.c  | 11 ++---
 drivers/media/platform/ti/omap3isp/isp.c      |  4 +-
 drivers/media/platform/video-mux.c            |  4 +-
 drivers/media/platform/xilinx/xilinx-vipp.c   |  4 +-
 drivers/media/v4l2-core/v4l2-async.c          | 44 +++++++------------
 drivers/media/v4l2-core/v4l2-fwnode.c         |  4 +-
 .../deprecated/atmel/atmel-sama5d2-isc.c      |  5 +--
 .../deprecated/atmel/atmel-sama7g5-isc.c      |  5 +--
 drivers/staging/media/imx/imx-media-csi.c     |  4 +-
 .../staging/media/imx/imx-media-dev-common.c  |  4 +-
 drivers/staging/media/imx/imx6-mipi-csi2.c    |  4 +-
 drivers/staging/media/imx/imx8mq-mipi-csi2.c  |  4 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |  4 +-
 drivers/staging/media/tegra-video/vi.c        |  4 +-
 include/media/v4l2-async.h                    | 33 ++++++++------
 48 files changed, 132 insertions(+), 143 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 44def5e3ba5d1..5f13d75f591ad 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -746,7 +746,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
 	if (!priv->nsources)
 		return 0;
 
-	v4l2_async_nf_init(&priv->notifier);
+	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
 
 	for_each_source(priv, source) {
 		unsigned int i = to_index(priv, source);
@@ -766,7 +766,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
 
 	priv->notifier.ops = &max9286_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+	ret = v4l2_async_nf_register(&priv->notifier);
 	if (ret) {
 		dev_err(dev, "Failed to register subdev_notifier");
 		v4l2_async_nf_cleanup(&priv->notifier);
diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index daea4cb29ec83..d3810e137ba52 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -902,7 +902,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 	bridge->rx = ep;
 
 	/* register async notifier so we get noticed when sensor is connected */
-	v4l2_async_nf_init(&bridge->notifier);
+	v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd);
 	asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
 					      of_fwnode_handle(ep_node),
 					      struct v4l2_async_connection);
@@ -915,7 +915,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 	}
 	bridge->notifier.ops = &mipid02_notifier_ops;
 
-	ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier);
+	ret = v4l2_async_nf_register(&bridge->notifier);
 	if (ret)
 		v4l2_async_nf_cleanup(&bridge->notifier);
 
diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
index a455848d60c15..6e4c484ae1bdc 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -1460,7 +1460,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 		return err;
 	}
 
-	v4l2_async_nf_init(&tc358746->notifier);
+	v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd);
 	asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep,
 					      struct v4l2_async_connection);
 	fwnode_handle_put(ep);
@@ -1472,7 +1472,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
 
 	tc358746->notifier.ops = &tc358746_notify_ops;
 
-	err = v4l2_async_subdev_nf_register(&tc358746->sd, &tc358746->notifier);
+	err = v4l2_async_nf_register(&tc358746->notifier);
 	if (err)
 		goto err_cleanup;
 
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 0f43b5e10f187..8de03d007d0b7 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1502,7 +1502,7 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
 	 * suspend.
 	 */
 	cio2->notifier.ops = &cio2_async_ops;
-	ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier);
+	ret = v4l2_async_nf_register(&cio2->notifier);
 	if (ret)
 		dev_err(dev, "failed to register async notifier : %d\n", ret);
 
@@ -1797,7 +1797,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
 	if (r)
 		goto fail_v4l2_device_unregister;
 
-	v4l2_async_nf_init(&cio2->notifier);
+	v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev);
 
 	/* Register notifier for subdevices we care */
 	r = cio2_parse_firmware(cio2);
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index 7dbad99d4e45e..121eaa6994084 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -1159,7 +1159,7 @@ static int isi_graph_init(struct atmel_isi *isi)
 	if (!ep)
 		return -EINVAL;
 
-	v4l2_async_nf_init(&isi->notifier);
+	v4l2_async_nf_init(&isi->notifier, &isi->v4l2_dev);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier,
 					      of_fwnode_handle(ep),
@@ -1171,7 +1171,7 @@ static int isi_graph_init(struct atmel_isi *isi)
 
 	isi->notifier.ops = &isi_graph_notify_ops;
 
-	ret = v4l2_async_nf_register(&isi->v4l2_dev, &isi->notifier);
+	ret = v4l2_async_nf_register(&isi->notifier);
 	if (ret < 0) {
 		dev_err(isi->dev, "Notifier registration failed\n");
 		v4l2_async_nf_cleanup(&isi->notifier);
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index b0731c07eace0..d7d6b63306521 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -399,7 +399,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 		return -EINVAL;
 	}
 
-	v4l2_async_nf_init(&csi2rx->notifier);
+	v4l2_async_subdev_nf_init(&csi2rx->notifier, &csi2rx->subdev);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
 					      struct v4l2_async_connection);
@@ -409,7 +409,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 
 	csi2rx->notifier.ops = &csi2rx_notifier_ops;
 
-	ret = v4l2_async_subdev_nf_register(&csi2rx->subdev, &csi2rx->notifier);
+	ret = v4l2_async_nf_register(&csi2rx->notifier);
 	if (ret)
 		v4l2_async_nf_cleanup(&csi2rx->notifier);
 
diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index 5df93fd4ff04b..44edd4bdc2c11 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -2311,7 +2311,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	v4l2_async_nf_init(&pcdev->notifier);
+	v4l2_async_nf_init(&pcdev->notifier, &pcdev->v4l2_dev);
 	pcdev->res = res;
 	pcdev->pdata = pdev->dev.platform_data;
 	if (pcdev->pdata) {
@@ -2403,7 +2403,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
 		goto exit_deactivate;
 
 	pcdev->notifier.ops = &pxa_camera_sensor_ops;
-	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
+	err = v4l2_async_nf_register(&pcdev->notifier);
 	if (err)
 		goto exit_deactivate;
 
diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
index fbfbb9f67ddfc..ef810249def61 100644
--- a/drivers/media/platform/marvell/cafe-driver.c
+++ b/drivers/media/platform/marvell/cafe-driver.c
@@ -540,7 +540,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto out_smbus_shutdown;
 
-	v4l2_async_nf_init(&mcam->notifier);
+	v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev);
 
 	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
 				    i2c_adapter_id(cam->i2c_adapter),
diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
index bcfcecdb03ea2..dbcd4f15bda30 100644
--- a/drivers/media/platform/marvell/mcam-core.c
+++ b/drivers/media/platform/marvell/mcam-core.c
@@ -1873,7 +1873,7 @@ int mccic_register(struct mcam_camera *cam)
 	cam->mbus_code = mcam_def_mbus_code;
 
 	cam->notifier.ops = &mccic_notify_ops;
-	ret = v4l2_async_nf_register(&cam->v4l2_dev, &cam->notifier);
+	ret = v4l2_async_nf_register(&cam->notifier);
 	if (ret < 0) {
 		cam_warn(cam, "failed to register a sensor notifier");
 		goto out;
diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c
index dbc1368b91210..76e0ac9cd34f3 100644
--- a/drivers/media/platform/marvell/mmp-driver.c
+++ b/drivers/media/platform/marvell/mmp-driver.c
@@ -239,7 +239,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	if (!ep)
 		return -ENODEV;
 
-	v4l2_async_nf_init(&mcam->notifier);
+	v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep,
 					      struct v4l2_async_connection);
diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c
index d631c3880c536..988c1cc1d8b6b 100644
--- a/drivers/media/platform/microchip/microchip-csi2dc.c
+++ b/drivers/media/platform/microchip/microchip-csi2dc.c
@@ -523,7 +523,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc,
 	struct v4l2_async_connection *asd;
 	int ret = 0;
 
-	v4l2_async_nf_init(&csi2dc->notifier);
+	v4l2_async_subdev_nf_init(&csi2dc->notifier, &csi2dc->csi2dc_sd);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2dc->notifier,
 					      input_fwnode,
@@ -542,8 +542,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc,
 
 	csi2dc->notifier.ops = &csi2dc_async_ops;
 
-	ret = v4l2_async_subdev_nf_register(&csi2dc->csi2dc_sd,
-					    &csi2dc->notifier);
+	ret = v4l2_async_nf_register(&csi2dc->notifier);
 	if (ret) {
 		dev_err(csi2dc->dev, "fail to register async notifier: %d\n",
 			ret);
diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
index 10e6cebf629e6..d78d289bd4250 100644
--- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
@@ -529,7 +529,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
-		v4l2_async_nf_init(&subdev_entity->notifier);
+		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
@@ -545,8 +545,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
 
 		subdev_entity->notifier.ops = &microchip_isc_async_ops;
 
-		ret = v4l2_async_nf_register(&isc->v4l2_dev,
-					     &subdev_entity->notifier);
+		ret = v4l2_async_nf_register(&subdev_entity->notifier);
 		if (ret) {
 			dev_err(dev, "fail to register async notifier\n");
 			goto cleanup_subdev;
diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
index 324810dbdc3af..6d556bb42c12a 100644
--- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
@@ -519,7 +519,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
-		v4l2_async_nf_init(&subdev_entity->notifier);
+		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
@@ -535,8 +535,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 
 		subdev_entity->notifier.ops = &microchip_isc_async_ops;
 
-		ret = v4l2_async_nf_register(&isc->v4l2_dev,
-					     &subdev_entity->notifier);
+		ret = v4l2_async_nf_register(&subdev_entity->notifier);
 		if (ret) {
 			dev_err(dev, "fail to register async notifier\n");
 			goto cleanup_subdev;
diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
index 390834ce482bd..c0439bd86b21b 100644
--- a/drivers/media/platform/nxp/imx-mipi-csis.c
+++ b/drivers/media/platform/nxp/imx-mipi-csis.c
@@ -1252,7 +1252,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
 	unsigned int i;
 	int ret;
 
-	v4l2_async_nf_init(&csis->notifier);
+	v4l2_async_subdev_nf_init(&csis->notifier, &csis->sd);
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
@@ -1288,7 +1288,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
 
 	csis->notifier.ops = &mipi_csis_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&csis->sd, &csis->notifier);
+	ret = v4l2_async_nf_register(&csis->notifier);
 	if (ret)
 		return ret;
 
diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
index 75b7ad65a1141..a9933a97dbef9 100644
--- a/drivers/media/platform/nxp/imx7-media-csi.c
+++ b/drivers/media/platform/nxp/imx7-media-csi.c
@@ -2107,7 +2107,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
 	struct fwnode_handle *ep;
 	int ret;
 
-	v4l2_async_nf_init(&csi->notifier);
+	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
@@ -2130,7 +2130,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
 
 	csi->notifier.ops = &imx7_csi_notify_ops;
 
-	ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier);
+	ret = v4l2_async_nf_register(&csi->notifier);
 	if (ret)
 		goto error;
 
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
index a09f416a64c4f..8d332ac328888 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
@@ -175,7 +175,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi)
 	}
 
 	/* Initialize, fill and register the async notifier. */
-	v4l2_async_nf_init(&isi->notifier);
+	v4l2_async_nf_init(&isi->notifier, v4l2_dev);
 	isi->notifier.ops = &mxc_isi_async_notifier_ops;
 
 	for (i = 0; i < isi->pdata->num_ports; ++i) {
@@ -200,7 +200,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi)
 		masd->port = i;
 	}
 
-	ret = v4l2_async_nf_register(v4l2_dev, &isi->notifier);
+	ret = v4l2_async_nf_register(&isi->notifier);
 	if (ret < 0) {
 		dev_err(isi->dev,
 			"Failed to register async notifier: %d\n", ret);
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index b89e2bb5b505e..f11dc59135a5a 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -1640,7 +1640,7 @@ static int camss_probe(struct platform_device *pdev)
 		goto err_cleanup;
 	}
 
-	v4l2_async_nf_init(&camss->notifier);
+	v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev);
 
 	num_subdevs = camss_of_parse_ports(camss);
 	if (num_subdevs < 0) {
@@ -1655,8 +1655,7 @@ static int camss_probe(struct platform_device *pdev)
 	if (num_subdevs) {
 		camss->notifier.ops = &camss_subdev_notifier_ops;
 
-		ret = v4l2_async_nf_register(&camss->v4l2_dev,
-					     &camss->notifier);
+		ret = v4l2_async_nf_register(&camss->notifier);
 		if (ret) {
 			dev_err(dev,
 				"Failed to register async subdev nodes: %d\n",
diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c
index 5d6d9ffb5201d..452d3b8da7e1c 100644
--- a/drivers/media/platform/renesas/rcar-isp.c
+++ b/drivers/media/platform/renesas/rcar-isp.c
@@ -392,7 +392,7 @@ static int risp_parse_dt(struct rcar_isp *isp)
 
 	dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode));
 
-	v4l2_async_nf_init(&isp->notifier);
+	v4l2_async_subdev_nf_init(&isp->notifier, &isp->subdev);
 	isp->notifier.ops = &risp_notify_ops;
 
 	asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode,
@@ -401,7 +401,7 @@ static int risp_parse_dt(struct rcar_isp *isp)
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
 
-	ret = v4l2_async_subdev_nf_register(&isp->subdev, &isp->notifier);
+	ret = v4l2_async_nf_register(&isp->notifier);
 	if (ret)
 		v4l2_async_nf_cleanup(&isp->notifier);
 
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
index 498778eb9892b..65be0f4c88457 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
@@ -376,7 +376,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
 
 	mutex_unlock(&vin->group->lock);
 
-	v4l2_async_nf_init(&vin->group->notifier);
+	v4l2_async_nf_init(&vin->group->notifier, &vin->v4l2_dev);
 
 	/*
 	 * Some subdevices may overlap but the parser function can handle it and
@@ -400,7 +400,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
 		return 0;
 
 	vin->group->notifier.ops = &rvin_group_notify_ops;
-	ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->group->notifier);
+	ret = v4l2_async_nf_register(&vin->group->notifier);
 	if (ret < 0) {
 		vin_err(vin, "Notifier registration failed\n");
 		v4l2_async_nf_cleanup(&vin->group->notifier);
@@ -713,7 +713,7 @@ static int rvin_parallel_init(struct rvin_dev *vin)
 {
 	int ret;
 
-	v4l2_async_nf_init(&vin->notifier);
+	v4l2_async_nf_init(&vin->notifier, &vin->v4l2_dev);
 
 	ret = rvin_parallel_parse_of(vin);
 	if (ret)
@@ -726,7 +726,7 @@ static int rvin_parallel_init(struct rvin_dev *vin)
 		to_of_node(vin->parallel.asc->match.fwnode));
 
 	vin->notifier.ops = &rvin_parallel_notify_ops;
-	ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier);
+	ret = v4l2_async_nf_register(&vin->notifier);
 	if (ret < 0) {
 		vin_err(vin, "Notifier registration failed\n");
 		v4l2_async_nf_cleanup(&vin->notifier);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
index de7b479df3a9d..21f8f4be0dfe5 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
@@ -1076,7 +1076,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
 
 	dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode));
 
-	v4l2_async_nf_init(&priv->notifier);
+	v4l2_async_subdev_nf_init(&priv->notifier, &priv->subdev);
 	priv->notifier.ops = &rcar_csi2_notify_ops;
 
 	asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,
@@ -1085,7 +1085,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
 	if (IS_ERR(asc))
 		return PTR_ERR(asc);
 
-	ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier);
+	ret = v4l2_async_nf_register(&priv->notifier);
 	if (ret)
 		v4l2_async_nf_cleanup(&priv->notifier);
 
diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c
index 90fda730030d7..c7a925f421228 100644
--- a/drivers/media/platform/renesas/rcar_drif.c
+++ b/drivers/media/platform/renesas/rcar_drif.c
@@ -1207,7 +1207,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
 	struct fwnode_handle *fwnode, *ep;
 	struct v4l2_async_connection *asd;
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_nf_init(&sdr->notifier, &sdr->v4l2_dev);
 
 	ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node),
 					    NULL);
@@ -1341,7 +1341,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
 	sdr->notifier.ops = &rcar_drif_notify_ops;
 
 	/* Register notifier */
-	ret = v4l2_async_nf_register(&sdr->v4l2_dev, &sdr->notifier);
+	ret = v4l2_async_nf_register(&sdr->notifier);
 	if (ret < 0) {
 		dev_err(sdr->dev, "failed: notifier register ret %d\n", ret);
 		goto cleanup;
diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c
index be6140c93fc0c..c2215205fb3c3 100644
--- a/drivers/media/platform/renesas/renesas-ceu.c
+++ b/drivers/media/platform/renesas/renesas-ceu.c
@@ -1667,7 +1667,7 @@ static int ceu_probe(struct platform_device *pdev)
 	if (ret)
 		goto error_pm_disable;
 
-	v4l2_async_nf_init(&ceudev->notifier);
+	v4l2_async_nf_init(&ceudev->notifier, &ceudev->v4l2_dev);
 
 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
 		ceu_data = of_device_get_match_data(dev);
@@ -1689,7 +1689,7 @@ static int ceu_probe(struct platform_device *pdev)
 
 	ceudev->notifier.v4l2_dev	= &ceudev->v4l2_dev;
 	ceudev->notifier.ops		= &ceu_notify_ops;
-	ret = v4l2_async_nf_register(&ceudev->v4l2_dev, &ceudev->notifier);
+	ret = v4l2_async_nf_register(&ceudev->notifier);
 	if (ret)
 		goto error_cleanup;
 
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
index e026ed5337513..fdef43fd1895b 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
@@ -183,7 +183,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
 {
 	int ret;
 
-	v4l2_async_nf_init(&cru->notifier);
+	v4l2_async_nf_init(&cru->notifier, &cru->v4l2_dev);
 
 	ret = rzg2l_cru_mc_parse_of(cru);
 	if (ret)
@@ -194,7 +194,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
 	if (list_empty(&cru->notifier.waiting_list))
 		return 0;
 
-	ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier);
+	ret = v4l2_async_nf_register(&cru->notifier);
 	if (ret < 0) {
 		dev_err(cru->dev, "Notifier registration failed\n");
 		v4l2_async_nf_cleanup(&cru->notifier);
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
index f6bf4cdff28c2..7f6a37f835415 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
@@ -674,7 +674,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
 	fwnode = fwnode_graph_get_remote_endpoint(ep);
 	fwnode_handle_put(ep);
 
-	v4l2_async_nf_init(&csi2->notifier);
+	v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->subdev);
 	csi2->notifier.ops = &rzg2l_csi2_notify_ops;
 
 	asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode,
@@ -683,7 +683,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
 	if (IS_ERR(asd))
 		return PTR_ERR(asd);
 
-	ret = v4l2_async_subdev_nf_register(&csi2->subdev, &csi2->notifier);
+	ret = v4l2_async_nf_register(&csi2->notifier);
 	if (ret)
 		v4l2_async_nf_cleanup(&csi2->notifier);
 
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index eb88494c2a427..543fd377ab2a4 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -187,7 +187,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
 	unsigned int index = 0;
 	int ret = 0;
 
-	v4l2_async_nf_init(ntf);
+	v4l2_async_nf_init(ntf, &rkisp1->v4l2_dev);
 
 	ntf->ops = &rkisp1_subdev_notifier_ops;
 
@@ -287,7 +287,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
 	if (!index)
 		dev_dbg(rkisp1->dev, "no remote subdevice found\n");
 
-	ret = v4l2_async_nf_register(&rkisp1->v4l2_dev, ntf);
+	ret = v4l2_async_nf_register(ntf);
 	if (ret) {
 		v4l2_async_nf_cleanup(ntf);
 		return ret;
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c
index 59070616cb1bd..623e52440ccd2 100644
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.c
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c
@@ -1479,7 +1479,7 @@ static int fimc_md_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, fmd);
 
-	v4l2_async_nf_init(&fmd->subdev_notifier);
+	v4l2_async_nf_init(&fmd->subdev_notifier, &fmd->v4l2_dev);
 
 	ret = fimc_md_register_platform_entities(fmd, dev->of_node);
 	if (ret)
@@ -1507,8 +1507,7 @@ static int fimc_md_probe(struct platform_device *pdev)
 		fmd->subdev_notifier.ops = &subdev_notifier_ops;
 		fmd->num_sensors = 0;
 
-		ret = v4l2_async_nf_register(&fmd->v4l2_dev,
-					     &fmd->subdev_notifier);
+		ret = v4l2_async_nf_register(&fmd->subdev_notifier);
 		if (ret)
 			goto err_clk_p;
 	}
diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
index 6d1197d4464e2..0e8f21602a066 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -1897,7 +1897,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
 		return -EINVAL;
 	}
 
-	v4l2_async_nf_init(&dcmi->notifier);
+	v4l2_async_nf_init(&dcmi->notifier, &dcmi->v4l2_dev);
 
 	asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier,
 					      of_fwnode_handle(ep),
@@ -1912,7 +1912,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
 
 	dcmi->notifier.ops = &dcmi_graph_notify_ops;
 
-	ret = v4l2_async_nf_register(&dcmi->v4l2_dev, &dcmi->notifier);
+	ret = v4l2_async_nf_register(&dcmi->notifier);
 	if (ret < 0) {
 		dev_err(dcmi->dev, "Failed to register notifier\n");
 		v4l2_async_nf_cleanup(&dcmi->notifier);
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index 38ca534842100..bb903e5ea35ea 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -122,7 +122,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
 	struct fwnode_handle *ep;
 	int ret;
 
-	v4l2_async_nf_init(&csi->notifier);
+	v4l2_async_nf_init(&csi->notifier, &csi->v4l);
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
@@ -240,7 +240,7 @@ static int sun4i_csi_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_unregister_media;
 
-	ret = v4l2_async_nf_register(&csi->v4l, &csi->notifier);
+	ret = v4l2_async_nf_register(&csi->notifier);
 	if (ret) {
 		dev_err(csi->dev, "Couldn't register our notifier.\n");
 		goto err_unregister_media;
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index ebb725fc11ba5..0dcf605f2764b 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -819,7 +819,7 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 
 	/* V4L2 Async */
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_subdev_nf_init(notifier, subdev);
 	notifier->ops = &sun6i_csi_bridge_notifier_ops;
 
 	sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_parallel,
@@ -829,9 +829,9 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 				      SUN6I_CSI_PORT_MIPI_CSI2, NULL);
 
 	if (csi_dev->isp_available)
-		ret = v4l2_async_subdev_nf_register(subdev, notifier);
+		ret = v4l2_async_nf_register(notifier);
 	else
-		ret = v4l2_async_nf_register(v4l2_dev, notifier);
+		ret = v4l2_async_nf_register(notifier);
 	if (ret) {
 		dev_err(dev, "failed to register v4l2 async notifier: %d\n",
 			ret);
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
index a78900dd0b7a6..adf966d2f5ca2 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
@@ -531,7 +531,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
 
 	/* V4L2 Async */
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_subdev_nf_init(notifier, subdev);
 	notifier->ops = &sun6i_mipi_csi2_notifier_ops;
 
 	ret = sun6i_mipi_csi2_bridge_source_setup(csi2_dev);
@@ -540,7 +540,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
 
 	/* Only register the notifier when a sensor is connected. */
 	if (ret != -ENODEV) {
-		ret = v4l2_async_subdev_nf_register(subdev, notifier);
+		ret = v4l2_async_nf_register(notifier);
 		if (ret < 0)
 			goto error_v4l2_notifier_cleanup;
 
diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
index 909aaef200989..50641d7af320d 100644
--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
@@ -569,7 +569,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
 
 	/* V4L2 Async */
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_subdev_nf_init(notifier, subdev);
 	notifier->ops = &sun8i_a83t_mipi_csi2_notifier_ops;
 
 	ret = sun8i_a83t_mipi_csi2_bridge_source_setup(csi2_dev);
@@ -578,7 +578,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
 
 	/* Only register the notifier when a sensor is connected. */
 	if (ret != -ENODEV) {
-		ret = v4l2_async_subdev_nf_register(subdev, notifier);
+		ret = v4l2_async_nf_register(notifier);
 		if (ret < 0)
 			goto error_v4l2_notifier_cleanup;
 
diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c
index 1457a188fea12..9ecd6b02467c8 100644
--- a/drivers/media/platform/ti/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c
@@ -2300,7 +2300,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
 
 	dev_dbg(dev, "vpfe_get_pdata\n");
 
-	v4l2_async_nf_init(&vpfe->notifier);
+	v4l2_async_nf_init(&vpfe->notifier, &vpfe->v4l2_dev);
 
 	if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
 		return dev->platform_data;
@@ -2466,7 +2466,7 @@ static int vpfe_probe(struct platform_device *pdev)
 	}
 
 	vpfe->notifier.ops = &vpfe_async_ops;
-	ret = v4l2_async_nf_register(&vpfe->v4l2_dev, &vpfe->notifier);
+	ret = v4l2_async_nf_register(&vpfe->notifier);
 	if (ret) {
 		vpfe_err(vpfe, "Error registering async notifier\n");
 		ret = -EINVAL;
diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c
index bf7a985168c7b..25780e1f103e7 100644
--- a/drivers/media/platform/ti/cal/cal.c
+++ b/drivers/media/platform/ti/cal/cal.c
@@ -895,7 +895,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 	unsigned int i;
 	int ret;
 
-	v4l2_async_nf_init(&cal->notifier);
+	v4l2_async_nf_init(&cal->notifier, &cal->v4l2_dev);
 	cal->notifier.ops = &cal_async_notifier_ops;
 
 	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
@@ -919,7 +919,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 		casd->phy = phy;
 	}
 
-	ret = v4l2_async_nf_register(&cal->v4l2_dev, &cal->notifier);
+	ret = v4l2_async_nf_register(&cal->notifier);
 	if (ret) {
 		cal_err(cal, "Error registering async notifier\n");
 		goto error;
diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c
index 9b97e26be0892..3f0b161ab50cf 100644
--- a/drivers/media/platform/ti/davinci/vpif_capture.c
+++ b/drivers/media/platform/ti/davinci/vpif_capture.c
@@ -1483,7 +1483,8 @@ static const struct v4l2_async_notifier_operations vpif_async_ops = {
 };
 
 static struct vpif_capture_config *
-vpif_capture_get_pdata(struct platform_device *pdev)
+vpif_capture_get_pdata(struct platform_device *pdev,
+		       struct v4l2_device *v4l2_dev)
 {
 	struct device_node *endpoint = NULL;
 	struct device_node *rem = NULL;
@@ -1492,7 +1493,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
 	struct vpif_capture_chan_config *chan;
 	unsigned int i;
 
-	v4l2_async_nf_init(&vpif_obj.notifier);
+	v4l2_async_nf_init(&vpif_obj.notifier, v4l2_dev);
 
 	/*
 	 * DT boot: OF node from parent device contains
@@ -1649,7 +1650,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 		goto vpif_unregister;
 	}
 
-	pdev->dev.platform_data = vpif_capture_get_pdata(pdev);
+	pdev->dev.platform_data =
+		vpif_capture_get_pdata(pdev, &vpif_obj.v4l2_dev);
 	if (!pdev->dev.platform_data) {
 		dev_warn(&pdev->dev, "Missing platform data.  Giving up.\n");
 		goto probe_subdev_out;
@@ -1683,8 +1685,7 @@ static __init int vpif_probe(struct platform_device *pdev)
 			goto probe_subdev_out;
 	} else {
 		vpif_obj.notifier.ops = &vpif_async_ops;
-		err = v4l2_async_nf_register(&vpif_obj.v4l2_dev,
-					     &vpif_obj.notifier);
+		err = v4l2_async_nf_register(&vpif_obj.notifier);
 		if (err) {
 			vpif_err("Error registering async notifier\n");
 			err = -EINVAL;
diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
index 5b3266b214874..44ddc1422cc75 100644
--- a/drivers/media/platform/ti/omap3isp/isp.c
+++ b/drivers/media/platform/ti/omap3isp/isp.c
@@ -2425,13 +2425,13 @@ static int isp_probe(struct platform_device *pdev)
 
 	isp->notifier.ops = &isp_subdev_notifier_ops;
 
-	v4l2_async_nf_init(&isp->notifier);
+	v4l2_async_nf_init(&isp->notifier, &isp->v4l2_dev);
 
 	ret = isp_parse_of_endpoints(isp);
 	if (ret < 0)
 		goto error_register_entities;
 
-	ret = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier);
+	ret = v4l2_async_nf_register(&isp->notifier);
 	if (ret)
 		goto error_register_entities;
 
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index e1dd798764312..315c65effe878 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -360,7 +360,7 @@ static int video_mux_async_register(struct video_mux *vmux,
 	unsigned int i;
 	int ret;
 
-	v4l2_async_nf_init(&vmux->notifier);
+	v4l2_async_subdev_nf_init(&vmux->notifier, &vmux->subdev);
 
 	for (i = 0; i < num_input_pads; i++) {
 		struct v4l2_async_connection *asd;
@@ -395,7 +395,7 @@ static int video_mux_async_register(struct video_mux *vmux,
 
 	vmux->notifier.ops = &video_mux_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier);
+	ret = v4l2_async_nf_register(&vmux->notifier);
 	if (ret)
 		return ret;
 
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 6bb426a25fe90..4285770fde184 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -494,7 +494,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
 		goto done;
 	}
 
-	v4l2_async_nf_init(&xdev->notifier);
+	v4l2_async_nf_init(&xdev->notifier, &xdev->v4l2_dev);
 
 	/* Parse the graph to extract a list of subdevice DT nodes. */
 	ret = xvip_graph_parse(xdev);
@@ -512,7 +512,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
 	/* Register the subdevices notifier. */
 	xdev->notifier.ops = &xvip_graph_notify_ops;
 
-	ret = v4l2_async_nf_register(&xdev->v4l2_dev, &xdev->notifier);
+	ret = v4l2_async_nf_register(&xdev->notifier);
 	if (ret < 0) {
 		dev_err(xdev->dev, "notifier registration failed\n");
 		goto done;
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 12b465a16ec1c..bb172cc18998a 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -558,13 +558,24 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
 	return 0;
 }
 
-void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
+void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
+			struct v4l2_device *v4l2_dev)
 {
 	INIT_LIST_HEAD(&notifier->waiting_list);
 	INIT_LIST_HEAD(&notifier->done_list);
+	notifier->v4l2_dev = v4l2_dev;
 }
 EXPORT_SYMBOL(v4l2_async_nf_init);
 
+void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
+			       struct v4l2_subdev *sd)
+{
+	INIT_LIST_HEAD(&notifier->waiting_list);
+	INIT_LIST_HEAD(&notifier->done_list);
+	notifier->sd = sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_subdev_nf_init);
+
 static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_connection *asc;
@@ -605,16 +616,13 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 	return ret;
 }
 
-int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
-			   struct v4l2_async_notifier *notifier)
+int v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
 {
 	int ret;
 
-	if (WARN_ON(!v4l2_dev || notifier->sd))
+	if (WARN_ON(!notifier->v4l2_dev == !notifier->sd))
 		return -EINVAL;
 
-	notifier->v4l2_dev = v4l2_dev;
-
 	ret = __v4l2_async_nf_register(notifier);
 	if (ret)
 		notifier->v4l2_dev = NULL;
@@ -623,24 +631,6 @@ int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
 }
 EXPORT_SYMBOL(v4l2_async_nf_register);
 
-int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
-				  struct v4l2_async_notifier *notifier)
-{
-	int ret;
-
-	if (WARN_ON(!sd || notifier->v4l2_dev))
-		return -EINVAL;
-
-	notifier->sd = sd;
-
-	ret = __v4l2_async_nf_register(notifier);
-	if (ret)
-		notifier->sd = NULL;
-
-	return ret;
-}
-EXPORT_SYMBOL(v4l2_async_subdev_nf_register);
-
 static void
 __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
 {
@@ -649,9 +639,6 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
 
 	v4l2_async_nf_unbind_all_subdevs(notifier);
 
-	notifier->sd = NULL;
-	notifier->v4l2_dev = NULL;
-
 	list_del(&notifier->notifier_entry);
 }
 
@@ -683,6 +670,9 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 
 		kfree(asc);
 	}
+
+	notifier->sd = NULL;
+	notifier->v4l2_dev = NULL;
 }
 
 void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 7c3e1648a0f49..dc5df557c3b33 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1205,7 +1205,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
 	if (!notifier)
 		return -ENOMEM;
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_subdev_nf_init(notifier, sd);
 
 	ret = v4l2_subdev_get_privacy_led(sd);
 	if (ret < 0)
@@ -1215,7 +1215,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
 	if (ret < 0)
 		goto out_cleanup;
 
-	ret = v4l2_async_subdev_nf_register(sd, notifier);
+	ret = v4l2_async_nf_register(notifier);
 	if (ret < 0)
 		goto out_cleanup;
 
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
index 58c8c7813e0f9..31b2b48085c59 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
@@ -507,7 +507,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
-		v4l2_async_nf_init(&subdev_entity->notifier);
+		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
@@ -523,8 +523,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
 
 		subdev_entity->notifier.ops = &atmel_isc_async_ops;
 
-		ret = v4l2_async_nf_register(&isc->v4l2_dev,
-					     &subdev_entity->notifier);
+		ret = v4l2_async_nf_register(&subdev_entity->notifier);
 		if (ret) {
 			dev_err(dev, "fail to register async notifier\n");
 			goto cleanup_subdev;
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
index f10ddee0949e1..020034f631f57 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
@@ -497,7 +497,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 		struct fwnode_handle *fwnode =
 			of_fwnode_handle(subdev_entity->epn);
 
-		v4l2_async_nf_init(&subdev_entity->notifier);
+		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
 
 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
 						      fwnode,
@@ -513,8 +513,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 
 		subdev_entity->notifier.ops = &atmel_isc_async_ops;
 
-		ret = v4l2_async_nf_register(&isc->v4l2_dev,
-					     &subdev_entity->notifier);
+		ret = v4l2_async_nf_register(&subdev_entity->notifier);
 		if (ret) {
 			dev_err(dev, "fail to register async notifier\n");
 			goto cleanup_subdev;
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 09b8b396022e0..dda1ebc34692a 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1918,7 +1918,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
 	unsigned int port;
 	int ret;
 
-	v4l2_async_nf_init(&priv->notifier);
+	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
 
 	/* get this CSI's port id */
 	ret = fwnode_property_read_u32(dev_fwnode(priv->dev), "reg", &port);
@@ -1944,7 +1944,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
 
 	priv->notifier.ops = &csi_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+	ret = v4l2_async_nf_register(&priv->notifier);
 	if (ret)
 		return ret;
 
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
index 67c1b16db6558..46bf717255b3e 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -367,7 +367,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
 
 	INIT_LIST_HEAD(&imxmd->vdev_list);
 
-	v4l2_async_nf_init(&imxmd->notifier);
+	v4l2_async_nf_init(&imxmd->notifier, &imxmd->v4l2_dev);
 
 	return imxmd;
 
@@ -391,7 +391,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
 
 	/* prepare the async subdev notifier and register it */
 	imxmd->notifier.ops = ops ? ops : &imx_media_notifier_ops;
-	ret = v4l2_async_nf_register(&imxmd->v4l2_dev, &imxmd->notifier);
+	ret = v4l2_async_nf_register(&imxmd->notifier);
 	if (ret) {
 		v4l2_err(&imxmd->v4l2_dev,
 			 "v4l2_async_nf_register failed with %d\n", ret);
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 2e86f82ad70cd..50f1df09c0a73 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -635,7 +635,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	struct fwnode_handle *ep;
 	int ret;
 
-	v4l2_async_nf_init(&csi2->notifier);
+	v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->sd);
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
@@ -660,7 +660,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
 
 	csi2->notifier.ops = &csi2_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&csi2->sd, &csi2->notifier);
+	ret = v4l2_async_nf_register(&csi2->notifier);
 	if (ret)
 		return ret;
 
diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
index 2f723ad34c2c5..6813c44b71039 100644
--- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
@@ -592,7 +592,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
 	unsigned int i;
 	int ret;
 
-	v4l2_async_nf_init(&state->notifier);
+	v4l2_async_subdev_nf_init(&state->notifier, &state->sd);
 
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
@@ -629,7 +629,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
 
 	state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
 
-	ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
+	ret = v4l2_async_nf_register(&state->notifier);
 	if (ret)
 		return ret;
 
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
index dd7dfecb9ef33..ccbb530aa2e23 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
@@ -536,7 +536,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
 
 	/* V4L2 Async */
 
-	v4l2_async_nf_init(notifier);
+	v4l2_async_nf_init(notifier, v4l2_dev);
 	notifier->ops = &sun6i_isp_proc_notifier_ops;
 
 	sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi0,
@@ -544,7 +544,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
 	sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi1,
 				    SUN6I_ISP_PORT_CSI1);
 
-	ret = v4l2_async_nf_register(v4l2_dev, notifier);
+	ret = v4l2_async_nf_register(notifier);
 	if (ret) {
 		v4l2_err(v4l2_dev,
 			 "failed to register v4l2 async notifier: %d\n", ret);
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 146b4fd3c8b52..f31d8babf499c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1280,7 +1280,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan)
 	}
 
 	if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
-		v4l2_async_nf_init(&chan->notifier);
+		v4l2_async_nf_init(&chan->notifier, &vid->v4l2_dev);
 
 	return 0;
 
@@ -1880,7 +1880,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
 			continue;
 
 		chan->notifier.ops = &tegra_vi_async_ops;
-		ret = v4l2_async_nf_register(&vid->v4l2_dev, &chan->notifier);
+		ret = v4l2_async_nf_register(&chan->notifier);
 		if (ret < 0) {
 			dev_err(vi->dev,
 				"failed to register channel %d notifier: %d\n",
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index d0bef6626e043..65e364d4033a4 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -146,13 +146,30 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
  * v4l2_async_nf_init - Initialize a notifier.
  *
  * @notifier: pointer to &struct v4l2_async_notifier
+ * @v4l2_dev: pointer to &struct v4l2_device
+ *
+ * This function initializes the notifier @asc_entry. It must be called
+ * before adding a subdevice to a notifier, using one of:
+ * v4l2_async_nf_add_fwnode_remote(),
+ * v4l2_async_nf_add_fwnode() or
+ * v4l2_async_nf_add_i2c().
+ */
+void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
+			struct v4l2_device *v4l2_dev);
+
+/**
+ * v4l2_async_subdev_nf_init - Initialize a sub-device notifier.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @sd: pointer to &struct v4l2_subdev
  *
  * This function initializes the notifier @asc_entry. It must be called
  * before adding a subdevice to a notifier, using one of:
  * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
  * v4l2_async_nf_add_i2c().
  */
-void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
+void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
+			       struct v4l2_subdev *sd);
 
 struct v4l2_async_connection *
 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
@@ -257,21 +274,9 @@ v4l2_async_connection_unique(struct v4l2_subdev *sd);
 /**
  * v4l2_async_nf_register - registers a subdevice asynchronous notifier
  *
- * @v4l2_dev: pointer to &struct v4l2_device
- * @notifier: pointer to &struct v4l2_async_notifier
- */
-int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
-			   struct v4l2_async_notifier *notifier);
-
-/**
- * v4l2_async_subdev_nf_register - registers a subdevice asynchronous
- *					 notifier for a sub-device
- *
- * @sd: pointer to &struct v4l2_subdev
  * @notifier: pointer to &struct v4l2_async_notifier
  */
-int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
-				  struct v4l2_async_notifier *notifier);
+int v4l2_async_nf_register(struct v4l2_async_notifier *notifier);
 
 /**
  * v4l2_async_nf_unregister - unregisters a subdevice
-- 
2.30.2


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

* [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (30 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init Sakari Ailus
@ 2023-05-25  9:16 ` Sakari Ailus
  2023-05-30  6:18   ` Laurent Pinchart
  2023-05-30 12:13   ` Aishwarya Kothari
  2023-05-25  9:22 ` [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
  32 siblings, 2 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:16 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Document that sub-device notifiers are now registered using
v4l2_async_subdev_nf_init(). No documentation is changed as it seems that
sub-device notifiers were not documented apart from kernel-doc comments.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 Documentation/driver-api/media/v4l2-subdev.rst | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
index 83d3d29608136..d62b341642c96 100644
--- a/Documentation/driver-api/media/v4l2-subdev.rst
+++ b/Documentation/driver-api/media/v4l2-subdev.rst
@@ -193,9 +193,7 @@ picked up by bridge drivers.
 Bridge drivers in turn have to register a notifier object. This is
 performed using the :c:func:`v4l2_async_nf_register` call. To
 unregister the notifier the driver has to call
-:c:func:`v4l2_async_nf_unregister`. The former of the two functions
-takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
-pointer to struct :c:type:`v4l2_async_notifier`.
+:c:func:`v4l2_async_nf_unregister`.
 
 Before registering the notifier, bridge drivers must do two things: first, the
 notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
@@ -204,6 +202,12 @@ that the bridge device needs for its operation. Several functions are available
 to add subdevice descriptors to a notifier, depending on the type of device and
 the needs of the driver.
 
+For a sub-device driver to register a notifier, the process is otherwise similar
+to that of a bridge driver, apart from that the notifier is initialised using
+:c:func:`v4l2_async_subdev_nf_init` instead. A sub-device notifier may complete
+only after the V4L2 device becomes available, i.e. there's a path via async
+sub-devices and notifiers to that root notifier.
+
 :c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
 :c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
 :c:with the notifier.
-- 
2.30.2


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

* Re: [RESEND PATCH v3 00/32] Separate links and async sub-devices
  2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
                   ` (31 preceding siblings ...)
  2023-05-25  9:16 ` [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
@ 2023-05-25  9:22 ` Sakari Ailus
  32 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-05-25  9:22 UTC (permalink / raw)
  Cc: linux-media, laurent.pinchart, Philipp Zabel, hverkuil,
	Francesco Dolcini, aishwarya.kothari, Robert Foss, Todor Tomov,
	Hyun Kwon, bingbu.cao, niklas.soderlund, Kieran Bingham,
	Benjamin Mugnier, Sylvain Petinot, Eugen Hristev, Nicolas Ferre,
	Maxime Ripard, Rui Miguel Silva, Fabio Estevam,
	Bryan O'Donoghue, Sylwester Nawrocki, Dafna Hirschfeld,
	Hugues Fruchet, Yong Deng, Paul Kocialkowski, Lad, Prabhakar,
	Benoit Parrot, Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On Thu, May 25, 2023 at 12:15:43PM +0300, Sakari Ailus wrote:
> The code also can be found in my async-multi branch, on media tree master.

I meant to say "on my linuxtv.org tree":

<URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=async-multi>

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints()
  2023-05-25  9:15 ` [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
@ 2023-05-30  2:13   ` Laurent Pinchart
  0 siblings, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:13 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari, Jacopo,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:44PM +0300, Sakari Ailus wrote:
> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> 
> The v4l2_async_nf_parse_fwnode_endpoints() function, part of
> v4l2-fwnode.c, was a helper meant to register one async sub-dev for each
> fwnode endpoint of a device.
> 
> The function is marked as deprecated in the documentation and is actually
> not used anywhere anymore. Drop it and remove the helper function
> v4l2_async_nf_fwnode_parse_endpoint() from v4l2-fwnode.c.
> 
> This change allows to make the helper function
> __v4l2_async_nf_add_connection() visibility private to v4l2-async.c so
> that there is no risk drivers can mistakenly use it.
> 
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> [Sakari Ailus: Small fixups on top.]
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> ---
>  drivers/media/v4l2-core/v4l2-async.c  |  6 +-
>  drivers/media/v4l2-core/v4l2-fwnode.c | 97 ---------------------------
>  include/media/v4l2-async.h            | 34 ++--------
>  include/media/v4l2-fwnode.h           | 66 ------------------
>  4 files changed, 7 insertions(+), 196 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index b16b5f4cb91e2..7831bc8792904 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -662,8 +662,9 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
>  
> -int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
> -			       struct v4l2_async_subdev *asd)
> +
> +static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
> +				      struct v4l2_async_subdev *asd)
>  {
>  	int ret;
>  
> @@ -679,7 +680,6 @@ int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
>  	mutex_unlock(&list_lock);
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_subdev);
>  
>  struct v4l2_async_subdev *
>  __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> index 049c2f2001eaa..b71561957b9fb 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -798,103 +798,6 @@ int v4l2_fwnode_device_parse(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
>  
> -static int
> -v4l2_async_nf_fwnode_parse_endpoint(struct device *dev,
> -				    struct v4l2_async_notifier *notifier,
> -				    struct fwnode_handle *endpoint,
> -				    unsigned int asd_struct_size,
> -				    parse_endpoint_func parse_endpoint)
> -{
> -	struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
> -	struct v4l2_async_subdev *asd;
> -	int ret;
> -
> -	asd = kzalloc(asd_struct_size, GFP_KERNEL);
> -	if (!asd)
> -		return -ENOMEM;
> -
> -	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	asd->match.fwnode =
> -		fwnode_graph_get_remote_port_parent(endpoint);
> -	if (!asd->match.fwnode) {
> -		dev_dbg(dev, "no remote endpoint found\n");
> -		ret = -ENOTCONN;
> -		goto out_err;
> -	}
> -
> -	ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep);
> -	if (ret) {
> -		dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
> -			 ret);
> -		goto out_err;
> -	}
> -
> -	ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0;
> -	if (ret == -ENOTCONN)
> -		dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port,
> -			vep.base.id);
> -	else if (ret < 0)
> -		dev_warn(dev,
> -			 "driver could not parse port@%u/endpoint@%u (%d)\n",
> -			 vep.base.port, vep.base.id, ret);
> -	v4l2_fwnode_endpoint_free(&vep);
> -	if (ret < 0)
> -		goto out_err;
> -
> -	ret = __v4l2_async_nf_add_subdev(notifier, asd);
> -	if (ret < 0) {
> -		/* not an error if asd already exists */
> -		if (ret == -EEXIST)
> -			ret = 0;
> -		goto out_err;
> -	}
> -
> -	return 0;
> -
> -out_err:
> -	fwnode_handle_put(asd->match.fwnode);
> -	kfree(asd);
> -
> -	return ret == -ENOTCONN ? 0 : ret;
> -}
> -
> -int
> -v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
> -				     struct v4l2_async_notifier *notifier,
> -				     size_t asd_struct_size,
> -				     parse_endpoint_func parse_endpoint)
> -{
> -	struct fwnode_handle *fwnode;
> -	int ret = 0;
> -
> -	if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
> -		return -EINVAL;
> -
> -	fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) {
> -		struct fwnode_handle *dev_fwnode;
> -		bool is_available;
> -
> -		dev_fwnode = fwnode_graph_get_port_parent(fwnode);
> -		is_available = fwnode_device_is_available(dev_fwnode);
> -		fwnode_handle_put(dev_fwnode);
> -		if (!is_available)
> -			continue;
> -
> -
> -		ret = v4l2_async_nf_fwnode_parse_endpoint(dev, notifier,
> -							  fwnode,
> -							  asd_struct_size,
> -							  parse_endpoint);
> -		if (ret < 0)
> -			break;
> -	}
> -
> -	fwnode_handle_put(fwnode);
> -
> -	return ret;
> -}
> -EXPORT_SYMBOL_GPL(v4l2_async_nf_parse_fwnode_endpoints);
> -
>  /*
>   * v4l2_fwnode_reference_parse - parse references for async sub-devices
>   * @dev: the device node the properties of which are parsed for references
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 25eb1d138c069..2c9baa3c9266a 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -131,32 +131,10 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>   *
>   * This function initializes the notifier @asd_list. It must be called
>   * before adding a subdevice to a notifier, using one of:
> - * v4l2_async_nf_add_fwnode_remote(),
> - * v4l2_async_nf_add_fwnode(),
> - * v4l2_async_nf_add_i2c(),
> - * __v4l2_async_nf_add_subdev() or
> - * v4l2_async_nf_parse_fwnode_endpoints().
> - */
> -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
> -
> -/**
> - * __v4l2_async_nf_add_subdev - Add an async subdev to the
> - *				notifier's master asd list.
> - *
> - * @notifier: pointer to &struct v4l2_async_notifier
> - * @asd: pointer to &struct v4l2_async_subdev
> - *
> - * \warning: Drivers should avoid using this function and instead use one of:
> - * v4l2_async_nf_add_fwnode(),
> - * v4l2_async_nf_add_fwnode_remote() or
> + * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
>   * v4l2_async_nf_add_i2c().
> - *
> - * Call this function before registering a notifier to link the provided @asd to
> - * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
> - * it will be freed by the framework when the notifier is destroyed.
>   */
> -int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
> -			       struct v4l2_async_subdev *asd);
> +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
>  
>  struct v4l2_async_subdev *
>  __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> @@ -263,12 +241,8 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier);
>   * Release memory resources related to a notifier, including the async
>   * sub-devices allocated for the purposes of the notifier but not the notifier
>   * itself. The user is responsible for calling this function to clean up the
> - * notifier after calling
> - * v4l2_async_nf_add_fwnode_remote(),
> - * v4l2_async_nf_add_fwnode(),
> - * v4l2_async_nf_add_i2c(),
> - * __v4l2_async_nf_add_subdev() or
> - * v4l2_async_nf_parse_fwnode_endpoints().
> + * notifier after calling v4l2_async_nf_add_fwnode_remote(),
> + * v4l2_async_nf_add_fwnode() or v4l2_async_nf_add_i2c().
>   *
>   * There is no harm from calling v4l2_async_nf_cleanup() in other
>   * cases as long as its memory has been zeroed after it has been
> diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
> index 394d798f3dfa4..855dae84b751d 100644
> --- a/include/media/v4l2-fwnode.h
> +++ b/include/media/v4l2-fwnode.h
> @@ -393,72 +393,6 @@ int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode,
>  int v4l2_fwnode_device_parse(struct device *dev,
>  			     struct v4l2_fwnode_device_properties *props);
>  
> -/**
> - * typedef parse_endpoint_func - Driver's callback function to be called on
> - *	each V4L2 fwnode endpoint.
> - *
> - * @dev: pointer to &struct device
> - * @vep: pointer to &struct v4l2_fwnode_endpoint
> - * @asd: pointer to &struct v4l2_async_subdev
> - *
> - * Return:
> - * * %0 on success
> - * * %-ENOTCONN if the endpoint is to be skipped but this
> - *   should not be considered as an error
> - * * %-EINVAL if the endpoint configuration is invalid
> - */
> -typedef int (*parse_endpoint_func)(struct device *dev,
> -				  struct v4l2_fwnode_endpoint *vep,
> -				  struct v4l2_async_subdev *asd);
> -
> -/**
> - * v4l2_async_nf_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
> - *						device node
> - * @dev: the device the endpoints of which are to be parsed
> - * @notifier: notifier for @dev
> - * @asd_struct_size: size of the driver's async sub-device struct, including
> - *		     sizeof(struct v4l2_async_subdev). The &struct
> - *		     v4l2_async_subdev shall be the first member of
> - *		     the driver's async sub-device struct, i.e. both
> - *		     begin at the same memory address.
> - * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
> - *		    endpoint. Optional.
> - *
> - * DEPRECATED! This function is deprecated. Don't use it in new drivers.
> - * Instead see an example in cio2_parse_firmware() function in
> - * drivers/media/pci/intel/ipu3/ipu3-cio2.c .
> - *
> - * Parse the fwnode endpoints of the @dev device and populate the async sub-
> - * devices list in the notifier. The @parse_endpoint callback function is
> - * called for each endpoint with the corresponding async sub-device pointer to
> - * let the caller initialize the driver-specific part of the async sub-device
> - * structure.
> - *
> - * The notifier memory shall be zeroed before this function is called on the
> - * notifier.
> - *
> - * This function may not be called on a registered notifier and may be called on
> - * a notifier only once.
> - *
> - * The &struct v4l2_fwnode_endpoint passed to the callback function
> - * @parse_endpoint is released once the function is finished. If there is a need
> - * to retain that configuration, the user needs to allocate memory for it.
> - *
> - * Any notifier populated using this function must be released with a call to
> - * v4l2_async_nf_cleanup() after it has been unregistered and the async
> - * sub-devices are no longer in use, even if the function returned an error.
> - *
> - * Return: %0 on success, including when no async sub-devices are found
> - *	   %-ENOMEM if memory allocation failed
> - *	   %-EINVAL if graph or endpoint parsing failed
> - *	   Other error codes as returned by @parse_endpoint
> - */
> -int
> -v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
> -				     struct v4l2_async_notifier *notifier,
> -				     size_t asd_struct_size,
> -				     parse_endpoint_func parse_endpoint);
> -
>  /* Helper macros to access the connector links. */
>  
>  /** v4l2_connector_last_link - Helper macro to get the first

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function
  2023-05-25  9:15 ` [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function Sakari Ailus
@ 2023-05-30  2:14   ` Laurent Pinchart
  2023-06-13 13:43     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:14 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:45PM +0300, Sakari Ailus wrote:
> Also v4l2_async_nf_add_fwnode() may be used to add an async sub-device
> descriptor to a notifier. Document this.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  Documentation/driver-api/media/v4l2-subdev.rst | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> index 602dadaa81d86..ce8e9d0a332bc 100644
> --- a/Documentation/driver-api/media/v4l2-subdev.rst
> +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> @@ -204,9 +204,9 @@ that the bridge device needs for its operation. Several functions are available
>  to add subdevice descriptors to a notifier, depending on the type of device and
>  the needs of the driver.
>  
> -:c:func:`v4l2_async_nf_add_fwnode_remote` and
> -:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
> -registering their async sub-devices with the notifier.
> +:c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
> +:c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices

The 'and' isn't in the right place. With this fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> +:c:with the notifier.
>  
>  :c:func:`v4l2_async_register_subdev_sensor` is a helper function for
>  sensor drivers registering their own async sub-device, but it also registers a

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback
  2023-05-25  9:15 ` [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
@ 2023-05-30  2:20   ` Laurent Pinchart
  2023-05-30  2:21   ` Laurent Pinchart
  1 sibling, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:20 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:46PM +0300, Sakari Ailus wrote:
> The async notifier bound callback does a lot of checks that have probably
> been always unnecessary. Remove the lookup of the async subev that we
> already have, as well as the debug print that is already printed by the
> framework.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/xilinx/xilinx-vipp.c | 32 ++++-----------------
>  1 file changed, 5 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index 3123216b3f70e..b309af0c83749 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -312,36 +312,14 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  
>  static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_subdev *subdev,
> -				   struct v4l2_async_subdev *unused)
> +				   struct v4l2_async_subdev *asd)
>  {
> -	struct xvip_composite_device *xdev =
> -		container_of(notifier, struct xvip_composite_device, notifier);
> -	struct xvip_graph_entity *entity;
> -	struct v4l2_async_subdev *asd;
> +	struct xvip_graph_entity *entity = to_xvip_entity(asd);
>  
> -	/* Locate the entity corresponding to the bound subdev and store the
> -	 * subdev pointer.
> -	 */
> -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> -		entity = to_xvip_entity(asd);
> +	entity->entity = &subdev->entity;
> +	entity->subdev = subdev;
>  
> -		if (entity->asd.match.fwnode != subdev->fwnode)
> -			continue;
> -
> -		if (entity->subdev) {
> -			dev_err(xdev->dev, "duplicate subdev for node %p\n",
> -				entity->asd.match.fwnode);
> -			return -EINVAL;
> -		}
> -
> -		dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name);
> -		entity->entity = &subdev->entity;
> -		entity->subdev = subdev;
> -		return 0;
> -	}
> -
> -	dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name);
> -	return -EINVAL;
> +	return 0;
>  }
>  
>  static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = {

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback
  2023-05-25  9:15 ` [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
  2023-05-30  2:20   ` Laurent Pinchart
@ 2023-05-30  2:21   ` Laurent Pinchart
  1 sibling, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:21 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Sakari Ailus, linux-media, Philipp Zabel, hverkuil,
	Francesco Dolcini, aishwarya.kothari, Robert Foss, Todor Tomov,
	Hyun Kwon, bingbu.cao, niklas.soderlund, Kieran Bingham,
	Benjamin Mugnier, Sylvain Petinot, Eugen Hristev, Nicolas Ferre,
	Maxime Ripard, Rui Miguel Silva, Fabio Estevam,
	Bryan O'Donoghue, Sylwester Nawrocki, Dafna Hirschfeld,
	Hugues Fruchet, Yong Deng, Paul Kocialkowski, Lad, Prabhakar,
	Benoit Parrot, Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Tomi, could you please test this patch ?

On Thu, May 25, 2023 at 12:15:46PM +0300, Sakari Ailus wrote:
> The async notifier bound callback does a lot of checks that have probably
> been always unnecessary. Remove the lookup of the async subev that we
> already have, as well as the debug print that is already printed by the
> framework.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/platform/xilinx/xilinx-vipp.c | 32 ++++-----------------
>  1 file changed, 5 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index 3123216b3f70e..b309af0c83749 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -312,36 +312,14 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  
>  static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_subdev *subdev,
> -				   struct v4l2_async_subdev *unused)
> +				   struct v4l2_async_subdev *asd)
>  {
> -	struct xvip_composite_device *xdev =
> -		container_of(notifier, struct xvip_composite_device, notifier);
> -	struct xvip_graph_entity *entity;
> -	struct v4l2_async_subdev *asd;
> +	struct xvip_graph_entity *entity = to_xvip_entity(asd);
>  
> -	/* Locate the entity corresponding to the bound subdev and store the
> -	 * subdev pointer.
> -	 */
> -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> -		entity = to_xvip_entity(asd);
> +	entity->entity = &subdev->entity;
> +	entity->subdev = subdev;
>  
> -		if (entity->asd.match.fwnode != subdev->fwnode)
> -			continue;
> -
> -		if (entity->subdev) {
> -			dev_err(xdev->dev, "duplicate subdev for node %p\n",
> -				entity->asd.match.fwnode);
> -			return -EINVAL;
> -		}
> -
> -		dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name);
> -		entity->entity = &subdev->entity;
> -		entity->subdev = subdev;
> -		return 0;
> -	}
> -
> -	dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name);
> -	return -EINVAL;
> +	return 0;
>  }
>  
>  static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = {

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier
  2023-05-25  9:15 ` [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier Sakari Ailus
@ 2023-05-30  2:23   ` Laurent Pinchart
  2023-06-13 13:19     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:23 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:47PM +0300, Sakari Ailus wrote:
> There's no need to check for a sub-device's notifier as we only register
> one notifier (and one V4L2 device). Remove this check and prepare for
> removing this field in struct v4l2_subdev.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/platform/ti/omap3isp/isp.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
> index f3aaa9e76492e..c2b222f7df892 100644
> --- a/drivers/media/platform/ti/omap3isp/isp.c
> +++ b/drivers/media/platform/ti/omap3isp/isp.c
> @@ -2039,9 +2039,6 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
>  	}
>  
>  	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
> -		if (sd->notifier != &isp->notifier)
> -			continue;

I don't think this is quite right. You could have a chain of external
subdevs, in which case only the one connected directly to the ISP should
be linked to the ISP.

> -
>  		ret = isp_link_entity(isp, &sd->entity,
>  				      v4l2_subdev_to_bus_cfg(sd)->interface);
>  		if (ret < 0) {

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints
  2023-05-25  9:15 ` [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints Sakari Ailus
@ 2023-05-30  2:34   ` Laurent Pinchart
  0 siblings, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:34 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:48PM +0300, Sakari Ailus wrote:
> Just add some debug prints for V4L2 async sub-device matching process.
> These might come useful in figuring out why things don't work as expected.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 71 ++++++++++++++++++++++++----
>  1 file changed, 63 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 7831bc8792904..c5781124337af 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -77,6 +77,17 @@ static bool match_i2c(struct v4l2_async_notifier *notifier,
>  #endif
>  }
>  
> +static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
> +{
> +	if (notifier->sd)
> +		return notifier->sd->dev;
> +
> +	if (notifier->v4l2_dev)
> +		return notifier->v4l2_dev->dev;
> +
> +	return NULL;
> +}
> +
>  static bool
>  match_fwnode_one(struct v4l2_async_notifier *notifier,
>  		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
> @@ -88,13 +99,20 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  	bool sd_fwnode_is_ep;
>  	struct device *dev;
>  
> +	dev_dbg(notifier_dev(notifier),
> +		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
> +		sd_fwnode, asd->match.fwnode);
> +
>  	/*
>  	 * Both the subdev and the async subdev can provide either an endpoint
>  	 * fwnode or a device fwnode. Start with the simple case of direct
>  	 * fwnode matching.
>  	 */
> -	if (sd_fwnode == asd->match.fwnode)
> +	if (sd_fwnode == asd->match.fwnode) {
> +		dev_dbg(notifier_dev(notifier),
> +			"v4l2-async: direct match found\n");
>  		return true;
> +	}
>  
>  	/*
>  	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
> @@ -107,8 +125,11 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
>  	asd_fwnode_is_ep = fwnode_graph_is_endpoint(asd->match.fwnode);
>  
> -	if (sd_fwnode_is_ep == asd_fwnode_is_ep)
> +	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
> +		dev_dbg(notifier_dev(notifier),
> +			"v4l2-async: direct match not found\n");
>  		return false;
> +	}
>  
>  	/*
>  	 * The sd and asd fwnodes are of different types. Get the device fwnode
> @@ -122,10 +143,17 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  		other_fwnode = sd_fwnode;
>  	}
>  
> +	dev_dbg(notifier_dev(notifier),
> +		"v4l2-async: fwnode compat match: need %pfw, trying %pfw\n",
> +		dev_fwnode, other_fwnode);
> +
>  	fwnode_handle_put(dev_fwnode);
>  
> -	if (dev_fwnode != other_fwnode)
> +	if (dev_fwnode != other_fwnode) {
> +		dev_dbg(notifier_dev(notifier),
> +			"v4l2-async: compat match not found\n");
>  		return false;
> +	}
>  
>  	/*
>  	 * We have a heterogeneous match. Retrieve the struct device of the side
> @@ -145,12 +173,18 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  			   dev->driver->name);
>  	}
>  
> +	dev_dbg(notifier_dev(notifier), "v4l2-async: compat match found\n");
> +
>  	return true;
>  }
>  
>  static bool match_fwnode(struct v4l2_async_notifier *notifier,
>  			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
>  {
> +	dev_dbg(notifier_dev(notifier),
> +		"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
> +		dev_fwnode(notifier_dev(notifier)), sd->fwnode);
> +
>  	if (match_fwnode_one(notifier, sd, sd->fwnode, asd))
>  		return true;
>  
> @@ -158,6 +192,9 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
>  	if (IS_ERR_OR_NULL(sd->fwnode->secondary))
>  		return false;
>  
> +	dev_dbg(notifier_dev(notifier),
> +		"v4l2-async: trying secondary fwnode match\n");
> +
>  	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd);
>  }
>  
> @@ -271,22 +308,33 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
>  static int
>  v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>  {
> +	struct v4l2_async_notifier *__notifier = notifier;
> +
>  	/* Quick check whether there are still more sub-devices here. */
>  	if (!list_empty(&notifier->waiting))
>  		return 0;
>  
> +	if (notifier->sd)
> +		dev_dbg(notifier_dev(notifier),
> +			"v4l2-async: trying to complete\n");

I don't understand how the check and the message relate to each other.

Apart from that,

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> +
>  	/* Check the entire notifier tree; find the root notifier first. */
>  	while (notifier->parent)
>  		notifier = notifier->parent;
>  
>  	/* This is root if it has v4l2_dev. */
> -	if (!notifier->v4l2_dev)
> +	if (!notifier->v4l2_dev) {
> +		dev_dbg(notifier_dev(__notifier),
> +			"v4l2-async: V4L2 device not available\n");
>  		return 0;
> +	}
>  
>  	/* Is everything ready? */
>  	if (!v4l2_async_nf_can_complete(notifier))
>  		return 0;
>  
> +	dev_dbg(notifier_dev(__notifier), "v4l2-async: complete\n");
> +
>  	return v4l2_async_nf_call_complete(notifier);
>  }
>  
> @@ -350,6 +398,9 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  	/* Move from the global subdevice list to notifier's done */
>  	list_move(&sd->async_list, &notifier->done);
>  
> +	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
> +		dev_name(sd->dev), ret);
> +
>  	/*
>  	 * See if the sub-device has a notifier. If not, return here.
>  	 */
> @@ -378,6 +429,8 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
>  	if (!v4l2_dev)
>  		return 0;
>  
> +	dev_dbg(notifier_dev(notifier), "v4l2-async: trying all sub-devices\n");
> +
>  again:
>  	list_for_each_entry(sd, &subdev_list, async_list) {
>  		struct v4l2_async_subdev *asd;
> @@ -387,6 +440,9 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
>  		if (!asd)
>  			continue;
>  
> +		dev_dbg(notifier_dev(notifier),
> +			"v4l2-async: match found, subdev %s\n", sd->name);
> +
>  		ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
>  		if (ret < 0)
>  			return ret;
> @@ -496,8 +552,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_async_subdev *asd,
>  				   int this_index)
>  {
> -	struct device *dev =
> -		notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
> +	struct device *dev = notifier_dev(notifier);
>  
>  	if (!asd)
>  		return -EINVAL;
> @@ -506,12 +561,12 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  	case V4L2_ASYNC_MATCH_I2C:
>  	case V4L2_ASYNC_MATCH_FWNODE:
>  		if (v4l2_async_nf_has_async_subdev(notifier, asd, this_index)) {
> -			dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n");
> +			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
>  			return -EEXIST;
>  		}
>  		break;
>  	default:
> -		dev_err(dev, "Invalid match type %u on %p\n",
> +		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
>  			asd->match_type, asd);
>  		return -EINVAL;
>  	}

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs
  2023-05-25  9:15 ` [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs Sakari Ailus
@ 2023-05-30  2:42   ` Laurent Pinchart
  2023-06-13 13:57     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:42 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:49PM +0300, Sakari Ailus wrote:
> There's a need to verify that a single async sub-device isn't being added
> multiple times, this would be an error. This takes place at the time of
> adding the async sub-device to the notifier's list as well as when the
> notifier is added to the global notifier's list.
> 
> Use the pointer to the sub-device for testing this instead of an index to
> an array that is long gone. (There was an array of async sub-devices in
> the notifier before it was converted to a linked list by commit
> 66beb323e4a0 ("media: v4l2: async: Remove notifier subdevs array").

Unbalanced opening and closing parentheses.

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 18 ++++++++----------
>  1 file changed, 8 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index c5781124337af..320fe5cbaaf41 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -520,21 +520,19 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
>  
>  /*
>   * Find out whether an async sub-device was set up already or
> - * whether it exists in a given notifier before @this_index.
> - * If @this_index < 0, search the notifier's entire @asd_list.
> + * whether it exists in a given notifier.

Please document what the skip_self parameter does. The parameter name
doesn't match the 'break' in the test below, I was expecting a
'continue'. If my expectation is wrong documentation should help, if
it's correct, then you can fix the code :-)

>   */
>  static bool
>  v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
> -			       struct v4l2_async_subdev *asd, int this_index)
> +			       struct v4l2_async_subdev *asd, bool skip_self)
>  {
>  	struct v4l2_async_subdev *asd_y;
> -	int j = 0;
>  
>  	lockdep_assert_held(&list_lock);
>  
>  	/* Check that an asd is not being added more than once. */
>  	list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
> -		if (this_index >= 0 && j++ >= this_index)
> +		if (skip_self && asd == asd_y)
>  			break;
>  		if (asd_equal(asd, asd_y))
>  			return true;
> @@ -550,7 +548,7 @@ v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
>  
>  static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_async_subdev *asd,
> -				   int this_index)
> +				   bool skip_self)
>  {
>  	struct device *dev = notifier_dev(notifier);
>  
> @@ -560,7 +558,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  	switch (asd->match_type) {
>  	case V4L2_ASYNC_MATCH_I2C:
>  	case V4L2_ASYNC_MATCH_FWNODE:
> -		if (v4l2_async_nf_has_async_subdev(notifier, asd, this_index)) {
> +		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
>  			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
>  			return -EEXIST;
>  		}
> @@ -583,7 +581,7 @@ EXPORT_SYMBOL(v4l2_async_nf_init);
>  static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  {
>  	struct v4l2_async_subdev *asd;
> -	int ret, i = 0;
> +	int ret;
>  
>  	INIT_LIST_HEAD(&notifier->waiting);
>  	INIT_LIST_HEAD(&notifier->done);
> @@ -591,7 +589,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	mutex_lock(&list_lock);
>  
>  	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> -		ret = v4l2_async_nf_asd_valid(notifier, asd, i++);
> +		ret = v4l2_async_nf_asd_valid(notifier, asd, true);
>  		if (ret)
>  			goto err_unlock;
>  
> @@ -725,7 +723,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
>  
>  	mutex_lock(&list_lock);
>  
> -	ret = v4l2_async_nf_asd_valid(notifier, asd, -1);
> +	ret = v4l2_async_nf_asd_valid(notifier, asd, false);
>  	if (ret)
>  		goto unlock;
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation
  2023-05-25  9:15 ` [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation Sakari Ailus
@ 2023-05-30  2:46   ` Laurent Pinchart
  2023-06-13 14:00     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:46 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:50PM +0300, Sakari Ailus wrote:
> The list entry is initialised as a head in v4l2_async_register_subdev()
> just before being added to the list. This isn't needed, drop the
> initialisation.

Is this really unneeded ? Before the initialization and the list_add()
call there are a few code paths that can access the async_list. For
instance, the error path calls v4l2_async_cleanup(), which calls

	list_del_init(&sd->async_list);

That won't work well on an uninitialized (or zero-initialized)
list_head.

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 320fe5cbaaf41..aef9a16e892ef 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -823,8 +823,6 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
>  
>  	mutex_lock(&list_lock);
>  
> -	INIT_LIST_HEAD(&sd->async_list);
> -
>  	list_for_each_entry(notifier, &notifier_list, list) {
>  		struct v4l2_device *v4l2_dev =
>  			v4l2_async_nf_find_v4l2_dev(notifier);

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check
  2023-05-25  9:15 ` [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check Sakari Ailus
@ 2023-05-30  2:48   ` Laurent Pinchart
  0 siblings, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:48 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:51PM +0300, Sakari Ailus wrote:
> The callers do pass a non-NULL asd to v4l2_async_nf_asd_valid() already.
> There's no need for the NULL check here.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> ---
>  drivers/media/v4l2-core/v4l2-async.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index aef9a16e892ef..7c924faac4c10 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -552,9 +552,6 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  {
>  	struct device *dev = notifier_dev(notifier);
>  
> -	if (!asd)
> -		return -EINVAL;
> -
>  	switch (asd->match_type) {
>  	case V4L2_ASYNC_MATCH_I2C:
>  	case V4L2_ASYNC_MATCH_FWNODE:

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct
  2023-05-25  9:15 ` [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct Sakari Ailus
@ 2023-05-30  2:52   ` Laurent Pinchart
  2023-06-13 14:35     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:52 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:52PM +0300, Sakari Ailus wrote:
> Make V4L2 async match information a struct, making it easier to use it
> elsewhere outside the scope of struct v4l2_async_subdev.
> 
> Also remove an obsolete comment --- none of these fields are supposed to
> be touched by drivers.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 20 +++++++-------
>  include/media/v4l2-async.h           | 41 ++++++++++++++++------------
>  2 files changed, 33 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 7c924faac4c10..7f56648e40c44 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -212,7 +212,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  
>  	list_for_each_entry(asd, &notifier->waiting, list) {
>  		/* bus_type has been verified valid before */
> -		switch (asd->match_type) {
> +		switch (asd->match.type) {
>  		case V4L2_ASYNC_MATCH_I2C:
>  			match = match_i2c;
>  			break;
> @@ -237,10 +237,10 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  static bool asd_equal(struct v4l2_async_subdev *asd_x,
>  		      struct v4l2_async_subdev *asd_y)
>  {
> -	if (asd_x->match_type != asd_y->match_type)
> +	if (asd_x->match.type != asd_y->match.type)
>  		return false;
>  
> -	switch (asd_x->match_type) {
> +	switch (asd_x->match.type) {
>  	case V4L2_ASYNC_MATCH_I2C:
>  		return asd_x->match.i2c.adapter_id ==
>  			asd_y->match.i2c.adapter_id &&
> @@ -552,7 +552,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  {
>  	struct device *dev = notifier_dev(notifier);
>  
> -	switch (asd->match_type) {
> +	switch (asd->match.type) {
>  	case V4L2_ASYNC_MATCH_I2C:
>  	case V4L2_ASYNC_MATCH_FWNODE:
>  		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
> @@ -561,8 +561,8 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  		}
>  		break;
>  	default:
> -		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
> -			asd->match_type, asd);
> +		dev_err(dev, "v4l2-asymc: Invalid match type %u on %p\n",

Is this for asymmetrical notification ?

With this fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> +			asd->match.type, asd);
>  		return -EINVAL;
>  	}
>  
> @@ -688,7 +688,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  		return;
>  
>  	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
> -		switch (asd->match_type) {
> +		switch (asd->match.type) {
>  		case V4L2_ASYNC_MATCH_FWNODE:
>  			fwnode_handle_put(asd->match.fwnode);
>  			break;
> @@ -743,7 +743,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
>  	if (!asd)
>  		return ERR_PTR(-ENOMEM);
>  
> -	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> +	asd->match.type = V4L2_ASYNC_MATCH_FWNODE;
>  	asd->match.fwnode = fwnode_handle_get(fwnode);
>  
>  	ret = __v4l2_async_nf_add_subdev(notifier, asd);
> @@ -790,7 +790,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
>  	if (!asd)
>  		return ERR_PTR(-ENOMEM);
>  
> -	asd->match_type = V4L2_ASYNC_MATCH_I2C;
> +	asd->match.type = V4L2_ASYNC_MATCH_I2C;
>  	asd->match.i2c.adapter_id = adapter_id;
>  	asd->match.i2c.address = address;
>  
> @@ -901,7 +901,7 @@ EXPORT_SYMBOL(v4l2_async_unregister_subdev);
>  static void print_waiting_subdev(struct seq_file *s,
>  				 struct v4l2_async_subdev *asd)
>  {
> -	switch (asd->match_type) {
> +	switch (asd->match.type) {
>  	case V4L2_ASYNC_MATCH_I2C:
>  		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
>  			   asd->match.i2c.address);
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 2c9baa3c9266a..d347ef32f4ecb 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -34,23 +34,37 @@ enum v4l2_async_match_type {
>  };
>  
>  /**
> - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> + * struct v4l2_async_match_desc - async sub-device match information
>   *
> - * @match_type:	type of match that will be used
> - * @match:	union of per-bus type matching data sets
> - * @match.fwnode:
> - *		pointer to &struct fwnode_handle to be matched.
> + * @type:	type of match that will be used
> + * @fwnode:	pointer to &struct fwnode_handle to be matched.
>   *		Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
> - * @match.i2c:	embedded struct with I2C parameters to be matched.
> + * @i2c:	embedded struct with I2C parameters to be matched.
>   *		Both @match.i2c.adapter_id and @match.i2c.address
>   *		should be matched.
>   *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> - * @match.i2c.adapter_id:
> + * @i2c.adapter_id:
>   *		I2C adapter ID to be matched.
>   *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> - * @match.i2c.address:
> + * @i2c.address:
>   *		I2C address to be matched.
>   *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> + */
> +struct v4l2_async_match_desc {
> +	enum v4l2_async_match_type type;
> +	union {
> +		struct fwnode_handle *fwnode;
> +		struct {
> +			int adapter_id;
> +			unsigned short address;
> +		} i2c;
> +	};
> +};
> +
> +/**
> + * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> + *
> + * @match:	struct of match type and per-bus type matching data sets
>   * @asd_list:	used to add struct v4l2_async_subdev objects to the
>   *		master notifier @asd_list
>   * @list:	used to link struct v4l2_async_subdev objects, waiting to be
> @@ -61,16 +75,7 @@ enum v4l2_async_match_type {
>   * v4l2_async_subdev as its first member.
>   */
>  struct v4l2_async_subdev {
> -	enum v4l2_async_match_type match_type;
> -	union {
> -		struct fwnode_handle *fwnode;
> -		struct {
> -			int adapter_id;
> -			unsigned short address;
> -		} i2c;
> -	} match;
> -
> -	/* v4l2-async core private: not to be used by drivers */
> +	struct v4l2_async_match_desc match;
>  	struct list_head list;
>  	struct list_head asd_list;
>  };

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_
  2023-05-25  9:15 ` [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ Sakari Ailus
@ 2023-05-30  2:55   ` Laurent Pinchart
  0 siblings, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  2:55 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:53PM +0300, Sakari Ailus wrote:
> The async match type is a struct field now, rename V4L2_ASYNC_MATCH_*
> macros as V4L2_ASYNC_MATCH_TYPE_* instead.
> 
> This patch has been produced by:
> 
> git grep -l V4L2_ASYNC_MATCH_ -- drivers/media/ drivers/staging/media/ \
> 	include/ Documentation/|xargs perl -i -pe \
> 	's/V4L2_ASYNC_MATCH_\K/TYPE_/g'
> 
> so it must be correct.

I was really hoping to prove you wrong here :-)

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> ---
>  drivers/media/v4l2-core/v4l2-async.c | 22 +++++++++++-----------
>  include/media/v4l2-async.h           | 16 ++++++++--------
>  2 files changed, 19 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 7f56648e40c44..93234c316aa6e 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -213,10 +213,10 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  	list_for_each_entry(asd, &notifier->waiting, list) {
>  		/* bus_type has been verified valid before */
>  		switch (asd->match.type) {
> -		case V4L2_ASYNC_MATCH_I2C:
> +		case V4L2_ASYNC_MATCH_TYPE_I2C:
>  			match = match_i2c;
>  			break;
> -		case V4L2_ASYNC_MATCH_FWNODE:
> +		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  			match = match_fwnode;
>  			break;
>  		default:
> @@ -241,12 +241,12 @@ static bool asd_equal(struct v4l2_async_subdev *asd_x,
>  		return false;
>  
>  	switch (asd_x->match.type) {
> -	case V4L2_ASYNC_MATCH_I2C:
> +	case V4L2_ASYNC_MATCH_TYPE_I2C:
>  		return asd_x->match.i2c.adapter_id ==
>  			asd_y->match.i2c.adapter_id &&
>  			asd_x->match.i2c.address ==
>  			asd_y->match.i2c.address;
> -	case V4L2_ASYNC_MATCH_FWNODE:
> +	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  		return asd_x->match.fwnode == asd_y->match.fwnode;
>  	default:
>  		break;
> @@ -553,8 +553,8 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
>  	struct device *dev = notifier_dev(notifier);
>  
>  	switch (asd->match.type) {
> -	case V4L2_ASYNC_MATCH_I2C:
> -	case V4L2_ASYNC_MATCH_FWNODE:
> +	case V4L2_ASYNC_MATCH_TYPE_I2C:
> +	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
>  			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
>  			return -EEXIST;
> @@ -689,7 +689,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  
>  	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
>  		switch (asd->match.type) {
> -		case V4L2_ASYNC_MATCH_FWNODE:
> +		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  			fwnode_handle_put(asd->match.fwnode);
>  			break;
>  		default:
> @@ -743,7 +743,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
>  	if (!asd)
>  		return ERR_PTR(-ENOMEM);
>  
> -	asd->match.type = V4L2_ASYNC_MATCH_FWNODE;
> +	asd->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
>  	asd->match.fwnode = fwnode_handle_get(fwnode);
>  
>  	ret = __v4l2_async_nf_add_subdev(notifier, asd);
> @@ -790,7 +790,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
>  	if (!asd)
>  		return ERR_PTR(-ENOMEM);
>  
> -	asd->match.type = V4L2_ASYNC_MATCH_I2C;
> +	asd->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
>  	asd->match.i2c.adapter_id = adapter_id;
>  	asd->match.i2c.address = address;
>  
> @@ -902,11 +902,11 @@ static void print_waiting_subdev(struct seq_file *s,
>  				 struct v4l2_async_subdev *asd)
>  {
>  	switch (asd->match.type) {
> -	case V4L2_ASYNC_MATCH_I2C:
> +	case V4L2_ASYNC_MATCH_TYPE_I2C:
>  		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
>  			   asd->match.i2c.address);
>  		break;
> -	case V4L2_ASYNC_MATCH_FWNODE: {
> +	case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
>  		struct fwnode_handle *devnode, *fwnode = asd->match.fwnode;
>  
>  		devnode = fwnode_graph_is_endpoint(fwnode) ?
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index d347ef32f4ecb..8d1506a9755c3 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -22,15 +22,15 @@ struct v4l2_async_notifier;
>   * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
>   *	in order to identify a match
>   *
> - * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address
> - * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node
> + * @V4L2_ASYNC_MATCH_TYPE_I2C: Match will check for I2C adapter ID and address
> + * @V4L2_ASYNC_MATCH_TYPE_FWNODE: Match will use firmware node
>   *
>   * This enum is used by the asynchronous sub-device logic to define the
>   * algorithm that will be used to match an asynchronous device.
>   */
>  enum v4l2_async_match_type {
> -	V4L2_ASYNC_MATCH_I2C,
> -	V4L2_ASYNC_MATCH_FWNODE,
> +	V4L2_ASYNC_MATCH_TYPE_I2C,
> +	V4L2_ASYNC_MATCH_TYPE_FWNODE,
>  };
>  
>  /**
> @@ -38,17 +38,17 @@ enum v4l2_async_match_type {
>   *
>   * @type:	type of match that will be used
>   * @fwnode:	pointer to &struct fwnode_handle to be matched.
> - *		Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
> + *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_FWNODE.
>   * @i2c:	embedded struct with I2C parameters to be matched.
>   *		Both @match.i2c.adapter_id and @match.i2c.address
>   *		should be matched.
> - *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> + *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
>   * @i2c.adapter_id:
>   *		I2C adapter ID to be matched.
> - *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> + *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
>   * @i2c.address:
>   *		I2C address to be matched.
> - *		Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
> + *		Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C.
>   */
>  struct v4l2_async_match_desc {
>  	enum v4l2_async_match_type type;

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation
  2023-05-25  9:15 ` [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation Sakari Ailus
@ 2023-05-30  3:02   ` Laurent Pinchart
  2023-06-13 14:37     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  3:02 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:54PM +0300, Sakari Ailus wrote:
> Pass only information required for sub-device matching to functions
> checking whether the async sub-device already exists. Do the same for
> debug message printing. This makes further changes to other aspects of
> async sub-devices easier.
> 
> Accordingly, also perform further renames:
> 
> 	asd_equal as v4l2_async_match_equal,
> 	v4l2_async_nf_has_async_subdev as v4l2_async_nf_has_async_match,
> 	__v4l2_async_nf_has_async_subdev as
> 		v4l2_async_nf_has_async_subdev_entry and
> 	v4l2_async_nf_asd_valid as v4l2_async_nf_match_valid.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 109 ++++++++++++++-------------
>  1 file changed, 56 insertions(+), 53 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 93234c316aa6e..5eb9850f1c6c4 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -64,14 +64,15 @@ static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n,
>  }
>  
>  static bool match_i2c(struct v4l2_async_notifier *notifier,
> -		      struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
> +		      struct v4l2_subdev *sd,
> +		      struct v4l2_async_match_desc *match)
>  {
>  #if IS_ENABLED(CONFIG_I2C)
>  	struct i2c_client *client = i2c_verify_client(sd->dev);
>  
>  	return client &&
> -		asd->match.i2c.adapter_id == client->adapter->nr &&
> -		asd->match.i2c.address == client->addr;
> +		match->i2c.adapter_id == client->adapter->nr &&
> +		match->i2c.address == client->addr;
>  #else
>  	return false;
>  #endif
> @@ -91,7 +92,7 @@ static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
>  static bool
>  match_fwnode_one(struct v4l2_async_notifier *notifier,
>  		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
> -		 struct v4l2_async_subdev *asd)
> +		 struct v4l2_async_match_desc *match)
>  {
>  	struct fwnode_handle *other_fwnode;
>  	struct fwnode_handle *dev_fwnode;
> @@ -101,14 +102,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  
>  	dev_dbg(notifier_dev(notifier),
>  		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
> -		sd_fwnode, asd->match.fwnode);
> +		sd_fwnode, match->fwnode);
>  
>  	/*
>  	 * Both the subdev and the async subdev can provide either an endpoint
>  	 * fwnode or a device fwnode. Start with the simple case of direct
>  	 * fwnode matching.
>  	 */
> -	if (sd_fwnode == asd->match.fwnode) {
> +	if (sd_fwnode == match->fwnode) {
>  		dev_dbg(notifier_dev(notifier),
>  			"v4l2-async: direct match found\n");
>  		return true;
> @@ -123,7 +124,7 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  	 * match unconnected endpoints.
>  	 */
>  	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
> -	asd_fwnode_is_ep = fwnode_graph_is_endpoint(asd->match.fwnode);
> +	asd_fwnode_is_ep = fwnode_graph_is_endpoint(match->fwnode);
>  
>  	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
>  		dev_dbg(notifier_dev(notifier),
> @@ -137,9 +138,9 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  	 */
>  	if (sd_fwnode_is_ep) {
>  		dev_fwnode = fwnode_graph_get_port_parent(sd_fwnode);
> -		other_fwnode = asd->match.fwnode;
> +		other_fwnode = match->fwnode;
>  	} else {
> -		dev_fwnode = fwnode_graph_get_port_parent(asd->match.fwnode);
> +		dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
>  		other_fwnode = sd_fwnode;
>  	}
>  
> @@ -179,13 +180,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  }
>  
>  static bool match_fwnode(struct v4l2_async_notifier *notifier,
> -			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
> +			 struct v4l2_subdev *sd,
> +			 struct v4l2_async_match_desc *match)
>  {
>  	dev_dbg(notifier_dev(notifier),
>  		"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
>  		dev_fwnode(notifier_dev(notifier)), sd->fwnode);
>  
> -	if (match_fwnode_one(notifier, sd, sd->fwnode, asd))
> +	if (match_fwnode_one(notifier, sd, sd->fwnode, match))
>  		return true;
>  
>  	/* Also check the secondary fwnode. */
> @@ -195,7 +197,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
>  	dev_dbg(notifier_dev(notifier),
>  		"v4l2-async: trying secondary fwnode match\n");
>  
> -	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd);
> +	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, match);
>  }
>  
>  static LIST_HEAD(subdev_list);
> @@ -207,7 +209,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  		      struct v4l2_subdev *sd)
>  {
>  	bool (*match)(struct v4l2_async_notifier *notifier,
> -		      struct v4l2_subdev *sd, struct v4l2_async_subdev *asd);
> +		      struct v4l2_subdev *sd,
> +		      struct v4l2_async_match_desc *match);
>  	struct v4l2_async_subdev *asd;
>  
>  	list_for_each_entry(asd, &notifier->waiting, list) {
> @@ -226,7 +229,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  		}
>  
>  		/* match cannot be NULL here */
> -		if (match(notifier, sd, asd))
> +		if (match(notifier, sd, &asd->match))
>  			return asd;
>  	}
>  
> @@ -234,20 +237,18 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  }
>  
>  /* Compare two async sub-device descriptors for equivalence */

s/sub-device/match/ ?

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> -static bool asd_equal(struct v4l2_async_subdev *asd_x,
> -		      struct v4l2_async_subdev *asd_y)
> +static bool v4l2_async_match_equal(struct v4l2_async_match_desc *match1,
> +				   struct v4l2_async_match_desc *match2)
>  {
> -	if (asd_x->match.type != asd_y->match.type)
> +	if (match1->type != match2->type)
>  		return false;
>  
> -	switch (asd_x->match.type) {
> +	switch (match1->type) {
>  	case V4L2_ASYNC_MATCH_TYPE_I2C:
> -		return asd_x->match.i2c.adapter_id ==
> -			asd_y->match.i2c.adapter_id &&
> -			asd_x->match.i2c.address ==
> -			asd_y->match.i2c.address;
> +		return match1->i2c.adapter_id == match2->i2c.adapter_id &&
> +			match1->i2c.address == match2->i2c.address;
>  	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
> -		return asd_x->match.fwnode == asd_y->match.fwnode;
> +		return match1->fwnode == match2->fwnode;
>  	default:
>  		break;
>  	}
> @@ -497,21 +498,21 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
>  
>  /* See if an async sub-device can be found in a notifier's lists. */
>  static bool
> -__v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
> -				 struct v4l2_async_subdev *asd)
> +v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
> +				    struct v4l2_async_match_desc *match)
>  {
> -	struct v4l2_async_subdev *asd_y;
> +	struct v4l2_async_subdev *asd;
>  	struct v4l2_subdev *sd;
>  
> -	list_for_each_entry(asd_y, &notifier->waiting, list)
> -		if (asd_equal(asd, asd_y))
> +	list_for_each_entry(asd, &notifier->waiting, list)
> +		if (v4l2_async_match_equal(&asd->match, match))
>  			return true;
>  
>  	list_for_each_entry(sd, &notifier->done, async_list) {
>  		if (WARN_ON(!sd->asd))
>  			continue;
>  
> -		if (asd_equal(asd, sd->asd))
> +		if (v4l2_async_match_equal(&sd->asd->match, match))
>  			return true;
>  	}
>  
> @@ -523,46 +524,48 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
>   * whether it exists in a given notifier.
>   */
>  static bool
> -v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
> -			       struct v4l2_async_subdev *asd, bool skip_self)
> +v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> +			      struct v4l2_async_match_desc *match,
> +			      bool skip_self)
>  {
> -	struct v4l2_async_subdev *asd_y;
> +	struct v4l2_async_subdev *asd;
>  
>  	lockdep_assert_held(&list_lock);
>  
>  	/* Check that an asd is not being added more than once. */
> -	list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
> -		if (skip_self && asd == asd_y)
> +	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> +		if (skip_self && &asd->match == match)
>  			break;
> -		if (asd_equal(asd, asd_y))
> +		if (v4l2_async_match_equal(&asd->match, match))
>  			return true;
>  	}
>  
>  	/* Check that an asd does not exist in other notifiers. */
>  	list_for_each_entry(notifier, &notifier_list, list)
> -		if (__v4l2_async_nf_has_async_subdev(notifier, asd))
> +		if (v4l2_async_nf_has_async_match_entry(notifier, match))
>  			return true;
>  
>  	return false;
>  }
>  
> -static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
> -				   struct v4l2_async_subdev *asd,
> -				   bool skip_self)
> +static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
> +				     struct v4l2_async_match_desc *match,
> +				     bool skip_self)
>  {
>  	struct device *dev = notifier_dev(notifier);
>  
> -	switch (asd->match.type) {
> +	switch (match->type) {
>  	case V4L2_ASYNC_MATCH_TYPE_I2C:
>  	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
> -		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
> -			dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n");
> +		if (v4l2_async_nf_has_async_match(notifier, match,
> +						  skip_self)) {
> +			dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
>  			return -EEXIST;
>  		}
>  		break;
>  	default:
> -		dev_err(dev, "v4l2-asymc: Invalid match type %u on %p\n",
> -			asd->match.type, asd);
> +		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
> +			match->type, match);
>  		return -EINVAL;
>  	}
>  
> @@ -586,7 +589,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	mutex_lock(&list_lock);
>  
>  	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> -		ret = v4l2_async_nf_asd_valid(notifier, asd, true);
> +		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
>  		if (ret)
>  			goto err_unlock;
>  
> @@ -720,7 +723,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
>  
>  	mutex_lock(&list_lock);
>  
> -	ret = v4l2_async_nf_asd_valid(notifier, asd, false);
> +	ret = v4l2_async_nf_match_valid(notifier, &asd->match, false);
>  	if (ret)
>  		goto unlock;
>  
> @@ -898,16 +901,16 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
>  }
>  EXPORT_SYMBOL(v4l2_async_unregister_subdev);
>  
> -static void print_waiting_subdev(struct seq_file *s,
> -				 struct v4l2_async_subdev *asd)
> +static void print_waiting_match(struct seq_file *s,
> +				struct v4l2_async_match_desc *match)
>  {
> -	switch (asd->match.type) {
> +	switch (match->type) {
>  	case V4L2_ASYNC_MATCH_TYPE_I2C:
> -		seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id,
> -			   asd->match.i2c.address);
> +		seq_printf(s, " [i2c] dev=%d-%04x\n", match->i2c.adapter_id,
> +			   match->i2c.address);
>  		break;
>  	case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
> -		struct fwnode_handle *devnode, *fwnode = asd->match.fwnode;
> +		struct fwnode_handle *devnode, *fwnode = match->fwnode;
>  
>  		devnode = fwnode_graph_is_endpoint(fwnode) ?
>  			  fwnode_graph_get_port_parent(fwnode) :
> @@ -944,7 +947,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
>  	list_for_each_entry(notif, &notifier_list, list) {
>  		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
>  		list_for_each_entry(asd, &notif->waiting, list)
> -			print_waiting_subdev(s, asd);
> +			print_waiting_match(s, &asd->match);
>  	}
>  
>  	mutex_unlock(&list_lock);

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries
  2023-05-25  9:15 ` [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries Sakari Ailus
@ 2023-05-30  3:09   ` Laurent Pinchart
  2023-05-30  5:40     ` Laurent Pinchart
  2023-06-13 14:51     ` Sakari Ailus
  0 siblings, 2 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  3:09 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:55PM +0300, Sakari Ailus wrote:
> The naming of list heads and list entries is confusing as they're named
> similarly. Use _list for list head and _entry for list entries.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  2 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c   |  6 +--
>  drivers/media/v4l2-core/v4l2-async.c          | 54 +++++++++----------
>  drivers/staging/media/tegra-video/vi.c        |  4 +-
>  include/media/v4l2-async.h                    | 36 ++++++-------
>  include/media/v4l2-subdev.h                   |  2 +-
>  6 files changed, 52 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 3c84cb1216320..9231d6a65f4ec 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
>  	unsigned int pad;
>  	int ret;
>  
> -	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) {
>  		s_asd = to_sensor_asd(asd);
>  		q = &cio2->queue[s_asd->csi2.port];
>  
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index b309af0c83749..52c5a7decf284 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
>  	struct xvip_graph_entity *entity;
>  	struct v4l2_async_subdev *asd;
>  
> -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
>  		entity = to_xvip_entity(asd);
>  		if (entity->asd.match.fwnode == fwnode)
>  			return entity;
> @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
>  
>  	/* Create links for every entity. */
> -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
>  		entity = to_xvip_entity(asd);
>  		ret = xvip_graph_build_one(xdev, entity);
>  		if (ret < 0)
> @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
>  	if (ret < 0)
>  		return 0;
>  
> -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
>  		entity = to_xvip_entity(asd);
>  		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
>  		if (ret < 0) {
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 5eb9850f1c6c4..06b1e1a1a5f87 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -213,7 +213,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  		      struct v4l2_async_match_desc *match);
>  	struct v4l2_async_subdev *asd;
>  
> -	list_for_each_entry(asd, &notifier->waiting, list) {
> +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry) {
>  		/* bus_type has been verified valid before */
>  		switch (asd->match.type) {
>  		case V4L2_ASYNC_MATCH_TYPE_I2C:
> @@ -262,7 +262,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
>  {
>  	struct v4l2_async_notifier *n;
>  
> -	list_for_each_entry(n, &notifier_list, list)
> +	list_for_each_entry(n, &notifier_list, notifier_entry)
>  		if (n->sd == sd)
>  			return n;
>  
> @@ -287,10 +287,10 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
>  {
>  	struct v4l2_subdev *sd;
>  
> -	if (!list_empty(&notifier->waiting))
> +	if (!list_empty(&notifier->waiting_list))
>  		return false;
>  
> -	list_for_each_entry(sd, &notifier->done, async_list) {
> +	list_for_each_entry(sd, &notifier->done_list, async_list) {
>  		struct v4l2_async_notifier *subdev_notifier =
>  			v4l2_async_find_subdev_notifier(sd);
>  
> @@ -312,7 +312,7 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>  	struct v4l2_async_notifier *__notifier = notifier;
>  
>  	/* Quick check whether there are still more sub-devices here. */
> -	if (!list_empty(&notifier->waiting))
> +	if (!list_empty(&notifier->waiting_list))
>  		return 0;
>  
>  	if (notifier->sd)
> @@ -391,13 +391,12 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  		return ret;
>  	}
>  
> -	/* Remove from the waiting list */
> -	list_del(&asd->list);
> +	list_del(&asd->waiting_entry);
>  	sd->asd = asd;
>  	sd->notifier = notifier;
>  
>  	/* Move from the global subdevice list to notifier's done */
> -	list_move(&sd->async_list, &notifier->done);
> +	list_move(&sd->async_list, &notifier->done_list);
>  
>  	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
>  		dev_name(sd->dev), ret);
> @@ -478,7 +477,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
>  {
>  	struct v4l2_subdev *sd, *tmp;
>  
> -	list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
> +	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
>  		struct v4l2_async_notifier *subdev_notifier =
>  			v4l2_async_find_subdev_notifier(sd);
>  
> @@ -487,7 +486,8 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
>  
>  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
>  		if (readd)
> -			list_add_tail(&sd->asd->list, &notifier->waiting);
> +			list_add_tail(&sd->asd->waiting_entry,
> +				      &notifier->waiting_list);
>  		v4l2_async_cleanup(sd);
>  
>  		list_move(&sd->async_list, &subdev_list);
> @@ -504,11 +504,11 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
>  	struct v4l2_async_subdev *asd;
>  	struct v4l2_subdev *sd;
>  
> -	list_for_each_entry(asd, &notifier->waiting, list)
> +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry)
>  		if (v4l2_async_match_equal(&asd->match, match))
>  			return true;
>  
> -	list_for_each_entry(sd, &notifier->done, async_list) {
> +	list_for_each_entry(sd, &notifier->done_list, async_list) {
>  		if (WARN_ON(!sd->asd))
>  			continue;
>  
> @@ -533,7 +533,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
>  	lockdep_assert_held(&list_lock);
>  
>  	/* Check that an asd is not being added more than once. */
> -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
>  		if (skip_self && &asd->match == match)
>  			break;
>  		if (v4l2_async_match_equal(&asd->match, match))
> @@ -541,7 +541,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
>  	}
>  
>  	/* Check that an asd does not exist in other notifiers. */
> -	list_for_each_entry(notifier, &notifier_list, list)
> +	list_for_each_entry(notifier, &notifier_list, notifier_entry)
>  		if (v4l2_async_nf_has_async_match_entry(notifier, match))
>  			return true;
>  
> @@ -583,17 +583,17 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	struct v4l2_async_subdev *asd;
>  	int ret;
>  
> -	INIT_LIST_HEAD(&notifier->waiting);
> -	INIT_LIST_HEAD(&notifier->done);
> +	INIT_LIST_HEAD(&notifier->waiting_list);
> +	INIT_LIST_HEAD(&notifier->done_list);
>  
>  	mutex_lock(&list_lock);
>  
> -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
>  		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
>  		if (ret)
>  			goto err_unlock;
>  
> -		list_add_tail(&asd->list, &notifier->waiting);
> +		list_add_tail(&asd->waiting_entry, &notifier->waiting_list);
>  	}
>  
>  	ret = v4l2_async_nf_try_all_subdevs(notifier);
> @@ -605,7 +605,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  		goto err_unbind;
>  
>  	/* Keep also completed notifiers on the list */
> -	list_add(&notifier->list, &notifier_list);
> +	list_add(&notifier->notifier_entry, &notifier_list);
>  
>  	mutex_unlock(&list_lock);
>  
> @@ -670,7 +670,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
>  	notifier->sd = NULL;
>  	notifier->v4l2_dev = NULL;
>  
> -	list_del(&notifier->list);
> +	list_del(&notifier->notifier_entry);
>  }
>  
>  void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
> @@ -690,7 +690,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  	if (!notifier || !notifier->asd_list.next)
>  		return;
>  
> -	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
> +	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_entry) {
>  		switch (asd->match.type) {
>  		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  			fwnode_handle_put(asd->match.fwnode);
> @@ -699,7 +699,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  			break;
>  		}
>  
> -		list_del(&asd->asd_list);
> +		list_del(&asd->asd_entry);
>  		v4l2_async_nf_call_destroy(notifier, asd);
>  		kfree(asd);
>  	}
> @@ -727,7 +727,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
>  	if (ret)
>  		goto unlock;
>  
> -	list_add_tail(&asd->asd_list, &notifier->asd_list);
> +	list_add_tail(&asd->asd_entry, &notifier->asd_list);
>  
>  unlock:
>  	mutex_unlock(&list_lock);
> @@ -823,7 +823,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
>  
>  	mutex_lock(&list_lock);
>  
> -	list_for_each_entry(notifier, &notifier_list, list) {
> +	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
>  		struct v4l2_device *v4l2_dev =
>  			v4l2_async_nf_find_v4l2_dev(notifier);
>  		struct v4l2_async_subdev *asd;
> @@ -890,7 +890,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
>  	if (sd->asd) {
>  		struct v4l2_async_notifier *notifier = sd->notifier;
>  
> -		list_add(&sd->asd->list, &notifier->waiting);
> +		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
>  
>  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
>  	}
> @@ -944,9 +944,9 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
>  
>  	mutex_lock(&list_lock);
>  
> -	list_for_each_entry(notif, &notifier_list, list) {
> +	list_for_each_entry(notif, &notifier_list, notifier_entry) {
>  		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
> -		list_for_each_entry(asd, &notif->waiting, list)
> +		list_for_each_entry(asd, &notif->waiting_list, waiting_entry)
>  			print_waiting_match(s, &asd->match);
>  	}
>  
> diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
> index 2f1aff7e87170..350871f34f7cc 100644
> --- a/drivers/staging/media/tegra-video/vi.c
> +++ b/drivers/staging/media/tegra-video/vi.c
> @@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
>  	struct tegra_vi_graph_entity *entity;
>  	struct v4l2_async_subdev *asd;
>  
> -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
>  		entity = to_tegra_vi_graph_entity(asd);
>  		if (entity->asd.match.fwnode == fwnode)
>  			return entity;
> @@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  	}
>  
>  	/* create links between the entities */
> -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
>  		entity = to_tegra_vi_graph_entity(asd);
>  		ret = tegra_vi_graph_build(chan, entity);
>  		if (ret < 0)
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 8d1506a9755c3..54f9f45ed3d8e 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -65,10 +65,10 @@ struct v4l2_async_match_desc {
>   * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
>   *
>   * @match:	struct of match type and per-bus type matching data sets
> - * @asd_list:	used to add struct v4l2_async_subdev objects to the
> - *		master notifier @asd_list
> - * @list:	used to link struct v4l2_async_subdev objects, waiting to be
> - *		probed, to a notifier->waiting list
> + * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> + *		master notifier @asd_entry

I think you mean 'master notifier @asd_list' here.

> + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> + *		probed, to a notifier->waiting_list list
>   *
>   * When this struct is used as a member in a driver specific struct,
>   * the driver specific struct shall contain the &struct
> @@ -76,8 +76,8 @@ struct v4l2_async_match_desc {
>   */
>  struct v4l2_async_subdev {
>  	struct v4l2_async_match_desc match;
> -	struct list_head list;
> -	struct list_head asd_list;
> +	struct list_head asd_entry;
> +	struct list_head waiting_entry;
>  };
>  
>  /**
> @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations {
>   * @sd:		sub-device that registered the notifier, NULL otherwise
>   * @parent:	parent notifier
>   * @asd_list:	master list of struct v4l2_async_subdev
> - * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
> - * @done:	list of struct v4l2_subdev, already probed
> - * @list:	member in a global list of notifiers
> + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
> + * @done_list:	list of struct v4l2_subdev, already probed
> + * @notifier_entry: member in a global list of notifiers
>   */
>  struct v4l2_async_notifier {
>  	const struct v4l2_async_notifier_operations *ops;
> @@ -117,9 +117,9 @@ struct v4l2_async_notifier {
>  	struct v4l2_subdev *sd;
>  	struct v4l2_async_notifier *parent;
>  	struct list_head asd_list;
> -	struct list_head waiting;
> -	struct list_head done;
> -	struct list_head list;
> +	struct list_head waiting_list;
> +	struct list_head done_list;
> +	struct list_head notifier_entry;
>  };
>  
>  /**
> @@ -134,7 +134,7 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   *
> - * This function initializes the notifier @asd_list. It must be called
> + * This function initializes the notifier @asd_entry. It must be called
>   * before adding a subdevice to a notifier, using one of:
>   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
>   * v4l2_async_nf_add_i2c().
> @@ -147,7 +147,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
>  			   unsigned int asd_struct_size);
>  /**
>   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> - *				subdev to the notifier's master asd_list.
> + *				subdev to the notifier's master asd_entry.
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
> @@ -157,7 +157,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
>   *	  sub-device struct, i.e. both begin at the same memory address.
>   *
>   * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> - * notifiers @asd_list. The function also gets a reference of the fwnode which
> + * notifiers @asd_entry. The function also gets a reference of the fwnode which
>   * is released later at notifier cleanup time.
>   */
>  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
> @@ -170,7 +170,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
>  /**
>   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
>   *						  remote async subdev to the
> - *						  notifier's master asd_list.
> + *						  notifier's master asd_entry.
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @ep: local endpoint pointing to the remote sub-device to be matched,
> @@ -180,7 +180,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
>   *	  sub-device struct, i.e. both begin at the same memory address.
>   *
>   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> - * matching and adds the async sub-device to the notifier's @asd_list. The
> + * matching and adds the async sub-device to the notifier's @asd_entry. The
>   * function also gets a reference of the fwnode which is released later at
>   * notifier cleanup time.
>   *
> @@ -196,7 +196,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
>  			unsigned int asd_struct_size);
>  /**
>   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> - *				subdev to the notifier's master asd_list.
> + *				subdev to the notifier's master asd_entry.
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @adapter: I2C adapter ID to be matched
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index cfd19e72d0fc4..82e4cf3dd2e05 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -1020,7 +1020,7 @@ struct v4l2_subdev_platform_data {
>   * @dev: pointer to the physical device, if any
>   * @fwnode: The fwnode_handle of the subdev, usually the same as
>   *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
> - * @async_list: Links this subdev to a global subdev_list or @notifier->done
> + * @async_list: Links this subdev to a global subdev_entry or @notifier->done

There's no subdev_entry, and the list is now called notifier->done_list.
Have you renamed the wrong thing ?

>   *	list.
>   * @asd: Pointer to respective &struct v4l2_async_subdev.
>   * @notifier: Pointer to the managing notifier.

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling
  2023-05-25  9:16 ` [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling Sakari Ailus
@ 2023-05-30  4:51   ` Laurent Pinchart
  2023-06-21 15:43     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  4:51 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:06PM +0300, Sakari Ailus wrote:
> Fix and simplify error handling in pxa_camera probe, by moving devm_*()
> functions early in the probe function and then tearing down what was set
> up on error patch.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/platform/intel/pxa_camera.c | 48 ++++++++++++-----------
>  1 file changed, 25 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> index f0d316d5fe27c..dad5e8d97683e 100644
> --- a/drivers/media/platform/intel/pxa_camera.c
> +++ b/drivers/media/platform/intel/pxa_camera.c
> @@ -2289,6 +2289,24 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	if (IS_ERR(pcdev->clk))
>  		return PTR_ERR(pcdev->clk);
>  
> +	/*
> +	 * Request the regions.
> +	 */
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	pcdev->irq = irq;
> +	pcdev->base = base;
> +
> +	/* request irq */
> +	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
> +			       PXA_CAM_DRV_NAME, pcdev);
> +	if (err) {
> +		dev_err(&pdev->dev, "Camera interrupt register failed\n");
> +		return err;
> +	}
> +

The IRQ should not be requested before the device is initialized, to
avoid spurious IRQs at probe time. I don't think the driver currently
handles this very well, but moving IRQ registration up is the wrong
direction. As this particular change isn't needed to clean up the
notifier, I would keep the devm_request_irq() call where it is.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

>  	v4l2_async_nf_init(&pcdev->notifier);
>  	pcdev->res = res;
>  	pcdev->pdata = pdev->dev.platform_data;
> @@ -2338,21 +2356,12 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	spin_lock_init(&pcdev->lock);
>  	mutex_init(&pcdev->mlock);
>  
> -	/*
> -	 * Request the regions.
> -	 */
> -	base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(base))
> -		return PTR_ERR(base);
> -
> -	pcdev->irq = irq;
> -	pcdev->base = base;
> -
>  	/* request dma */
>  	pcdev->dma_chans[0] = dma_request_chan(&pdev->dev, "CI_Y");
>  	if (IS_ERR(pcdev->dma_chans[0])) {
>  		dev_err(&pdev->dev, "Can't request DMA for Y\n");
> -		return PTR_ERR(pcdev->dma_chans[0]);
> +		err = PTR_ERR(pcdev->dma_chans[0]);
> +		goto exit_notifier_cleanup;
>  	}
>  
>  	pcdev->dma_chans[1] = dma_request_chan(&pdev->dev, "CI_U");
> @@ -2379,14 +2388,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	/* request irq */
> -	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
> -			       PXA_CAM_DRV_NAME, pcdev);
> -	if (err) {
> -		dev_err(&pdev->dev, "Camera interrupt register failed\n");
> -		goto exit_free_dma;
> -	}
> -
>  	tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
>  
>  	pxa_camera_activate(pcdev);
> @@ -2398,16 +2399,15 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  
>  	err = pxa_camera_init_videobuf2(pcdev);
>  	if (err)
> -		goto exit_notifier_cleanup;
> +		goto exit_v4l2_device_unregister;
>  
>  	pcdev->notifier.ops = &pxa_camera_sensor_ops;
>  	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
>  	if (err)
> -		goto exit_notifier_cleanup;
> +		goto exit_v4l2_device_unregister;
>  
>  	return 0;
> -exit_notifier_cleanup:
> -	v4l2_async_nf_cleanup(&pcdev->notifier);
> +exit_v4l2_device_unregister:
>  	v4l2_device_unregister(&pcdev->v4l2_dev);
>  exit_deactivate:
>  	pxa_camera_deactivate(pcdev);
> @@ -2418,6 +2418,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	dma_release_channel(pcdev->dma_chans[1]);
>  exit_free_dma_y:
>  	dma_release_channel(pcdev->dma_chans[0]);
> +exit_notifier_cleanup:
> +	v4l2_async_nf_cleanup(&pcdev->notifier);
>  	return err;
>  }
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early
  2023-05-25  9:16 ` [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early Sakari Ailus
@ 2023-05-30  4:54   ` Laurent Pinchart
  2023-05-30  4:56     ` Laurent Pinchart
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  4:54 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:07PM +0300, Sakari Ailus wrote:
> Register V4L2 device before initialising the notifier. This way the device
> is available to the notifier from the beginning which makes it possible to
> use it for debug prints.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/platform/intel/pxa_camera.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> index dad5e8d97683e..5df93fd4ff04b 100644
> --- a/drivers/media/platform/intel/pxa_camera.c
> +++ b/drivers/media/platform/intel/pxa_camera.c
> @@ -2307,6 +2307,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  		return err;
>  	}
>  
> +	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> +	if (err)
> +		return err;
> +
>  	v4l2_async_nf_init(&pcdev->notifier);
>  	pcdev->res = res;
>  	pcdev->pdata = pdev->dev.platform_data;
> @@ -2324,10 +2328,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	} else if (pdev->dev.of_node) {
>  		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
>  	} else {
> -		return -ENODEV;
> +		err = -ENODEV;
>  	}
>  	if (err < 0)
> -		return err;
> +		goto exit_v4l2_device_unregister;
>  
>  	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
>  			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
> @@ -2393,22 +2397,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	pxa_camera_activate(pcdev);
>  
>  	platform_set_drvdata(pdev, pcdev);
> -	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> -	if (err)
> -		goto exit_deactivate;
>  
>  	err = pxa_camera_init_videobuf2(pcdev);
>  	if (err)
> -		goto exit_v4l2_device_unregister;
> +		goto exit_deactivate;
>  
>  	pcdev->notifier.ops = &pxa_camera_sensor_ops;
>  	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);

The v4l2_device isn't made available to the notifier before this call,
so why is it necessary to register it earlier ?

>  	if (err)
> -		goto exit_v4l2_device_unregister;
> +		goto exit_deactivate;
>  
>  	return 0;
> -exit_v4l2_device_unregister:
> -	v4l2_device_unregister(&pcdev->v4l2_dev);
>  exit_deactivate:
>  	pxa_camera_deactivate(pcdev);
>  	tasklet_kill(&pcdev->task_eof);
> @@ -2420,6 +2419,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	dma_release_channel(pcdev->dma_chans[0]);
>  exit_notifier_cleanup:
>  	v4l2_async_nf_cleanup(&pcdev->notifier);
> +exit_v4l2_device_unregister:
> +	v4l2_device_unregister(&pcdev->v4l2_dev);
>  	return err;
>  }
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early
  2023-05-30  4:54   ` Laurent Pinchart
@ 2023-05-30  4:56     ` Laurent Pinchart
  2023-06-13 15:08       ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  4:56 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On Tue, May 30, 2023 at 07:54:46AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:07PM +0300, Sakari Ailus wrote:
> > Register V4L2 device before initialising the notifier. This way the device
> > is available to the notifier from the beginning which makes it possible to
> > use it for debug prints.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/platform/intel/pxa_camera.c | 19 ++++++++++---------
> >  1 file changed, 10 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> > index dad5e8d97683e..5df93fd4ff04b 100644
> > --- a/drivers/media/platform/intel/pxa_camera.c
> > +++ b/drivers/media/platform/intel/pxa_camera.c
> > @@ -2307,6 +2307,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
> >  		return err;
> >  	}
> >  
> > +	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> > +	if (err)
> > +		return err;
> > +
> >  	v4l2_async_nf_init(&pcdev->notifier);
> >  	pcdev->res = res;
> >  	pcdev->pdata = pdev->dev.platform_data;
> > @@ -2324,10 +2328,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
> >  	} else if (pdev->dev.of_node) {
> >  		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
> >  	} else {
> > -		return -ENODEV;
> > +		err = -ENODEV;
> >  	}
> >  	if (err < 0)
> > -		return err;
> > +		goto exit_v4l2_device_unregister;
> >  
> >  	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
> >  			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
> > @@ -2393,22 +2397,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
> >  	pxa_camera_activate(pcdev);
> >  
> >  	platform_set_drvdata(pdev, pcdev);
> > -	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> > -	if (err)
> > -		goto exit_deactivate;
> >  
> >  	err = pxa_camera_init_videobuf2(pcdev);
> >  	if (err)
> > -		goto exit_v4l2_device_unregister;
> > +		goto exit_deactivate;
> >  
> >  	pcdev->notifier.ops = &pxa_camera_sensor_ops;
> >  	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
> 
> The v4l2_device isn't made available to the notifier before this call,
> so why is it necessary to register it earlier ?

Ah, it's because of patch 31/32. Please record this in the commit
message.

> >  	if (err)
> > -		goto exit_v4l2_device_unregister;
> > +		goto exit_deactivate;
> >  
> >  	return 0;
> > -exit_v4l2_device_unregister:
> > -	v4l2_device_unregister(&pcdev->v4l2_dev);
> >  exit_deactivate:
> >  	pxa_camera_deactivate(pcdev);
> >  	tasklet_kill(&pcdev->task_eof);
> > @@ -2420,6 +2419,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
> >  	dma_release_channel(pcdev->dma_chans[0]);
> >  exit_notifier_cleanup:
> >  	v4l2_async_nf_cleanup(&pcdev->notifier);
> > +exit_v4l2_device_unregister:
> > +	v4l2_device_unregister(&pcdev->v4l2_dev);
> >  	return err;
> >  }
> >  

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier
  2023-05-25  9:16 ` [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier Sakari Ailus
@ 2023-05-30  5:00   ` Laurent Pinchart
  2023-06-20  9:43     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  5:00 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:08PM +0300, Sakari Ailus wrote:
> Register V4L2 device before the async notifier so the struct device will
> be available for the notifier which makes it possible to use it for debug
> prints.

Please record in the commit message that this is to prepare for patch
31/32. Same comment for other patches in this series.

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/platform/marvell/cafe-driver.c | 11 +++++++++--
>  drivers/media/platform/marvell/mcam-core.c   |  6 ------
>  2 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
> index dd1bba70bd791..fbfbb9f67ddfc 100644
> --- a/drivers/media/platform/marvell/cafe-driver.c
> +++ b/drivers/media/platform/marvell/cafe-driver.c
> @@ -536,6 +536,10 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  	if (ret)
>  		goto out_pdown;
>  
> +	ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev);
> +	if (ret)
> +		goto out_smbus_shutdown;
> +
>  	v4l2_async_nf_init(&mcam->notifier);
>  
>  	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
> @@ -544,12 +548,12 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  				    struct v4l2_async_connection);
>  	if (IS_ERR(asd)) {
>  		ret = PTR_ERR(asd);
> -		goto out_smbus_shutdown;
> +		goto out_v4l2_device_unregister;
>  	}
>  
>  	ret = mccic_register(mcam);
>  	if (ret)
> -		goto out_smbus_shutdown;
> +		goto out_v4l2_device_unregister;
>  
>  	clkdev_create(mcam->mclk, "xclk", "%d-%04x",
>  		i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
> @@ -565,6 +569,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  
>  out_mccic_shutdown:
>  	mccic_shutdown(mcam);
> +out_v4l2_device_unregister:
> +	v4l2_device_unregister(&mcam->v4l2_dev);
>  out_smbus_shutdown:
>  	cafe_smbus_shutdown(cam);
>  out_pdown:
> @@ -587,6 +593,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  static void cafe_shutdown(struct cafe_camera *cam)
>  {
>  	mccic_shutdown(&cam->mcam);
> +	v4l2_device_unregister(&cam->mcam.v4l2_dev);
>  	cafe_smbus_shutdown(cam);
>  	free_irq(cam->pdev->irq, cam);
>  	pci_iounmap(cam->pdev, cam->mcam.regs);
> diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
> index 3cee6d6b83fa9..bcfcecdb03ea2 100644
> --- a/drivers/media/platform/marvell/mcam-core.c
> +++ b/drivers/media/platform/marvell/mcam-core.c
> @@ -1866,10 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
>  	/*
>  	 * Register with V4L
>  	 */

The comment doesn't seem valid anymore.

> -	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
> -	if (ret)
> -		goto out;
> -
>  	mutex_init(&cam->s_mutex);
>  	cam->state = S_NOTREADY;
>  	mcam_set_config_needed(cam, 1);
> @@ -1915,7 +1911,6 @@ int mccic_register(struct mcam_camera *cam)
>  
>  out:
>  	v4l2_async_nf_unregister(&cam->notifier);
> -	v4l2_device_unregister(&cam->v4l2_dev);
>  	v4l2_async_nf_cleanup(&cam->notifier);
>  	return ret;
>  }
> @@ -1937,7 +1932,6 @@ void mccic_shutdown(struct mcam_camera *cam)
>  		mcam_free_dma_bufs(cam);
>  	v4l2_ctrl_handler_free(&cam->ctrl_handler);
>  	v4l2_async_nf_unregister(&cam->notifier);
> -	v4l2_device_unregister(&cam->v4l2_dev);
>  	v4l2_async_nf_cleanup(&cam->notifier);
>  }
>  EXPORT_SYMBOL_GPL(mccic_shutdown);

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching
  2023-05-25  9:15 ` [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching Sakari Ailus
@ 2023-05-30  5:08   ` Laurent Pinchart
  2023-06-13 15:10     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  5:08 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:56PM +0300, Sakari Ailus wrote:
> V4L2 async sub-device matching originally used the device nodes only.
> Endpoint nodes were taken into use instead as using the device nodes was
> problematic for it was in some cases ambiguous which link might have been
> in question.
> 
> There is however no need to use endpoint nodes on both sides, as the async
> sub-device's fwnode can always be trivially obtained using
> fwnode_graph_get_remote_endpoint() when needed while what counts is
> whether or not the link is between two device nodes, i.e. the device nodes
> match.
> 
> This will briefly break the adv748x driver but it will be fixed later in
> the set, by patch "media: adv748x: Return to endpoint matching".

I'm afraid I don't like this. This series is complex and has a high risk
of causing tricky issues. I would like to be able to bisect the changes.

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/i2c/adv748x/adv748x-csi2.c   |  5 +-
>  drivers/media/i2c/max9286.c                | 14 +---
>  drivers/media/i2c/rdacm20.c                | 16 +---
>  drivers/media/i2c/rdacm21.c                | 15 +---
>  drivers/media/i2c/tc358746.c               |  5 --
>  drivers/media/platform/nxp/imx-mipi-csis.c |  7 --
>  drivers/media/v4l2-core/v4l2-async.c       | 88 ++++++----------------
>  7 files changed, 26 insertions(+), 124 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
> index bd4f3fe0e3096..b6f93c1db3d2a 100644
> --- a/drivers/media/i2c/adv748x/adv748x-csi2.c
> +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
> @@ -296,13 +296,12 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
>  	if (!is_tx_enabled(tx))
>  		return 0;
>  
> +	/* FIXME: Do endpoint matching again! */
> +
>  	adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
>  			    MEDIA_ENT_F_VID_IF_BRIDGE,
>  			    is_txa(tx) ? "txa" : "txb");
>  
> -	/* Ensure that matching is based upon the endpoint fwnodes */
> -	tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]);
> -
>  	/* Register internal ops for incremental subdev registration */
>  	tx->sd.internal_ops = &adv748x_csi2_internal_ops;
>  
> diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
> index 13a986b885889..64f5c49cae776 100644
> --- a/drivers/media/i2c/max9286.c
> +++ b/drivers/media/i2c/max9286.c
> @@ -1051,7 +1051,6 @@ static const struct v4l2_ctrl_ops max9286_ctrl_ops = {
>  static int max9286_v4l2_register(struct max9286_priv *priv)
>  {
>  	struct device *dev = &priv->client->dev;
> -	struct fwnode_handle *ep;
>  	int ret;
>  	int i;
>  
> @@ -1093,25 +1092,14 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
>  	if (ret)
>  		goto err_async;
>  
> -	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), MAX9286_SRC_PAD,
> -					     0, 0);
> -	if (!ep) {
> -		dev_err(dev, "Unable to retrieve endpoint on \"port@4\"\n");
> -		ret = -ENOENT;
> -		goto err_async;
> -	}
> -	priv->sd.fwnode = ep;
> -
>  	ret = v4l2_async_register_subdev(&priv->sd);
>  	if (ret < 0) {
>  		dev_err(dev, "Unable to register subdevice\n");
> -		goto err_put_node;
> +		goto err_async;
>  	}
>  
>  	return 0;
>  
> -err_put_node:
> -	fwnode_handle_put(ep);
>  err_async:
>  	v4l2_ctrl_handler_free(&priv->ctrls);
>  	max9286_v4l2_notifier_unregister(priv);
> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
> index a2263fa825b59..9d8a8f9efd835 100644
> --- a/drivers/media/i2c/rdacm20.c
> +++ b/drivers/media/i2c/rdacm20.c
> @@ -567,7 +567,6 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
>  static int rdacm20_probe(struct i2c_client *client)
>  {
>  	struct rdacm20_device *dev;
> -	struct fwnode_handle *ep;
>  	int ret;
>  
>  	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
> @@ -616,24 +615,12 @@ static int rdacm20_probe(struct i2c_client *client)
>  	if (ret < 0)
>  		goto error_free_ctrls;
>  
> -	ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
> -	if (!ep) {
> -		dev_err(&client->dev,
> -			"Unable to get endpoint in node %pOF\n",
> -			client->dev.of_node);
> -		ret = -ENOENT;
> -		goto error_free_ctrls;
> -	}
> -	dev->sd.fwnode = ep;
> -
>  	ret = v4l2_async_register_subdev(&dev->sd);
>  	if (ret)
> -		goto error_put_node;
> +		goto error_free_ctrls;
>  
>  	return 0;
>  
> -error_put_node:
> -	fwnode_handle_put(ep);
>  error_free_ctrls:
>  	v4l2_ctrl_handler_free(&dev->ctrls);
>  error:
> @@ -650,7 +637,6 @@ static void rdacm20_remove(struct i2c_client *client)
>  {
>  	struct rdacm20_device *dev = i2c_to_rdacm20(client);
>  
> -	fwnode_handle_put(dev->sd.fwnode);
>  	v4l2_async_unregister_subdev(&dev->sd);
>  	v4l2_ctrl_handler_free(&dev->ctrls);
>  	media_entity_cleanup(&dev->sd.entity);
> diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
> index 9ccc56c30d3b0..d67cfcb2e05a4 100644
> --- a/drivers/media/i2c/rdacm21.c
> +++ b/drivers/media/i2c/rdacm21.c
> @@ -543,7 +543,6 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
>  static int rdacm21_probe(struct i2c_client *client)
>  {
>  	struct rdacm21_device *dev;
> -	struct fwnode_handle *ep;
>  	int ret;
>  
>  	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
> @@ -588,24 +587,12 @@ static int rdacm21_probe(struct i2c_client *client)
>  	if (ret < 0)
>  		goto error_free_ctrls;
>  
> -	ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
> -	if (!ep) {
> -		dev_err(&client->dev,
> -			"Unable to get endpoint in node %pOF\n",
> -			client->dev.of_node);
> -		ret = -ENOENT;
> -		goto error_free_ctrls;
> -	}
> -	dev->sd.fwnode = ep;
> -
>  	ret = v4l2_async_register_subdev(&dev->sd);
>  	if (ret)
> -		goto error_put_node;
> +		goto error_free_ctrls;
>  
>  	return 0;
>  
> -error_put_node:
> -	fwnode_handle_put(dev->sd.fwnode);
>  error_free_ctrls:
>  	v4l2_ctrl_handler_free(&dev->ctrls);
>  error:
> diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
> index ec1a193ba161a..b37a9ff73f6ad 100644
> --- a/drivers/media/i2c/tc358746.c
> +++ b/drivers/media/i2c/tc358746.c
> @@ -1476,9 +1476,6 @@ static int tc358746_async_register(struct tc358746 *tc358746)
>  	if (err)
>  		goto err_cleanup;
>  
> -	tc358746->sd.fwnode = fwnode_graph_get_endpoint_by_id(
> -		dev_fwnode(tc358746->sd.dev), TC358746_SOURCE, 0, 0);
> -
>  	err = v4l2_async_register_subdev(&tc358746->sd);
>  	if (err)
>  		goto err_unregister;
> @@ -1486,7 +1483,6 @@ static int tc358746_async_register(struct tc358746 *tc358746)
>  	return 0;
>  
>  err_unregister:
> -	fwnode_handle_put(tc358746->sd.fwnode);
>  	v4l2_async_nf_unregister(&tc358746->notifier);
>  err_cleanup:
>  	v4l2_async_nf_cleanup(&tc358746->notifier);
> @@ -1605,7 +1601,6 @@ static void tc358746_remove(struct i2c_client *client)
>  	v4l2_fwnode_endpoint_free(&tc358746->csi_vep);
>  	v4l2_async_nf_unregister(&tc358746->notifier);
>  	v4l2_async_nf_cleanup(&tc358746->notifier);
> -	fwnode_handle_put(sd->fwnode);
>  	v4l2_async_unregister_subdev(sd);
>  	media_entity_cleanup(&sd->entity);
>  
> diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
> index 05d52762e7926..d0dc30187775d 100644
> --- a/drivers/media/platform/nxp/imx-mipi-csis.c
> +++ b/drivers/media/platform/nxp/imx-mipi-csis.c
> @@ -1365,13 +1365,6 @@ static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
>  
>  	sd->dev = csis->dev;
>  
> -	sd->fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev),
> -						     1, 0, 0);
> -	if (!sd->fwnode) {
> -		dev_err(csis->dev, "Unable to retrieve endpoint for port@1\n");
> -		return -ENOENT;
> -	}
> -
>  	csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
>  					 | MEDIA_PAD_FL_MUST_CONNECT;
>  	csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 06b1e1a1a5f87..335597889f365 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -94,89 +94,36 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
>  		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
>  		 struct v4l2_async_match_desc *match)
>  {
> -	struct fwnode_handle *other_fwnode;
> -	struct fwnode_handle *dev_fwnode;
> -	bool asd_fwnode_is_ep;
> -	bool sd_fwnode_is_ep;
> -	struct device *dev;
> +	struct fwnode_handle *asd_dev_fwnode;
> +	bool ret;
>  
>  	dev_dbg(notifier_dev(notifier),
>  		"v4l2-async: fwnode match: need %pfw, trying %pfw\n",
>  		sd_fwnode, match->fwnode);
>  
> -	/*
> -	 * Both the subdev and the async subdev can provide either an endpoint
> -	 * fwnode or a device fwnode. Start with the simple case of direct
> -	 * fwnode matching.
> -	 */
>  	if (sd_fwnode == match->fwnode) {
>  		dev_dbg(notifier_dev(notifier),
>  			"v4l2-async: direct match found\n");
>  		return true;
>  	}
>  
> -	/*
> -	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
> -	 * endpoint or a device. If they're of the same type, there's no match.
> -	 * Technically speaking this checks if the nodes refer to a connected
> -	 * endpoint, which is the simplest check that works for both OF and
> -	 * ACPI. This won't make a difference, as drivers should not try to
> -	 * match unconnected endpoints.
> -	 */
> -	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);
> -	asd_fwnode_is_ep = fwnode_graph_is_endpoint(match->fwnode);
> -
> -	if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
> +	if (!fwnode_graph_is_endpoint(match->fwnode)) {
>  		dev_dbg(notifier_dev(notifier),
>  			"v4l2-async: direct match not found\n");
>  		return false;
>  	}
>  
> -	/*
> -	 * The sd and asd fwnodes are of different types. Get the device fwnode
> -	 * parent of the endpoint fwnode, and compare it with the other fwnode.
> -	 */
> -	if (sd_fwnode_is_ep) {
> -		dev_fwnode = fwnode_graph_get_port_parent(sd_fwnode);
> -		other_fwnode = match->fwnode;
> -	} else {
> -		dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
> -		other_fwnode = sd_fwnode;
> -	}
> +	asd_dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
>  
> -	dev_dbg(notifier_dev(notifier),
> -		"v4l2-async: fwnode compat match: need %pfw, trying %pfw\n",
> -		dev_fwnode, other_fwnode);
> +	ret = sd_fwnode == asd_dev_fwnode;
>  
> -	fwnode_handle_put(dev_fwnode);
> +	fwnode_handle_put(asd_dev_fwnode);
>  
> -	if (dev_fwnode != other_fwnode) {
> -		dev_dbg(notifier_dev(notifier),
> -			"v4l2-async: compat match not found\n");
> -		return false;
> -	}
> -
> -	/*
> -	 * We have a heterogeneous match. Retrieve the struct device of the side
> -	 * that matched on a device fwnode to print its driver name.
> -	 */
> -	if (sd_fwnode_is_ep)
> -		dev = notifier->v4l2_dev ? notifier->v4l2_dev->dev
> -		    : notifier->sd->dev;
> -	else
> -		dev = sd->dev;
> -
> -	if (dev && dev->driver) {
> -		if (sd_fwnode_is_ep)
> -			dev_warn(dev, "Driver %s uses device fwnode, incorrect match may occur\n",
> -				 dev->driver->name);
> -		dev_notice(dev, "Consider updating driver %s to match on endpoints\n",
> -			   dev->driver->name);
> -	}
> -
> -	dev_dbg(notifier_dev(notifier), "v4l2-async: compat match found\n");
> +	dev_dbg(notifier_dev(notifier),
> +		"v4l2-async: device--endpoint match %sfound\n",
> +		ret ? "" : "not ");
>  
> -	return true;
> +	return ret;
>  }
>  
>  static bool match_fwnode(struct v4l2_async_notifier *notifier,
> @@ -814,12 +761,19 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
>  	int ret;
>  
>  	/*
> -	 * No reference taken. The reference is held by the device
> -	 * (struct v4l2_subdev.dev), and async sub-device does not
> -	 * exist independently of the device at any point of time.
> +	 * No reference taken. The reference is held by the device (struct
> +	 * v4l2_subdev.dev), and async sub-device does not exist independently
> +	 * of the device at any point of time.
> +	 *
> +	 * The async sub-device shall always be registered for its device node,
> +	 * not the endpoint node.
>  	 */
> -	if (!sd->fwnode && sd->dev)
> +	if (!sd->fwnode && sd->dev) {
>  		sd->fwnode = dev_fwnode(sd->dev);
> +	} else if (fwnode_graph_is_endpoint(sd->fwnode)) {
> +		dev_warn(sd->dev, "sub-device fwnode is an endpoint!\n");
> +		return -EINVAL;
> +	}
>  
>  	mutex_lock(&list_lock);
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries
  2023-05-30  3:09   ` Laurent Pinchart
@ 2023-05-30  5:40     ` Laurent Pinchart
  2023-06-13 14:58       ` Sakari Ailus
  2023-06-13 14:51     ` Sakari Ailus
  1 sibling, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  5:40 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On Tue, May 30, 2023 at 06:09:29AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:55PM +0300, Sakari Ailus wrote:
> > The naming of list heads and list entries is confusing as they're named
> > similarly. Use _list for list head and _entry for list entries.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  2 +-
> >  drivers/media/platform/xilinx/xilinx-vipp.c   |  6 +--
> >  drivers/media/v4l2-core/v4l2-async.c          | 54 +++++++++----------
> >  drivers/staging/media/tegra-video/vi.c        |  4 +-
> >  include/media/v4l2-async.h                    | 36 ++++++-------
> >  include/media/v4l2-subdev.h                   |  2 +-
> >  6 files changed, 52 insertions(+), 52 deletions(-)
> > 
> > diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > index 3c84cb1216320..9231d6a65f4ec 100644
> > --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > @@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
> >  	unsigned int pad;
> >  	int ret;
> >  
> > -	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) {
> >  		s_asd = to_sensor_asd(asd);
> >  		q = &cio2->queue[s_asd->csi2.port];
> >  
> > diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> > index b309af0c83749..52c5a7decf284 100644
> > --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> > +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> > @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
> >  	struct xvip_graph_entity *entity;
> >  	struct v4l2_async_subdev *asd;
> >  
> > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> >  		entity = to_xvip_entity(asd);
> >  		if (entity->asd.match.fwnode == fwnode)
> >  			return entity;
> > @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
> >  	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
> >  
> >  	/* Create links for every entity. */
> > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> >  		entity = to_xvip_entity(asd);
> >  		ret = xvip_graph_build_one(xdev, entity);
> >  		if (ret < 0)
> > @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
> >  	if (ret < 0)
> >  		return 0;
> >  
> > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> >  		entity = to_xvip_entity(asd);
> >  		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
> >  		if (ret < 0) {
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > index 5eb9850f1c6c4..06b1e1a1a5f87 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -213,7 +213,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
> >  		      struct v4l2_async_match_desc *match);
> >  	struct v4l2_async_subdev *asd;
> >  
> > -	list_for_each_entry(asd, &notifier->waiting, list) {
> > +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry) {
> >  		/* bus_type has been verified valid before */
> >  		switch (asd->match.type) {
> >  		case V4L2_ASYNC_MATCH_TYPE_I2C:
> > @@ -262,7 +262,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
> >  {
> >  	struct v4l2_async_notifier *n;
> >  
> > -	list_for_each_entry(n, &notifier_list, list)
> > +	list_for_each_entry(n, &notifier_list, notifier_entry)
> >  		if (n->sd == sd)
> >  			return n;
> >  
> > @@ -287,10 +287,10 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
> >  {
> >  	struct v4l2_subdev *sd;
> >  
> > -	if (!list_empty(&notifier->waiting))
> > +	if (!list_empty(&notifier->waiting_list))
> >  		return false;
> >  
> > -	list_for_each_entry(sd, &notifier->done, async_list) {
> > +	list_for_each_entry(sd, &notifier->done_list, async_list) {
> >  		struct v4l2_async_notifier *subdev_notifier =
> >  			v4l2_async_find_subdev_notifier(sd);
> >  
> > @@ -312,7 +312,7 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> >  	struct v4l2_async_notifier *__notifier = notifier;
> >  
> >  	/* Quick check whether there are still more sub-devices here. */
> > -	if (!list_empty(&notifier->waiting))
> > +	if (!list_empty(&notifier->waiting_list))
> >  		return 0;
> >  
> >  	if (notifier->sd)
> > @@ -391,13 +391,12 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >  		return ret;
> >  	}
> >  
> > -	/* Remove from the waiting list */
> > -	list_del(&asd->list);
> > +	list_del(&asd->waiting_entry);
> >  	sd->asd = asd;
> >  	sd->notifier = notifier;
> >  
> >  	/* Move from the global subdevice list to notifier's done */
> > -	list_move(&sd->async_list, &notifier->done);
> > +	list_move(&sd->async_list, &notifier->done_list);
> >  
> >  	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
> >  		dev_name(sd->dev), ret);
> > @@ -478,7 +477,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
> >  {
> >  	struct v4l2_subdev *sd, *tmp;
> >  
> > -	list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
> > +	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
> >  		struct v4l2_async_notifier *subdev_notifier =
> >  			v4l2_async_find_subdev_notifier(sd);
> >  
> > @@ -487,7 +486,8 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
> >  
> >  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> >  		if (readd)
> > -			list_add_tail(&sd->asd->list, &notifier->waiting);
> > +			list_add_tail(&sd->asd->waiting_entry,
> > +				      &notifier->waiting_list);
> >  		v4l2_async_cleanup(sd);
> >  
> >  		list_move(&sd->async_list, &subdev_list);
> > @@ -504,11 +504,11 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
> >  	struct v4l2_async_subdev *asd;
> >  	struct v4l2_subdev *sd;
> >  
> > -	list_for_each_entry(asd, &notifier->waiting, list)
> > +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry)
> >  		if (v4l2_async_match_equal(&asd->match, match))
> >  			return true;
> >  
> > -	list_for_each_entry(sd, &notifier->done, async_list) {
> > +	list_for_each_entry(sd, &notifier->done_list, async_list) {
> >  		if (WARN_ON(!sd->asd))
> >  			continue;
> >  
> > @@ -533,7 +533,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> >  	lockdep_assert_held(&list_lock);
> >  
> >  	/* Check that an asd is not being added more than once. */
> > -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> > +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
> >  		if (skip_self && &asd->match == match)
> >  			break;
> >  		if (v4l2_async_match_equal(&asd->match, match))
> > @@ -541,7 +541,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> >  	}
> >  
> >  	/* Check that an asd does not exist in other notifiers. */
> > -	list_for_each_entry(notifier, &notifier_list, list)
> > +	list_for_each_entry(notifier, &notifier_list, notifier_entry)
> >  		if (v4l2_async_nf_has_async_match_entry(notifier, match))
> >  			return true;
> >  
> > @@ -583,17 +583,17 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
> >  	struct v4l2_async_subdev *asd;
> >  	int ret;
> >  
> > -	INIT_LIST_HEAD(&notifier->waiting);
> > -	INIT_LIST_HEAD(&notifier->done);
> > +	INIT_LIST_HEAD(&notifier->waiting_list);
> > +	INIT_LIST_HEAD(&notifier->done_list);
> >  
> >  	mutex_lock(&list_lock);
> >  
> > -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> > +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
> >  		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
> >  		if (ret)
> >  			goto err_unlock;
> >  
> > -		list_add_tail(&asd->list, &notifier->waiting);
> > +		list_add_tail(&asd->waiting_entry, &notifier->waiting_list);
> >  	}
> >  
> >  	ret = v4l2_async_nf_try_all_subdevs(notifier);
> > @@ -605,7 +605,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
> >  		goto err_unbind;
> >  
> >  	/* Keep also completed notifiers on the list */
> > -	list_add(&notifier->list, &notifier_list);
> > +	list_add(&notifier->notifier_entry, &notifier_list);
> >  
> >  	mutex_unlock(&list_lock);
> >  
> > @@ -670,7 +670,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
> >  	notifier->sd = NULL;
> >  	notifier->v4l2_dev = NULL;
> >  
> > -	list_del(&notifier->list);
> > +	list_del(&notifier->notifier_entry);
> >  }
> >  
> >  void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
> > @@ -690,7 +690,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
> >  	if (!notifier || !notifier->asd_list.next)
> >  		return;
> >  
> > -	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
> > +	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_entry) {
> >  		switch (asd->match.type) {
> >  		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
> >  			fwnode_handle_put(asd->match.fwnode);
> > @@ -699,7 +699,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
> >  			break;
> >  		}
> >  
> > -		list_del(&asd->asd_list);
> > +		list_del(&asd->asd_entry);
> >  		v4l2_async_nf_call_destroy(notifier, asd);
> >  		kfree(asd);
> >  	}
> > @@ -727,7 +727,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
> >  	if (ret)
> >  		goto unlock;
> >  
> > -	list_add_tail(&asd->asd_list, &notifier->asd_list);
> > +	list_add_tail(&asd->asd_entry, &notifier->asd_list);
> >  
> >  unlock:
> >  	mutex_unlock(&list_lock);
> > @@ -823,7 +823,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
> >  
> >  	mutex_lock(&list_lock);
> >  
> > -	list_for_each_entry(notifier, &notifier_list, list) {
> > +	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
> >  		struct v4l2_device *v4l2_dev =
> >  			v4l2_async_nf_find_v4l2_dev(notifier);
> >  		struct v4l2_async_subdev *asd;
> > @@ -890,7 +890,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
> >  	if (sd->asd) {
> >  		struct v4l2_async_notifier *notifier = sd->notifier;
> >  
> > -		list_add(&sd->asd->list, &notifier->waiting);
> > +		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
> >  
> >  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> >  	}
> > @@ -944,9 +944,9 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
> >  
> >  	mutex_lock(&list_lock);
> >  
> > -	list_for_each_entry(notif, &notifier_list, list) {
> > +	list_for_each_entry(notif, &notifier_list, notifier_entry) {
> >  		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
> > -		list_for_each_entry(asd, &notif->waiting, list)
> > +		list_for_each_entry(asd, &notif->waiting_list, waiting_entry)
> >  			print_waiting_match(s, &asd->match);
> >  	}
> >  
> > diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
> > index 2f1aff7e87170..350871f34f7cc 100644
> > --- a/drivers/staging/media/tegra-video/vi.c
> > +++ b/drivers/staging/media/tegra-video/vi.c
> > @@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
> >  	struct tegra_vi_graph_entity *entity;
> >  	struct v4l2_async_subdev *asd;
> >  
> > -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
> >  		entity = to_tegra_vi_graph_entity(asd);
> >  		if (entity->asd.match.fwnode == fwnode)
> >  			return entity;
> > @@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
> >  	}
> >  
> >  	/* create links between the entities */
> > -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> > +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
> >  		entity = to_tegra_vi_graph_entity(asd);
> >  		ret = tegra_vi_graph_build(chan, entity);
> >  		if (ret < 0)
> > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > index 8d1506a9755c3..54f9f45ed3d8e 100644
> > --- a/include/media/v4l2-async.h
> > +++ b/include/media/v4l2-async.h
> > @@ -65,10 +65,10 @@ struct v4l2_async_match_desc {
> >   * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> >   *
> >   * @match:	struct of match type and per-bus type matching data sets
> > - * @asd_list:	used to add struct v4l2_async_subdev objects to the
> > - *		master notifier @asd_list
> > - * @list:	used to link struct v4l2_async_subdev objects, waiting to be
> > - *		probed, to a notifier->waiting list
> > + * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> > + *		master notifier @asd_entry
> 
> I think you mean 'master notifier @asd_list' here.
> 
> > + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> > + *		probed, to a notifier->waiting_list list
> >   *
> >   * When this struct is used as a member in a driver specific struct,
> >   * the driver specific struct shall contain the &struct
> > @@ -76,8 +76,8 @@ struct v4l2_async_match_desc {
> >   */
> >  struct v4l2_async_subdev {
> >  	struct v4l2_async_match_desc match;
> > -	struct list_head list;
> > -	struct list_head asd_list;
> > +	struct list_head asd_entry;
> > +	struct list_head waiting_entry;
> >  };
> >  
> >  /**
> > @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations {
> >   * @sd:		sub-device that registered the notifier, NULL otherwise
> >   * @parent:	parent notifier
> >   * @asd_list:	master list of struct v4l2_async_subdev
> > - * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
> > - * @done:	list of struct v4l2_subdev, already probed
> > - * @list:	member in a global list of notifiers
> > + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
> > + * @done_list:	list of struct v4l2_subdev, already probed
> > + * @notifier_entry: member in a global list of notifiers
> >   */
> >  struct v4l2_async_notifier {
> >  	const struct v4l2_async_notifier_operations *ops;
> > @@ -117,9 +117,9 @@ struct v4l2_async_notifier {
> >  	struct v4l2_subdev *sd;
> >  	struct v4l2_async_notifier *parent;
> >  	struct list_head asd_list;
> > -	struct list_head waiting;
> > -	struct list_head done;
> > -	struct list_head list;
> > +	struct list_head waiting_list;
> > +	struct list_head done_list;
> > +	struct list_head notifier_entry;
> >  };
> >  
> >  /**
> > @@ -134,7 +134,7 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   *
> > - * This function initializes the notifier @asd_list. It must be called
> > + * This function initializes the notifier @asd_entry. It must be called
> >   * before adding a subdevice to a notifier, using one of:
> >   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
> >   * v4l2_async_nf_add_i2c().
> > @@ -147,7 +147,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> >  			   unsigned int asd_struct_size);
> >  /**
> >   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> > - *				subdev to the notifier's master asd_list.
> > + *				subdev to the notifier's master asd_entry.
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
> > @@ -157,7 +157,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> >   *
> >   * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> > - * notifiers @asd_list. The function also gets a reference of the fwnode which
> > + * notifiers @asd_entry. The function also gets a reference of the fwnode which

This rename doesn't seem correct, I think it refers to the notifier's
asd_list, which didn't get renamed, not the v4l2_async_subdev.asd_list.

> >   * is released later at notifier cleanup time.
> >   */
> >  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
> > @@ -170,7 +170,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >  /**
> >   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
> >   *						  remote async subdev to the
> > - *						  notifier's master asd_list.
> > + *						  notifier's master asd_entry.

Same here.

> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @ep: local endpoint pointing to the remote sub-device to be matched,
> > @@ -180,7 +180,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> >   *
> >   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> > - * matching and adds the async sub-device to the notifier's @asd_list. The
> > + * matching and adds the async sub-device to the notifier's @asd_entry. The

Same here.

> >   * function also gets a reference of the fwnode which is released later at
> >   * notifier cleanup time.
> >   *
> > @@ -196,7 +196,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
> >  			unsigned int asd_struct_size);
> >  /**
> >   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> > - *				subdev to the notifier's master asd_list.
> > + *				subdev to the notifier's master asd_entry.

Same here.

> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @adapter: I2C adapter ID to be matched
> > diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> > index cfd19e72d0fc4..82e4cf3dd2e05 100644
> > --- a/include/media/v4l2-subdev.h
> > +++ b/include/media/v4l2-subdev.h
> > @@ -1020,7 +1020,7 @@ struct v4l2_subdev_platform_data {
> >   * @dev: pointer to the physical device, if any
> >   * @fwnode: The fwnode_handle of the subdev, usually the same as
> >   *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
> > - * @async_list: Links this subdev to a global subdev_list or @notifier->done
> > + * @async_list: Links this subdev to a global subdev_entry or @notifier->done
> 
> There's no subdev_entry, and the list is now called notifier->done_list.
> Have you renamed the wrong thing ?
> 
> >   *	list.
> >   * @asd: Pointer to respective &struct v4l2_async_subdev.
> >   * @notifier: Pointer to the managing notifier.

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection
  2023-05-25  9:15 ` [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection Sakari Ailus
@ 2023-05-30  5:50   ` Laurent Pinchart
  2023-06-13 16:39     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  5:50 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:57PM +0300, Sakari Ailus wrote:
> Rename v4l2_async_subdev as v4l2_async_connection, in order to
> differentiate between the sub-devices and their connections: one
> sub-device can have many connections but the V4L2 async framework has so
> far allowed just a single one. Connections in this context will later
> translate into either MC ancillary or data links.
> 
> This patch prepares changing that relation by changing existing users of
> v4l2_async_subdev to switch to v4l2_async_connection. Async sub-devices
> themselves will not be needed anymore
> 
> Additionally, __v4l2_async_nf_add_subdev() has been renamed as

s/renamed as/renamed to/

> __v4l2_async_nf_add_connection().

I still don't like the name "connection" at all :-( It may seem fine as
you've been working on this extensively, but for people less familiar
with v4l2-async (myself included), I fear it will make the framework
more difficult to understand.

At the very least I'd like a detailed and clear glossary, to explain
what a connection *is*. The v4l2-async documentation is fairly bad (and
what is currently documented in v4l2-subdev.rst should likely be moved
to v4l2-async.rst).

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  .../driver-api/media/v4l2-subdev.rst          |  12 +-
>  drivers/media/i2c/max9286.c                   |   9 +-
>  drivers/media/i2c/st-mipid02.c                |   8 +-
>  drivers/media/i2c/tc358746.c                  |   6 +-
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  10 +-
>  drivers/media/platform/atmel/atmel-isi.c      |   8 +-
>  drivers/media/platform/atmel/atmel-isi.h      |   2 +-
>  drivers/media/platform/cadence/cdns-csi2rx.c  |   6 +-
>  drivers/media/platform/intel/pxa_camera.c     |  12 +-
>  drivers/media/platform/marvell/cafe-driver.c  |   5 +-
>  drivers/media/platform/marvell/mcam-core.c    |   4 +-
>  drivers/media/platform/marvell/mmp-driver.c   |   4 +-
>  .../platform/microchip/microchip-csi2dc.c     |   6 +-
>  .../platform/microchip/microchip-isc-base.c   |   4 +-
>  .../media/platform/microchip/microchip-isc.h  |   2 +-
>  .../microchip/microchip-sama5d2-isc.c         |   4 +-
>  .../microchip/microchip-sama7g5-isc.c         |   4 +-
>  drivers/media/platform/nxp/imx-mipi-csis.c    |   6 +-
>  drivers/media/platform/nxp/imx7-media-csi.c   |   6 +-
>  .../platform/nxp/imx8-isi/imx8-isi-core.c     |   8 +-
>  drivers/media/platform/qcom/camss/camss.c     |   2 +-
>  drivers/media/platform/qcom/camss/camss.h     |   2 +-
>  drivers/media/platform/renesas/rcar-isp.c     |   8 +-
>  .../platform/renesas/rcar-vin/rcar-core.c     |  44 ++---
>  .../platform/renesas/rcar-vin/rcar-csi2.c     |  16 +-
>  .../platform/renesas/rcar-vin/rcar-vin.h      |   8 +-
>  drivers/media/platform/renesas/rcar_drif.c    |   8 +-
>  drivers/media/platform/renesas/renesas-ceu.c  |   6 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  10 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-cru.h    |   2 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |   8 +-
>  .../platform/rockchip/rkisp1/rkisp1-common.h  |   2 +-
>  .../platform/rockchip/rkisp1/rkisp1-dev.c     |   8 +-
>  .../platform/samsung/exynos4-is/media-dev.c   |   6 +-
>  .../platform/samsung/exynos4-is/media-dev.h   |   2 +-
>  drivers/media/platform/st/stm32/stm32-dcmi.c  |   8 +-
>  .../platform/sunxi/sun4i-csi/sun4i_csi.c      |   6 +-
>  .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |   2 +-
>  .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   2 +-
>  .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |   6 +-
>  .../sun8i_a83t_mipi_csi2.c                    |   6 +-
>  .../media/platform/ti/am437x/am437x-vpfe.c    |   5 +-
>  .../media/platform/ti/am437x/am437x-vpfe.h    |   2 +-
>  drivers/media/platform/ti/cal/cal.c           |   6 +-
>  .../media/platform/ti/davinci/vpif_capture.c  |   7 +-
>  drivers/media/platform/ti/omap3isp/isp.h      |   2 +-
>  drivers/media/platform/video-mux.c            |   6 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c   |  22 +--
>  drivers/media/v4l2-core/v4l2-async.c          | 159 +++++++++---------
>  drivers/media/v4l2-core/v4l2-fwnode.c         |   8 +-
>  .../media/deprecated/atmel/atmel-isc-base.c   |   4 +-
>  .../media/deprecated/atmel/atmel-isc.h        |   2 +-
>  .../deprecated/atmel/atmel-sama5d2-isc.c      |   4 +-
>  .../deprecated/atmel/atmel-sama7g5-isc.c      |   4 +-
>  drivers/staging/media/imx/imx-media-csi.c     |   6 +-
>  .../staging/media/imx/imx-media-dev-common.c  |   2 +-
>  drivers/staging/media/imx/imx-media-dev.c     |   2 +-
>  drivers/staging/media/imx/imx-media-of.c      |   4 +-
>  drivers/staging/media/imx/imx6-mipi-csi2.c    |   8 +-
>  drivers/staging/media/imx/imx8mq-mipi-csi2.c  |   6 +-
>  .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |   2 +-
>  .../media/sunxi/sun6i-isp/sun6i_isp_proc.h    |   2 +-
>  drivers/staging/media/tegra-video/vi.c        |  14 +-
>  drivers/staging/media/tegra-video/vi.h        |   2 +-
>  include/media/davinci/vpif_types.h            |   2 +-
>  include/media/v4l2-async.h                    |  66 ++++----
>  include/media/v4l2-fwnode.h                   |   2 +-
>  include/media/v4l2-subdev.h                   |   5 +-
>  68 files changed, 320 insertions(+), 322 deletions(-)
> 
> diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> index ce8e9d0a332bc..83d3d29608136 100644
> --- a/Documentation/driver-api/media/v4l2-subdev.rst
> +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> @@ -214,14 +214,14 @@ notifier and further registers async sub-devices for lens and flash devices
>  found in firmware. The notifier for the sub-device is unregistered with the
>  async sub-device.
>  
> -These functions allocate an async sub-device descriptor which is of type struct
> -:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct
> -:c:type:`v4l2_async_subdev` shall be the first member of this struct:
> +These functions allocate an async connection descriptor which is of type struct
> +:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct
> +:c:type:`v4l2_async_connection` shall be the first member of this struct:
>  
>  .. code-block:: c
>  
>  	struct my_async_subdev {
> -		struct v4l2_async_subdev asd;
> +		struct v4l2_async_connection asd;

s/asd/asc/

>  		...
>  	};
>  
> @@ -244,10 +244,10 @@ notifier callback is called. After all subdevices have been located the
>  system the .unbind() method is called. All three callbacks are optional.
>  
>  Drivers can store any type of custom data in their driver-specific
> -:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special
> +:c:type:`v4l2_async_connection` wrapper. If any of that data requires special
>  handling when the structure is freed, drivers must implement the ``.destroy()``
>  notifier callback. The framework will call it right before freeing the
> -:c:type:`v4l2_async_subdev`.
> +:c:type:`v4l2_async_connection`.
>  
>  Calling subdev operations
>  ~~~~~~~~~~~~~~~~~~~~~~~~~
> diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
> index 64f5c49cae776..44def5e3ba5d1 100644
> --- a/drivers/media/i2c/max9286.c
> +++ b/drivers/media/i2c/max9286.c
> @@ -161,11 +161,12 @@ struct max9286_source {
>  };
>  
>  struct max9286_asd {

This should be renamed to max9286_asc. I said in the review of a
previous version that I was fine keeping the name as-is, as the
v4l2_async_subdev structure was reintroduced later in the series, but
that's not the case anymore.

> -	struct v4l2_async_subdev base;
> +	struct v4l2_async_connection base;
>  	struct max9286_source *source;
>  };
>  
> -static inline struct max9286_asd *to_max9286_asd(struct v4l2_async_subdev *asd)
> +static inline struct max9286_asd *
> +to_max9286_asd(struct v4l2_async_connection *asd)

s/asd/asc/g

There's more below, in most drivers.

>  {
>  	return container_of(asd, struct max9286_asd, base);
>  }
> @@ -659,7 +660,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
>  
>  static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
>  				struct v4l2_subdev *subdev,
> -				struct v4l2_async_subdev *asd)
> +				struct v4l2_async_connection *asd)
>  {
>  	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
>  	struct max9286_source *source = to_max9286_asd(asd)->source;
> @@ -721,7 +722,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
>  
>  static void max9286_notify_unbind(struct v4l2_async_notifier *notifier,
>  				  struct v4l2_subdev *subdev,
> -				  struct v4l2_async_subdev *asd)
> +				  struct v4l2_async_connection *asd)
>  {
>  	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
>  	struct max9286_source *source = to_max9286_asd(asd)->source;

[snip]

> diff --git a/drivers/media/platform/atmel/atmel-isi.h b/drivers/media/platform/atmel/atmel-isi.h
> index 7ad3895a2c87e..58ce900ca4c90 100644
> --- a/drivers/media/platform/atmel/atmel-isi.h
> +++ b/drivers/media/platform/atmel/atmel-isi.h
> @@ -121,7 +121,7 @@
>  #define ISI_DATAWIDTH_8				0x01
>  #define ISI_DATAWIDTH_10			0x02
>  
> -struct v4l2_async_subdev;
> +struct v4l2_async_connection;

You can actually drop this, it's not used in this file.

>  
>  struct isi_platform_data {
>  	u8 has_emb_sync;

[snip]

> diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> index cb206d3976ddf..c99d64e1cb01f 100644
> --- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> @@ -106,7 +106,7 @@ struct rvin_video_format {
>  
>  /**
>   * struct rvin_parallel_entity - Parallel video input endpoint descriptor
> - * @asd:	sub-device descriptor for async framework
> + * @asc:	sub-device descriptor for async framework

The description of the field should also be updated.

>   * @subdev:	subdevice matched using async framework
>   * @mbus_type:	media bus type
>   * @bus:	media bus parallel configuration
> @@ -115,7 +115,7 @@ struct rvin_video_format {
>   *
>   */
>  struct rvin_parallel_entity {
> -	struct v4l2_async_subdev *asd;
> +	struct v4l2_async_connection *asc;
>  	struct v4l2_subdev *subdev;
>  
>  	enum v4l2_mbus_type mbus_type;
> @@ -275,7 +275,7 @@ struct rvin_dev {
>   * @notifier:		group notifier for CSI-2 async subdevices
>   * @vin:		VIN instances which are part of the group
>   * @link_setup:		Callback to create all links for the media graph
> - * @remotes:		array of pairs of fwnode and subdev pointers
> + * @remotes:		array of pairs of async connection and subdev pointers
>   *			to all remote subdevices.
>   */
>  struct rvin_group {
> @@ -291,7 +291,7 @@ struct rvin_group {
>  	int (*link_setup)(struct rvin_dev *vin);
>  
>  	struct {
> -		struct v4l2_async_subdev *asd;
> +		struct v4l2_async_connection *asc;
>  		struct v4l2_subdev *subdev;
>  	} remotes[RVIN_REMOTES_MAX];
>  };

[snip]

> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 54f9f45ed3d8e..38d9d097fdb52 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -34,7 +34,7 @@ enum v4l2_async_match_type {
>  };
>  
>  /**
> - * struct v4l2_async_match_desc - async sub-device match information
> + * struct v4l2_async_match_desc - async connection match information
>   *
>   * @type:	type of match that will be used
>   * @fwnode:	pointer to &struct fwnode_handle to be matched.
> @@ -62,21 +62,21 @@ struct v4l2_async_match_desc {
>  };
>  
>  /**
> - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> + * struct v4l2_async_connection - connection descriptor, as known to a bridge
>   *
>   * @match:	struct of match type and per-bus type matching data sets
> - * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> - *		master notifier @asd_entry
> - * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> - *		probed, to a notifier->waiting_list list
> + * @asc_entry:	used to add struct v4l2_async_connection objects to the
> + *		master notifier @asc_list
> + * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to
> + *		be probed, to a notifier->waiting_list list
>   *
>   * When this struct is used as a member in a driver specific struct,
>   * the driver specific struct shall contain the &struct
> - * v4l2_async_subdev as its first member.
> + * v4l2_async_connection as its first member.
>   */
> -struct v4l2_async_subdev {
> +struct v4l2_async_connection {
>  	struct v4l2_async_match_desc match;
> -	struct list_head asd_entry;
> +	struct list_head asc_entry;
>  	struct list_head waiting_entry;
>  };
>  
> @@ -86,17 +86,17 @@ struct v4l2_async_subdev {
>   * @complete:	All subdevices have been probed successfully. The complete
>   *		callback is only executed for the root notifier.
>   * @unbind:	a subdevice is leaving
> - * @destroy:	the asd is about to be freed
> + * @destroy:	the asc is about to be freed
>   */
>  struct v4l2_async_notifier_operations {
>  	int (*bound)(struct v4l2_async_notifier *notifier,
>  		     struct v4l2_subdev *subdev,
> -		     struct v4l2_async_subdev *asd);
> +		     struct v4l2_async_connection *asc);
>  	int (*complete)(struct v4l2_async_notifier *notifier);
>  	void (*unbind)(struct v4l2_async_notifier *notifier,
>  		       struct v4l2_subdev *subdev,
> -		       struct v4l2_async_subdev *asd);
> -	void (*destroy)(struct v4l2_async_subdev *asd);
> +		       struct v4l2_async_connection *asc);
> +	void (*destroy)(struct v4l2_async_connection *asc);
>  };
>  
>  /**
> @@ -106,7 +106,7 @@ struct v4l2_async_notifier_operations {
>   * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
>   * @sd:		sub-device that registered the notifier, NULL otherwise
>   * @parent:	parent notifier
> - * @asd_list:	master list of struct v4l2_async_subdev
> + * @asc_list:	master list of struct v4l2_async_subdev

v4l2_async_subdev is no more.

>   * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers

Same here.

>   * @done_list:	list of struct v4l2_subdev, already probed
>   * @notifier_entry: member in a global list of notifiers
> @@ -116,7 +116,7 @@ struct v4l2_async_notifier {
>  	struct v4l2_device *v4l2_dev;
>  	struct v4l2_subdev *sd;
>  	struct v4l2_async_notifier *parent;
> -	struct list_head asd_list;
> +	struct list_head asc_list;
>  	struct list_head waiting_list;
>  	struct list_head done_list;
>  	struct list_head notifier_entry;
> @@ -134,53 +134,53 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   *
> - * This function initializes the notifier @asd_entry. It must be called
> + * This function initializes the notifier @asc_entry. It must be called

This sounds like it should be asc_list. The issues was likely introduced
in an earlier patch in the series.

>   * before adding a subdevice to a notifier, using one of:
>   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
>   * v4l2_async_nf_add_i2c().
>   */
>  void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
>  
> -struct v4l2_async_subdev *
> +struct v4l2_async_connection *
>  __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
>  			   struct fwnode_handle *fwnode,
> -			   unsigned int asd_struct_size);
> +			   unsigned int asc_struct_size);
>  /**
>   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> - *				subdev to the notifier's master asd_entry.
> + *				subdev to the notifier's master asc_entry.

Same here.

>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
>   *	    &struct fwnode_handle
> - * @type: Type of the driver's async sub-device struct. The &struct
> - *	  v4l2_async_subdev shall be the first member of the driver's async
> - *	  sub-device struct, i.e. both begin at the same memory address.
> + * @type: Type of the driver's async sub-device or connection struct. The
> + *	  &struct v4l2_async_connection shall be the first member of the
> + *	  driver's async struct, i.e. both begin at the same memory address.
>   *
> - * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> - * notifiers @asd_entry. The function also gets a reference of the fwnode which
> + * Allocate a fwnode-matched asc of size asc_struct_size, and add it to the
> + * notifiers @asc_entry. The function also gets a reference of the fwnode which

Here too.

>   * is released later at notifier cleanup time.
>   */
>  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
>  	((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type)))
>  
> -struct v4l2_async_subdev *
> +struct v4l2_async_connection *
>  __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
>  				  struct fwnode_handle *endpoint,
> -				  unsigned int asd_struct_size);
> +				  unsigned int asc_struct_size);
>  /**
>   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
>   *						  remote async subdev to the
> - *						  notifier's master asd_entry.
> + *						  notifier's master asc_entry.

And here.

>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @ep: local endpoint pointing to the remote sub-device to be matched,
>   *	pointer to &struct fwnode_handle
>   * @type: Type of the driver's async sub-device struct. The &struct
> - *	  v4l2_async_subdev shall be the first member of the driver's async
> + *	  v4l2_async_connection shall be the first member of the driver's async
>   *	  sub-device struct, i.e. both begin at the same memory address.
>   *
>   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> - * matching and adds the async sub-device to the notifier's @asd_entry. The
> + * matching and adds the async connection to the notifier's @asc_entry. The

Here too again.

>   * function also gets a reference of the fwnode which is released later at
>   * notifier cleanup time.
>   *
> @@ -190,19 +190,19 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
>  #define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \
>  	((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type)))
>  
> -struct v4l2_async_subdev *
> +struct v4l2_async_connection *
>  __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
>  			int adapter_id, unsigned short address,
> -			unsigned int asd_struct_size);
> +			unsigned int asc_struct_size);
>  /**
>   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> - *				subdev to the notifier's master asd_entry.
> + *				subdev to the notifier's master asc_entry.

And finally here.

>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
>   * @adapter: I2C adapter ID to be matched
>   * @address: I2C address of sub-device to be matched
>   * @type: Type of the driver's async sub-device struct. The &struct
> - *	  v4l2_async_subdev shall be the first member of the driver's async
> + *	  v4l2_async_connection shall be the first member of the driver's async
>   *	  sub-device struct, i.e. both begin at the same memory address.

s/sub-device/connection/ ? Please double-check if other instances of
subdev(ice) have been forgotten.

>   *
>   * Same as v4l2_async_nf_add_fwnode() but for I2C matched
> diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
> index 855dae84b751d..4e4a6cf83097a 100644
> --- a/include/media/v4l2-fwnode.h
> +++ b/include/media/v4l2-fwnode.h
> @@ -23,7 +23,7 @@
>  
>  struct fwnode_handle;
>  struct v4l2_async_notifier;
> -struct v4l2_async_subdev;
> +struct v4l2_async_connection;

This is a sign the forward-declaration isn't needed.

>  
>  /**
>   * struct v4l2_fwnode_endpoint - the endpoint data structure
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 82e4cf3dd2e05..215fc8af87614 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -1022,8 +1022,7 @@ struct v4l2_subdev_platform_data {
>   *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
>   * @async_list: Links this subdev to a global subdev_entry or @notifier->done
>   *	list.
> - * @asd: Pointer to respective &struct v4l2_async_subdev.
> - * @notifier: Pointer to the managing notifier.

Did you drop this field by mistake ?

> + * @asd: Pointer to respective &struct v4l2_async_connection.
>   * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
>   *		     device using v4l2_async_register_subdev_sensor().
>   * @pdata: common part of subdevice platform data
> @@ -1065,7 +1064,7 @@ struct v4l2_subdev {
>  	struct device *dev;
>  	struct fwnode_handle *fwnode;
>  	struct list_head async_list;
> -	struct v4l2_async_subdev *asd;
> +	struct v4l2_async_connection *asd;
>  	struct v4l2_async_notifier *notifier;
>  	struct v4l2_async_notifier *subdev_notifier;
>  	struct v4l2_subdev_platform_data *pdata;

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify
  2023-05-25  9:15 ` [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify Sakari Ailus
@ 2023-05-30  5:52   ` Laurent Pinchart
  2023-06-13 16:55     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  5:52 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:15:58PM +0300, Sakari Ailus wrote:
> Add labels for error handling instead of doing it all in individual cases.
> Prepare for more functionality in this function.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 21 ++++++++++++---------
>  1 file changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index b1025dfc27a92..f51f0c37210c9 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -320,10 +320,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  		return ret;
>  
>  	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
> -	if (ret < 0) {
> -		v4l2_device_unregister_subdev(sd);
> -		return ret;
> -	}
> +	if (ret < 0)
> +		goto err_unregister_subdev;
>  
>  	/*
>  	 * Depending of the function of the entities involved, we may want to
> @@ -332,11 +330,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  	 * pad).
>  	 */
>  	ret = v4l2_async_create_ancillary_links(notifier, sd);
> -	if (ret) {
> -		v4l2_async_nf_call_unbind(notifier, sd, asc);
> -		v4l2_device_unregister_subdev(sd);
> -		return ret;
> -	}
> +	if (ret)
> +		goto err_call_unbind;
>  
>  	list_del(&asc->waiting_entry);
>  	sd->asd = asc;
> @@ -363,6 +358,14 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  	subdev_notifier->parent = notifier;
>  
>  	return v4l2_async_nf_try_all_subdevs(subdev_notifier);

Unrelated to this patch, but shoulnd't this have error handling too ?

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

> +
> +err_call_unbind:
> +	v4l2_async_nf_call_unbind(notifier, sd, asc);
> +
> +err_unregister_subdev:
> +	v4l2_device_unregister_subdev(sd);
> +
> +	return ret;
>  }
>  
>  /* Test all async sub-devices in a notifier for a match. */

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections
  2023-05-25  9:15 ` [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections Sakari Ailus
@ 2023-05-30  6:01   ` Laurent Pinchart
  2023-06-13 16:58     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  6:01 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

On Thu, May 25, 2023 at 12:15:59PM +0300, Sakari Ailus wrote:
> The connections are checked for duplicates already when the notifier is
> registered. This is effectively a sanity check for driver (and possibly
> obscure firmware) bugs. Don't do this when adding the connection.

Isn't it better to have this sanity check when the connection is added,
instead of later when the notifier is registered ? The latter is more
difficult to debug. If you want to avoid duplicate checks, could we drop
the one at notifier registration time ?

> Retain the int return type for now. It'll be needed very soon again.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 23 +++++++----------------
>  1 file changed, 7 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index f51f0c37210c9..5dfc6d5f6a7c3 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -475,8 +475,7 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
>   */
>  static bool
>  v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> -			      struct v4l2_async_match_desc *match,
> -			      bool skip_self)
> +			      struct v4l2_async_match_desc *match)
>  {
>  	struct v4l2_async_connection *asc;
>  
> @@ -484,7 +483,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
>  
>  	/* Check that an asd is not being added more than once. */
>  	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
> -		if (skip_self && &asc->match == match)
> +		if (&asc->match == match)
>  			break;
>  		if (v4l2_async_match_equal(&asc->match, match))
>  			return true;
> @@ -499,16 +498,14 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
>  }
>  
>  static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
> -				     struct v4l2_async_match_desc *match,
> -				     bool skip_self)
> +				     struct v4l2_async_match_desc *match)
>  {
>  	struct device *dev = notifier_dev(notifier);
>  
>  	switch (match->type) {
>  	case V4L2_ASYNC_MATCH_TYPE_I2C:
>  	case V4L2_ASYNC_MATCH_TYPE_FWNODE:
> -		if (v4l2_async_nf_has_async_match(notifier, match,
> -						  skip_self)) {
> +		if (v4l2_async_nf_has_async_match(notifier, match)) {
>  			dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
>  			return -EEXIST;
>  		}
> @@ -539,7 +536,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	mutex_lock(&list_lock);
>  
>  	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
> -		ret = v4l2_async_nf_match_valid(notifier, &asc->match, true);
> +		ret = v4l2_async_nf_match_valid(notifier, &asc->match);
>  		if (ret)
>  			goto err_unlock;
>  
> @@ -668,19 +665,13 @@ EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
>  static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
>  					  struct v4l2_async_connection *asc)
>  {
> -	int ret;
> -
>  	mutex_lock(&list_lock);
>  
> -	ret = v4l2_async_nf_match_valid(notifier, &asc->match, false);
> -	if (ret)
> -		goto unlock;
> -
>  	list_add_tail(&asc->asc_entry, &notifier->asc_list);
>  
> -unlock:
>  	mutex_unlock(&list_lock);
> -	return ret;
> +
> +	return 0;
>  }
>  
>  struct v4l2_async_connection *

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists
  2023-05-25  9:16 ` [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists Sakari Ailus
@ 2023-05-30  6:11   ` Laurent Pinchart
  2023-06-22 12:02     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  6:11 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:00PM +0300, Sakari Ailus wrote:
> This patch re-arranges internal V4L2 async lists for preparation of
> supporting multiple connections per sub-device as well as cleaning up used
> lists.
> 
> The list of unbound V4L2 sub-devices is maintained for the purpose of
> listing those sub-devices only, not for their binding status. Also, the
> V4L2 async connections have a single list entry in the notifier's list, be
> that either waiting or done lists, while the notifier's asc_list is
> removed.

Please use the imperative style in commit messages. To me it's unclear
if "is" here refers to the status before or after this patch. I need a
clear description of what you're doing in order to check if the code
matches the intent. Guessing the intent from the code makes review more
difficult and less useful.

> The one-to-one relation between a sub-device and a connection is still
> maintained in this patch.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |   2 +-
>  .../platform/renesas/rcar-vin/rcar-core.c     |   2 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-core.c   |   2 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c   |   8 +-
>  drivers/media/v4l2-core/v4l2-async.c          | 102 +++++++++---------
>  .../staging/media/imx/imx-media-dev-common.c  |   2 +-
>  drivers/staging/media/tegra-video/vi.c        |   6 +-
>  include/media/v4l2-async.h                    |   9 +-
>  8 files changed, 68 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 1893d1ff4f169..0f43b5e10f187 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
>  	unsigned int pad;
>  	int ret;
>  
> -	list_for_each_entry(asd, &cio2->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &cio2->notifier.done_list, asc_entry) {
>  		s_asd = to_sensor_asd(asd);
>  		q = &cio2->queue[s_asd->csi2.port];
>  
> diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> index b0f76477b54c7..498778eb9892b 100644
> --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> @@ -396,7 +396,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
>  		}
>  	}
>  
> -	if (list_empty(&vin->group->notifier.asc_list))
> +	if (list_empty(&vin->group->notifier.waiting_list))
>  		return 0;
>  
>  	vin->group->notifier.ops = &rvin_group_notify_ops;
> diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> index 2d1093997db52..e026ed5337513 100644
> --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> @@ -191,7 +191,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
>  
>  	cru->notifier.ops = &rzg2l_cru_async_ops;
>  
> -	if (list_empty(&cru->notifier.asc_list))
> +	if (list_empty(&cru->notifier.waiting_list))
>  		return 0;
>  
>  	ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier);
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index 96fbbc55eb12c..a535a7584da0f 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
>  	struct xvip_graph_entity *entity;
>  	struct v4l2_async_connection *asd;
>  
> -	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) {
>  		entity = to_xvip_entity(asd);
>  		if (entity->asd.match.fwnode == fwnode)
>  			return entity;
> @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
>  
>  	/* Create links for every entity. */
> -	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) {
>  		entity = to_xvip_entity(asd);
>  		ret = xvip_graph_build_one(xdev, entity);
>  		if (ret < 0)
> @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
>  	if (ret < 0)
>  		return 0;
>  
> -	list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &xdev->notifier.waiting_list, asc_entry) {
>  		entity = to_xvip_entity(asd);
>  		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
>  		if (ret < 0) {
> @@ -501,7 +501,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
>  		goto done;
>  	}
>  
> -	if (list_empty(&xdev->notifier.asc_list)) {
> +	if (list_empty(&xdev->notifier.waiting_list)) {
>  		dev_err(xdev->dev, "no subdev found in graph\n");
>  		ret = -ENOENT;
>  		goto done;
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 5dfc6d5f6a7c3..d8de9ff3249d4 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -160,7 +160,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
>  		      struct v4l2_async_match_desc *match);
>  	struct v4l2_async_connection *asc;
>  
> -	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry) {
> +	list_for_each_entry(asc, &notifier->waiting_list, asc_entry) {
>  		/* bus_type has been verified valid before */
>  		switch (asc->match.type) {
>  		case V4L2_ASYNC_MATCH_TYPE_I2C:
> @@ -232,14 +232,14 @@ v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier *notifier)
>  static bool
>  v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
>  {
> -	struct v4l2_subdev *sd;
> +	struct v4l2_async_connection *asc;
>  
>  	if (!list_empty(&notifier->waiting_list))
>  		return false;
>  
> -	list_for_each_entry(sd, &notifier->done_list, async_list) {
> +	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
>  		struct v4l2_async_notifier *subdev_notifier =
> -			v4l2_async_find_subdev_notifier(sd);
> +			v4l2_async_find_subdev_notifier(asc->sd);
>  
>  		if (subdev_notifier &&
>  		    !v4l2_async_nf_can_complete(subdev_notifier))
> @@ -333,12 +333,13 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  	if (ret)
>  		goto err_call_unbind;
>  
> -	list_del(&asc->waiting_entry);
>  	sd->asd = asc;
>  	sd->notifier = notifier;
>  
> -	/* Move from the global subdevice list to notifier's done */
> -	list_move(&sd->async_list, &notifier->done_list);
> +	asc->sd = sd;
> +
> +	/* Move from the waiting list to notifier's done */
> +	list_move(&asc->asc_entry, &notifier->done_list);
>  
>  	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
>  		dev_name(sd->dev), ret);
> @@ -422,25 +423,23 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
>  
>  /* Unbind all sub-devices in the notifier tree. */
>  static void
> -v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
> -				 bool readd)
> +v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
>  {
> -	struct v4l2_subdev *sd, *tmp;
> +	struct v4l2_async_connection *asc, *asc_tmp;
>  
> -	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
> +	list_for_each_entry_safe(asc, asc_tmp, &notifier->done_list,
> +				 asc_entry) {
>  		struct v4l2_async_notifier *subdev_notifier =
> -			v4l2_async_find_subdev_notifier(sd);
> +			v4l2_async_find_subdev_notifier(asc->sd);
>  
>  		if (subdev_notifier)
> -			v4l2_async_nf_unbind_all_subdevs(subdev_notifier, true);
> +			v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
>  
> -		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> -		if (readd)
> -			list_add_tail(&sd->asd->waiting_entry,
> -				      &notifier->waiting_list);
> -		v4l2_async_cleanup(sd);
> -
> -		list_move(&sd->async_list, &subdev_list);
> +		v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
> +		v4l2_async_cleanup(asc->sd);
> +		list_move_tail(&asc->asc_entry, &notifier->waiting_list);
> +		list_move(&asc->sd->async_list, &subdev_list);
> +		asc->sd = NULL;
>  	}
>  
>  	notifier->parent = NULL;
> @@ -452,17 +451,16 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
>  				    struct v4l2_async_match_desc *match)
>  {
>  	struct v4l2_async_connection *asc;
> -	struct v4l2_subdev *sd;
>  
> -	list_for_each_entry(asc, &notifier->waiting_list, waiting_entry)
> +	list_for_each_entry(asc, &notifier->waiting_list, asc_entry)
>  		if (v4l2_async_match_equal(&asc->match, match))
>  			return true;
>  
> -	list_for_each_entry(sd, &notifier->done_list, async_list) {
> -		if (WARN_ON(!sd->asd))
> +	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
> +		if (WARN_ON(!asc->sd->asd))
>  			continue;
>  
> -		if (v4l2_async_match_equal(&sd->asd->match, match))
> +		if (v4l2_async_match_equal(&asc->match, match))
>  			return true;
>  	}
>  
> @@ -477,16 +475,24 @@ static bool
>  v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
>  			      struct v4l2_async_match_desc *match)
>  {
> -	struct v4l2_async_connection *asc;
> +	struct list_head *heads[] = {
> +		&notifier->waiting_list,
> +		&notifier->done_list,
> +	};
> +	unsigned int i;
>  
>  	lockdep_assert_held(&list_lock);
>  
>  	/* Check that an asd is not being added more than once. */
> -	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
> -		if (&asc->match == match)
> -			break;
> -		if (v4l2_async_match_equal(&asc->match, match))
> -			return true;
> +	for (i = 0; i < ARRAY_SIZE(heads); i++) {
> +		struct v4l2_async_connection *asc;
> +
> +		list_for_each_entry(asc, heads[i], asc_entry) {
> +			if (&asc->match == match)
> +				break;
> +			if (v4l2_async_match_equal(&asc->match, match))
> +				return true;
> +		}
>  	}
>  
>  	/* Check that an asc does not exist in other notifiers. */
> @@ -521,7 +527,8 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
>  
>  void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
>  {
> -	INIT_LIST_HEAD(&notifier->asc_list);
> +	INIT_LIST_HEAD(&notifier->waiting_list);
> +	INIT_LIST_HEAD(&notifier->done_list);
>  }
>  EXPORT_SYMBOL(v4l2_async_nf_init);
>  
> @@ -530,17 +537,12 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	struct v4l2_async_connection *asc;
>  	int ret;
>  
> -	INIT_LIST_HEAD(&notifier->waiting_list);
> -	INIT_LIST_HEAD(&notifier->done_list);
> -
>  	mutex_lock(&list_lock);
>  
> -	list_for_each_entry(asc, &notifier->asc_list, asc_entry) {
> +	list_for_each_entry(asc, &notifier->waiting_list, asc_entry) {
>  		ret = v4l2_async_nf_match_valid(notifier, &asc->match);
>  		if (ret)
>  			goto err_unlock;
> -
> -		list_add_tail(&asc->waiting_entry, &notifier->waiting_list);
>  	}
>  
>  	ret = v4l2_async_nf_try_all_subdevs(notifier);
> @@ -562,7 +564,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	/*
>  	 * On failure, unbind all sub-devices registered through this notifier.
>  	 */
> -	v4l2_async_nf_unbind_all_subdevs(notifier, false);
> +	v4l2_async_nf_unbind_all_subdevs(notifier);
>  
>  err_unlock:
>  	mutex_unlock(&list_lock);
> @@ -612,7 +614,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
>  	if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
>  		return;
>  
> -	v4l2_async_nf_unbind_all_subdevs(notifier, false);
> +	v4l2_async_nf_unbind_all_subdevs(notifier);
>  
>  	notifier->sd = NULL;
>  	notifier->v4l2_dev = NULL;
> @@ -634,10 +636,12 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  {
>  	struct v4l2_async_connection *asc, *tmp;
>  
> -	if (!notifier || !notifier->asc_list.next)
> +	if (!notifier || !notifier->waiting_list.next)
>  		return;
>  
> -	list_for_each_entry_safe(asc, tmp, &notifier->asc_list, asc_entry) {
> +	WARN_ON(!list_empty(&notifier->done_list));
> +
> +	list_for_each_entry_safe(asc, tmp, &notifier->waiting_list, asc_entry) {
>  		switch (asc->match.type) {
>  		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
>  			fwnode_handle_put(asc->match.fwnode);
> @@ -667,7 +671,7 @@ static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
>  {
>  	mutex_lock(&list_lock);
>  
> -	list_add_tail(&asc->asc_entry, &notifier->asc_list);
> +	list_add_tail(&asc->asc_entry, &notifier->waiting_list);
>  
>  	mutex_unlock(&list_lock);
>  
> @@ -808,10 +812,12 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
>  	 */
>  	subdev_notifier = v4l2_async_find_subdev_notifier(sd);
>  	if (subdev_notifier)
> -		v4l2_async_nf_unbind_all_subdevs(subdev_notifier, false);
> +		v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
>  
> -	if (sd->asd)
> +	if (sd->asd) {
>  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> +		sd->asd->sd = NULL;
> +	}
>  	v4l2_async_cleanup(sd);
>  
>  	mutex_unlock(&list_lock);
> @@ -837,9 +843,9 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
>  	if (sd->asd) {
>  		struct v4l2_async_notifier *notifier = sd->notifier;
>  
> -		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
> -
> +		list_move(&sd->asd->asc_entry, &notifier->waiting_list);
>  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> +		sd->asd->sd = NULL;
>  	}
>  
>  	v4l2_async_cleanup(sd);
> @@ -893,7 +899,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
>  
>  	list_for_each_entry(notif, &notifier_list, notifier_entry) {
>  		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
> -		list_for_each_entry(asc, &notif->waiting_list, waiting_entry)
> +		list_for_each_entry(asc, &notif->waiting_list, asc_entry)
>  			print_waiting_match(s, &asc->match);
>  	}
>  
> diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
> index c1216b4557b69..67c1b16db6558 100644
> --- a/drivers/staging/media/imx/imx-media-dev-common.c
> +++ b/drivers/staging/media/imx/imx-media-dev-common.c
> @@ -384,7 +384,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
>  	int ret;
>  
>  	/* no subdevs? just bail */
> -	if (list_empty(&imxmd->notifier.asc_list)) {
> +	if (list_empty(&imxmd->notifier.waiting_list)) {
>  		v4l2_err(&imxmd->v4l2_dev, "no subdevs\n");
>  		return -ENODEV;
>  	}
> diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
> index c93e5ac9dbf0c..146b4fd3c8b52 100644
> --- a/drivers/staging/media/tegra-video/vi.c
> +++ b/drivers/staging/media/tegra-video/vi.c
> @@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
>  	struct tegra_vi_graph_entity *entity;
>  	struct v4l2_async_connection *asd;
>  
> -	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) {
>  		entity = to_tegra_vi_graph_entity(asd);
>  		if (entity->asd.match.fwnode == fwnode)
>  			return entity;
> @@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  	}
>  
>  	/* create links between the entities */
> -	list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) {
> +	list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) {
>  		entity = to_tegra_vi_graph_entity(asd);
>  		ret = tegra_vi_graph_build(chan, entity);
>  		if (ret < 0)
> @@ -1876,7 +1876,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
>  
>  		ret = tegra_vi_graph_parse_one(chan, remote);
>  		fwnode_handle_put(remote);
> -		if (ret < 0 || list_empty(&chan->notifier.asc_list))
> +		if (ret < 0 || list_empty(&chan->notifier.waiting_list))
>  			continue;
>  
>  		chan->notifier.ops = &tegra_vi_async_ops;
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 38d9d097fdb52..56b7238e2cbe2 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -66,9 +66,8 @@ struct v4l2_async_match_desc {
>   *
>   * @match:	struct of match type and per-bus type matching data sets
>   * @asc_entry:	used to add struct v4l2_async_connection objects to the
> - *		master notifier @asc_list
> - * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to
> - *		be probed, to a notifier->waiting_list list
> + *		notifier @waiting_list or @done_list
> + * @sd:		the related sub-device
>   *
>   * When this struct is used as a member in a driver specific struct,
>   * the driver specific struct shall contain the &struct
> @@ -77,7 +76,7 @@ struct v4l2_async_match_desc {
>  struct v4l2_async_connection {
>  	struct v4l2_async_match_desc match;
>  	struct list_head asc_entry;
> -	struct list_head waiting_entry;
> +	struct v4l2_subdev *sd;
>  };
>  
>  /**
> @@ -106,7 +105,6 @@ struct v4l2_async_notifier_operations {
>   * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
>   * @sd:		sub-device that registered the notifier, NULL otherwise
>   * @parent:	parent notifier
> - * @asc_list:	master list of struct v4l2_async_subdev
>   * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
>   * @done_list:	list of struct v4l2_subdev, already probed
>   * @notifier_entry: member in a global list of notifiers
> @@ -116,7 +114,6 @@ struct v4l2_async_notifier {
>  	struct v4l2_device *v4l2_dev;
>  	struct v4l2_subdev *sd;
>  	struct v4l2_async_notifier *parent;
> -	struct list_head asc_list;
>  	struct list_head waiting_list;
>  	struct list_head done_list;
>  	struct list_head notifier_entry;

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers
  2023-05-25  9:16 ` [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
@ 2023-05-30  6:18   ` Laurent Pinchart
  2023-06-20 10:14     ` Sakari Ailus
  2023-05-30 12:13   ` Aishwarya Kothari
  1 sibling, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  6:18 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:15PM +0300, Sakari Ailus wrote:
> Document that sub-device notifiers are now registered using
> v4l2_async_subdev_nf_init(). No documentation is changed as it seems that
> sub-device notifiers were not documented apart from kernel-doc comments.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  Documentation/driver-api/media/v4l2-subdev.rst | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> index 83d3d29608136..d62b341642c96 100644
> --- a/Documentation/driver-api/media/v4l2-subdev.rst
> +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> @@ -193,9 +193,7 @@ picked up by bridge drivers.
>  Bridge drivers in turn have to register a notifier object. This is
>  performed using the :c:func:`v4l2_async_nf_register` call. To
>  unregister the notifier the driver has to call
> -:c:func:`v4l2_async_nf_unregister`. The former of the two functions
> -takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
> -pointer to struct :c:type:`v4l2_async_notifier`.
> +:c:func:`v4l2_async_nf_unregister`.
>  
>  Before registering the notifier, bridge drivers must do two things: first, the
>  notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
> @@ -204,6 +202,12 @@ that the bridge device needs for its operation. Several functions are available
>  to add subdevice descriptors to a notifier, depending on the type of device and
>  the needs of the driver.
>  
> +For a sub-device driver to register a notifier, the process is otherwise similar
> +to that of a bridge driver, apart from that the notifier is initialised using
> +:c:func:`v4l2_async_subdev_nf_init` instead. A sub-device notifier may complete
> +only after the V4L2 device becomes available, i.e. there's a path via async
> +sub-devices and notifiers to that root notifier.

This is correct, but I doubt anyone who doesn't have an in-depth
knowledge of the v4l2-async framework will be able to understand it. For
instance, the concept of "root notifier" isn't explained anywhere. And
the v4l2_async_subdev_nf_register() function isn't mentioned.

The v4l2-async documentation needs a rewrite.

> +
>  :c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
>  :c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
>  :c:with the notifier.

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init
  2023-05-25  9:16 ` [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init Sakari Ailus
@ 2023-05-30  6:22   ` Laurent Pinchart
  2023-06-14 12:43     ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Laurent Pinchart @ 2023-05-30  6:22 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Sakari,

Thank you for the patch.

On Thu, May 25, 2023 at 12:16:14PM +0300, Sakari Ailus wrote:
> Set the v4l2_device already in async notifier init, so struct device
> related to it will be available before the notifier is registered.
> 
> This is done in order to make struct device available earlier, during
> construction of the async connections, for sensible debug prints.

I'm worried that the tighter dependency between the notifier and the
v4l2_device will cause issues later. If it's just to get a struct device
pointer, wouldn't it be better to pass the struct device to
v4l2_async_nf_init() ?

> This patch has been mostly generated using the following two commands:
> 
> git grep -l v4l2_async_nf_init -- drivers/media/ drivers/staging/media/ |
> 	while read i; do perl -e '
> 	@a=<>; unlink("'$i'"); open(F, "> '$i'");
> 	for $f ({i=>"v4l2_async_nf_init", r=>"v4l2_async_nf_register"},
> 		{i=>"v4l2_async_subdev_nf_init",
> 		 r=>"v4l2_async_subdev_nf_register"} ) {
> 	my $b; @a = map { $b = "$1, $2" if
> 	s/$f->{r}\(([^,]*),\s*([^\)]*)\)/v4l2_async_nf_register\($2\)/;
> 	$_; } @a; @a = map { if (defined $b) {
> 	s/v4l2_async_nf_init\([^\)]*\)/$f->{i}\($b\)/;
> 	s/$f->{r}\(\K[^,]*,\s*//; }; $_; } @a; }; print F @a; close F;'
> 	< $i; done
> 
> git grep -lP 'v4l2_async_(subdev_|)nf_init' | xargs perl -i -pe \
> 	's/v4l2_async_(subdev_|)nf_init\(\K([^,]*),\s*([^,]*)\)/$3, $2\)/'

It may be nice to play with perl code, but I'd like more focus on the
human-readable part of the commit message, please. The above isn't
useful to anyone but you, while an English text that explains how the
v4l2_async_nf_init() function has now been split into
v4l2_async_nf_init() and v4l2_async_subdev_nf_init() is missing.

> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/i2c/max9286.c                   |  4 +-
>  drivers/media/i2c/st-mipid02.c                |  4 +-
>  drivers/media/i2c/tc358746.c                  |  4 +-
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  4 +-
>  drivers/media/platform/atmel/atmel-isi.c      |  4 +-
>  drivers/media/platform/cadence/cdns-csi2rx.c  |  4 +-
>  drivers/media/platform/intel/pxa_camera.c     |  4 +-
>  drivers/media/platform/marvell/cafe-driver.c  |  2 +-
>  drivers/media/platform/marvell/mcam-core.c    |  2 +-
>  drivers/media/platform/marvell/mmp-driver.c   |  2 +-
>  .../platform/microchip/microchip-csi2dc.c     |  5 +--
>  .../microchip/microchip-sama5d2-isc.c         |  5 +--
>  .../microchip/microchip-sama7g5-isc.c         |  5 +--
>  drivers/media/platform/nxp/imx-mipi-csis.c    |  4 +-
>  drivers/media/platform/nxp/imx7-media-csi.c   |  4 +-
>  .../platform/nxp/imx8-isi/imx8-isi-core.c     |  4 +-
>  drivers/media/platform/qcom/camss/camss.c     |  5 +--
>  drivers/media/platform/renesas/rcar-isp.c     |  4 +-
>  .../platform/renesas/rcar-vin/rcar-core.c     |  8 ++--
>  .../platform/renesas/rcar-vin/rcar-csi2.c     |  4 +-
>  drivers/media/platform/renesas/rcar_drif.c    |  4 +-
>  drivers/media/platform/renesas/renesas-ceu.c  |  4 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  4 +-
>  .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |  4 +-
>  .../platform/rockchip/rkisp1/rkisp1-dev.c     |  4 +-
>  .../platform/samsung/exynos4-is/media-dev.c   |  5 +--
>  drivers/media/platform/st/stm32/stm32-dcmi.c  |  4 +-
>  .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  4 +-
>  .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |  6 +--
>  .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |  4 +-
>  .../sun8i_a83t_mipi_csi2.c                    |  4 +-
>  .../media/platform/ti/am437x/am437x-vpfe.c    |  4 +-
>  drivers/media/platform/ti/cal/cal.c           |  4 +-
>  .../media/platform/ti/davinci/vpif_capture.c  | 11 ++---
>  drivers/media/platform/ti/omap3isp/isp.c      |  4 +-
>  drivers/media/platform/video-mux.c            |  4 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c   |  4 +-
>  drivers/media/v4l2-core/v4l2-async.c          | 44 +++++++------------
>  drivers/media/v4l2-core/v4l2-fwnode.c         |  4 +-
>  .../deprecated/atmel/atmel-sama5d2-isc.c      |  5 +--
>  .../deprecated/atmel/atmel-sama7g5-isc.c      |  5 +--
>  drivers/staging/media/imx/imx-media-csi.c     |  4 +-
>  .../staging/media/imx/imx-media-dev-common.c  |  4 +-
>  drivers/staging/media/imx/imx6-mipi-csi2.c    |  4 +-
>  drivers/staging/media/imx/imx8mq-mipi-csi2.c  |  4 +-
>  .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |  4 +-
>  drivers/staging/media/tegra-video/vi.c        |  4 +-
>  include/media/v4l2-async.h                    | 33 ++++++++------
>  48 files changed, 132 insertions(+), 143 deletions(-)
> 
> diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
> index 44def5e3ba5d1..5f13d75f591ad 100644
> --- a/drivers/media/i2c/max9286.c
> +++ b/drivers/media/i2c/max9286.c
> @@ -746,7 +746,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
>  	if (!priv->nsources)
>  		return 0;
>  
> -	v4l2_async_nf_init(&priv->notifier);
> +	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
>  
>  	for_each_source(priv, source) {
>  		unsigned int i = to_index(priv, source);
> @@ -766,7 +766,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
>  
>  	priv->notifier.ops = &max9286_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
> +	ret = v4l2_async_nf_register(&priv->notifier);
>  	if (ret) {
>  		dev_err(dev, "Failed to register subdev_notifier");
>  		v4l2_async_nf_cleanup(&priv->notifier);
> diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
> index daea4cb29ec83..d3810e137ba52 100644
> --- a/drivers/media/i2c/st-mipid02.c
> +++ b/drivers/media/i2c/st-mipid02.c
> @@ -902,7 +902,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
>  	bridge->rx = ep;
>  
>  	/* register async notifier so we get noticed when sensor is connected */
> -	v4l2_async_nf_init(&bridge->notifier);
> +	v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd);
>  	asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
>  					      of_fwnode_handle(ep_node),
>  					      struct v4l2_async_connection);
> @@ -915,7 +915,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
>  	}
>  	bridge->notifier.ops = &mipid02_notifier_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier);
> +	ret = v4l2_async_nf_register(&bridge->notifier);
>  	if (ret)
>  		v4l2_async_nf_cleanup(&bridge->notifier);
>  
> diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
> index a455848d60c15..6e4c484ae1bdc 100644
> --- a/drivers/media/i2c/tc358746.c
> +++ b/drivers/media/i2c/tc358746.c
> @@ -1460,7 +1460,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
>  		return err;
>  	}
>  
> -	v4l2_async_nf_init(&tc358746->notifier);
> +	v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd);
>  	asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep,
>  					      struct v4l2_async_connection);
>  	fwnode_handle_put(ep);
> @@ -1472,7 +1472,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
>  
>  	tc358746->notifier.ops = &tc358746_notify_ops;
>  
> -	err = v4l2_async_subdev_nf_register(&tc358746->sd, &tc358746->notifier);
> +	err = v4l2_async_nf_register(&tc358746->notifier);
>  	if (err)
>  		goto err_cleanup;
>  
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 0f43b5e10f187..8de03d007d0b7 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1502,7 +1502,7 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
>  	 * suspend.
>  	 */
>  	cio2->notifier.ops = &cio2_async_ops;
> -	ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier);
> +	ret = v4l2_async_nf_register(&cio2->notifier);
>  	if (ret)
>  		dev_err(dev, "failed to register async notifier : %d\n", ret);
>  
> @@ -1797,7 +1797,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
>  	if (r)
>  		goto fail_v4l2_device_unregister;
>  
> -	v4l2_async_nf_init(&cio2->notifier);
> +	v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev);
>  
>  	/* Register notifier for subdevices we care */
>  	r = cio2_parse_firmware(cio2);
> diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
> index 7dbad99d4e45e..121eaa6994084 100644
> --- a/drivers/media/platform/atmel/atmel-isi.c
> +++ b/drivers/media/platform/atmel/atmel-isi.c
> @@ -1159,7 +1159,7 @@ static int isi_graph_init(struct atmel_isi *isi)
>  	if (!ep)
>  		return -EINVAL;
>  
> -	v4l2_async_nf_init(&isi->notifier);
> +	v4l2_async_nf_init(&isi->notifier, &isi->v4l2_dev);
>  
>  	asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier,
>  					      of_fwnode_handle(ep),
> @@ -1171,7 +1171,7 @@ static int isi_graph_init(struct atmel_isi *isi)
>  
>  	isi->notifier.ops = &isi_graph_notify_ops;
>  
> -	ret = v4l2_async_nf_register(&isi->v4l2_dev, &isi->notifier);
> +	ret = v4l2_async_nf_register(&isi->notifier);
>  	if (ret < 0) {
>  		dev_err(isi->dev, "Notifier registration failed\n");
>  		v4l2_async_nf_cleanup(&isi->notifier);
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index b0731c07eace0..d7d6b63306521 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -399,7 +399,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>  		return -EINVAL;
>  	}
>  
> -	v4l2_async_nf_init(&csi2rx->notifier);
> +	v4l2_async_subdev_nf_init(&csi2rx->notifier, &csi2rx->subdev);
>  
>  	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
>  					      struct v4l2_async_connection);
> @@ -409,7 +409,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>  
>  	csi2rx->notifier.ops = &csi2rx_notifier_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&csi2rx->subdev, &csi2rx->notifier);
> +	ret = v4l2_async_nf_register(&csi2rx->notifier);
>  	if (ret)
>  		v4l2_async_nf_cleanup(&csi2rx->notifier);
>  
> diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> index 5df93fd4ff04b..44edd4bdc2c11 100644
> --- a/drivers/media/platform/intel/pxa_camera.c
> +++ b/drivers/media/platform/intel/pxa_camera.c
> @@ -2311,7 +2311,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  	if (err)
>  		return err;
>  
> -	v4l2_async_nf_init(&pcdev->notifier);
> +	v4l2_async_nf_init(&pcdev->notifier, &pcdev->v4l2_dev);
>  	pcdev->res = res;
>  	pcdev->pdata = pdev->dev.platform_data;
>  	if (pcdev->pdata) {
> @@ -2403,7 +2403,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
>  		goto exit_deactivate;
>  
>  	pcdev->notifier.ops = &pxa_camera_sensor_ops;
> -	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
> +	err = v4l2_async_nf_register(&pcdev->notifier);
>  	if (err)
>  		goto exit_deactivate;
>  
> diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
> index fbfbb9f67ddfc..ef810249def61 100644
> --- a/drivers/media/platform/marvell/cafe-driver.c
> +++ b/drivers/media/platform/marvell/cafe-driver.c
> @@ -540,7 +540,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  	if (ret)
>  		goto out_smbus_shutdown;
>  
> -	v4l2_async_nf_init(&mcam->notifier);
> +	v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev);
>  
>  	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
>  				    i2c_adapter_id(cam->i2c_adapter),
> diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
> index bcfcecdb03ea2..dbcd4f15bda30 100644
> --- a/drivers/media/platform/marvell/mcam-core.c
> +++ b/drivers/media/platform/marvell/mcam-core.c
> @@ -1873,7 +1873,7 @@ int mccic_register(struct mcam_camera *cam)
>  	cam->mbus_code = mcam_def_mbus_code;
>  
>  	cam->notifier.ops = &mccic_notify_ops;
> -	ret = v4l2_async_nf_register(&cam->v4l2_dev, &cam->notifier);
> +	ret = v4l2_async_nf_register(&cam->notifier);
>  	if (ret < 0) {
>  		cam_warn(cam, "failed to register a sensor notifier");
>  		goto out;
> diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c
> index dbc1368b91210..76e0ac9cd34f3 100644
> --- a/drivers/media/platform/marvell/mmp-driver.c
> +++ b/drivers/media/platform/marvell/mmp-driver.c
> @@ -239,7 +239,7 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	if (!ep)
>  		return -ENODEV;
>  
> -	v4l2_async_nf_init(&mcam->notifier);
> +	v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev);
>  
>  	asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep,
>  					      struct v4l2_async_connection);
> diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c
> index d631c3880c536..988c1cc1d8b6b 100644
> --- a/drivers/media/platform/microchip/microchip-csi2dc.c
> +++ b/drivers/media/platform/microchip/microchip-csi2dc.c
> @@ -523,7 +523,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc,
>  	struct v4l2_async_connection *asd;
>  	int ret = 0;
>  
> -	v4l2_async_nf_init(&csi2dc->notifier);
> +	v4l2_async_subdev_nf_init(&csi2dc->notifier, &csi2dc->csi2dc_sd);
>  
>  	asd = v4l2_async_nf_add_fwnode_remote(&csi2dc->notifier,
>  					      input_fwnode,
> @@ -542,8 +542,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc,
>  
>  	csi2dc->notifier.ops = &csi2dc_async_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&csi2dc->csi2dc_sd,
> -					    &csi2dc->notifier);
> +	ret = v4l2_async_nf_register(&csi2dc->notifier);
>  	if (ret) {
>  		dev_err(csi2dc->dev, "fail to register async notifier: %d\n",
>  			ret);
> diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
> index 10e6cebf629e6..d78d289bd4250 100644
> --- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
> +++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
> @@ -529,7 +529,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
>  		struct fwnode_handle *fwnode =
>  			of_fwnode_handle(subdev_entity->epn);
>  
> -		v4l2_async_nf_init(&subdev_entity->notifier);
> +		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
>  
>  		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
>  						      fwnode,
> @@ -545,8 +545,7 @@ static int microchip_isc_probe(struct platform_device *pdev)
>  
>  		subdev_entity->notifier.ops = &microchip_isc_async_ops;
>  
> -		ret = v4l2_async_nf_register(&isc->v4l2_dev,
> -					     &subdev_entity->notifier);
> +		ret = v4l2_async_nf_register(&subdev_entity->notifier);
>  		if (ret) {
>  			dev_err(dev, "fail to register async notifier\n");
>  			goto cleanup_subdev;
> diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
> index 324810dbdc3af..6d556bb42c12a 100644
> --- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
> +++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
> @@ -519,7 +519,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
>  		struct fwnode_handle *fwnode =
>  			of_fwnode_handle(subdev_entity->epn);
>  
> -		v4l2_async_nf_init(&subdev_entity->notifier);
> +		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
>  
>  		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
>  						      fwnode,
> @@ -535,8 +535,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
>  
>  		subdev_entity->notifier.ops = &microchip_isc_async_ops;
>  
> -		ret = v4l2_async_nf_register(&isc->v4l2_dev,
> -					     &subdev_entity->notifier);
> +		ret = v4l2_async_nf_register(&subdev_entity->notifier);
>  		if (ret) {
>  			dev_err(dev, "fail to register async notifier\n");
>  			goto cleanup_subdev;
> diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
> index 390834ce482bd..c0439bd86b21b 100644
> --- a/drivers/media/platform/nxp/imx-mipi-csis.c
> +++ b/drivers/media/platform/nxp/imx-mipi-csis.c
> @@ -1252,7 +1252,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
>  	unsigned int i;
>  	int ret;
>  
> -	v4l2_async_nf_init(&csis->notifier);
> +	v4l2_async_subdev_nf_init(&csis->notifier, &csis->sd);
>  
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
> @@ -1288,7 +1288,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis)
>  
>  	csis->notifier.ops = &mipi_csis_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&csis->sd, &csis->notifier);
> +	ret = v4l2_async_nf_register(&csis->notifier);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
> index 75b7ad65a1141..a9933a97dbef9 100644
> --- a/drivers/media/platform/nxp/imx7-media-csi.c
> +++ b/drivers/media/platform/nxp/imx7-media-csi.c
> @@ -2107,7 +2107,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> -	v4l2_async_nf_init(&csi->notifier);
> +	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
>  
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
> @@ -2130,7 +2130,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
>  
>  	csi->notifier.ops = &imx7_csi_notify_ops;
>  
> -	ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier);
> +	ret = v4l2_async_nf_register(&csi->notifier);
>  	if (ret)
>  		goto error;
>  
> diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> index a09f416a64c4f..8d332ac328888 100644
> --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> @@ -175,7 +175,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi)
>  	}
>  
>  	/* Initialize, fill and register the async notifier. */
> -	v4l2_async_nf_init(&isi->notifier);
> +	v4l2_async_nf_init(&isi->notifier, v4l2_dev);
>  	isi->notifier.ops = &mxc_isi_async_notifier_ops;
>  
>  	for (i = 0; i < isi->pdata->num_ports; ++i) {
> @@ -200,7 +200,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi)
>  		masd->port = i;
>  	}
>  
> -	ret = v4l2_async_nf_register(v4l2_dev, &isi->notifier);
> +	ret = v4l2_async_nf_register(&isi->notifier);
>  	if (ret < 0) {
>  		dev_err(isi->dev,
>  			"Failed to register async notifier: %d\n", ret);
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index b89e2bb5b505e..f11dc59135a5a 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -1640,7 +1640,7 @@ static int camss_probe(struct platform_device *pdev)
>  		goto err_cleanup;
>  	}
>  
> -	v4l2_async_nf_init(&camss->notifier);
> +	v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev);
>  
>  	num_subdevs = camss_of_parse_ports(camss);
>  	if (num_subdevs < 0) {
> @@ -1655,8 +1655,7 @@ static int camss_probe(struct platform_device *pdev)
>  	if (num_subdevs) {
>  		camss->notifier.ops = &camss_subdev_notifier_ops;
>  
> -		ret = v4l2_async_nf_register(&camss->v4l2_dev,
> -					     &camss->notifier);
> +		ret = v4l2_async_nf_register(&camss->notifier);
>  		if (ret) {
>  			dev_err(dev,
>  				"Failed to register async subdev nodes: %d\n",
> diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c
> index 5d6d9ffb5201d..452d3b8da7e1c 100644
> --- a/drivers/media/platform/renesas/rcar-isp.c
> +++ b/drivers/media/platform/renesas/rcar-isp.c
> @@ -392,7 +392,7 @@ static int risp_parse_dt(struct rcar_isp *isp)
>  
>  	dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode));
>  
> -	v4l2_async_nf_init(&isp->notifier);
> +	v4l2_async_subdev_nf_init(&isp->notifier, &isp->subdev);
>  	isp->notifier.ops = &risp_notify_ops;
>  
>  	asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode,
> @@ -401,7 +401,7 @@ static int risp_parse_dt(struct rcar_isp *isp)
>  	if (IS_ERR(asd))
>  		return PTR_ERR(asd);
>  
> -	ret = v4l2_async_subdev_nf_register(&isp->subdev, &isp->notifier);
> +	ret = v4l2_async_nf_register(&isp->notifier);
>  	if (ret)
>  		v4l2_async_nf_cleanup(&isp->notifier);
>  
> diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> index 498778eb9892b..65be0f4c88457 100644
> --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
> @@ -376,7 +376,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
>  
>  	mutex_unlock(&vin->group->lock);
>  
> -	v4l2_async_nf_init(&vin->group->notifier);
> +	v4l2_async_nf_init(&vin->group->notifier, &vin->v4l2_dev);
>  
>  	/*
>  	 * Some subdevices may overlap but the parser function can handle it and
> @@ -400,7 +400,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port,
>  		return 0;
>  
>  	vin->group->notifier.ops = &rvin_group_notify_ops;
> -	ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->group->notifier);
> +	ret = v4l2_async_nf_register(&vin->group->notifier);
>  	if (ret < 0) {
>  		vin_err(vin, "Notifier registration failed\n");
>  		v4l2_async_nf_cleanup(&vin->group->notifier);
> @@ -713,7 +713,7 @@ static int rvin_parallel_init(struct rvin_dev *vin)
>  {
>  	int ret;
>  
> -	v4l2_async_nf_init(&vin->notifier);
> +	v4l2_async_nf_init(&vin->notifier, &vin->v4l2_dev);
>  
>  	ret = rvin_parallel_parse_of(vin);
>  	if (ret)
> @@ -726,7 +726,7 @@ static int rvin_parallel_init(struct rvin_dev *vin)
>  		to_of_node(vin->parallel.asc->match.fwnode));
>  
>  	vin->notifier.ops = &rvin_parallel_notify_ops;
> -	ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier);
> +	ret = v4l2_async_nf_register(&vin->notifier);
>  	if (ret < 0) {
>  		vin_err(vin, "Notifier registration failed\n");
>  		v4l2_async_nf_cleanup(&vin->notifier);
> diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
> index de7b479df3a9d..21f8f4be0dfe5 100644
> --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
> +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
> @@ -1076,7 +1076,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
>  
>  	dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode));
>  
> -	v4l2_async_nf_init(&priv->notifier);
> +	v4l2_async_subdev_nf_init(&priv->notifier, &priv->subdev);
>  	priv->notifier.ops = &rcar_csi2_notify_ops;
>  
>  	asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,
> @@ -1085,7 +1085,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
>  	if (IS_ERR(asc))
>  		return PTR_ERR(asc);
>  
> -	ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier);
> +	ret = v4l2_async_nf_register(&priv->notifier);
>  	if (ret)
>  		v4l2_async_nf_cleanup(&priv->notifier);
>  
> diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c
> index 90fda730030d7..c7a925f421228 100644
> --- a/drivers/media/platform/renesas/rcar_drif.c
> +++ b/drivers/media/platform/renesas/rcar_drif.c
> @@ -1207,7 +1207,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
>  	struct fwnode_handle *fwnode, *ep;
>  	struct v4l2_async_connection *asd;
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_nf_init(&sdr->notifier, &sdr->v4l2_dev);
>  
>  	ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node),
>  					    NULL);
> @@ -1341,7 +1341,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
>  	sdr->notifier.ops = &rcar_drif_notify_ops;
>  
>  	/* Register notifier */
> -	ret = v4l2_async_nf_register(&sdr->v4l2_dev, &sdr->notifier);
> +	ret = v4l2_async_nf_register(&sdr->notifier);
>  	if (ret < 0) {
>  		dev_err(sdr->dev, "failed: notifier register ret %d\n", ret);
>  		goto cleanup;
> diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c
> index be6140c93fc0c..c2215205fb3c3 100644
> --- a/drivers/media/platform/renesas/renesas-ceu.c
> +++ b/drivers/media/platform/renesas/renesas-ceu.c
> @@ -1667,7 +1667,7 @@ static int ceu_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto error_pm_disable;
>  
> -	v4l2_async_nf_init(&ceudev->notifier);
> +	v4l2_async_nf_init(&ceudev->notifier, &ceudev->v4l2_dev);
>  
>  	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
>  		ceu_data = of_device_get_match_data(dev);
> @@ -1689,7 +1689,7 @@ static int ceu_probe(struct platform_device *pdev)
>  
>  	ceudev->notifier.v4l2_dev	= &ceudev->v4l2_dev;
>  	ceudev->notifier.ops		= &ceu_notify_ops;
> -	ret = v4l2_async_nf_register(&ceudev->v4l2_dev, &ceudev->notifier);
> +	ret = v4l2_async_nf_register(&ceudev->notifier);
>  	if (ret)
>  		goto error_cleanup;
>  
> diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> index e026ed5337513..fdef43fd1895b 100644
> --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
> @@ -183,7 +183,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
>  {
>  	int ret;
>  
> -	v4l2_async_nf_init(&cru->notifier);
> +	v4l2_async_nf_init(&cru->notifier, &cru->v4l2_dev);
>  
>  	ret = rzg2l_cru_mc_parse_of(cru);
>  	if (ret)
> @@ -194,7 +194,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru)
>  	if (list_empty(&cru->notifier.waiting_list))
>  		return 0;
>  
> -	ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier);
> +	ret = v4l2_async_nf_register(&cru->notifier);
>  	if (ret < 0) {
>  		dev_err(cru->dev, "Notifier registration failed\n");
>  		v4l2_async_nf_cleanup(&cru->notifier);
> diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> index f6bf4cdff28c2..7f6a37f835415 100644
> --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
> @@ -674,7 +674,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
>  	fwnode = fwnode_graph_get_remote_endpoint(ep);
>  	fwnode_handle_put(ep);
>  
> -	v4l2_async_nf_init(&csi2->notifier);
> +	v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->subdev);
>  	csi2->notifier.ops = &rzg2l_csi2_notify_ops;
>  
>  	asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode,
> @@ -683,7 +683,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2)
>  	if (IS_ERR(asd))
>  		return PTR_ERR(asd);
>  
> -	ret = v4l2_async_subdev_nf_register(&csi2->subdev, &csi2->notifier);
> +	ret = v4l2_async_nf_register(&csi2->notifier);
>  	if (ret)
>  		v4l2_async_nf_cleanup(&csi2->notifier);
>  
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> index eb88494c2a427..543fd377ab2a4 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> @@ -187,7 +187,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
>  	unsigned int index = 0;
>  	int ret = 0;
>  
> -	v4l2_async_nf_init(ntf);
> +	v4l2_async_nf_init(ntf, &rkisp1->v4l2_dev);
>  
>  	ntf->ops = &rkisp1_subdev_notifier_ops;
>  
> @@ -287,7 +287,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
>  	if (!index)
>  		dev_dbg(rkisp1->dev, "no remote subdevice found\n");
>  
> -	ret = v4l2_async_nf_register(&rkisp1->v4l2_dev, ntf);
> +	ret = v4l2_async_nf_register(ntf);
>  	if (ret) {
>  		v4l2_async_nf_cleanup(ntf);
>  		return ret;
> diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c
> index 59070616cb1bd..623e52440ccd2 100644
> --- a/drivers/media/platform/samsung/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c
> @@ -1479,7 +1479,7 @@ static int fimc_md_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, fmd);
>  
> -	v4l2_async_nf_init(&fmd->subdev_notifier);
> +	v4l2_async_nf_init(&fmd->subdev_notifier, &fmd->v4l2_dev);
>  
>  	ret = fimc_md_register_platform_entities(fmd, dev->of_node);
>  	if (ret)
> @@ -1507,8 +1507,7 @@ static int fimc_md_probe(struct platform_device *pdev)
>  		fmd->subdev_notifier.ops = &subdev_notifier_ops;
>  		fmd->num_sensors = 0;
>  
> -		ret = v4l2_async_nf_register(&fmd->v4l2_dev,
> -					     &fmd->subdev_notifier);
> +		ret = v4l2_async_nf_register(&fmd->subdev_notifier);
>  		if (ret)
>  			goto err_clk_p;
>  	}
> diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
> index 6d1197d4464e2..0e8f21602a066 100644
> --- a/drivers/media/platform/st/stm32/stm32-dcmi.c
> +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
> @@ -1897,7 +1897,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
>  		return -EINVAL;
>  	}
>  
> -	v4l2_async_nf_init(&dcmi->notifier);
> +	v4l2_async_nf_init(&dcmi->notifier, &dcmi->v4l2_dev);
>  
>  	asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier,
>  					      of_fwnode_handle(ep),
> @@ -1912,7 +1912,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
>  
>  	dcmi->notifier.ops = &dcmi_graph_notify_ops;
>  
> -	ret = v4l2_async_nf_register(&dcmi->v4l2_dev, &dcmi->notifier);
> +	ret = v4l2_async_nf_register(&dcmi->notifier);
>  	if (ret < 0) {
>  		dev_err(dcmi->dev, "Failed to register notifier\n");
>  		v4l2_async_nf_cleanup(&dcmi->notifier);
> diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> index 38ca534842100..bb903e5ea35ea 100644
> --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> @@ -122,7 +122,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> -	v4l2_async_nf_init(&csi->notifier);
> +	v4l2_async_nf_init(&csi->notifier, &csi->v4l);
>  
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
> @@ -240,7 +240,7 @@ static int sun4i_csi_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto err_unregister_media;
>  
> -	ret = v4l2_async_nf_register(&csi->v4l, &csi->notifier);
> +	ret = v4l2_async_nf_register(&csi->notifier);
>  	if (ret) {
>  		dev_err(csi->dev, "Couldn't register our notifier.\n");
>  		goto err_unregister_media;
> diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
> index ebb725fc11ba5..0dcf605f2764b 100644
> --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
> +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
> @@ -819,7 +819,7 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
>  
>  	/* V4L2 Async */
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_subdev_nf_init(notifier, subdev);
>  	notifier->ops = &sun6i_csi_bridge_notifier_ops;
>  
>  	sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_parallel,
> @@ -829,9 +829,9 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
>  				      SUN6I_CSI_PORT_MIPI_CSI2, NULL);
>  
>  	if (csi_dev->isp_available)
> -		ret = v4l2_async_subdev_nf_register(subdev, notifier);
> +		ret = v4l2_async_nf_register(notifier);
>  	else
> -		ret = v4l2_async_nf_register(v4l2_dev, notifier);
> +		ret = v4l2_async_nf_register(notifier);
>  	if (ret) {
>  		dev_err(dev, "failed to register v4l2 async notifier: %d\n",
>  			ret);
> diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
> index a78900dd0b7a6..adf966d2f5ca2 100644
> --- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
> +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
> @@ -531,7 +531,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
>  
>  	/* V4L2 Async */
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_subdev_nf_init(notifier, subdev);
>  	notifier->ops = &sun6i_mipi_csi2_notifier_ops;
>  
>  	ret = sun6i_mipi_csi2_bridge_source_setup(csi2_dev);
> @@ -540,7 +540,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
>  
>  	/* Only register the notifier when a sensor is connected. */
>  	if (ret != -ENODEV) {
> -		ret = v4l2_async_subdev_nf_register(subdev, notifier);
> +		ret = v4l2_async_nf_register(notifier);
>  		if (ret < 0)
>  			goto error_v4l2_notifier_cleanup;
>  
> diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> index 909aaef200989..50641d7af320d 100644
> --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> @@ -569,7 +569,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
>  
>  	/* V4L2 Async */
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_subdev_nf_init(notifier, subdev);
>  	notifier->ops = &sun8i_a83t_mipi_csi2_notifier_ops;
>  
>  	ret = sun8i_a83t_mipi_csi2_bridge_source_setup(csi2_dev);
> @@ -578,7 +578,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
>  
>  	/* Only register the notifier when a sensor is connected. */
>  	if (ret != -ENODEV) {
> -		ret = v4l2_async_subdev_nf_register(subdev, notifier);
> +		ret = v4l2_async_nf_register(notifier);
>  		if (ret < 0)
>  			goto error_v4l2_notifier_cleanup;
>  
> diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c
> index 1457a188fea12..9ecd6b02467c8 100644
> --- a/drivers/media/platform/ti/am437x/am437x-vpfe.c
> +++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c
> @@ -2300,7 +2300,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
>  
>  	dev_dbg(dev, "vpfe_get_pdata\n");
>  
> -	v4l2_async_nf_init(&vpfe->notifier);
> +	v4l2_async_nf_init(&vpfe->notifier, &vpfe->v4l2_dev);
>  
>  	if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
>  		return dev->platform_data;
> @@ -2466,7 +2466,7 @@ static int vpfe_probe(struct platform_device *pdev)
>  	}
>  
>  	vpfe->notifier.ops = &vpfe_async_ops;
> -	ret = v4l2_async_nf_register(&vpfe->v4l2_dev, &vpfe->notifier);
> +	ret = v4l2_async_nf_register(&vpfe->notifier);
>  	if (ret) {
>  		vpfe_err(vpfe, "Error registering async notifier\n");
>  		ret = -EINVAL;
> diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c
> index bf7a985168c7b..25780e1f103e7 100644
> --- a/drivers/media/platform/ti/cal/cal.c
> +++ b/drivers/media/platform/ti/cal/cal.c
> @@ -895,7 +895,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
>  	unsigned int i;
>  	int ret;
>  
> -	v4l2_async_nf_init(&cal->notifier);
> +	v4l2_async_nf_init(&cal->notifier, &cal->v4l2_dev);
>  	cal->notifier.ops = &cal_async_notifier_ops;
>  
>  	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
> @@ -919,7 +919,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
>  		casd->phy = phy;
>  	}
>  
> -	ret = v4l2_async_nf_register(&cal->v4l2_dev, &cal->notifier);
> +	ret = v4l2_async_nf_register(&cal->notifier);
>  	if (ret) {
>  		cal_err(cal, "Error registering async notifier\n");
>  		goto error;
> diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c
> index 9b97e26be0892..3f0b161ab50cf 100644
> --- a/drivers/media/platform/ti/davinci/vpif_capture.c
> +++ b/drivers/media/platform/ti/davinci/vpif_capture.c
> @@ -1483,7 +1483,8 @@ static const struct v4l2_async_notifier_operations vpif_async_ops = {
>  };
>  
>  static struct vpif_capture_config *
> -vpif_capture_get_pdata(struct platform_device *pdev)
> +vpif_capture_get_pdata(struct platform_device *pdev,
> +		       struct v4l2_device *v4l2_dev)
>  {
>  	struct device_node *endpoint = NULL;
>  	struct device_node *rem = NULL;
> @@ -1492,7 +1493,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
>  	struct vpif_capture_chan_config *chan;
>  	unsigned int i;
>  
> -	v4l2_async_nf_init(&vpif_obj.notifier);
> +	v4l2_async_nf_init(&vpif_obj.notifier, v4l2_dev);
>  
>  	/*
>  	 * DT boot: OF node from parent device contains
> @@ -1649,7 +1650,8 @@ static __init int vpif_probe(struct platform_device *pdev)
>  		goto vpif_unregister;
>  	}
>  
> -	pdev->dev.platform_data = vpif_capture_get_pdata(pdev);
> +	pdev->dev.platform_data =
> +		vpif_capture_get_pdata(pdev, &vpif_obj.v4l2_dev);
>  	if (!pdev->dev.platform_data) {
>  		dev_warn(&pdev->dev, "Missing platform data.  Giving up.\n");
>  		goto probe_subdev_out;
> @@ -1683,8 +1685,7 @@ static __init int vpif_probe(struct platform_device *pdev)
>  			goto probe_subdev_out;
>  	} else {
>  		vpif_obj.notifier.ops = &vpif_async_ops;
> -		err = v4l2_async_nf_register(&vpif_obj.v4l2_dev,
> -					     &vpif_obj.notifier);
> +		err = v4l2_async_nf_register(&vpif_obj.notifier);
>  		if (err) {
>  			vpif_err("Error registering async notifier\n");
>  			err = -EINVAL;
> diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
> index 5b3266b214874..44ddc1422cc75 100644
> --- a/drivers/media/platform/ti/omap3isp/isp.c
> +++ b/drivers/media/platform/ti/omap3isp/isp.c
> @@ -2425,13 +2425,13 @@ static int isp_probe(struct platform_device *pdev)
>  
>  	isp->notifier.ops = &isp_subdev_notifier_ops;
>  
> -	v4l2_async_nf_init(&isp->notifier);
> +	v4l2_async_nf_init(&isp->notifier, &isp->v4l2_dev);
>  
>  	ret = isp_parse_of_endpoints(isp);
>  	if (ret < 0)
>  		goto error_register_entities;
>  
> -	ret = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier);
> +	ret = v4l2_async_nf_register(&isp->notifier);
>  	if (ret)
>  		goto error_register_entities;
>  
> diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
> index e1dd798764312..315c65effe878 100644
> --- a/drivers/media/platform/video-mux.c
> +++ b/drivers/media/platform/video-mux.c
> @@ -360,7 +360,7 @@ static int video_mux_async_register(struct video_mux *vmux,
>  	unsigned int i;
>  	int ret;
>  
> -	v4l2_async_nf_init(&vmux->notifier);
> +	v4l2_async_subdev_nf_init(&vmux->notifier, &vmux->subdev);
>  
>  	for (i = 0; i < num_input_pads; i++) {
>  		struct v4l2_async_connection *asd;
> @@ -395,7 +395,7 @@ static int video_mux_async_register(struct video_mux *vmux,
>  
>  	vmux->notifier.ops = &video_mux_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier);
> +	ret = v4l2_async_nf_register(&vmux->notifier);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index 6bb426a25fe90..4285770fde184 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -494,7 +494,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
>  		goto done;
>  	}
>  
> -	v4l2_async_nf_init(&xdev->notifier);
> +	v4l2_async_nf_init(&xdev->notifier, &xdev->v4l2_dev);
>  
>  	/* Parse the graph to extract a list of subdevice DT nodes. */
>  	ret = xvip_graph_parse(xdev);
> @@ -512,7 +512,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
>  	/* Register the subdevices notifier. */
>  	xdev->notifier.ops = &xvip_graph_notify_ops;
>  
> -	ret = v4l2_async_nf_register(&xdev->v4l2_dev, &xdev->notifier);
> +	ret = v4l2_async_nf_register(&xdev->notifier);
>  	if (ret < 0) {
>  		dev_err(xdev->dev, "notifier registration failed\n");
>  		goto done;
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 12b465a16ec1c..bb172cc18998a 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -558,13 +558,24 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
>  	return 0;
>  }
>  
> -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
> +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
> +			struct v4l2_device *v4l2_dev)
>  {
>  	INIT_LIST_HEAD(&notifier->waiting_list);
>  	INIT_LIST_HEAD(&notifier->done_list);
> +	notifier->v4l2_dev = v4l2_dev;
>  }
>  EXPORT_SYMBOL(v4l2_async_nf_init);
>  
> +void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
> +			       struct v4l2_subdev *sd)
> +{
> +	INIT_LIST_HEAD(&notifier->waiting_list);
> +	INIT_LIST_HEAD(&notifier->done_list);
> +	notifier->sd = sd;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_async_subdev_nf_init);
> +
>  static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  {
>  	struct v4l2_async_connection *asc;
> @@ -605,16 +616,13 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  	return ret;
>  }
>  
> -int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
> -			   struct v4l2_async_notifier *notifier)
> +int v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
>  {
>  	int ret;
>  
> -	if (WARN_ON(!v4l2_dev || notifier->sd))
> +	if (WARN_ON(!notifier->v4l2_dev == !notifier->sd))
>  		return -EINVAL;
>  
> -	notifier->v4l2_dev = v4l2_dev;
> -
>  	ret = __v4l2_async_nf_register(notifier);
>  	if (ret)
>  		notifier->v4l2_dev = NULL;
> @@ -623,24 +631,6 @@ int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
>  }
>  EXPORT_SYMBOL(v4l2_async_nf_register);
>  
> -int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
> -				  struct v4l2_async_notifier *notifier)
> -{
> -	int ret;
> -
> -	if (WARN_ON(!sd || notifier->v4l2_dev))
> -		return -EINVAL;
> -
> -	notifier->sd = sd;
> -
> -	ret = __v4l2_async_nf_register(notifier);
> -	if (ret)
> -		notifier->sd = NULL;
> -
> -	return ret;
> -}
> -EXPORT_SYMBOL(v4l2_async_subdev_nf_register);
> -
>  static void
>  __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
>  {
> @@ -649,9 +639,6 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
>  
>  	v4l2_async_nf_unbind_all_subdevs(notifier);
>  
> -	notifier->sd = NULL;
> -	notifier->v4l2_dev = NULL;
> -
>  	list_del(&notifier->notifier_entry);
>  }
>  
> @@ -683,6 +670,9 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
>  
>  		kfree(asc);
>  	}
> +
> +	notifier->sd = NULL;
> +	notifier->v4l2_dev = NULL;
>  }
>  
>  void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> index 7c3e1648a0f49..dc5df557c3b33 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -1205,7 +1205,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
>  	if (!notifier)
>  		return -ENOMEM;
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_subdev_nf_init(notifier, sd);
>  
>  	ret = v4l2_subdev_get_privacy_led(sd);
>  	if (ret < 0)
> @@ -1215,7 +1215,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
>  	if (ret < 0)
>  		goto out_cleanup;
>  
> -	ret = v4l2_async_subdev_nf_register(sd, notifier);
> +	ret = v4l2_async_nf_register(notifier);
>  	if (ret < 0)
>  		goto out_cleanup;
>  
> diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
> index 58c8c7813e0f9..31b2b48085c59 100644
> --- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
> +++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
> @@ -507,7 +507,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
>  		struct fwnode_handle *fwnode =
>  			of_fwnode_handle(subdev_entity->epn);
>  
> -		v4l2_async_nf_init(&subdev_entity->notifier);
> +		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
>  
>  		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
>  						      fwnode,
> @@ -523,8 +523,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
>  
>  		subdev_entity->notifier.ops = &atmel_isc_async_ops;
>  
> -		ret = v4l2_async_nf_register(&isc->v4l2_dev,
> -					     &subdev_entity->notifier);
> +		ret = v4l2_async_nf_register(&subdev_entity->notifier);
>  		if (ret) {
>  			dev_err(dev, "fail to register async notifier\n");
>  			goto cleanup_subdev;
> diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
> index f10ddee0949e1..020034f631f57 100644
> --- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
> +++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
> @@ -497,7 +497,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
>  		struct fwnode_handle *fwnode =
>  			of_fwnode_handle(subdev_entity->epn);
>  
> -		v4l2_async_nf_init(&subdev_entity->notifier);
> +		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
>  
>  		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
>  						      fwnode,
> @@ -513,8 +513,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
>  
>  		subdev_entity->notifier.ops = &atmel_isc_async_ops;
>  
> -		ret = v4l2_async_nf_register(&isc->v4l2_dev,
> -					     &subdev_entity->notifier);
> +		ret = v4l2_async_nf_register(&subdev_entity->notifier);
>  		if (ret) {
>  			dev_err(dev, "fail to register async notifier\n");
>  			goto cleanup_subdev;
> diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> index 09b8b396022e0..dda1ebc34692a 100644
> --- a/drivers/staging/media/imx/imx-media-csi.c
> +++ b/drivers/staging/media/imx/imx-media-csi.c
> @@ -1918,7 +1918,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
>  	unsigned int port;
>  	int ret;
>  
> -	v4l2_async_nf_init(&priv->notifier);
> +	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
>  
>  	/* get this CSI's port id */
>  	ret = fwnode_property_read_u32(dev_fwnode(priv->dev), "reg", &port);
> @@ -1944,7 +1944,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
>  
>  	priv->notifier.ops = &csi_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
> +	ret = v4l2_async_nf_register(&priv->notifier);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
> index 67c1b16db6558..46bf717255b3e 100644
> --- a/drivers/staging/media/imx/imx-media-dev-common.c
> +++ b/drivers/staging/media/imx/imx-media-dev-common.c
> @@ -367,7 +367,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
>  
>  	INIT_LIST_HEAD(&imxmd->vdev_list);
>  
> -	v4l2_async_nf_init(&imxmd->notifier);
> +	v4l2_async_nf_init(&imxmd->notifier, &imxmd->v4l2_dev);
>  
>  	return imxmd;
>  
> @@ -391,7 +391,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
>  
>  	/* prepare the async subdev notifier and register it */
>  	imxmd->notifier.ops = ops ? ops : &imx_media_notifier_ops;
> -	ret = v4l2_async_nf_register(&imxmd->v4l2_dev, &imxmd->notifier);
> +	ret = v4l2_async_nf_register(&imxmd->notifier);
>  	if (ret) {
>  		v4l2_err(&imxmd->v4l2_dev,
>  			 "v4l2_async_nf_register failed with %d\n", ret);
> diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
> index 2e86f82ad70cd..50f1df09c0a73 100644
> --- a/drivers/staging/media/imx/imx6-mipi-csi2.c
> +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
> @@ -635,7 +635,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> -	v4l2_async_nf_init(&csi2->notifier);
> +	v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->sd);
>  
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
> @@ -660,7 +660,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
>  
>  	csi2->notifier.ops = &csi2_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&csi2->sd, &csi2->notifier);
> +	ret = v4l2_async_nf_register(&csi2->notifier);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
> index 2f723ad34c2c5..6813c44b71039 100644
> --- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
> +++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
> @@ -592,7 +592,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
>  	unsigned int i;
>  	int ret;
>  
> -	v4l2_async_nf_init(&state->notifier);
> +	v4l2_async_subdev_nf_init(&state->notifier, &state->sd);
>  
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
> @@ -629,7 +629,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
>  
>  	state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
>  
> -	ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
> +	ret = v4l2_async_nf_register(&state->notifier);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> index dd7dfecb9ef33..ccbb530aa2e23 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> @@ -536,7 +536,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
>  
>  	/* V4L2 Async */
>  
> -	v4l2_async_nf_init(notifier);
> +	v4l2_async_nf_init(notifier, v4l2_dev);
>  	notifier->ops = &sun6i_isp_proc_notifier_ops;
>  
>  	sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi0,
> @@ -544,7 +544,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
>  	sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi1,
>  				    SUN6I_ISP_PORT_CSI1);
>  
> -	ret = v4l2_async_nf_register(v4l2_dev, notifier);
> +	ret = v4l2_async_nf_register(notifier);
>  	if (ret) {
>  		v4l2_err(v4l2_dev,
>  			 "failed to register v4l2 async notifier: %d\n", ret);
> diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
> index 146b4fd3c8b52..f31d8babf499c 100644
> --- a/drivers/staging/media/tegra-video/vi.c
> +++ b/drivers/staging/media/tegra-video/vi.c
> @@ -1280,7 +1280,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan)
>  	}
>  
>  	if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
> -		v4l2_async_nf_init(&chan->notifier);
> +		v4l2_async_nf_init(&chan->notifier, &vid->v4l2_dev);
>  
>  	return 0;
>  
> @@ -1880,7 +1880,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
>  			continue;
>  
>  		chan->notifier.ops = &tegra_vi_async_ops;
> -		ret = v4l2_async_nf_register(&vid->v4l2_dev, &chan->notifier);
> +		ret = v4l2_async_nf_register(&chan->notifier);
>  		if (ret < 0) {
>  			dev_err(vi->dev,
>  				"failed to register channel %d notifier: %d\n",
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index d0bef6626e043..65e364d4033a4 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -146,13 +146,30 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>   * v4l2_async_nf_init - Initialize a notifier.
>   *
>   * @notifier: pointer to &struct v4l2_async_notifier
> + * @v4l2_dev: pointer to &struct v4l2_device
> + *
> + * This function initializes the notifier @asc_entry. It must be called
> + * before adding a subdevice to a notifier, using one of:
> + * v4l2_async_nf_add_fwnode_remote(),
> + * v4l2_async_nf_add_fwnode() or
> + * v4l2_async_nf_add_i2c().
> + */
> +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
> +			struct v4l2_device *v4l2_dev);
> +
> +/**
> + * v4l2_async_subdev_nf_init - Initialize a sub-device notifier.
> + *
> + * @notifier: pointer to &struct v4l2_async_notifier
> + * @sd: pointer to &struct v4l2_subdev
>   *
>   * This function initializes the notifier @asc_entry. It must be called
>   * before adding a subdevice to a notifier, using one of:
>   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
>   * v4l2_async_nf_add_i2c().
>   */
> -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
> +void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
> +			       struct v4l2_subdev *sd);
>  
>  struct v4l2_async_connection *
>  __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> @@ -257,21 +274,9 @@ v4l2_async_connection_unique(struct v4l2_subdev *sd);
>  /**
>   * v4l2_async_nf_register - registers a subdevice asynchronous notifier
>   *
> - * @v4l2_dev: pointer to &struct v4l2_device
> - * @notifier: pointer to &struct v4l2_async_notifier
> - */
> -int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
> -			   struct v4l2_async_notifier *notifier);
> -
> -/**
> - * v4l2_async_subdev_nf_register - registers a subdevice asynchronous
> - *					 notifier for a sub-device
> - *
> - * @sd: pointer to &struct v4l2_subdev
>   * @notifier: pointer to &struct v4l2_async_notifier
>   */
> -int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
> -				  struct v4l2_async_notifier *notifier);
> +int v4l2_async_nf_register(struct v4l2_async_notifier *notifier);
>  
>  /**
>   * v4l2_async_nf_unregister - unregisters a subdevice

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers
  2023-05-25  9:16 ` [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
  2023-05-30  6:18   ` Laurent Pinchart
@ 2023-05-30 12:13   ` Aishwarya Kothari
  1 sibling, 0 replies; 80+ messages in thread
From: Aishwarya Kothari @ 2023-05-30 12:13 UTC (permalink / raw)
  To: Sakari Ailus, linux-media
  Cc: laurent.pinchart, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On 25.05.23 11:16, Sakari Ailus wrote:
> Document that sub-device notifiers are now registered using
> v4l2_async_subdev_nf_init(). No documentation is changed as it seems that
> sub-device notifiers were not documented apart from kernel-doc comments.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>   Documentation/driver-api/media/v4l2-subdev.rst | 10 +++++++---
>   1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> index 83d3d29608136..d62b341642c96 100644
> --- a/Documentation/driver-api/media/v4l2-subdev.rst
> +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> @@ -193,9 +193,7 @@ picked up by bridge drivers.
>   Bridge drivers in turn have to register a notifier object. This is
>   performed using the :c:func:`v4l2_async_nf_register` call. To
>   unregister the notifier the driver has to call
> -:c:func:`v4l2_async_nf_unregister`. The former of the two functions
> -takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
> -pointer to struct :c:type:`v4l2_async_notifier`.
> +:c:func:`v4l2_async_nf_unregister`.
>   
>   Before registering the notifier, bridge drivers must do two things: first, the
>   notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
> @@ -204,6 +202,12 @@ that the bridge device needs for its operation. Several functions are available
>   to add subdevice descriptors to a notifier, depending on the type of device and
>   the needs of the driver.
>   
> +For a sub-device driver to register a notifier, the process is otherwise similar
> +to that of a bridge driver, apart from that the notifier is initialised using
> +:c:func:`v4l2_async_subdev_nf_init` instead. A sub-device notifier may complete
> +only after the V4L2 device becomes available, i.e. there's a path via async
> +sub-devices and notifiers to that root notifier.
> +
>   :c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
>   :c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
>   :c:with the notifier.

Works on Apalis i.MX6Q with TC358743.

Tested-by: Aishwarya Kothari <aishwarya.kothari@toradex.com>

regards,
Aishwarya

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

* Re: [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier
  2023-05-30  2:23   ` Laurent Pinchart
@ 2023-06-13 13:19     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 13:19 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

Thanks for the review.

On Tue, May 30, 2023 at 05:23:23AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:47PM +0300, Sakari Ailus wrote:
> > There's no need to check for a sub-device's notifier as we only register
> > one notifier (and one V4L2 device). Remove this check and prepare for
> > removing this field in struct v4l2_subdev.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/platform/ti/omap3isp/isp.c | 3 ---
> >  1 file changed, 3 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
> > index f3aaa9e76492e..c2b222f7df892 100644
> > --- a/drivers/media/platform/ti/omap3isp/isp.c
> > +++ b/drivers/media/platform/ti/omap3isp/isp.c
> > @@ -2039,9 +2039,6 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
> >  	}
> >  
> >  	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
> > -		if (sd->notifier != &isp->notifier)
> > -			continue;
> 
> I don't think this is quite right. You could have a chain of external
> subdevs, in which case only the one connected directly to the ISP should
> be linked to the ISP.

You're right, in principle this could take place. Going forward sub-devices
may be bound to multiple notifiers so this field should go. I'll see if we
could have another test for this.

-- 
Kind regrads,

Sakari Ailus

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

* Re: [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function
  2023-05-30  2:14   ` Laurent Pinchart
@ 2023-06-13 13:43     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 13:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 05:14:43AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:45PM +0300, Sakari Ailus wrote:
> > Also v4l2_async_nf_add_fwnode() may be used to add an async sub-device
> > descriptor to a notifier. Document this.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  Documentation/driver-api/media/v4l2-subdev.rst | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> > index 602dadaa81d86..ce8e9d0a332bc 100644
> > --- a/Documentation/driver-api/media/v4l2-subdev.rst
> > +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> > @@ -204,9 +204,9 @@ that the bridge device needs for its operation. Several functions are available
> >  to add subdevice descriptors to a notifier, depending on the type of device and
> >  the needs of the driver.
> >  
> > -:c:func:`v4l2_async_nf_add_fwnode_remote` and
> > -:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
> > -registering their async sub-devices with the notifier.
> > +:c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
> > +:c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
> 
> The 'and' isn't in the right place. With this fixed,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thanks. Same below. Joe's word wrap sometimes does little tricks...

> > +:c:with the notifier.
> >  
> >  :c:func:`v4l2_async_register_subdev_sensor` is a helper function for
> >  sensor drivers registering their own async sub-device, but it also registers a

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs
  2023-05-30  2:42   ` Laurent Pinchart
@ 2023-06-13 13:57     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 13:57 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 05:42:29AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:49PM +0300, Sakari Ailus wrote:
> > There's a need to verify that a single async sub-device isn't being added
> > multiple times, this would be an error. This takes place at the time of
> > adding the async sub-device to the notifier's list as well as when the
> > notifier is added to the global notifier's list.
> > 
> > Use the pointer to the sub-device for testing this instead of an index to
> > an array that is long gone. (There was an array of async sub-devices in
> > the notifier before it was converted to a linked list by commit
> > 66beb323e4a0 ("media: v4l2: async: Remove notifier subdevs array").
> 
> Unbalanced opening and closing parentheses.
> 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/v4l2-core/v4l2-async.c | 18 ++++++++----------
> >  1 file changed, 8 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > index c5781124337af..320fe5cbaaf41 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -520,21 +520,19 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
> >  
> >  /*
> >   * Find out whether an async sub-device was set up already or
> > - * whether it exists in a given notifier before @this_index.
> > - * If @this_index < 0, search the notifier's entire @asd_list.
> > + * whether it exists in a given notifier.
> 
> Please document what the skip_self parameter does. The parameter name
> doesn't match the 'break' in the test below, I was expecting a
> 'continue'. If my expectation is wrong documentation should help, if
> it's correct, then you can fix the code :-)

I can add some, the argument will disappear later in the series though.

This patch mirrors the old functionality, nothing more. Changing the break
to continue is functionally equivalent here as this is the end of the list,
I can do that, too.

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation
  2023-05-30  2:46   ` Laurent Pinchart
@ 2023-06-13 14:00     ` Sakari Ailus
  2023-06-13 14:08       ` Sakari Ailus
  0 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:00 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 05:46:50AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:50PM +0300, Sakari Ailus wrote:
> > The list entry is initialised as a head in v4l2_async_register_subdev()
> > just before being added to the list. This isn't needed, drop the
> > initialisation.
> 
> Is this really unneeded ? Before the initialization and the list_add()
> call there are a few code paths that can access the async_list. For
> instance, the error path calls v4l2_async_cleanup(), which calls
> 
> 	list_del_init(&sd->async_list);
> 
> That won't work well on an uninitialized (or zero-initialized)
> list_head.

I think you're right, I'll drop this patch. This initialisation will be
removed in a later patch though, as the list will be redundant soon.

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation
  2023-06-13 14:00     ` Sakari Ailus
@ 2023-06-13 14:08       ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On Tue, Jun 13, 2023 at 02:00:43PM +0000, Sakari Ailus wrote:
> Hi Laurent,
> 
> On Tue, May 30, 2023 at 05:46:50AM +0300, Laurent Pinchart wrote:
> > Hi Sakari,
> > 
> > Thank you for the patch.
> > 
> > On Thu, May 25, 2023 at 12:15:50PM +0300, Sakari Ailus wrote:
> > > The list entry is initialised as a head in v4l2_async_register_subdev()
> > > just before being added to the list. This isn't needed, drop the
> > > initialisation.
> > 
> > Is this really unneeded ? Before the initialization and the list_add()
> > call there are a few code paths that can access the async_list. For
> > instance, the error path calls v4l2_async_cleanup(), which calls
> > 
> > 	list_del_init(&sd->async_list);
> > 
> > That won't work well on an uninitialized (or zero-initialized)
> > list_head.
> 
> I think you're right, I'll drop this patch. This initialisation will be
> removed in a later patch though, as the list will be redundant soon.

Actually the list and the field remains, although it becomes unnecessary to
initialise it. I'll see if this patch would be meaningful later on in the
series or squashed to another patch.

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct
  2023-05-30  2:52   ` Laurent Pinchart
@ 2023-06-13 14:35     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 05:52:22AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:52PM +0300, Sakari Ailus wrote:
> > Make V4L2 async match information a struct, making it easier to use it
> > elsewhere outside the scope of struct v4l2_async_subdev.
> > 
> > Also remove an obsolete comment --- none of these fields are supposed to
> > be touched by drivers.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/v4l2-core/v4l2-async.c | 20 +++++++-------
> >  include/media/v4l2-async.h           | 41 ++++++++++++++++------------
> >  2 files changed, 33 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > index 7c924faac4c10..7f56648e40c44 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -212,7 +212,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
> >  
> >  	list_for_each_entry(asd, &notifier->waiting, list) {
> >  		/* bus_type has been verified valid before */
> > -		switch (asd->match_type) {
> > +		switch (asd->match.type) {
> >  		case V4L2_ASYNC_MATCH_I2C:
> >  			match = match_i2c;
> >  			break;
> > @@ -237,10 +237,10 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
> >  static bool asd_equal(struct v4l2_async_subdev *asd_x,
> >  		      struct v4l2_async_subdev *asd_y)
> >  {
> > -	if (asd_x->match_type != asd_y->match_type)
> > +	if (asd_x->match.type != asd_y->match.type)
> >  		return false;
> >  
> > -	switch (asd_x->match_type) {
> > +	switch (asd_x->match.type) {
> >  	case V4L2_ASYNC_MATCH_I2C:
> >  		return asd_x->match.i2c.adapter_id ==
> >  			asd_y->match.i2c.adapter_id &&
> > @@ -552,7 +552,7 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
> >  {
> >  	struct device *dev = notifier_dev(notifier);
> >  
> > -	switch (asd->match_type) {
> > +	switch (asd->match.type) {
> >  	case V4L2_ASYNC_MATCH_I2C:
> >  	case V4L2_ASYNC_MATCH_FWNODE:
> >  		if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) {
> > @@ -561,8 +561,8 @@ static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
> >  		}
> >  		break;
> >  	default:
> > -		dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
> > -			asd->match_type, asd);
> > +		dev_err(dev, "v4l2-asymc: Invalid match type %u on %p\n",
> 
> Is this for asymmetrical notification ?

Oops.

> 
> With this fixed,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thank you! :-)

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation
  2023-05-30  3:02   ` Laurent Pinchart
@ 2023-06-13 14:37     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:37 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 06:02:15AM +0300, Laurent Pinchart wrote:
> > @@ -234,20 +237,18 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
> >  }
> >  
> >  /* Compare two async sub-device descriptors for equivalence */
> 
> s/sub-device/match/ ?

Yes.

> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thanks!

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries
  2023-05-30  3:09   ` Laurent Pinchart
  2023-05-30  5:40     ` Laurent Pinchart
@ 2023-06-13 14:51     ` Sakari Ailus
  1 sibling, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 06:09:29AM +0300, Laurent Pinchart wrote:
> > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > index 8d1506a9755c3..54f9f45ed3d8e 100644
> > --- a/include/media/v4l2-async.h
> > +++ b/include/media/v4l2-async.h
> > @@ -65,10 +65,10 @@ struct v4l2_async_match_desc {
> >   * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> >   *
> >   * @match:	struct of match type and per-bus type matching data sets
> > - * @asd_list:	used to add struct v4l2_async_subdev objects to the
> > - *		master notifier @asd_list
> > - * @list:	used to link struct v4l2_async_subdev objects, waiting to be
> > - *		probed, to a notifier->waiting list
> > + * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> > + *		master notifier @asd_entry
> 
> I think you mean 'master notifier @asd_list' here.

Yes, thank you.

> 
> > + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> > + *		probed, to a notifier->waiting_list list
> >   *
> >   * When this struct is used as a member in a driver specific struct,
> >   * the driver specific struct shall contain the &struct
> > @@ -76,8 +76,8 @@ struct v4l2_async_match_desc {
> >   */
> >  struct v4l2_async_subdev {
> >  	struct v4l2_async_match_desc match;
> > -	struct list_head list;
> > -	struct list_head asd_list;
> > +	struct list_head asd_entry;
> > +	struct list_head waiting_entry;
> >  };
> >  
> >  /**
> > @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations {
> >   * @sd:		sub-device that registered the notifier, NULL otherwise
> >   * @parent:	parent notifier
> >   * @asd_list:	master list of struct v4l2_async_subdev
> > - * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
> > - * @done:	list of struct v4l2_subdev, already probed
> > - * @list:	member in a global list of notifiers
> > + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
> > + * @done_list:	list of struct v4l2_subdev, already probed
> > + * @notifier_entry: member in a global list of notifiers
> >   */
> >  struct v4l2_async_notifier {
> >  	const struct v4l2_async_notifier_operations *ops;
> > @@ -117,9 +117,9 @@ struct v4l2_async_notifier {
> >  	struct v4l2_subdev *sd;
> >  	struct v4l2_async_notifier *parent;
> >  	struct list_head asd_list;
> > -	struct list_head waiting;
> > -	struct list_head done;
> > -	struct list_head list;
> > +	struct list_head waiting_list;
> > +	struct list_head done_list;
> > +	struct list_head notifier_entry;
> >  };
> >  
> >  /**
> > @@ -134,7 +134,7 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   *
> > - * This function initializes the notifier @asd_list. It must be called
> > + * This function initializes the notifier @asd_entry. It must be called
> >   * before adding a subdevice to a notifier, using one of:
> >   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
> >   * v4l2_async_nf_add_i2c().
> > @@ -147,7 +147,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> >  			   unsigned int asd_struct_size);
> >  /**
> >   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> > - *				subdev to the notifier's master asd_list.
> > + *				subdev to the notifier's master asd_entry.
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
> > @@ -157,7 +157,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> >   *
> >   * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> > - * notifiers @asd_list. The function also gets a reference of the fwnode which
> > + * notifiers @asd_entry. The function also gets a reference of the fwnode which
> >   * is released later at notifier cleanup time.
> >   */
> >  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
> > @@ -170,7 +170,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >  /**
> >   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
> >   *						  remote async subdev to the
> > - *						  notifier's master asd_list.
> > + *						  notifier's master asd_entry.
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @ep: local endpoint pointing to the remote sub-device to be matched,
> > @@ -180,7 +180,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> >   *
> >   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> > - * matching and adds the async sub-device to the notifier's @asd_list. The
> > + * matching and adds the async sub-device to the notifier's @asd_entry. The
> >   * function also gets a reference of the fwnode which is released later at
> >   * notifier cleanup time.
> >   *
> > @@ -196,7 +196,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
> >  			unsigned int asd_struct_size);
> >  /**
> >   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> > - *				subdev to the notifier's master asd_list.
> > + *				subdev to the notifier's master asd_entry.
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @adapter: I2C adapter ID to be matched
> > diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> > index cfd19e72d0fc4..82e4cf3dd2e05 100644
> > --- a/include/media/v4l2-subdev.h
> > +++ b/include/media/v4l2-subdev.h
> > @@ -1020,7 +1020,7 @@ struct v4l2_subdev_platform_data {
> >   * @dev: pointer to the physical device, if any
> >   * @fwnode: The fwnode_handle of the subdev, usually the same as
> >   *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
> > - * @async_list: Links this subdev to a global subdev_list or @notifier->done
> > + * @async_list: Links this subdev to a global subdev_entry or @notifier->done
> 
> There's no subdev_entry, and the list is now called notifier->done_list.
> Have you renamed the wrong thing ?

Oops. I'll fix this for v4.

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries
  2023-05-30  5:40     ` Laurent Pinchart
@ 2023-06-13 14:58       ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 14:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 08:40:59AM +0300, Laurent Pinchart wrote:
> On Tue, May 30, 2023 at 06:09:29AM +0300, Laurent Pinchart wrote:
> > Hi Sakari,
> > 
> > Thank you for the patch.
> > 
> > On Thu, May 25, 2023 at 12:15:55PM +0300, Sakari Ailus wrote:
> > > The naming of list heads and list entries is confusing as they're named
> > > similarly. Use _list for list head and _entry for list entries.
> > > 
> > > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > > ---
> > >  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  2 +-
> > >  drivers/media/platform/xilinx/xilinx-vipp.c   |  6 +--
> > >  drivers/media/v4l2-core/v4l2-async.c          | 54 +++++++++----------
> > >  drivers/staging/media/tegra-video/vi.c        |  4 +-
> > >  include/media/v4l2-async.h                    | 36 ++++++-------
> > >  include/media/v4l2-subdev.h                   |  2 +-
> > >  6 files changed, 52 insertions(+), 52 deletions(-)
> > > 
> > > diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > > index 3c84cb1216320..9231d6a65f4ec 100644
> > > --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > > +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> > > @@ -1420,7 +1420,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
> > >  	unsigned int pad;
> > >  	int ret;
> > >  
> > > -	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) {
> > >  		s_asd = to_sensor_asd(asd);
> > >  		q = &cio2->queue[s_asd->csi2.port];
> > >  
> > > diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> > > index b309af0c83749..52c5a7decf284 100644
> > > --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> > > +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> > > @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev,
> > >  	struct xvip_graph_entity *entity;
> > >  	struct v4l2_async_subdev *asd;
> > >  
> > > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> > >  		entity = to_xvip_entity(asd);
> > >  		if (entity->asd.match.fwnode == fwnode)
> > >  			return entity;
> > > @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
> > >  	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
> > >  
> > >  	/* Create links for every entity. */
> > > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> > >  		entity = to_xvip_entity(asd);
> > >  		ret = xvip_graph_build_one(xdev, entity);
> > >  		if (ret < 0)
> > > @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
> > >  	if (ret < 0)
> > >  		return 0;
> > >  
> > > -	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) {
> > >  		entity = to_xvip_entity(asd);
> > >  		ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
> > >  		if (ret < 0) {
> > > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > > index 5eb9850f1c6c4..06b1e1a1a5f87 100644
> > > --- a/drivers/media/v4l2-core/v4l2-async.c
> > > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > > @@ -213,7 +213,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
> > >  		      struct v4l2_async_match_desc *match);
> > >  	struct v4l2_async_subdev *asd;
> > >  
> > > -	list_for_each_entry(asd, &notifier->waiting, list) {
> > > +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry) {
> > >  		/* bus_type has been verified valid before */
> > >  		switch (asd->match.type) {
> > >  		case V4L2_ASYNC_MATCH_TYPE_I2C:
> > > @@ -262,7 +262,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
> > >  {
> > >  	struct v4l2_async_notifier *n;
> > >  
> > > -	list_for_each_entry(n, &notifier_list, list)
> > > +	list_for_each_entry(n, &notifier_list, notifier_entry)
> > >  		if (n->sd == sd)
> > >  			return n;
> > >  
> > > @@ -287,10 +287,10 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
> > >  {
> > >  	struct v4l2_subdev *sd;
> > >  
> > > -	if (!list_empty(&notifier->waiting))
> > > +	if (!list_empty(&notifier->waiting_list))
> > >  		return false;
> > >  
> > > -	list_for_each_entry(sd, &notifier->done, async_list) {
> > > +	list_for_each_entry(sd, &notifier->done_list, async_list) {
> > >  		struct v4l2_async_notifier *subdev_notifier =
> > >  			v4l2_async_find_subdev_notifier(sd);
> > >  
> > > @@ -312,7 +312,7 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> > >  	struct v4l2_async_notifier *__notifier = notifier;
> > >  
> > >  	/* Quick check whether there are still more sub-devices here. */
> > > -	if (!list_empty(&notifier->waiting))
> > > +	if (!list_empty(&notifier->waiting_list))
> > >  		return 0;
> > >  
> > >  	if (notifier->sd)
> > > @@ -391,13 +391,12 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> > >  		return ret;
> > >  	}
> > >  
> > > -	/* Remove from the waiting list */
> > > -	list_del(&asd->list);
> > > +	list_del(&asd->waiting_entry);
> > >  	sd->asd = asd;
> > >  	sd->notifier = notifier;
> > >  
> > >  	/* Move from the global subdevice list to notifier's done */
> > > -	list_move(&sd->async_list, &notifier->done);
> > > +	list_move(&sd->async_list, &notifier->done_list);
> > >  
> > >  	dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
> > >  		dev_name(sd->dev), ret);
> > > @@ -478,7 +477,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
> > >  {
> > >  	struct v4l2_subdev *sd, *tmp;
> > >  
> > > -	list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
> > > +	list_for_each_entry_safe(sd, tmp, &notifier->done_list, async_list) {
> > >  		struct v4l2_async_notifier *subdev_notifier =
> > >  			v4l2_async_find_subdev_notifier(sd);
> > >  
> > > @@ -487,7 +486,8 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
> > >  
> > >  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> > >  		if (readd)
> > > -			list_add_tail(&sd->asd->list, &notifier->waiting);
> > > +			list_add_tail(&sd->asd->waiting_entry,
> > > +				      &notifier->waiting_list);
> > >  		v4l2_async_cleanup(sd);
> > >  
> > >  		list_move(&sd->async_list, &subdev_list);
> > > @@ -504,11 +504,11 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
> > >  	struct v4l2_async_subdev *asd;
> > >  	struct v4l2_subdev *sd;
> > >  
> > > -	list_for_each_entry(asd, &notifier->waiting, list)
> > > +	list_for_each_entry(asd, &notifier->waiting_list, waiting_entry)
> > >  		if (v4l2_async_match_equal(&asd->match, match))
> > >  			return true;
> > >  
> > > -	list_for_each_entry(sd, &notifier->done, async_list) {
> > > +	list_for_each_entry(sd, &notifier->done_list, async_list) {
> > >  		if (WARN_ON(!sd->asd))
> > >  			continue;
> > >  
> > > @@ -533,7 +533,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> > >  	lockdep_assert_held(&list_lock);
> > >  
> > >  	/* Check that an asd is not being added more than once. */
> > > -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
> > >  		if (skip_self && &asd->match == match)
> > >  			break;
> > >  		if (v4l2_async_match_equal(&asd->match, match))
> > > @@ -541,7 +541,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
> > >  	}
> > >  
> > >  	/* Check that an asd does not exist in other notifiers. */
> > > -	list_for_each_entry(notifier, &notifier_list, list)
> > > +	list_for_each_entry(notifier, &notifier_list, notifier_entry)
> > >  		if (v4l2_async_nf_has_async_match_entry(notifier, match))
> > >  			return true;
> > >  
> > > @@ -583,17 +583,17 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
> > >  	struct v4l2_async_subdev *asd;
> > >  	int ret;
> > >  
> > > -	INIT_LIST_HEAD(&notifier->waiting);
> > > -	INIT_LIST_HEAD(&notifier->done);
> > > +	INIT_LIST_HEAD(&notifier->waiting_list);
> > > +	INIT_LIST_HEAD(&notifier->done_list);
> > >  
> > >  	mutex_lock(&list_lock);
> > >  
> > > -	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &notifier->asd_list, asd_entry) {
> > >  		ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
> > >  		if (ret)
> > >  			goto err_unlock;
> > >  
> > > -		list_add_tail(&asd->list, &notifier->waiting);
> > > +		list_add_tail(&asd->waiting_entry, &notifier->waiting_list);
> > >  	}
> > >  
> > >  	ret = v4l2_async_nf_try_all_subdevs(notifier);
> > > @@ -605,7 +605,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
> > >  		goto err_unbind;
> > >  
> > >  	/* Keep also completed notifiers on the list */
> > > -	list_add(&notifier->list, &notifier_list);
> > > +	list_add(&notifier->notifier_entry, &notifier_list);
> > >  
> > >  	mutex_unlock(&list_lock);
> > >  
> > > @@ -670,7 +670,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
> > >  	notifier->sd = NULL;
> > >  	notifier->v4l2_dev = NULL;
> > >  
> > > -	list_del(&notifier->list);
> > > +	list_del(&notifier->notifier_entry);
> > >  }
> > >  
> > >  void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
> > > @@ -690,7 +690,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
> > >  	if (!notifier || !notifier->asd_list.next)
> > >  		return;
> > >  
> > > -	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
> > > +	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_entry) {
> > >  		switch (asd->match.type) {
> > >  		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
> > >  			fwnode_handle_put(asd->match.fwnode);
> > > @@ -699,7 +699,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
> > >  			break;
> > >  		}
> > >  
> > > -		list_del(&asd->asd_list);
> > > +		list_del(&asd->asd_entry);
> > >  		v4l2_async_nf_call_destroy(notifier, asd);
> > >  		kfree(asd);
> > >  	}
> > > @@ -727,7 +727,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
> > >  	if (ret)
> > >  		goto unlock;
> > >  
> > > -	list_add_tail(&asd->asd_list, &notifier->asd_list);
> > > +	list_add_tail(&asd->asd_entry, &notifier->asd_list);
> > >  
> > >  unlock:
> > >  	mutex_unlock(&list_lock);
> > > @@ -823,7 +823,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
> > >  
> > >  	mutex_lock(&list_lock);
> > >  
> > > -	list_for_each_entry(notifier, &notifier_list, list) {
> > > +	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
> > >  		struct v4l2_device *v4l2_dev =
> > >  			v4l2_async_nf_find_v4l2_dev(notifier);
> > >  		struct v4l2_async_subdev *asd;
> > > @@ -890,7 +890,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
> > >  	if (sd->asd) {
> > >  		struct v4l2_async_notifier *notifier = sd->notifier;
> > >  
> > > -		list_add(&sd->asd->list, &notifier->waiting);
> > > +		list_add(&sd->asd->waiting_entry, &notifier->waiting_list);
> > >  
> > >  		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
> > >  	}
> > > @@ -944,9 +944,9 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
> > >  
> > >  	mutex_lock(&list_lock);
> > >  
> > > -	list_for_each_entry(notif, &notifier_list, list) {
> > > +	list_for_each_entry(notif, &notifier_list, notifier_entry) {
> > >  		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
> > > -		list_for_each_entry(asd, &notif->waiting, list)
> > > +		list_for_each_entry(asd, &notif->waiting_list, waiting_entry)
> > >  			print_waiting_match(s, &asd->match);
> > >  	}
> > >  
> > > diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
> > > index 2f1aff7e87170..350871f34f7cc 100644
> > > --- a/drivers/staging/media/tegra-video/vi.c
> > > +++ b/drivers/staging/media/tegra-video/vi.c
> > > @@ -1565,7 +1565,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
> > >  	struct tegra_vi_graph_entity *entity;
> > >  	struct v4l2_async_subdev *asd;
> > >  
> > > -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
> > >  		entity = to_tegra_vi_graph_entity(asd);
> > >  		if (entity->asd.match.fwnode == fwnode)
> > >  			return entity;
> > > @@ -1709,7 +1709,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
> > >  	}
> > >  
> > >  	/* create links between the entities */
> > > -	list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) {
> > > +	list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) {
> > >  		entity = to_tegra_vi_graph_entity(asd);
> > >  		ret = tegra_vi_graph_build(chan, entity);
> > >  		if (ret < 0)
> > > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > > index 8d1506a9755c3..54f9f45ed3d8e 100644
> > > --- a/include/media/v4l2-async.h
> > > +++ b/include/media/v4l2-async.h
> > > @@ -65,10 +65,10 @@ struct v4l2_async_match_desc {
> > >   * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> > >   *
> > >   * @match:	struct of match type and per-bus type matching data sets
> > > - * @asd_list:	used to add struct v4l2_async_subdev objects to the
> > > - *		master notifier @asd_list
> > > - * @list:	used to link struct v4l2_async_subdev objects, waiting to be
> > > - *		probed, to a notifier->waiting list
> > > + * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> > > + *		master notifier @asd_entry
> > 
> > I think you mean 'master notifier @asd_list' here.
> > 
> > > + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> > > + *		probed, to a notifier->waiting_list list
> > >   *
> > >   * When this struct is used as a member in a driver specific struct,
> > >   * the driver specific struct shall contain the &struct
> > > @@ -76,8 +76,8 @@ struct v4l2_async_match_desc {
> > >   */
> > >  struct v4l2_async_subdev {
> > >  	struct v4l2_async_match_desc match;
> > > -	struct list_head list;
> > > -	struct list_head asd_list;
> > > +	struct list_head asd_entry;
> > > +	struct list_head waiting_entry;
> > >  };
> > >  
> > >  /**
> > > @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations {
> > >   * @sd:		sub-device that registered the notifier, NULL otherwise
> > >   * @parent:	parent notifier
> > >   * @asd_list:	master list of struct v4l2_async_subdev
> > > - * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
> > > - * @done:	list of struct v4l2_subdev, already probed
> > > - * @list:	member in a global list of notifiers
> > > + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
> > > + * @done_list:	list of struct v4l2_subdev, already probed
> > > + * @notifier_entry: member in a global list of notifiers
> > >   */
> > >  struct v4l2_async_notifier {
> > >  	const struct v4l2_async_notifier_operations *ops;
> > > @@ -117,9 +117,9 @@ struct v4l2_async_notifier {
> > >  	struct v4l2_subdev *sd;
> > >  	struct v4l2_async_notifier *parent;
> > >  	struct list_head asd_list;
> > > -	struct list_head waiting;
> > > -	struct list_head done;
> > > -	struct list_head list;
> > > +	struct list_head waiting_list;
> > > +	struct list_head done_list;
> > > +	struct list_head notifier_entry;
> > >  };
> > >  
> > >  /**
> > > @@ -134,7 +134,7 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> > >   *
> > >   * @notifier: pointer to &struct v4l2_async_notifier
> > >   *
> > > - * This function initializes the notifier @asd_list. It must be called
> > > + * This function initializes the notifier @asd_entry. It must be called
> > >   * before adding a subdevice to a notifier, using one of:
> > >   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
> > >   * v4l2_async_nf_add_i2c().
> > > @@ -147,7 +147,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> > >  			   unsigned int asd_struct_size);
> > >  /**
> > >   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> > > - *				subdev to the notifier's master asd_list.
> > > + *				subdev to the notifier's master asd_entry.
> > >   *
> > >   * @notifier: pointer to &struct v4l2_async_notifier
> > >   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
> > > @@ -157,7 +157,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> > >   *	  sub-device struct, i.e. both begin at the same memory address.
> > >   *
> > >   * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> > > - * notifiers @asd_list. The function also gets a reference of the fwnode which
> > > + * notifiers @asd_entry. The function also gets a reference of the fwnode which
> 
> This rename doesn't seem correct, I think it refers to the notifier's
> asd_list, which didn't get renamed, not the v4l2_async_subdev.asd_list.
> 
> > >   * is released later at notifier cleanup time.
> > >   */
> > >  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
> > > @@ -170,7 +170,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> > >  /**
> > >   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
> > >   *						  remote async subdev to the
> > > - *						  notifier's master asd_list.
> > > + *						  notifier's master asd_entry.
> 
> Same here.
> 
> > >   *
> > >   * @notifier: pointer to &struct v4l2_async_notifier
> > >   * @ep: local endpoint pointing to the remote sub-device to be matched,
> > > @@ -180,7 +180,7 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> > >   *	  sub-device struct, i.e. both begin at the same memory address.
> > >   *
> > >   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> > > - * matching and adds the async sub-device to the notifier's @asd_list. The
> > > + * matching and adds the async sub-device to the notifier's @asd_entry. The
> 
> Same here.
> 
> > >   * function also gets a reference of the fwnode which is released later at
> > >   * notifier cleanup time.
> > >   *
> > > @@ -196,7 +196,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
> > >  			unsigned int asd_struct_size);
> > >  /**
> > >   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> > > - *				subdev to the notifier's master asd_list.
> > > + *				subdev to the notifier's master asd_entry.
> 
> Same here.

There were six instances of this, I think I've renamed them all by mistake.

Thanks for spotting this.

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early
  2023-05-30  4:56     ` Laurent Pinchart
@ 2023-06-13 15:08       ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 15:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 07:56:08AM +0300, Laurent Pinchart wrote:
> On Tue, May 30, 2023 at 07:54:46AM +0300, Laurent Pinchart wrote:
> > Hi Sakari,
> > 
> > Thank you for the patch.
> > 
> > On Thu, May 25, 2023 at 12:16:07PM +0300, Sakari Ailus wrote:
> > > Register V4L2 device before initialising the notifier. This way the device
> > > is available to the notifier from the beginning which makes it possible to
> > > use it for debug prints.
> > > 
> > > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > > ---
> > >  drivers/media/platform/intel/pxa_camera.c | 19 ++++++++++---------
> > >  1 file changed, 10 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> > > index dad5e8d97683e..5df93fd4ff04b 100644
> > > --- a/drivers/media/platform/intel/pxa_camera.c
> > > +++ b/drivers/media/platform/intel/pxa_camera.c
> > > @@ -2307,6 +2307,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
> > >  		return err;
> > >  	}
> > >  
> > > +	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> > > +	if (err)
> > > +		return err;
> > > +
> > >  	v4l2_async_nf_init(&pcdev->notifier);
> > >  	pcdev->res = res;
> > >  	pcdev->pdata = pdev->dev.platform_data;
> > > @@ -2324,10 +2328,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
> > >  	} else if (pdev->dev.of_node) {
> > >  		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
> > >  	} else {
> > > -		return -ENODEV;
> > > +		err = -ENODEV;
> > >  	}
> > >  	if (err < 0)
> > > -		return err;
> > > +		goto exit_v4l2_device_unregister;
> > >  
> > >  	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
> > >  			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
> > > @@ -2393,22 +2397,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
> > >  	pxa_camera_activate(pcdev);
> > >  
> > >  	platform_set_drvdata(pdev, pcdev);
> > > -	err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
> > > -	if (err)
> > > -		goto exit_deactivate;
> > >  
> > >  	err = pxa_camera_init_videobuf2(pcdev);
> > >  	if (err)
> > > -		goto exit_v4l2_device_unregister;
> > > +		goto exit_deactivate;
> > >  
> > >  	pcdev->notifier.ops = &pxa_camera_sensor_ops;
> > >  	err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
> > 
> > The v4l2_device isn't made available to the notifier before this call,
> > so why is it necessary to register it earlier ?
> 
> Ah, it's because of patch 31/32. Please record this in the commit
> message.

It's already in the commit message, as you requested in an earlier review.

-- 
Sakari Ailus

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

* Re: [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching
  2023-05-30  5:08   ` Laurent Pinchart
@ 2023-06-13 15:10     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 15:10 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 08:08:48AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:56PM +0300, Sakari Ailus wrote:
> > V4L2 async sub-device matching originally used the device nodes only.
> > Endpoint nodes were taken into use instead as using the device nodes was
> > problematic for it was in some cases ambiguous which link might have been
> > in question.
> > 
> > There is however no need to use endpoint nodes on both sides, as the async
> > sub-device's fwnode can always be trivially obtained using
> > fwnode_graph_get_remote_endpoint() when needed while what counts is
> > whether or not the link is between two device nodes, i.e. the device nodes
> > match.
> > 
> > This will briefly break the adv748x driver but it will be fixed later in
> > the set, by patch "media: adv748x: Return to endpoint matching".
> 
> I'm afraid I don't like this. This series is complex and has a high risk
> of causing tricky issues. I would like to be able to bisect the changes.

As we discussed separately, this has been tested on both rcar-vin + adv748x
and i.MX6, I'm not overly concerned of this.

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection
  2023-05-30  5:50   ` Laurent Pinchart
@ 2023-06-13 16:39     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 16:39 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

Thank you for the review, again.

On Tue, May 30, 2023 at 08:50:03AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:57PM +0300, Sakari Ailus wrote:
> > Rename v4l2_async_subdev as v4l2_async_connection, in order to
> > differentiate between the sub-devices and their connections: one
> > sub-device can have many connections but the V4L2 async framework has so
> > far allowed just a single one. Connections in this context will later
> > translate into either MC ancillary or data links.
> > 
> > This patch prepares changing that relation by changing existing users of
> > v4l2_async_subdev to switch to v4l2_async_connection. Async sub-devices
> > themselves will not be needed anymore
> > 
> > Additionally, __v4l2_async_nf_add_subdev() has been renamed as
> 
> s/renamed as/renamed to/
> 
> > __v4l2_async_nf_add_connection().

Actually I think there should be no preposition at all here.

> 
> I still don't like the name "connection" at all :-( It may seem fine as
> you've been working on this extensively, but for people less familiar
> with v4l2-async (myself included), I fear it will make the framework
> more difficult to understand.
> 
> At the very least I'd like a detailed and clear glossary, to explain
> what a connection *is*. The v4l2-async documentation is fairly bad (and
> what is currently documented in v4l2-subdev.rst should likely be moved
> to v4l2-async.rst).

That's a fair point. I'll add documentation on this.

What I do like with this is that there's now a clear separation between the
placeholder registered with the notifier and the sub-device itself. That
used to be sometimes a bit confusing.

> 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  .../driver-api/media/v4l2-subdev.rst          |  12 +-
> >  drivers/media/i2c/max9286.c                   |   9 +-
> >  drivers/media/i2c/st-mipid02.c                |   8 +-
> >  drivers/media/i2c/tc358746.c                  |   6 +-
> >  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  10 +-
> >  drivers/media/platform/atmel/atmel-isi.c      |   8 +-
> >  drivers/media/platform/atmel/atmel-isi.h      |   2 +-
> >  drivers/media/platform/cadence/cdns-csi2rx.c  |   6 +-
> >  drivers/media/platform/intel/pxa_camera.c     |  12 +-
> >  drivers/media/platform/marvell/cafe-driver.c  |   5 +-
> >  drivers/media/platform/marvell/mcam-core.c    |   4 +-
> >  drivers/media/platform/marvell/mmp-driver.c   |   4 +-
> >  .../platform/microchip/microchip-csi2dc.c     |   6 +-
> >  .../platform/microchip/microchip-isc-base.c   |   4 +-
> >  .../media/platform/microchip/microchip-isc.h  |   2 +-
> >  .../microchip/microchip-sama5d2-isc.c         |   4 +-
> >  .../microchip/microchip-sama7g5-isc.c         |   4 +-
> >  drivers/media/platform/nxp/imx-mipi-csis.c    |   6 +-
> >  drivers/media/platform/nxp/imx7-media-csi.c   |   6 +-
> >  .../platform/nxp/imx8-isi/imx8-isi-core.c     |   8 +-
> >  drivers/media/platform/qcom/camss/camss.c     |   2 +-
> >  drivers/media/platform/qcom/camss/camss.h     |   2 +-
> >  drivers/media/platform/renesas/rcar-isp.c     |   8 +-
> >  .../platform/renesas/rcar-vin/rcar-core.c     |  44 ++---
> >  .../platform/renesas/rcar-vin/rcar-csi2.c     |  16 +-
> >  .../platform/renesas/rcar-vin/rcar-vin.h      |   8 +-
> >  drivers/media/platform/renesas/rcar_drif.c    |   8 +-
> >  drivers/media/platform/renesas/renesas-ceu.c  |   6 +-
> >  .../platform/renesas/rzg2l-cru/rzg2l-core.c   |  10 +-
> >  .../platform/renesas/rzg2l-cru/rzg2l-cru.h    |   2 +-
> >  .../platform/renesas/rzg2l-cru/rzg2l-csi2.c   |   8 +-
> >  .../platform/rockchip/rkisp1/rkisp1-common.h  |   2 +-
> >  .../platform/rockchip/rkisp1/rkisp1-dev.c     |   8 +-
> >  .../platform/samsung/exynos4-is/media-dev.c   |   6 +-
> >  .../platform/samsung/exynos4-is/media-dev.h   |   2 +-
> >  drivers/media/platform/st/stm32/stm32-dcmi.c  |   8 +-
> >  .../platform/sunxi/sun4i-csi/sun4i_csi.c      |   6 +-
> >  .../sunxi/sun6i-csi/sun6i_csi_bridge.c        |   2 +-
> >  .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   2 +-
> >  .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   |   6 +-
> >  .../sun8i_a83t_mipi_csi2.c                    |   6 +-
> >  .../media/platform/ti/am437x/am437x-vpfe.c    |   5 +-
> >  .../media/platform/ti/am437x/am437x-vpfe.h    |   2 +-
> >  drivers/media/platform/ti/cal/cal.c           |   6 +-
> >  .../media/platform/ti/davinci/vpif_capture.c  |   7 +-
> >  drivers/media/platform/ti/omap3isp/isp.h      |   2 +-
> >  drivers/media/platform/video-mux.c            |   6 +-
> >  drivers/media/platform/xilinx/xilinx-vipp.c   |  22 +--
> >  drivers/media/v4l2-core/v4l2-async.c          | 159 +++++++++---------
> >  drivers/media/v4l2-core/v4l2-fwnode.c         |   8 +-
> >  .../media/deprecated/atmel/atmel-isc-base.c   |   4 +-
> >  .../media/deprecated/atmel/atmel-isc.h        |   2 +-
> >  .../deprecated/atmel/atmel-sama5d2-isc.c      |   4 +-
> >  .../deprecated/atmel/atmel-sama7g5-isc.c      |   4 +-
> >  drivers/staging/media/imx/imx-media-csi.c     |   6 +-
> >  .../staging/media/imx/imx-media-dev-common.c  |   2 +-
> >  drivers/staging/media/imx/imx-media-dev.c     |   2 +-
> >  drivers/staging/media/imx/imx-media-of.c      |   4 +-
> >  drivers/staging/media/imx/imx6-mipi-csi2.c    |   8 +-
> >  drivers/staging/media/imx/imx8mq-mipi-csi2.c  |   6 +-
> >  .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    |   2 +-
> >  .../media/sunxi/sun6i-isp/sun6i_isp_proc.h    |   2 +-
> >  drivers/staging/media/tegra-video/vi.c        |  14 +-
> >  drivers/staging/media/tegra-video/vi.h        |   2 +-
> >  include/media/davinci/vpif_types.h            |   2 +-
> >  include/media/v4l2-async.h                    |  66 ++++----
> >  include/media/v4l2-fwnode.h                   |   2 +-
> >  include/media/v4l2-subdev.h                   |   5 +-
> >  68 files changed, 320 insertions(+), 322 deletions(-)
> > 
> > diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> > index ce8e9d0a332bc..83d3d29608136 100644
> > --- a/Documentation/driver-api/media/v4l2-subdev.rst
> > +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> > @@ -214,14 +214,14 @@ notifier and further registers async sub-devices for lens and flash devices
> >  found in firmware. The notifier for the sub-device is unregistered with the
> >  async sub-device.
> >  
> > -These functions allocate an async sub-device descriptor which is of type struct
> > -:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct
> > -:c:type:`v4l2_async_subdev` shall be the first member of this struct:
> > +These functions allocate an async connection descriptor which is of type struct
> > +:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct
> > +:c:type:`v4l2_async_connection` shall be the first member of this struct:
> >  
> >  .. code-block:: c
> >  
> >  	struct my_async_subdev {
> > -		struct v4l2_async_subdev asd;
> > +		struct v4l2_async_connection asd;
> 
> s/asd/asc/

Yes.

There are other minor issues in the example, I'll address them in a
separate patch.

> 
> >  		...
> >  	};
> >  
> > @@ -244,10 +244,10 @@ notifier callback is called. After all subdevices have been located the
> >  system the .unbind() method is called. All three callbacks are optional.
> >  
> >  Drivers can store any type of custom data in their driver-specific
> > -:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special
> > +:c:type:`v4l2_async_connection` wrapper. If any of that data requires special
> >  handling when the structure is freed, drivers must implement the ``.destroy()``
> >  notifier callback. The framework will call it right before freeing the
> > -:c:type:`v4l2_async_subdev`.
> > +:c:type:`v4l2_async_connection`.
> >  
> >  Calling subdev operations
> >  ~~~~~~~~~~~~~~~~~~~~~~~~~
> > diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
> > index 64f5c49cae776..44def5e3ba5d1 100644
> > --- a/drivers/media/i2c/max9286.c
> > +++ b/drivers/media/i2c/max9286.c
> > @@ -161,11 +161,12 @@ struct max9286_source {
> >  };
> >  
> >  struct max9286_asd {
> 
> This should be renamed to max9286_asc. I said in the review of a
> previous version that I was fine keeping the name as-is, as the
> v4l2_async_subdev structure was reintroduced later in the series, but
> that's not the case anymore.

This should be less confusing now than with v2 where the internal async
sub-device struct was not the same object that was used by drivers
previously.

> 
> > -	struct v4l2_async_subdev base;
> > +	struct v4l2_async_connection base;
> >  	struct max9286_source *source;
> >  };
> >  
> > -static inline struct max9286_asd *to_max9286_asd(struct v4l2_async_subdev *asd)
> > +static inline struct max9286_asd *
> > +to_max9286_asd(struct v4l2_async_connection *asd)
> 
> s/asd/asc/g
> 
> There's more below, in most drivers.

Yes, but is it worth renaming them? In all existing drivers there's no
functional change here. If you'd like them to be renamed, I think it should
be done after this set, that has already more than 32 patches and more than
2000 lines of changes.

> 
> >  {
> >  	return container_of(asd, struct max9286_asd, base);
> >  }
> > @@ -659,7 +660,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
> >  
> >  static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
> >  				struct v4l2_subdev *subdev,
> > -				struct v4l2_async_subdev *asd)
> > +				struct v4l2_async_connection *asd)
> >  {
> >  	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
> >  	struct max9286_source *source = to_max9286_asd(asd)->source;
> > @@ -721,7 +722,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
> >  
> >  static void max9286_notify_unbind(struct v4l2_async_notifier *notifier,
> >  				  struct v4l2_subdev *subdev,
> > -				  struct v4l2_async_subdev *asd)
> > +				  struct v4l2_async_connection *asd)
> >  {
> >  	struct max9286_priv *priv = sd_to_max9286(notifier->sd);
> >  	struct max9286_source *source = to_max9286_asd(asd)->source;
> 
> [snip]
> 
> > diff --git a/drivers/media/platform/atmel/atmel-isi.h b/drivers/media/platform/atmel/atmel-isi.h
> > index 7ad3895a2c87e..58ce900ca4c90 100644
> > --- a/drivers/media/platform/atmel/atmel-isi.h
> > +++ b/drivers/media/platform/atmel/atmel-isi.h
> > @@ -121,7 +121,7 @@
> >  #define ISI_DATAWIDTH_8				0x01
> >  #define ISI_DATAWIDTH_10			0x02
> >  
> > -struct v4l2_async_subdev;
> > +struct v4l2_async_connection;
> 
> You can actually drop this, it's not used in this file.

Ack. I think I'll add a new patch for this as these don't really belong
here.

> 
> >  
> >  struct isi_platform_data {
> >  	u8 has_emb_sync;
> 
> [snip]
> 
> > diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> > index cb206d3976ddf..c99d64e1cb01f 100644
> > --- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> > +++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
> > @@ -106,7 +106,7 @@ struct rvin_video_format {
> >  
> >  /**
> >   * struct rvin_parallel_entity - Parallel video input endpoint descriptor
> > - * @asd:	sub-device descriptor for async framework
> > + * @asc:	sub-device descriptor for async framework
> 
> The description of the field should also be updated.

I'll address that in v4.

> 
> >   * @subdev:	subdevice matched using async framework
> >   * @mbus_type:	media bus type
> >   * @bus:	media bus parallel configuration
> > @@ -115,7 +115,7 @@ struct rvin_video_format {
> >   *
> >   */
> >  struct rvin_parallel_entity {
> > -	struct v4l2_async_subdev *asd;
> > +	struct v4l2_async_connection *asc;
> >  	struct v4l2_subdev *subdev;
> >  
> >  	enum v4l2_mbus_type mbus_type;
> > @@ -275,7 +275,7 @@ struct rvin_dev {
> >   * @notifier:		group notifier for CSI-2 async subdevices
> >   * @vin:		VIN instances which are part of the group
> >   * @link_setup:		Callback to create all links for the media graph
> > - * @remotes:		array of pairs of fwnode and subdev pointers
> > + * @remotes:		array of pairs of async connection and subdev pointers
> >   *			to all remote subdevices.
> >   */
> >  struct rvin_group {
> > @@ -291,7 +291,7 @@ struct rvin_group {
> >  	int (*link_setup)(struct rvin_dev *vin);
> >  
> >  	struct {
> > -		struct v4l2_async_subdev *asd;
> > +		struct v4l2_async_connection *asc;
> >  		struct v4l2_subdev *subdev;
> >  	} remotes[RVIN_REMOTES_MAX];
> >  };
> 
> [snip]
> 
> > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > index 54f9f45ed3d8e..38d9d097fdb52 100644
> > --- a/include/media/v4l2-async.h
> > +++ b/include/media/v4l2-async.h
> > @@ -34,7 +34,7 @@ enum v4l2_async_match_type {
> >  };
> >  
> >  /**
> > - * struct v4l2_async_match_desc - async sub-device match information
> > + * struct v4l2_async_match_desc - async connection match information
> >   *
> >   * @type:	type of match that will be used
> >   * @fwnode:	pointer to &struct fwnode_handle to be matched.
> > @@ -62,21 +62,21 @@ struct v4l2_async_match_desc {
> >  };
> >  
> >  /**
> > - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
> > + * struct v4l2_async_connection - connection descriptor, as known to a bridge
> >   *
> >   * @match:	struct of match type and per-bus type matching data sets
> > - * @asd_entry:	used to add struct v4l2_async_subdev objects to the
> > - *		master notifier @asd_entry
> > - * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be
> > - *		probed, to a notifier->waiting_list list
> > + * @asc_entry:	used to add struct v4l2_async_connection objects to the
> > + *		master notifier @asc_list
> > + * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to
> > + *		be probed, to a notifier->waiting_list list
> >   *
> >   * When this struct is used as a member in a driver specific struct,
> >   * the driver specific struct shall contain the &struct
> > - * v4l2_async_subdev as its first member.
> > + * v4l2_async_connection as its first member.
> >   */
> > -struct v4l2_async_subdev {
> > +struct v4l2_async_connection {
> >  	struct v4l2_async_match_desc match;
> > -	struct list_head asd_entry;
> > +	struct list_head asc_entry;
> >  	struct list_head waiting_entry;
> >  };
> >  
> > @@ -86,17 +86,17 @@ struct v4l2_async_subdev {
> >   * @complete:	All subdevices have been probed successfully. The complete
> >   *		callback is only executed for the root notifier.
> >   * @unbind:	a subdevice is leaving
> > - * @destroy:	the asd is about to be freed
> > + * @destroy:	the asc is about to be freed
> >   */
> >  struct v4l2_async_notifier_operations {
> >  	int (*bound)(struct v4l2_async_notifier *notifier,
> >  		     struct v4l2_subdev *subdev,
> > -		     struct v4l2_async_subdev *asd);
> > +		     struct v4l2_async_connection *asc);
> >  	int (*complete)(struct v4l2_async_notifier *notifier);
> >  	void (*unbind)(struct v4l2_async_notifier *notifier,
> >  		       struct v4l2_subdev *subdev,
> > -		       struct v4l2_async_subdev *asd);
> > -	void (*destroy)(struct v4l2_async_subdev *asd);
> > +		       struct v4l2_async_connection *asc);
> > +	void (*destroy)(struct v4l2_async_connection *asc);
> >  };
> >  
> >  /**
> > @@ -106,7 +106,7 @@ struct v4l2_async_notifier_operations {
> >   * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
> >   * @sd:		sub-device that registered the notifier, NULL otherwise
> >   * @parent:	parent notifier
> > - * @asd_list:	master list of struct v4l2_async_subdev
> > + * @asc_list:	master list of struct v4l2_async_subdev
> 
> v4l2_async_subdev is no more.
> 
> >   * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers
> 
> Same here.

I'll check these for v4.

> 
> >   * @done_list:	list of struct v4l2_subdev, already probed
> >   * @notifier_entry: member in a global list of notifiers
> > @@ -116,7 +116,7 @@ struct v4l2_async_notifier {
> >  	struct v4l2_device *v4l2_dev;
> >  	struct v4l2_subdev *sd;
> >  	struct v4l2_async_notifier *parent;
> > -	struct list_head asd_list;
> > +	struct list_head asc_list;
> >  	struct list_head waiting_list;
> >  	struct list_head done_list;
> >  	struct list_head notifier_entry;
> > @@ -134,53 +134,53 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   *
> > - * This function initializes the notifier @asd_entry. It must be called
> > + * This function initializes the notifier @asc_entry. It must be called
> 
> This sounds like it should be asc_list. The issues was likely introduced
> in an earlier patch in the series.

I believe so, yes. For v4.

> 
> >   * before adding a subdevice to a notifier, using one of:
> >   * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or
> >   * v4l2_async_nf_add_i2c().
> >   */
> >  void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
> >  
> > -struct v4l2_async_subdev *
> > +struct v4l2_async_connection *
> >  __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
> >  			   struct fwnode_handle *fwnode,
> > -			   unsigned int asd_struct_size);
> > +			   unsigned int asc_struct_size);
> >  /**
> >   * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
> > - *				subdev to the notifier's master asd_entry.
> > + *				subdev to the notifier's master asc_entry.
> 
> Same here.
> 
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @fwnode: fwnode handle of the sub-device to be matched, pointer to
> >   *	    &struct fwnode_handle
> > - * @type: Type of the driver's async sub-device struct. The &struct
> > - *	  v4l2_async_subdev shall be the first member of the driver's async
> > - *	  sub-device struct, i.e. both begin at the same memory address.
> > + * @type: Type of the driver's async sub-device or connection struct. The
> > + *	  &struct v4l2_async_connection shall be the first member of the
> > + *	  driver's async struct, i.e. both begin at the same memory address.
> >   *
> > - * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
> > - * notifiers @asd_entry. The function also gets a reference of the fwnode which
> > + * Allocate a fwnode-matched asc of size asc_struct_size, and add it to the
> > + * notifiers @asc_entry. The function also gets a reference of the fwnode which
> 
> Here too.
> 
> >   * is released later at notifier cleanup time.
> >   */
> >  #define v4l2_async_nf_add_fwnode(notifier, fwnode, type)		\
> >  	((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type)))
> >  
> > -struct v4l2_async_subdev *
> > +struct v4l2_async_connection *
> >  __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >  				  struct fwnode_handle *endpoint,
> > -				  unsigned int asd_struct_size);
> > +				  unsigned int asc_struct_size);
> >  /**
> >   * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
> >   *						  remote async subdev to the
> > - *						  notifier's master asd_entry.
> > + *						  notifier's master asc_entry.
> 
> And here.
> 
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @ep: local endpoint pointing to the remote sub-device to be matched,
> >   *	pointer to &struct fwnode_handle
> >   * @type: Type of the driver's async sub-device struct. The &struct
> > - *	  v4l2_async_subdev shall be the first member of the driver's async
> > + *	  v4l2_async_connection shall be the first member of the driver's async
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> >   *
> >   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
> > - * matching and adds the async sub-device to the notifier's @asd_entry. The
> > + * matching and adds the async connection to the notifier's @asc_entry. The
> 
> Here too again.
> 
> >   * function also gets a reference of the fwnode which is released later at
> >   * notifier cleanup time.
> >   *
> > @@ -190,19 +190,19 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
> >  #define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \
> >  	((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type)))
> >  
> > -struct v4l2_async_subdev *
> > +struct v4l2_async_connection *
> >  __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
> >  			int adapter_id, unsigned short address,
> > -			unsigned int asd_struct_size);
> > +			unsigned int asc_struct_size);
> >  /**
> >   * v4l2_async_nf_add_i2c - Allocate and add an i2c async
> > - *				subdev to the notifier's master asd_entry.
> > + *				subdev to the notifier's master asc_entry.
> 
> And finally here.
> 
> >   *
> >   * @notifier: pointer to &struct v4l2_async_notifier
> >   * @adapter: I2C adapter ID to be matched
> >   * @address: I2C address of sub-device to be matched
> >   * @type: Type of the driver's async sub-device struct. The &struct
> > - *	  v4l2_async_subdev shall be the first member of the driver's async
> > + *	  v4l2_async_connection shall be the first member of the driver's async
> >   *	  sub-device struct, i.e. both begin at the same memory address.
> 
> s/sub-device/connection/ ? Please double-check if other instances of
> subdev(ice) have been forgotten.

Sure.

> 
> >   *
> >   * Same as v4l2_async_nf_add_fwnode() but for I2C matched
> > diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
> > index 855dae84b751d..4e4a6cf83097a 100644
> > --- a/include/media/v4l2-fwnode.h
> > +++ b/include/media/v4l2-fwnode.h
> > @@ -23,7 +23,7 @@
> >  
> >  struct fwnode_handle;
> >  struct v4l2_async_notifier;
> > -struct v4l2_async_subdev;
> > +struct v4l2_async_connection;
> 
> This is a sign the forward-declaration isn't needed.

Actually I think they all can be now removed, probably due to Jacopo's
patch. I'll address this for v4.

> 
> >  
> >  /**
> >   * struct v4l2_fwnode_endpoint - the endpoint data structure
> > diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> > index 82e4cf3dd2e05..215fc8af87614 100644
> > --- a/include/media/v4l2-subdev.h
> > +++ b/include/media/v4l2-subdev.h
> > @@ -1022,8 +1022,7 @@ struct v4l2_subdev_platform_data {
> >   *	    either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL).
> >   * @async_list: Links this subdev to a global subdev_entry or @notifier->done
> >   *	list.
> > - * @asd: Pointer to respective &struct v4l2_async_subdev.
> > - * @notifier: Pointer to the managing notifier.
> 
> Did you drop this field by mistake ?

Oops. This indeed belongs to a later patch, not here.

> 
> > + * @asd: Pointer to respective &struct v4l2_async_connection.
> >   * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
> >   *		     device using v4l2_async_register_subdev_sensor().
> >   * @pdata: common part of subdevice platform data
> > @@ -1065,7 +1064,7 @@ struct v4l2_subdev {
> >  	struct device *dev;
> >  	struct fwnode_handle *fwnode;
> >  	struct list_head async_list;
> > -	struct v4l2_async_subdev *asd;
> > +	struct v4l2_async_connection *asd;
> >  	struct v4l2_async_notifier *notifier;
> >  	struct v4l2_async_notifier *subdev_notifier;
> >  	struct v4l2_subdev_platform_data *pdata;
> 

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify
  2023-05-30  5:52   ` Laurent Pinchart
@ 2023-06-13 16:55     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 16:55 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 08:52:24AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:15:58PM +0300, Sakari Ailus wrote:
> > Add labels for error handling instead of doing it all in individual cases.
> > Prepare for more functionality in this function.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/v4l2-core/v4l2-async.c | 21 ++++++++++++---------
> >  1 file changed, 12 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > index b1025dfc27a92..f51f0c37210c9 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -320,10 +320,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >  		return ret;
> >  
> >  	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
> > -	if (ret < 0) {
> > -		v4l2_device_unregister_subdev(sd);
> > -		return ret;
> > -	}
> > +	if (ret < 0)
> > +		goto err_unregister_subdev;
> >  
> >  	/*
> >  	 * Depending of the function of the entities involved, we may want to
> > @@ -332,11 +330,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >  	 * pad).
> >  	 */
> >  	ret = v4l2_async_create_ancillary_links(notifier, sd);
> > -	if (ret) {
> > -		v4l2_async_nf_call_unbind(notifier, sd, asc);
> > -		v4l2_device_unregister_subdev(sd);
> > -		return ret;
> > -	}
> > +	if (ret)
> > +		goto err_call_unbind;
> >  
> >  	list_del(&asc->waiting_entry);
> >  	sd->asd = asc;
> > @@ -363,6 +358,14 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >  	subdev_notifier->parent = notifier;
> >  
> >  	return v4l2_async_nf_try_all_subdevs(subdev_notifier);
> 
> Unrelated to this patch, but shoulnd't this have error handling too ?

You're absolutely right. Bad things will happen if this fails. :-(

> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thank you!

> 
> > +
> > +err_call_unbind:
> > +	v4l2_async_nf_call_unbind(notifier, sd, asc);
> > +
> > +err_unregister_subdev:
> > +	v4l2_device_unregister_subdev(sd);
> > +
> > +	return ret;
> >  }
> >  
> >  /* Test all async sub-devices in a notifier for a match. */

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections
  2023-05-30  6:01   ` Laurent Pinchart
@ 2023-06-13 16:58     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-13 16:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 09:01:15AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Thu, May 25, 2023 at 12:15:59PM +0300, Sakari Ailus wrote:
> > The connections are checked for duplicates already when the notifier is
> > registered. This is effectively a sanity check for driver (and possibly
> > obscure firmware) bugs. Don't do this when adding the connection.
> 
> Isn't it better to have this sanity check when the connection is added,
> instead of later when the notifier is registered ? The latter is more
> difficult to debug. If you want to avoid duplicate checks, could we drop
> the one at notifier registration time ?

I've never seen or heard this check failing. I'm therefore not very
concerned keeping it as easy to debug as possible, instead I prefer simpler
implementation.

Checking at the registration time is still necessary as the same match
could have been added to another notifier while this one was being set up.

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init
  2023-05-30  6:22   ` Laurent Pinchart
@ 2023-06-14 12:43     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-14 12:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 09:22:09AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:14PM +0300, Sakari Ailus wrote:
> > Set the v4l2_device already in async notifier init, so struct device
> > related to it will be available before the notifier is registered.
> > 
> > This is done in order to make struct device available earlier, during
> > construction of the async connections, for sensible debug prints.
> 
> I'm worried that the tighter dependency between the notifier and the
> v4l2_device will cause issues later. If it's just to get a struct device
> pointer, wouldn't it be better to pass the struct device to
> v4l2_async_nf_init() ?

And add a device field to the notifier?

I'm really not too worried about this; the device field is available from
the very beginning of the driver's probe function and registering the V4L2
device does not expose any driver interfaces. So I don't see a technical
reason for this.

A better name for v4l2_device_register() would actually be
v4l2_device_init(). Other renaming may follow from that, too. But that is
out of scope of this set in any case.

> 
> > This patch has been mostly generated using the following two commands:
> > 
> > git grep -l v4l2_async_nf_init -- drivers/media/ drivers/staging/media/ |
> > 	while read i; do perl -e '
> > 	@a=<>; unlink("'$i'"); open(F, "> '$i'");
> > 	for $f ({i=>"v4l2_async_nf_init", r=>"v4l2_async_nf_register"},
> > 		{i=>"v4l2_async_subdev_nf_init",
> > 		 r=>"v4l2_async_subdev_nf_register"} ) {
> > 	my $b; @a = map { $b = "$1, $2" if
> > 	s/$f->{r}\(([^,]*),\s*([^\)]*)\)/v4l2_async_nf_register\($2\)/;
> > 	$_; } @a; @a = map { if (defined $b) {
> > 	s/v4l2_async_nf_init\([^\)]*\)/$f->{i}\($b\)/;
> > 	s/$f->{r}\(\K[^,]*,\s*//; }; $_; } @a; }; print F @a; close F;'
> > 	< $i; done
> > 
> > git grep -lP 'v4l2_async_(subdev_|)nf_init' | xargs perl -i -pe \
> > 	's/v4l2_async_(subdev_|)nf_init\(\K([^,]*),\s*([^,]*)\)/$3, $2\)/'
> 
> It may be nice to play with perl code, but I'd like more focus on the
> human-readable part of the commit message, please. The above isn't
> useful to anyone but you, while an English text that explains how the
> v4l2_async_nf_init() function has now been split into
> v4l2_async_nf_init() and v4l2_async_subdev_nf_init() is missing.

I can add a few words about this.

The Perl code was useful for re-creating the patch but by now it has been
modified manually so much it's no longer useful. I'll drop it.

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier
  2023-05-30  5:00   ` Laurent Pinchart
@ 2023-06-20  9:43     ` Sakari Ailus
  2023-06-20 16:50       ` Laurent Pinchart
  0 siblings, 1 reply; 80+ messages in thread
From: Sakari Ailus @ 2023-06-20  9:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 08:00:33AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:08PM +0300, Sakari Ailus wrote:
> > Register V4L2 device before the async notifier so the struct device will
> > be available for the notifier which makes it possible to use it for debug
> > prints.
> 
> Please record in the commit message that this is to prepare for patch
> 31/32. Same comment for other patches in this series.

I've already added the text that tells the purpose is to make future debug
prints possible (with the device). Would you like to have the patch subject
here or something else?

> 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/platform/marvell/cafe-driver.c | 11 +++++++++--
> >  drivers/media/platform/marvell/mcam-core.c   |  6 ------
> >  2 files changed, 9 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
> > index dd1bba70bd791..fbfbb9f67ddfc 100644
> > --- a/drivers/media/platform/marvell/cafe-driver.c
> > +++ b/drivers/media/platform/marvell/cafe-driver.c
> > @@ -536,6 +536,10 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> >  	if (ret)
> >  		goto out_pdown;
> >  
> > +	ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev);
> > +	if (ret)
> > +		goto out_smbus_shutdown;
> > +
> >  	v4l2_async_nf_init(&mcam->notifier);
> >  
> >  	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
> > @@ -544,12 +548,12 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> >  				    struct v4l2_async_connection);
> >  	if (IS_ERR(asd)) {
> >  		ret = PTR_ERR(asd);
> > -		goto out_smbus_shutdown;
> > +		goto out_v4l2_device_unregister;
> >  	}
> >  
> >  	ret = mccic_register(mcam);
> >  	if (ret)
> > -		goto out_smbus_shutdown;
> > +		goto out_v4l2_device_unregister;
> >  
> >  	clkdev_create(mcam->mclk, "xclk", "%d-%04x",
> >  		i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
> > @@ -565,6 +569,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> >  
> >  out_mccic_shutdown:
> >  	mccic_shutdown(mcam);
> > +out_v4l2_device_unregister:
> > +	v4l2_device_unregister(&mcam->v4l2_dev);
> >  out_smbus_shutdown:
> >  	cafe_smbus_shutdown(cam);
> >  out_pdown:
> > @@ -587,6 +593,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> >  static void cafe_shutdown(struct cafe_camera *cam)
> >  {
> >  	mccic_shutdown(&cam->mcam);
> > +	v4l2_device_unregister(&cam->mcam.v4l2_dev);
> >  	cafe_smbus_shutdown(cam);
> >  	free_irq(cam->pdev->irq, cam);
> >  	pci_iounmap(cam->pdev, cam->mcam.regs);
> > diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
> > index 3cee6d6b83fa9..bcfcecdb03ea2 100644
> > --- a/drivers/media/platform/marvell/mcam-core.c
> > +++ b/drivers/media/platform/marvell/mcam-core.c
> > @@ -1866,10 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
> >  	/*
> >  	 * Register with V4L
> >  	 */
> 
> The comment doesn't seem valid anymore.

I'll drop it from v4.

> 
> > -	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
> > -	if (ret)
> > -		goto out;
> > -
> >  	mutex_init(&cam->s_mutex);
> >  	cam->state = S_NOTREADY;
> >  	mcam_set_config_needed(cam, 1);
> > @@ -1915,7 +1911,6 @@ int mccic_register(struct mcam_camera *cam)
> >  
> >  out:
> >  	v4l2_async_nf_unregister(&cam->notifier);
> > -	v4l2_device_unregister(&cam->v4l2_dev);
> >  	v4l2_async_nf_cleanup(&cam->notifier);
> >  	return ret;
> >  }
> > @@ -1937,7 +1932,6 @@ void mccic_shutdown(struct mcam_camera *cam)
> >  		mcam_free_dma_bufs(cam);
> >  	v4l2_ctrl_handler_free(&cam->ctrl_handler);
> >  	v4l2_async_nf_unregister(&cam->notifier);
> > -	v4l2_device_unregister(&cam->v4l2_dev);
> >  	v4l2_async_nf_cleanup(&cam->notifier);
> >  }
> >  EXPORT_SYMBOL_GPL(mccic_shutdown);

-- 
Kind regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers
  2023-05-30  6:18   ` Laurent Pinchart
@ 2023-06-20 10:14     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-20 10:14 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 09:18:20AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:15PM +0300, Sakari Ailus wrote:
> > Document that sub-device notifiers are now registered using
> > v4l2_async_subdev_nf_init(). No documentation is changed as it seems that
> > sub-device notifiers were not documented apart from kernel-doc comments.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  Documentation/driver-api/media/v4l2-subdev.rst | 10 +++++++---
> >  1 file changed, 7 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> > index 83d3d29608136..d62b341642c96 100644
> > --- a/Documentation/driver-api/media/v4l2-subdev.rst
> > +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> > @@ -193,9 +193,7 @@ picked up by bridge drivers.
> >  Bridge drivers in turn have to register a notifier object. This is
> >  performed using the :c:func:`v4l2_async_nf_register` call. To
> >  unregister the notifier the driver has to call
> > -:c:func:`v4l2_async_nf_unregister`. The former of the two functions
> > -takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
> > -pointer to struct :c:type:`v4l2_async_notifier`.
> > +:c:func:`v4l2_async_nf_unregister`.
> >  
> >  Before registering the notifier, bridge drivers must do two things: first, the
> >  notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
> > @@ -204,6 +202,12 @@ that the bridge device needs for its operation. Several functions are available
> >  to add subdevice descriptors to a notifier, depending on the type of device and
> >  the needs of the driver.
> >  
> > +For a sub-device driver to register a notifier, the process is otherwise similar
> > +to that of a bridge driver, apart from that the notifier is initialised using
> > +:c:func:`v4l2_async_subdev_nf_init` instead. A sub-device notifier may complete
> > +only after the V4L2 device becomes available, i.e. there's a path via async
> > +sub-devices and notifiers to that root notifier.
> 
> This is correct, but I doubt anyone who doesn't have an in-depth
> knowledge of the v4l2-async framework will be able to understand it. For
> instance, the concept of "root notifier" isn't explained anywhere. And
> the v4l2_async_subdev_nf_register() function isn't mentioned.

That's because the function no longer exists. :-)

> 
> The v4l2-async documentation needs a rewrite.

It would benefit from improvements, yes. I can add patches for this if you
prefer.

> 
> > +
> >  :c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote`
> >  :c:and func:`v4l2_async_nf_add_i2c` are for registering their async sub-devices
> >  :c:with the notifier.
> 

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier
  2023-06-20  9:43     ` Sakari Ailus
@ 2023-06-20 16:50       ` Laurent Pinchart
  0 siblings, 0 replies; 80+ messages in thread
From: Laurent Pinchart @ 2023-06-20 16:50 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

On Tue, Jun 20, 2023 at 09:43:38AM +0000, Sakari Ailus wrote:
> Hi Laurent,
> 
> On Tue, May 30, 2023 at 08:00:33AM +0300, Laurent Pinchart wrote:
> > Hi Sakari,
> > 
> > Thank you for the patch.
> > 
> > On Thu, May 25, 2023 at 12:16:08PM +0300, Sakari Ailus wrote:
> > > Register V4L2 device before the async notifier so the struct device will
> > > be available for the notifier which makes it possible to use it for debug
> > > prints.
> > 
> > Please record in the commit message that this is to prepare for patch
> > 31/32. Same comment for other patches in this series.
> 
> I've already added the text that tells the purpose is to make future debug
> prints possible (with the device). Would you like to have the patch subject
> here or something else?

I meant it would be nice to record in the commit message here that the
v4l2-async framework will start making use of the dev field in a
subsequent patch, and that this patch prepares for it.

> > > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > > ---
> > >  drivers/media/platform/marvell/cafe-driver.c | 11 +++++++++--
> > >  drivers/media/platform/marvell/mcam-core.c   |  6 ------
> > >  2 files changed, 9 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c
> > > index dd1bba70bd791..fbfbb9f67ddfc 100644
> > > --- a/drivers/media/platform/marvell/cafe-driver.c
> > > +++ b/drivers/media/platform/marvell/cafe-driver.c
> > > @@ -536,6 +536,10 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> > >  	if (ret)
> > >  		goto out_pdown;
> > >  
> > > +	ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev);
> > > +	if (ret)
> > > +		goto out_smbus_shutdown;
> > > +
> > >  	v4l2_async_nf_init(&mcam->notifier);
> > >  
> > >  	asd = v4l2_async_nf_add_i2c(&mcam->notifier,
> > > @@ -544,12 +548,12 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> > >  				    struct v4l2_async_connection);
> > >  	if (IS_ERR(asd)) {
> > >  		ret = PTR_ERR(asd);
> > > -		goto out_smbus_shutdown;
> > > +		goto out_v4l2_device_unregister;
> > >  	}
> > >  
> > >  	ret = mccic_register(mcam);
> > >  	if (ret)
> > > -		goto out_smbus_shutdown;
> > > +		goto out_v4l2_device_unregister;
> > >  
> > >  	clkdev_create(mcam->mclk, "xclk", "%d-%04x",
> > >  		i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
> > > @@ -565,6 +569,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> > >  
> > >  out_mccic_shutdown:
> > >  	mccic_shutdown(mcam);
> > > +out_v4l2_device_unregister:
> > > +	v4l2_device_unregister(&mcam->v4l2_dev);
> > >  out_smbus_shutdown:
> > >  	cafe_smbus_shutdown(cam);
> > >  out_pdown:
> > > @@ -587,6 +593,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
> > >  static void cafe_shutdown(struct cafe_camera *cam)
> > >  {
> > >  	mccic_shutdown(&cam->mcam);
> > > +	v4l2_device_unregister(&cam->mcam.v4l2_dev);
> > >  	cafe_smbus_shutdown(cam);
> > >  	free_irq(cam->pdev->irq, cam);
> > >  	pci_iounmap(cam->pdev, cam->mcam.regs);
> > > diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
> > > index 3cee6d6b83fa9..bcfcecdb03ea2 100644
> > > --- a/drivers/media/platform/marvell/mcam-core.c
> > > +++ b/drivers/media/platform/marvell/mcam-core.c
> > > @@ -1866,10 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
> > >  	/*
> > >  	 * Register with V4L
> > >  	 */
> > 
> > The comment doesn't seem valid anymore.
> 
> I'll drop it from v4.
> 
> > > -	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
> > > -	if (ret)
> > > -		goto out;
> > > -
> > >  	mutex_init(&cam->s_mutex);
> > >  	cam->state = S_NOTREADY;
> > >  	mcam_set_config_needed(cam, 1);
> > > @@ -1915,7 +1911,6 @@ int mccic_register(struct mcam_camera *cam)
> > >  
> > >  out:
> > >  	v4l2_async_nf_unregister(&cam->notifier);
> > > -	v4l2_device_unregister(&cam->v4l2_dev);
> > >  	v4l2_async_nf_cleanup(&cam->notifier);
> > >  	return ret;
> > >  }
> > > @@ -1937,7 +1932,6 @@ void mccic_shutdown(struct mcam_camera *cam)
> > >  		mcam_free_dma_bufs(cam);
> > >  	v4l2_ctrl_handler_free(&cam->ctrl_handler);
> > >  	v4l2_async_nf_unregister(&cam->notifier);
> > > -	v4l2_device_unregister(&cam->v4l2_dev);
> > >  	v4l2_async_nf_cleanup(&cam->notifier);
> > >  }
> > >  EXPORT_SYMBOL_GPL(mccic_shutdown);

-- 
Regards,

Laurent Pinchart

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

* Re: [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling
  2023-05-30  4:51   ` Laurent Pinchart
@ 2023-06-21 15:43     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-21 15:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

Thanks for the review.

On Tue, May 30, 2023 at 07:51:25AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:06PM +0300, Sakari Ailus wrote:
> > Fix and simplify error handling in pxa_camera probe, by moving devm_*()
> > functions early in the probe function and then tearing down what was set
> > up on error patch.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/platform/intel/pxa_camera.c | 48 ++++++++++++-----------
> >  1 file changed, 25 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
> > index f0d316d5fe27c..dad5e8d97683e 100644
> > --- a/drivers/media/platform/intel/pxa_camera.c
> > +++ b/drivers/media/platform/intel/pxa_camera.c
> > @@ -2289,6 +2289,24 @@ static int pxa_camera_probe(struct platform_device *pdev)
> >  	if (IS_ERR(pcdev->clk))
> >  		return PTR_ERR(pcdev->clk);
> >  
> > +	/*
> > +	 * Request the regions.
> > +	 */
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	pcdev->irq = irq;
> > +	pcdev->base = base;
> > +
> > +	/* request irq */
> > +	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
> > +			       PXA_CAM_DRV_NAME, pcdev);
> > +	if (err) {
> > +		dev_err(&pdev->dev, "Camera interrupt register failed\n");
> > +		return err;
> > +	}
> > +
> 
> The IRQ should not be requested before the device is initialized, to
> avoid spurious IRQs at probe time. I don't think the driver currently
> handles this very well, but moving IRQ registration up is the wrong
> direction. As this particular change isn't needed to clean up the
> notifier, I would keep the devm_request_irq() call where it is.
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Fair enough. I'll move this to just before registering the async
sub-device.

devm_request_irq() is also problematic as an IRQ may still happen once the
driver has executed much of its remove function. I this case this isn't
probably too much of an issue though.

-- 
Regards,

Sakari Ailus

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

* Re: [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists
  2023-05-30  6:11   ` Laurent Pinchart
@ 2023-06-22 12:02     ` Sakari Ailus
  0 siblings, 0 replies; 80+ messages in thread
From: Sakari Ailus @ 2023-06-22 12:02 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Philipp Zabel, hverkuil, Francesco Dolcini,
	aishwarya.kothari, Robert Foss, Todor Tomov, Hyun Kwon,
	bingbu.cao, niklas.soderlund, Kieran Bingham, Benjamin Mugnier,
	Sylvain Petinot, Eugen Hristev, Nicolas Ferre, Maxime Ripard,
	Rui Miguel Silva, Fabio Estevam, Bryan O'Donoghue,
	Sylwester Nawrocki, Dafna Hirschfeld, Hugues Fruchet, Yong Deng,
	Paul Kocialkowski, Lad, Prabhakar, Benoit Parrot,
	Steve Longerbeam, Thierry Reding, Jonathan Hunter,
	Sowjanya Komatineni, Marco Felsch

Hi Laurent,

On Tue, May 30, 2023 at 09:11:53AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Thu, May 25, 2023 at 12:16:00PM +0300, Sakari Ailus wrote:
> > This patch re-arranges internal V4L2 async lists for preparation of
> > supporting multiple connections per sub-device as well as cleaning up used
> > lists.
> > 
> > The list of unbound V4L2 sub-devices is maintained for the purpose of
> > listing those sub-devices only, not for their binding status. Also, the
> > V4L2 async connections have a single list entry in the notifier's list, be
> > that either waiting or done lists, while the notifier's asc_list is
> > removed.
> 
> Please use the imperative style in commit messages. To me it's unclear
> if "is" here refers to the status before or after this patch. I need a
> clear description of what you're doing in order to check if the code
> matches the intent. Guessing the intent from the code makes review more
> difficult and less useful.

I'll reword this as:

The list of unbound V4L2 sub-devices shall be maintained for the purpose of
listing those sub-devices only, not for their bindin status. Also, the V4L2
async connections now have, instead of two list entries, a single list
entry in the notifier's list, be that either waiting or done lists, while
the notifier's asc_list is removed.

-- 
Kind regards,

Sakari Ailus

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

end of thread, other threads:[~2023-06-22 12:03 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-25  9:15 [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 01/32] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
2023-05-30  2:13   ` Laurent Pinchart
2023-05-25  9:15 ` [RESEND PATCH v3 02/32] media: Documentation: v4l: Document missing async subdev function Sakari Ailus
2023-05-30  2:14   ` Laurent Pinchart
2023-06-13 13:43     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 03/32] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
2023-05-30  2:20   ` Laurent Pinchart
2023-05-30  2:21   ` Laurent Pinchart
2023-05-25  9:15 ` [RESEND PATCH v3 04/32] media: omap3isp: Don't check for the sub-device's notifier Sakari Ailus
2023-05-30  2:23   ` Laurent Pinchart
2023-06-13 13:19     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 05/32] media: v4l: async: Add some debug prints Sakari Ailus
2023-05-30  2:34   ` Laurent Pinchart
2023-05-25  9:15 ` [RESEND PATCH v3 06/32] media: v4l: async: Clean up testing for duplicate async subdevs Sakari Ailus
2023-05-30  2:42   ` Laurent Pinchart
2023-06-13 13:57     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 07/32] media: v4l: async: Drop unneeded list entry initialisation Sakari Ailus
2023-05-30  2:46   ` Laurent Pinchart
2023-06-13 14:00     ` Sakari Ailus
2023-06-13 14:08       ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 08/32] media: v4l: async: Don't check whether asd is NULL in validity check Sakari Ailus
2023-05-30  2:48   ` Laurent Pinchart
2023-05-25  9:15 ` [RESEND PATCH v3 09/32] media: v4l: async: Make V4L2 async match information a struct Sakari Ailus
2023-05-30  2:52   ` Laurent Pinchart
2023-06-13 14:35     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 10/32] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ Sakari Ailus
2023-05-30  2:55   ` Laurent Pinchart
2023-05-25  9:15 ` [RESEND PATCH v3 11/32] media: v4l: async: Only pass match information for async subdev validation Sakari Ailus
2023-05-30  3:02   ` Laurent Pinchart
2023-06-13 14:37     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 12/32] media: v4l: async: Clean up list heads and entries Sakari Ailus
2023-05-30  3:09   ` Laurent Pinchart
2023-05-30  5:40     ` Laurent Pinchart
2023-06-13 14:58       ` Sakari Ailus
2023-06-13 14:51     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 13/32] media: v4l: async: Simplify async sub-device fwnode matching Sakari Ailus
2023-05-30  5:08   ` Laurent Pinchart
2023-06-13 15:10     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 14/32] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection Sakari Ailus
2023-05-30  5:50   ` Laurent Pinchart
2023-06-13 16:39     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 15/32] media: v4l: async: Clean up error handling in v4l2_async_match_notify Sakari Ailus
2023-05-30  5:52   ` Laurent Pinchart
2023-06-13 16:55     ` Sakari Ailus
2023-05-25  9:15 ` [RESEND PATCH v3 16/32] media: v4l: async: Drop duplicate handling when adding connections Sakari Ailus
2023-05-30  6:01   ` Laurent Pinchart
2023-06-13 16:58     ` Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 17/32] media: v4l: async: Rework internal lists Sakari Ailus
2023-05-30  6:11   ` Laurent Pinchart
2023-06-22 12:02     ` Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 18/32] media: v4l: async: Obtain async connection based on sub-device Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 19/32] media: v4l: async: Allow multiple connections between entities Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 20/32] media: v4l: async: Try more connections Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 21/32] media: v4l: async: Support fwnode endpoint list matching for subdevs Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 22/32] media: adv748x: Return to endpoint matching Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 23/32] media: pxa_camera: Fix probe error handling Sakari Ailus
2023-05-30  4:51   ` Laurent Pinchart
2023-06-21 15:43     ` Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 24/32] media: pxa_camera: Register V4L2 device early Sakari Ailus
2023-05-30  4:54   ` Laurent Pinchart
2023-05-30  4:56     ` Laurent Pinchart
2023-06-13 15:08       ` Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 25/32] media: marvell: cafe: Register V4L2 device earlier Sakari Ailus
2023-05-30  5:00   ` Laurent Pinchart
2023-06-20  9:43     ` Sakari Ailus
2023-06-20 16:50       ` Laurent Pinchart
2023-05-25  9:16 ` [RESEND PATCH v3 26/32] media: am437x-vpfe: Register V4L2 device early Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 27/32] media: omap3isp: Initialise V4L2 async notifier later Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 28/32] media: xilinx-vipp: Init async notifier after registering V4L2 device Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 29/32] media: davinci: " Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 30/32] media: qcom: Initialise V4L2 async notifier later Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 31/32] media: v4l: async: Set v4l2_device in async notifier init Sakari Ailus
2023-05-30  6:22   ` Laurent Pinchart
2023-06-14 12:43     ` Sakari Ailus
2023-05-25  9:16 ` [RESEND PATCH v3 32/32] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
2023-05-30  6:18   ` Laurent Pinchart
2023-06-20 10:14     ` Sakari Ailus
2023-05-30 12:13   ` Aishwarya Kothari
2023-05-25  9:22 ` [RESEND PATCH v3 00/32] Separate links and async sub-devices Sakari Ailus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).