linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/34] component: Make into an aggregate bus
@ 2021-10-06 19:37 Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
                   ` (35 more replies)
  0 siblings, 36 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Arnd Bergmann,
	Benjamin Gaignard, Chen Feng, Chen-Yu Tsai, Christian Gmeiner,
	Chun-Kuang Hu, Daniel Vetter, Emma Anholt, Heiko Stübner,
	Inki Dae, James Qian Wang, Jaroslav Kysela, Joerg Roedel,
	John Stultz, Joonyoung Shim, Jyri Sarha, Kai Vehmanen,
	Kyungmin Park, Laurent Pinchart, linux-fbdev, linux-omap,
	linux-pm, Liviu Dudau, Lucas Stach, Mark Brown, Maxime Ripard,
	Neil Armstrong, Paul Cercueil, Philipp Zabel, Rafael J. Wysocki,
	Rob Clark, Russell King, Russell King, Russell King, Sandy Huang,
	Saravana Kannan, Sebastian Reichel, Seung-Woo Kim, Takashi Iwai,
	Tian Tao, Tomas Winkler, Tomi Valkeinen, Will Deacon,
	Xinliang Liu, Xinwei Kong, Yong Wu

This series is from discussion we had on reordering the device lists for
drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put
the aggregate device onto and then we probe the aggregate device once
all the components are probed and call component_add(). The probe/remove
hooks are where the bind/unbind calls go, and then a shutdown hook is
added that can be used to shutdown the drm display pipeline at the right
time.

This works for me on my sc7180 board. I no longer get a warning from i2c
at shutdown that we're trying to make an i2c transaction after the i2c
bus has been shutdown. There's more work to do on the msm drm driver to
extract component device resources like clks, regulators, etc. out of
the component bind function into the driver probe but I wanted to move
everything over now in other component drivers before tackling that
problem.

I'll definitely be sending a v3 so this is partially a request for
testing to shake out any more problems. Tested-by tags would be appreciated,
and Acked-by/Reviewed-by tags too. I sent this to gregkh which may be
incorrect but I don't know what better tree to send it all through.
Maybe drm?

I'll be faster at resending this next time, sorry for the long delay!

Changes since v1 (https://lore.kernel.org/r/20210520002519.3538432-1-swboyd@chromium.org):
 - Use devlink to connect components to the aggregate device
 - Don't set the registering device as a parent of the aggregate device
 - New patch for bind_component/unbind_component ops that takes the
   aggregate device
 - Convert all drivers in the tree to use the aggregate driver approach
 - Allow one aggregate driver to be used for multiple aggregate devices

[1] https://lore.kernel.org/r/20210508074118.1621729-1-swboyd@chromium.org

Stephen Boyd (34):
  component: Introduce struct aggregate_device
  component: Introduce the aggregate bus_type
  component: Move struct aggregate_device out to header file
  drm/msm: Migrate to aggregate driver
  component: Add {bind,unbind}_component() ops that take aggregate
    device
  drm/of: Add a drm_of_aggregate_probe() API
  drm/komeda: Migrate to aggregate driver
  drm/arm/hdlcd: Migrate to aggregate driver
  drm/malidp: Migrate to aggregate driver
  drm/armada: Migrate to aggregate driver
  drm/etnaviv: Migrate to aggregate driver
  drm/kirin: Migrate to aggregate driver
  drm/exynos: Migrate to aggregate driver
  drm/imx: Migrate to aggregate driver
  drm/ingenic: Migrate to aggregate driver
  drm/mcde: Migrate to aggregate driver
  drm/mediatek: Migrate to aggregate driver
  drm/meson: Migrate to aggregate driver
  drm/omap: Migrate to aggregate driver
  drm/rockchip: Migrate to aggregate driver
  drm/sti: Migrate to aggregate driver
  drm/sun4i: Migrate to aggregate driver
  drm/tilcdc: Migrate to aggregate driver
  drm/vc4: Migrate to aggregate driver
  drm/zte: Migrate to aggregate driver
  iommu/mtk: Migrate to aggregate driver
  mei: Migrate to aggregate driver
  power: supply: ab8500: Migrate to aggregate driver
  fbdev: omap2: Migrate to aggregate driver
  sound: hdac: Migrate to aggregate driver
  ASoC: codecs: wcd938x: Migrate to aggregate driver
  component: Get rid of drm_of_component_probe()
  component: Remove component_master_ops and friends
  component: Remove all references to 'master'

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Cc: Chen Feng <puck.chen@hisilicon.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
Cc: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Emma Anholt <emma@anholt.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Heiko Stübner" <heiko@sntech.de>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Cc: Jyri Sarha <jyri.sarha@iki.fi>
Cc: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: <linux-fbdev@vger.kernel.org>
Cc: <linux-omap@vger.kernel.org>
Cc: <linux-pm@vger.kernel.org>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Mark Brown <broonie@kernel.org>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Paul Cercueil <paul@crapouillou.net>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Russell King <linux+etnaviv@armlinux.org.uk>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Sandy Huang <hjc@rock-chips.com>
Cc: Saravana Kannan <saravanak@google.com>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: Seung-Woo Kim <sw0312.kim@samsung.com>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Tian Tao <tiantao6@hisilicon.com>
Cc: Tomas Winkler <tomas.winkler@intel.com>
Cc: Tomi Valkeinen <tomba@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
Cc: Yong Wu <yong.wu@mediatek.com>

 drivers/base/component.c                      | 555 +++++++++++-------
 .../gpu/drm/arm/display/komeda/komeda_drv.c   |  20 +-
 drivers/gpu/drm/arm/hdlcd_drv.c               |  21 +-
 drivers/gpu/drm/arm/malidp_drv.c              |  21 +-
 drivers/gpu/drm/armada/armada_drv.c           |  23 +-
 drivers/gpu/drm/drm_drv.c                     |   2 +-
 drivers/gpu/drm/drm_of.c                      |  20 +-
 drivers/gpu/drm/etnaviv/etnaviv_drv.c         |  20 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c       |  21 +-
 .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c   |  20 +-
 drivers/gpu/drm/imx/imx-drm-core.c            |  20 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |  24 +-
 drivers/gpu/drm/mcde/mcde_drv.c               |  23 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  20 +-
 drivers/gpu/drm/meson/meson_drv.c             |  21 +-
 drivers/gpu/drm/msm/msm_drv.c                 |  46 +-
 drivers/gpu/drm/omapdrm/dss/dss.c             |  17 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |  20 +-
 drivers/gpu/drm/sti/sti_drv.c                 |  20 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c             |  26 +-
 drivers/gpu/drm/tilcdc/tilcdc_drv.c           |  28 +-
 drivers/gpu/drm/vc4/vc4_drv.c                 |  20 +-
 drivers/gpu/drm/zte/zx_drm_drv.c              |  20 +-
 drivers/iommu/mtk_iommu.c                     |  14 +-
 drivers/iommu/mtk_iommu.h                     |   6 +-
 drivers/iommu/mtk_iommu_v1.c                  |  14 +-
 drivers/misc/mei/hdcp/mei_hdcp.c              |  22 +-
 drivers/power/supply/ab8500_charger.c         |  22 +-
 drivers/video/fbdev/omap2/omapfb/dss/dss.c    |  20 +-
 include/drm/drm_of.h                          |   9 +-
 include/linux/component.h                     |  92 ++-
 sound/hda/hdac_component.c                    |  21 +-
 sound/soc/codecs/wcd938x.c                    |  20 +-
 33 files changed, 780 insertions(+), 488 deletions(-)


base-commit: e4e737bb5c170df6135a127739a9e6148ee3da82
-- 
https://chromeos.dev


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

* [PATCH v2 01/34] component: Introduce struct aggregate_device
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-07  1:17   ` Laurent Pinchart
  2021-10-13 12:22   ` Daniel Vetter
  2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
                   ` (34 subsequent siblings)
  35 siblings, 2 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Replace 'struct master' with 'struct aggregate_device' and then rename
'master' to 'adev' everywhere in the code. While we're here, put a
struct device inside the aggregate device so that we can register it
with a bus_type in the next patch.

The diff is large but that's because this is mostly a rename, where
sometimes 'master' is replaced with 'adev' and other times it is
replaced with 'parent' to indicate that the struct device that was being
used is actually the parent of the aggregate device and driver.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c  | 250 ++++++++++++++++++++------------------
 include/linux/component.h |   2 +-
 2 files changed, 134 insertions(+), 118 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index 5e79299f6c3f..0a41bbe14981 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -9,6 +9,7 @@
  */
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/idr.h>
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -58,18 +59,21 @@ struct component_match {
 	struct component_match_array *compare;
 };
 
-struct master {
+struct aggregate_device {
 	struct list_head node;
 	bool bound;
 
 	const struct component_master_ops *ops;
 	struct device *parent;
+	struct device dev;
 	struct component_match *match;
+
+	int id;
 };
 
 struct component {
 	struct list_head node;
-	struct master *master;
+	struct aggregate_device *adev;
 	bool bound;
 
 	const struct component_ops *ops;
@@ -79,7 +83,9 @@ struct component {
 
 static DEFINE_MUTEX(component_mutex);
 static LIST_HEAD(component_list);
-static LIST_HEAD(masters);
+static LIST_HEAD(aggregate_devices);
+
+static DEFINE_IDA(aggregate_ida);
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -87,12 +93,12 @@ static struct dentry *component_debugfs_dir;
 
 static int component_devices_show(struct seq_file *s, void *data)
 {
-	struct master *m = s->private;
+	struct aggregate_device *m = s->private;
 	struct component_match *match = m->match;
 	size_t i;
 
 	mutex_lock(&component_mutex);
-	seq_printf(s, "%-40s %20s\n", "master name", "status");
+	seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
 	seq_puts(s, "-------------------------------------------------------------\n");
 	seq_printf(s, "%-40s %20s\n\n",
 		   dev_name(m->parent), m->bound ? "bound" : "not bound");
@@ -122,46 +128,46 @@ static int __init component_debug_init(void)
 
 core_initcall(component_debug_init);
 
-static void component_master_debugfs_add(struct master *m)
+static void component_master_debugfs_add(struct aggregate_device *m)
 {
 	debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m,
 			    &component_devices_fops);
 }
 
-static void component_master_debugfs_del(struct master *m)
+static void component_master_debugfs_del(struct aggregate_device *m)
 {
 	debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir));
 }
 
 #else
 
-static void component_master_debugfs_add(struct master *m)
+static void component_master_debugfs_add(struct aggregate_device *m)
 { }
 
-static void component_master_debugfs_del(struct master *m)
+static void component_master_debugfs_del(struct aggregate_device *m)
 { }
 
 #endif
 
-static struct master *__master_find(struct device *parent,
+static struct aggregate_device *__aggregate_find(struct device *parent,
 	const struct component_master_ops *ops)
 {
-	struct master *m;
+	struct aggregate_device *m;
 
-	list_for_each_entry(m, &masters, node)
+	list_for_each_entry(m, &aggregate_devices, node)
 		if (m->parent == parent && (!ops || m->ops == ops))
 			return m;
 
 	return NULL;
 }
 
-static struct component *find_component(struct master *master,
+static struct component *find_component(struct aggregate_device *adev,
 	struct component_match_array *mc)
 {
 	struct component *c;
 
 	list_for_each_entry(c, &component_list, node) {
-		if (c->master && c->master != master)
+		if (c->adev && c->adev != adev)
 			continue;
 
 		if (mc->compare && mc->compare(c->dev, mc->data))
@@ -175,101 +181,102 @@ static struct component *find_component(struct master *master,
 	return NULL;
 }
 
-static int find_components(struct master *master)
+static int find_components(struct aggregate_device *adev)
 {
-	struct component_match *match = master->match;
+	struct component_match *match = adev->match;
 	size_t i;
 	int ret = 0;
 
 	/*
 	 * Scan the array of match functions and attach
-	 * any components which are found to this master.
+	 * any components which are found to this adev.
 	 */
 	for (i = 0; i < match->num; i++) {
 		struct component_match_array *mc = &match->compare[i];
 		struct component *c;
 
-		dev_dbg(master->parent, "Looking for component %zu\n", i);
+		dev_dbg(adev->parent, "Looking for component %zu\n", i);
 
 		if (match->compare[i].component)
 			continue;
 
-		c = find_component(master, mc);
+		c = find_component(adev, mc);
 		if (!c) {
 			ret = -ENXIO;
 			break;
 		}
 
-		dev_dbg(master->parent, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
+		dev_dbg(adev->parent, "found component %s, duplicate %u\n",
+			dev_name(c->dev), !!c->adev);
 
-		/* Attach this component to the master */
-		match->compare[i].duplicate = !!c->master;
+		/* Attach this component to the adev */
+		match->compare[i].duplicate = !!c->adev;
 		match->compare[i].component = c;
-		c->master = master;
+		c->adev = adev;
 	}
 	return ret;
 }
 
-/* Detach component from associated master */
-static void remove_component(struct master *master, struct component *c)
+/* Detach component from associated aggregate_device */
+static void remove_component(struct aggregate_device *adev, struct component *c)
 {
 	size_t i;
 
-	/* Detach the component from this master. */
-	for (i = 0; i < master->match->num; i++)
-		if (master->match->compare[i].component == c)
-			master->match->compare[i].component = NULL;
+	/* Detach the component from this adev. */
+	for (i = 0; i < adev->match->num; i++)
+		if (adev->match->compare[i].component == c)
+			adev->match->compare[i].component = NULL;
 }
 
 /*
- * Try to bring up a master.  If component is NULL, we're interested in
- * this master, otherwise it's a component which must be present to try
- * and bring up the master.
+ * Try to bring up an aggregate device.  If component is NULL, we're interested
+ * in this aggregate device, otherwise it's a component which must be present
+ * to try and bring up the aggregate device.
  *
  * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
  */
-static int try_to_bring_up_master(struct master *master,
+static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
 	struct component *component)
 {
 	int ret;
 
-	dev_dbg(master->parent, "trying to bring up master\n");
+	dev_dbg(adev->parent, "trying to bring up adev\n");
 
-	if (find_components(master)) {
-		dev_dbg(master->parent, "master has incomplete components\n");
+	if (find_components(adev)) {
+		dev_dbg(adev->parent, "master has incomplete components\n");
 		return 0;
 	}
 
-	if (component && component->master != master) {
-		dev_dbg(master->parent, "master is not for this component (%s)\n",
+	if (component && component->adev != adev) {
+		dev_dbg(adev->parent, "master is not for this component (%s)\n",
 			dev_name(component->dev));
 		return 0;
 	}
 
-	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
+	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
 		return -ENOMEM;
 
 	/* Found all components */
-	ret = master->ops->bind(master->parent);
+	ret = adev->ops->bind(adev->parent);
 	if (ret < 0) {
-		devres_release_group(master->parent, NULL);
+		devres_release_group(adev->parent, NULL);
 		if (ret != -EPROBE_DEFER)
-			dev_info(master->parent, "master bind failed: %d\n", ret);
+			dev_info(adev->parent, "adev bind failed: %d\n", ret);
 		return ret;
 	}
 
-	master->bound = true;
+	adev->bound = true;
 	return 1;
 }
 
 static int try_to_bring_up_masters(struct component *component)
 {
-	struct master *m;
+	struct aggregate_device *adev;
 	int ret = 0;
 
-	list_for_each_entry(m, &masters, node) {
-		if (!m->bound) {
-			ret = try_to_bring_up_master(m, component);
+	list_for_each_entry(adev, &aggregate_devices, node) {
+		if (!adev->bound) {
+			ret = try_to_bring_up_aggregate_device(adev, component);
 			if (ret != 0)
 				break;
 		}
@@ -278,12 +285,12 @@ static int try_to_bring_up_masters(struct component *component)
 	return ret;
 }
 
-static void take_down_master(struct master *master)
+static void take_down_aggregate_device(struct aggregate_device *adev)
 {
-	if (master->bound) {
-		master->ops->unbind(master->parent);
-		devres_release_group(master->parent, NULL);
-		master->bound = false;
+	if (adev->bound) {
+		adev->ops->unbind(adev->parent);
+		devres_release_group(adev->parent, NULL);
+		adev->bound = false;
 	}
 }
 
@@ -324,7 +331,7 @@ static int component_match_realloc(struct component_match *match, size_t num)
 	return 0;
 }
 
-static void __component_match_add(struct device *master,
+static void __component_match_add(struct device *parent,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *),
@@ -344,7 +351,7 @@ static void __component_match_add(struct device *master,
 			return;
 		}
 
-		devres_add(master, match);
+		devres_add(parent, match);
 
 		*matchptr = match;
 	}
@@ -370,13 +377,13 @@ static void __component_match_add(struct device *master,
 
 /**
  * component_match_add_release - add a component match entry with release callback
- * @master: device with the aggregate driver
+ * @parent: parent device of the aggregate driver
  * @matchptr: pointer to the list of component matches
  * @release: release function for @compare_data
  * @compare: compare function to match against all components
  * @compare_data: opaque pointer passed to the @compare function
  *
- * Adds a new component match to the list stored in @matchptr, which the @master
+ * Adds a new component match to the list stored in @matchptr, which the
  * aggregate driver needs to function. The list of component matches pointed to
  * by @matchptr must be initialized to NULL before adding the first match. This
  * only matches against components added with component_add().
@@ -388,19 +395,19 @@ static void __component_match_add(struct device *master,
  *
  * See also component_match_add() and component_match_add_typed().
  */
-void component_match_add_release(struct device *master,
+void component_match_add_release(struct device *parent,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data)
 {
-	__component_match_add(master, matchptr, release, compare, NULL,
+	__component_match_add(parent, matchptr, release, compare, NULL,
 			      compare_data);
 }
 EXPORT_SYMBOL(component_match_add_release);
 
 /**
  * component_match_add_typed - add a component match entry for a typed component
- * @master: device with the aggregate driver
+ * @parent: parent device of the aggregate driver
  * @matchptr: pointer to the list of component matches
  * @compare_typed: compare function to match against all typed components
  * @compare_data: opaque pointer passed to the @compare function
@@ -415,32 +422,33 @@ EXPORT_SYMBOL(component_match_add_release);
  *
  * See also component_match_add_release() and component_match_add_typed().
  */
-void component_match_add_typed(struct device *master,
+void component_match_add_typed(struct device *parent,
 	struct component_match **matchptr,
 	int (*compare_typed)(struct device *, int, void *), void *compare_data)
 {
-	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
+	__component_match_add(parent, matchptr, NULL, NULL, compare_typed,
 			      compare_data);
 }
 EXPORT_SYMBOL(component_match_add_typed);
 
-static void free_master(struct master *master)
+static void free_aggregate_device(struct aggregate_device *adev)
 {
-	struct component_match *match = master->match;
+	struct component_match *match = adev->match;
 	int i;
 
-	component_master_debugfs_del(master);
-	list_del(&master->node);
+	component_master_debugfs_del(adev);
+	list_del(&adev->node);
 
 	if (match) {
 		for (i = 0; i < match->num; i++) {
 			struct component *c = match->compare[i].component;
 			if (c)
-				c->master = NULL;
+				c->adev = NULL;
 		}
 	}
 
-	kfree(master);
+	ida_free(&aggregate_ida, adev->id);
+	kfree(adev);
 }
 
 /**
@@ -459,31 +467,39 @@ int component_master_add_with_match(struct device *parent,
 	const struct component_master_ops *ops,
 	struct component_match *match)
 {
-	struct master *master;
-	int ret;
+	struct aggregate_device *adev;
+	int ret, id;
 
 	/* Reallocate the match array for its true size */
 	ret = component_match_realloc(match, match->num);
 	if (ret)
 		return ret;
 
-	master = kzalloc(sizeof(*master), GFP_KERNEL);
-	if (!master)
+	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+	if (!adev)
 		return -ENOMEM;
 
-	master->parent = parent;
-	master->ops = ops;
-	master->match = match;
+	id = ida_alloc(&aggregate_ida, GFP_KERNEL);
+	if (id < 0) {
+		kfree(adev);
+		return id;
+	}
+
+	adev->id = id;
+	adev->parent = parent;
+	adev->ops = ops;
+	adev->match = match;
+	dev_set_name(&adev->dev, "aggregate%d", id);
 
-	component_master_debugfs_add(master);
-	/* Add to the list of available masters. */
+	component_master_debugfs_add(adev);
+	/* Add to the list of available aggregate devices. */
 	mutex_lock(&component_mutex);
-	list_add(&master->node, &masters);
+	list_add(&adev->node, &aggregate_devices);
 
-	ret = try_to_bring_up_master(master, NULL);
+	ret = try_to_bring_up_aggregate_device(adev, NULL);
 
 	if (ret < 0)
-		free_master(master);
+		free_aggregate_device(adev);
 
 	mutex_unlock(&component_mutex);
 
@@ -503,25 +519,25 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
 void component_master_del(struct device *parent,
 	const struct component_master_ops *ops)
 {
-	struct master *master;
+	struct aggregate_device *adev;
 
 	mutex_lock(&component_mutex);
-	master = __master_find(parent, ops);
-	if (master) {
-		take_down_master(master);
-		free_master(master);
+	adev = __aggregate_find(parent, ops);
+	if (adev) {
+		take_down_aggregate_device(adev);
+		free_aggregate_device(adev);
 	}
 	mutex_unlock(&component_mutex);
 }
 EXPORT_SYMBOL_GPL(component_master_del);
 
 static void component_unbind(struct component *component,
-	struct master *master, void *data)
+	struct aggregate_device *adev, void *data)
 {
 	WARN_ON(!component->bound);
 
 	if (component->ops && component->ops->unbind)
-		component->ops->unbind(component->dev, master->parent, data);
+		component->ops->unbind(component->dev, adev->parent, data);
 	component->bound = false;
 
 	/* Release all resources claimed in the binding of this component */
@@ -539,26 +555,26 @@ static void component_unbind(struct component *component,
  */
 void component_unbind_all(struct device *parent, void *data)
 {
-	struct master *master;
+	struct aggregate_device *adev;
 	struct component *c;
 	size_t i;
 
 	WARN_ON(!mutex_is_locked(&component_mutex));
 
-	master = __master_find(parent, NULL);
-	if (!master)
+	adev = __aggregate_find(parent, NULL);
+	if (!adev)
 		return;
 
 	/* Unbind components in reverse order */
-	for (i = master->match->num; i--; )
-		if (!master->match->compare[i].duplicate) {
-			c = master->match->compare[i].component;
-			component_unbind(c, master, data);
+	for (i = adev->match->num; i--; )
+		if (!adev->match->compare[i].duplicate) {
+			c = adev->match->compare[i].component;
+			component_unbind(c, adev, data);
 		}
 }
 EXPORT_SYMBOL_GPL(component_unbind_all);
 
-static int component_bind(struct component *component, struct master *master,
+static int component_bind(struct component *component, struct aggregate_device *adev,
 	void *data)
 {
 	int ret;
@@ -568,7 +584,7 @@ static int component_bind(struct component *component, struct master *master,
 	 * This allows us to roll-back a failed component without
 	 * affecting anything else.
 	 */
-	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
+	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
 		return -ENOMEM;
 
 	/*
@@ -577,14 +593,14 @@ static int component_bind(struct component *component, struct master *master,
 	 * at the appropriate moment.
 	 */
 	if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
-		devres_release_group(master->parent, NULL);
+		devres_release_group(adev->parent, NULL);
 		return -ENOMEM;
 	}
 
-	dev_dbg(master->parent, "binding %s (ops %ps)\n",
+	dev_dbg(adev->parent, "binding %s (ops %ps)\n",
 		dev_name(component->dev), component->ops);
 
-	ret = component->ops->bind(component->dev, master->parent, data);
+	ret = component->ops->bind(component->dev, adev->parent, data);
 	if (!ret) {
 		component->bound = true;
 
@@ -595,16 +611,16 @@ static int component_bind(struct component *component, struct master *master,
 		 * can clean those resources up independently.
 		 */
 		devres_close_group(component->dev, NULL);
-		devres_remove_group(master->parent, NULL);
+		devres_remove_group(adev->parent, NULL);
 
-		dev_info(master->parent, "bound %s (ops %ps)\n",
+		dev_info(adev->parent, "bound %s (ops %ps)\n",
 			 dev_name(component->dev), component->ops);
 	} else {
 		devres_release_group(component->dev, NULL);
-		devres_release_group(master->parent, NULL);
+		devres_release_group(adev->parent, NULL);
 
 		if (ret != -EPROBE_DEFER)
-			dev_err(master->parent, "failed to bind %s (ops %ps): %d\n",
+			dev_err(adev->parent, "failed to bind %s (ops %ps): %d\n",
 				dev_name(component->dev), component->ops, ret);
 	}
 
@@ -622,31 +638,31 @@ static int component_bind(struct component *component, struct master *master,
  */
 int component_bind_all(struct device *parent, void *data)
 {
-	struct master *master;
+	struct aggregate_device *adev;
 	struct component *c;
 	size_t i;
 	int ret = 0;
 
 	WARN_ON(!mutex_is_locked(&component_mutex));
 
-	master = __master_find(parent, NULL);
-	if (!master)
+	adev = __aggregate_find(parent, NULL);
+	if (!adev)
 		return -EINVAL;
 
 	/* Bind components in match order */
-	for (i = 0; i < master->match->num; i++)
-		if (!master->match->compare[i].duplicate) {
-			c = master->match->compare[i].component;
-			ret = component_bind(c, master, data);
+	for (i = 0; i < adev->match->num; i++)
+		if (!adev->match->compare[i].duplicate) {
+			c = adev->match->compare[i].component;
+			ret = component_bind(c, adev, data);
 			if (ret)
 				break;
 		}
 
 	if (ret != 0) {
 		for (; i > 0; i--)
-			if (!master->match->compare[i - 1].duplicate) {
-				c = master->match->compare[i - 1].component;
-				component_unbind(c, master, data);
+			if (!adev->match->compare[i - 1].duplicate) {
+				c = adev->match->compare[i - 1].component;
+				component_unbind(c, adev, data);
 			}
 	}
 
@@ -675,8 +691,8 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
 
 	ret = try_to_bring_up_masters(component);
 	if (ret < 0) {
-		if (component->master)
-			remove_component(component->master, component);
+		if (component->adev)
+			remove_component(component->adev, component);
 		list_del(&component->node);
 
 		kfree(component);
@@ -757,9 +773,9 @@ void component_del(struct device *dev, const struct component_ops *ops)
 			break;
 		}
 
-	if (component && component->master) {
-		take_down_master(component->master);
-		remove_component(component->master, component);
+	if (component && component->adev) {
+		take_down_aggregate_device(component->adev);
+		remove_component(component->adev, component);
 	}
 
 	mutex_unlock(&component_mutex);
diff --git a/include/linux/component.h b/include/linux/component.h
index 16de18f473d7..71bfc3862633 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -41,7 +41,7 @@ void component_del(struct device *, const struct component_ops *);
 int component_bind_all(struct device *master, void *master_data);
 void component_unbind_all(struct device *master, void *master_data);
 
-struct master;
+struct aggregate_device;
 
 /**
  * struct component_master_ops - callback for the aggregate driver
-- 
https://chromeos.dev


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

* [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 22:42   ` kernel test robot
                     ` (2 more replies)
  2021-10-06 19:37 ` [PATCH v2 03/34] component: Move struct aggregate_device out to header file Stephen Boyd
                   ` (33 subsequent siblings)
  35 siblings, 3 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

The component driver only provides 'bind' and 'unbind' callbacks to tell
the host driver that it is time to assemble the aggregate driver now
that all the components have probed. The component driver model doesn't
attempt to resolve runtime PM or suspend/resume ordering, and explicitly
mentions this in the code. This lack of support leads to some pretty
gnarly usages of the 'prepare' and 'complete' power management hooks in
drivers that host the aggregate device, and it fully breaks down when
faced with ordering shutdown between the various components, the
aggregate driver, and the host driver that registers the whole thing.

In a concrete example, the MSM display driver at drivers/gpu/drm/msm is
using 'prepare' and 'complete' to call the drm helpers
drm_mode_config_helper_suspend() and drm_mode_config_helper_resume()
respectively, so that it can move the aggregate driver suspend/resume
callbacks to be before and after the components that make up the drm
device call any suspend/resume hooks they have. This only works as long
as the component devices don't do anything in their own 'prepare' and
'complete' callbacks. If they did, then the ordering would be incorrect
and we would be doing something in the component drivers before the
aggregate driver could do anything. Yuck!

Similarly, when trying to add shutdown support to the MSM driver we run
across a problem where we're trying to shutdown the drm device via
drm_atomic_helper_shutdown(), but some of the devices in the encoder
chain have already been shutdown. This time, the component devices
aren't the problem (although they could be if they did anything in their
shutdown callbacks), but there's a DSI to eDP bridge in the encoder
chain that has already been shutdown before the driver hosting the
aggregate device runs shutdown. The ordering of driver probe is like
this:

 1. msm_pdev_probe() (host driver)
 2. DSI bridge
 3. aggregate bind

When it comes to shutdown we have this order:

 1. DSI bridge
 2. msm_pdev_shutdown() (host driver)

and so the bridge is already off, but we want to communicate to it to
turn things off on the display during msm_pdev_shutdown(). Double yuck!
Unfortunately, this time we can't split shutdown into multiple phases
and swap msm_pdev_shutdown() with the DSI bridge.

Let's make the component driver into an actual device driver that has
probe/remove/shutdown functions. The driver will only be bound to the
aggregate device once all component drivers have called component_add()
to indicate they're ready to assemble the aggregate driver. This allows
us to attach shutdown logic (and in the future runtime PM logic) to the
aggregate driver so that it runs the hooks in the correct order.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c  | 454 +++++++++++++++++++++++++++-----------
 include/linux/component.h |  62 +++++-
 2 files changed, 381 insertions(+), 135 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index 0a41bbe14981..d99e99cabb99 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -15,6 +15,9 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
+
+#include "base.h"
 
 /**
  * DOC: overview
@@ -38,8 +41,8 @@
  *
  * Aggregate drivers first assemble a component match list of what they need
  * using component_match_add(). This is then registered as an aggregate driver
- * using component_master_add_with_match(), and unregistered using
- * component_master_del().
+ * using component_aggregate_register(), and unregistered using
+ * component_aggregate_unregister().
  */
 
 struct component;
@@ -60,17 +63,20 @@ struct component_match {
 };
 
 struct aggregate_device {
-	struct list_head node;
-	bool bound;
-
 	const struct component_master_ops *ops;
 	struct device *parent;
 	struct device dev;
 	struct component_match *match;
+	struct aggregate_driver *adrv;
 
 	int id;
 };
 
+static inline struct aggregate_device *to_aggregate_device(struct device *d)
+{
+	return container_of(d, struct aggregate_device, dev);
+}
+
 struct component {
 	struct list_head node;
 	struct aggregate_device *adev;
@@ -79,11 +85,11 @@ struct component {
 	const struct component_ops *ops;
 	int subcomponent;
 	struct device *dev;
+	struct device_link *link;
 };
 
 static DEFINE_MUTEX(component_mutex);
 static LIST_HEAD(component_list);
-static LIST_HEAD(aggregate_devices);
 
 static DEFINE_IDA(aggregate_ida);
 
@@ -101,7 +107,7 @@ static int component_devices_show(struct seq_file *s, void *data)
 	seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
 	seq_puts(s, "-------------------------------------------------------------\n");
 	seq_printf(s, "%-40s %20s\n\n",
-		   dev_name(m->parent), m->bound ? "bound" : "not bound");
+		   dev_name(m->parent), m->dev.driver ? "bound" : "not bound");
 
 	seq_printf(s, "%-40s %20s\n", "device name", "status");
 	seq_puts(s, "-------------------------------------------------------------\n");
@@ -149,16 +155,21 @@ static void component_master_debugfs_del(struct aggregate_device *m)
 
 #endif
 
-static struct aggregate_device *__aggregate_find(struct device *parent,
-	const struct component_master_ops *ops)
+struct aggregate_bus_find_data {
+	const struct component_master_ops *ops;
+	struct device *parent;
+};
+
+static int aggregate_bus_find_match(struct device *dev, const void *_data)
 {
-	struct aggregate_device *m;
+	struct aggregate_device *adev = to_aggregate_device(dev);
+	const struct aggregate_bus_find_data *data = _data;
 
-	list_for_each_entry(m, &aggregate_devices, node)
-		if (m->parent == parent && (!ops || m->ops == ops))
-			return m;
+	if (adev->parent == data->parent &&
+	    (!data->ops || adev->ops == data->ops))
+		return 1;
 
-	return NULL;
+	return 0;
 }
 
 static struct component *find_component(struct aggregate_device *adev,
@@ -185,7 +196,6 @@ static int find_components(struct aggregate_device *adev)
 {
 	struct component_match *match = adev->match;
 	size_t i;
-	int ret = 0;
 
 	/*
 	 * Scan the array of match functions and attach
@@ -194,6 +204,7 @@ static int find_components(struct aggregate_device *adev)
 	for (i = 0; i < match->num; i++) {
 		struct component_match_array *mc = &match->compare[i];
 		struct component *c;
+		bool duplicate;
 
 		dev_dbg(adev->parent, "Looking for component %zu\n", i);
 
@@ -201,20 +212,27 @@ static int find_components(struct aggregate_device *adev)
 			continue;
 
 		c = find_component(adev, mc);
-		if (!c) {
-			ret = -ENXIO;
-			break;
-		}
+		if (!c)
+			return 0;
 
+		duplicate = !!c->adev;
 		dev_dbg(adev->parent, "found component %s, duplicate %u\n",
-			dev_name(c->dev), !!c->adev);
+			dev_name(c->dev), duplicate);
 
 		/* Attach this component to the adev */
-		match->compare[i].duplicate = !!c->adev;
+		match->compare[i].duplicate = duplicate;
 		match->compare[i].component = c;
+		if (duplicate)
+			continue;
+
+		/* Matches put in component_del() */
+		get_device(&adev->dev);
+		c->link = device_link_add(&adev->dev, c->dev,
+					  DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
 		c->adev = adev;
 	}
-	return ret;
+
+	return 1;
 }
 
 /* Detach component from associated aggregate_device */
@@ -228,72 +246,6 @@ static void remove_component(struct aggregate_device *adev, struct component *c)
 			adev->match->compare[i].component = NULL;
 }
 
-/*
- * Try to bring up an aggregate device.  If component is NULL, we're interested
- * in this aggregate device, otherwise it's a component which must be present
- * to try and bring up the aggregate device.
- *
- * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
- */
-static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
-	struct component *component)
-{
-	int ret;
-
-	dev_dbg(adev->parent, "trying to bring up adev\n");
-
-	if (find_components(adev)) {
-		dev_dbg(adev->parent, "master has incomplete components\n");
-		return 0;
-	}
-
-	if (component && component->adev != adev) {
-		dev_dbg(adev->parent, "master is not for this component (%s)\n",
-			dev_name(component->dev));
-		return 0;
-	}
-
-	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
-		return -ENOMEM;
-
-	/* Found all components */
-	ret = adev->ops->bind(adev->parent);
-	if (ret < 0) {
-		devres_release_group(adev->parent, NULL);
-		if (ret != -EPROBE_DEFER)
-			dev_info(adev->parent, "adev bind failed: %d\n", ret);
-		return ret;
-	}
-
-	adev->bound = true;
-	return 1;
-}
-
-static int try_to_bring_up_masters(struct component *component)
-{
-	struct aggregate_device *adev;
-	int ret = 0;
-
-	list_for_each_entry(adev, &aggregate_devices, node) {
-		if (!adev->bound) {
-			ret = try_to_bring_up_aggregate_device(adev, component);
-			if (ret != 0)
-				break;
-		}
-	}
-
-	return ret;
-}
-
-static void take_down_aggregate_device(struct aggregate_device *adev)
-{
-	if (adev->bound) {
-		adev->ops->unbind(adev->parent);
-		devres_release_group(adev->parent, NULL);
-		adev->bound = false;
-	}
-}
-
 static void devm_component_match_release(struct device *parent, void *res)
 {
 	struct component_match *match = res;
@@ -437,7 +389,6 @@ static void free_aggregate_device(struct aggregate_device *adev)
 	int i;
 
 	component_master_debugfs_del(adev);
-	list_del(&adev->node);
 
 	if (match) {
 		for (i = 0; i < match->num; i++) {
@@ -451,20 +402,143 @@ static void free_aggregate_device(struct aggregate_device *adev)
 	kfree(adev);
 }
 
-/**
- * component_master_add_with_match - register an aggregate driver
- * @parent: parent device of the aggregate driver
- * @ops: callbacks for the aggregate driver
- * @match: component match list for the aggregate driver
- *
- * Registers a new aggregate driver consisting of the components added to @match
- * by calling one of the component_match_add() functions. Once all components in
- * @match are available, it will be assembled by calling
- * &component_master_ops.bind from @ops. Must be unregistered by calling
- * component_master_del().
- */
-int component_master_add_with_match(struct device *parent,
-	const struct component_master_ops *ops,
+static void aggregate_device_release(struct device *dev)
+{
+	struct aggregate_device *adev = to_aggregate_device(dev);
+
+	free_aggregate_device(adev);
+}
+
+static int aggregate_device_match(struct device *dev, struct device_driver *drv)
+{
+	const struct aggregate_driver *adrv = to_aggregate_driver(drv);
+	struct aggregate_device *adev = to_aggregate_device(dev);
+	int ret;
+
+	/* Is this driver associated with this device */
+	if (adrv != adev->adrv)
+		return 0;
+
+	/* Should we start to assemble? */
+	mutex_lock(&component_mutex);
+	ret = find_components(adev);
+	mutex_unlock(&component_mutex);
+
+	return ret;
+}
+
+/* TODO: Remove once all aggregate drivers use component_aggregate_register() */
+static int component_probe_bind(struct aggregate_device *adev)
+{
+	return adev->ops->bind(adev->parent);
+}
+
+static void component_remove_unbind(struct aggregate_device *adev)
+{
+	adev->ops->unbind(adev->parent);
+}
+
+static int aggregate_driver_probe(struct device *dev)
+{
+	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
+	struct aggregate_device *adev = to_aggregate_device(dev);
+	bool modern = adrv->probe != component_probe_bind;
+	int ret;
+
+	/* Only do runtime PM when drivers migrate */
+	if (modern) {
+		pm_runtime_get_noresume(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+	}
+
+	mutex_lock(&component_mutex);
+	if (devres_open_group(adev->parent, NULL, GFP_KERNEL)) {
+		ret = adrv->probe(adev);
+		if (ret)
+			devres_release_group(adev->parent, NULL);
+	} else {
+		ret = -ENOMEM;
+	}
+	mutex_unlock(&component_mutex);
+
+	if (ret && modern) {
+		pm_runtime_disable(dev);
+		pm_runtime_set_suspended(dev);
+		pm_runtime_put_noidle(dev);
+	}
+
+	return ret;
+}
+
+static int aggregate_driver_remove(struct device *dev)
+{
+	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
+	struct aggregate_device *adev = to_aggregate_device(dev);
+	bool modern = adrv->remove != component_remove_unbind;
+
+	/* Only do runtime PM when drivers migrate */
+	if (modern)
+		pm_runtime_get_sync(dev);
+	adrv->remove(to_aggregate_device(dev));
+	devres_release_group(adev->parent, NULL);
+	if (!modern)
+		return 0;
+
+	pm_runtime_put_noidle(dev);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+
+	return 0;
+}
+
+static void aggregate_driver_shutdown(struct device *dev)
+{
+	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
+
+	if (adrv && adrv->shutdown)
+		adrv->shutdown(to_aggregate_device(dev));
+}
+
+static struct bus_type aggregate_bus_type = {
+	.name		= "aggregate",
+	.match		= aggregate_device_match,
+	.probe		= aggregate_driver_probe,
+	.remove		= aggregate_driver_remove,
+	.shutdown	= aggregate_driver_shutdown,
+};
+
+/* Callers take ownership of return value, should call put_device() */
+static struct aggregate_device *__aggregate_find(struct device *parent,
+	const struct component_master_ops *ops)
+{
+	struct device *dev;
+	struct aggregate_bus_find_data data = {
+		.ops = ops,
+		.parent = parent,
+	};
+
+	dev = bus_find_device(&aggregate_bus_type, NULL, &data,
+			      aggregate_bus_find_match);
+
+	return dev ? to_aggregate_device(dev) : NULL;
+}
+
+static int aggregate_driver_register(struct aggregate_driver *adrv)
+{
+	adrv->driver.bus = &aggregate_bus_type;
+	return driver_register(&adrv->driver);
+}
+
+static void aggregate_driver_unregister(struct aggregate_driver *adrv)
+{
+	driver_unregister(&adrv->driver);
+}
+
+static struct aggregate_device *aggregate_device_add(struct device *parent,
+	const struct component_master_ops *ops, struct aggregate_driver *adrv,
 	struct component_match *match)
 {
 	struct aggregate_device *adev;
@@ -473,40 +547,114 @@ int component_master_add_with_match(struct device *parent,
 	/* Reallocate the match array for its true size */
 	ret = component_match_realloc(match, match->num);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
 
 	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
 	if (!adev)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	id = ida_alloc(&aggregate_ida, GFP_KERNEL);
 	if (id < 0) {
 		kfree(adev);
-		return id;
+		return ERR_PTR(id);
 	}
 
 	adev->id = id;
 	adev->parent = parent;
+	adev->dev.bus = &aggregate_bus_type;
+	adev->dev.release = aggregate_device_release;
 	adev->ops = ops;
 	adev->match = match;
+	adev->adrv = adrv;
 	dev_set_name(&adev->dev, "aggregate%d", id);
 
+	ret = device_register(&adev->dev);
+	if (ret) {
+		put_device(&adev->dev);
+		return ERR_PTR(ret);
+	}
+
 	component_master_debugfs_add(adev);
-	/* Add to the list of available aggregate devices. */
-	mutex_lock(&component_mutex);
-	list_add(&adev->node, &aggregate_devices);
 
-	ret = try_to_bring_up_aggregate_device(adev, NULL);
+	return adev;
+}
+
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @parent: parent device of the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ *
+ * Deprecated: Use component_aggregate_register() instead.
+ */
+int component_master_add_with_match(struct device *parent,
+	const struct component_master_ops *ops,
+	struct component_match *match)
+{
+	struct aggregate_driver *adrv;
+	struct aggregate_device *adev;
+	int ret = 0;
+
+	adrv = kzalloc(sizeof(*adrv), GFP_KERNEL);
+	if (!adrv)
+		return -ENOMEM;
 
-	if (ret < 0)
-		free_aggregate_device(adev);
+	adev = aggregate_device_add(parent, ops, adrv, match);
+	if (IS_ERR(adev)) {
+		ret = PTR_ERR(adev);
+		goto err;
+	}
 
-	mutex_unlock(&component_mutex);
+	adrv->probe = component_probe_bind;
+	adrv->remove = component_remove_unbind;
+	adrv->driver.owner = THIS_MODULE;
+	adrv->driver.name = dev_name(&adev->dev);
+
+	ret = aggregate_driver_register(adrv);
+	if (!ret)
+		return 0;
 
-	return ret < 0 ? ret : 0;
+	put_device(&adev->dev);
+err:
+	kfree(adrv);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_aggregate_register - register an aggregate driver
+ * @parent: parent device of the aggregate driver
+ * @adrv: aggregate driver to register
+ *
+ * Registers a new aggregate driver consisting of the components added to @adrv.match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, the aggregate driver will be assembled by calling
+ * &adrv.bind. Must be unregistered by calling component_aggregate_unregister().
+ */
+int component_aggregate_register(struct device *parent,
+	struct aggregate_driver *adrv, struct component_match *match)
+{
+	struct aggregate_device *adev;
+	int ret;
+
+	adev = aggregate_device_add(parent, NULL, adrv, match);
+	if (IS_ERR(adev))
+		return PTR_ERR(adev);
+
+	ret = aggregate_driver_register(adrv);
+	if (ret)
+		put_device(&adev->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(component_aggregate_register);
+
 /**
  * component_master_del - unregister an aggregate driver
  * @parent: parent device of the aggregate driver
@@ -515,22 +663,60 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
  * Unregisters an aggregate driver registered with
  * component_master_add_with_match(). If necessary the aggregate driver is first
  * disassembled by calling &component_master_ops.unbind from @ops.
+ *
+ * Deprecated: Use component_aggregate_unregister() instead.
  */
 void component_master_del(struct device *parent,
 	const struct component_master_ops *ops)
 {
 	struct aggregate_device *adev;
+	struct aggregate_driver *adrv;
+	struct device_driver *drv;
 
 	mutex_lock(&component_mutex);
 	adev = __aggregate_find(parent, ops);
+	mutex_unlock(&component_mutex);
+
 	if (adev) {
-		take_down_aggregate_device(adev);
-		free_aggregate_device(adev);
+		drv = adev->dev.driver;
+		if (drv) {
+			adrv = to_aggregate_driver(drv);
+			aggregate_driver_unregister(adrv);
+			kfree(adrv);
+		}
+
+		device_unregister(&adev->dev);
 	}
-	mutex_unlock(&component_mutex);
+	put_device(&adev->dev);
 }
 EXPORT_SYMBOL_GPL(component_master_del);
 
+/**
+ * component_aggregate_unregister - unregister an aggregate driver
+ * @parent: parent device of the aggregate driver
+ * @adrv: registered aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_aggregate_register(). If necessary the aggregate driver is first
+ * disassembled.
+ */
+void component_aggregate_unregister(struct device *parent,
+	struct aggregate_driver *adrv)
+{
+	struct aggregate_device *adev;
+
+	mutex_lock(&component_mutex);
+	adev = __aggregate_find(parent, NULL);
+	mutex_unlock(&component_mutex);
+
+	if (adev)
+		device_unregister(&adev->dev);
+	put_device(&adev->dev);
+
+	aggregate_driver_unregister(adrv);
+}
+EXPORT_SYMBOL_GPL(component_aggregate_unregister);
+
 static void component_unbind(struct component *component,
 	struct aggregate_device *adev, void *data)
 {
@@ -571,6 +757,8 @@ void component_unbind_all(struct device *parent, void *data)
 			c = adev->match->compare[i].component;
 			component_unbind(c, adev, data);
 		}
+
+	put_device(&adev->dev);
 }
 EXPORT_SYMBOL_GPL(component_unbind_all);
 
@@ -665,6 +853,7 @@ int component_bind_all(struct device *parent, void *data)
 				component_unbind(c, adev, data);
 			}
 	}
+	put_device(&adev->dev);
 
 	return ret;
 }
@@ -674,7 +863,6 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
 	int subcomponent)
 {
 	struct component *component;
-	int ret;
 
 	component = kzalloc(sizeof(*component), GFP_KERNEL);
 	if (!component)
@@ -688,18 +876,10 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
 
 	mutex_lock(&component_mutex);
 	list_add_tail(&component->node, &component_list);
-
-	ret = try_to_bring_up_masters(component);
-	if (ret < 0) {
-		if (component->adev)
-			remove_component(component->adev, component);
-		list_del(&component->node);
-
-		kfree(component);
-	}
 	mutex_unlock(&component_mutex);
 
-	return ret < 0 ? ret : 0;
+	/* Try to bind */
+	return bus_rescan_devices(&aggregate_bus_type);
 }
 
 /**
@@ -763,6 +943,7 @@ EXPORT_SYMBOL_GPL(component_add);
  */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
+	struct aggregate_device *adev = NULL;
 	struct component *c, *component = NULL;
 
 	mutex_lock(&component_mutex);
@@ -774,13 +955,26 @@ void component_del(struct device *dev, const struct component_ops *ops)
 		}
 
 	if (component && component->adev) {
-		take_down_aggregate_device(component->adev);
-		remove_component(component->adev, component);
+		adev = component->adev;
+		remove_component(adev, component);
 	}
 
 	mutex_unlock(&component_mutex);
 
+	if (adev) {
+		/* Force unbind */
+		device_driver_detach(&adev->dev);
+		device_link_del(component->link);
+		put_device(&adev->dev);
+	}
+
 	WARN_ON(!component);
 	kfree(component);
 }
 EXPORT_SYMBOL_GPL(component_del);
+
+static int __init aggregate_bus_init(void)
+{
+	return bus_register(&aggregate_bus_type);
+}
+postcore_initcall(aggregate_bus_init);
diff --git a/include/linux/component.h b/include/linux/component.h
index 71bfc3862633..95d1b23ede8a 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -3,9 +3,7 @@
 #define COMPONENT_H
 
 #include <linux/stddef.h>
-
-
-struct device;
+#include <linux/device.h>
 
 /**
  * struct component_ops - callbacks for component drivers
@@ -82,11 +80,65 @@ struct component_master_ops {
 	void (*unbind)(struct device *master);
 };
 
+struct component_match;
+
+/**
+ * struct aggregate_driver - Aggregate driver (made up of other drivers)
+ * @driver: device driver
+ * @match: component match list
+ */
+struct aggregate_driver {
+	/**
+	 * @probe:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the @match list are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a struct aggregate_driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 */
+	int (*probe)(struct aggregate_device *adev);
+	/**
+	 * @remove:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_aggregate_unregister(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
+	void (*remove)(struct aggregate_device *adev);
+	/**
+	 * @shutdown:
+	 *
+	 * Called when the system is shutting down.
+	 */
+	void (*shutdown)(struct aggregate_device *adev);
+
+	struct device_driver	driver;
+};
+
+static inline struct aggregate_driver *to_aggregate_driver(struct device_driver *d)
+{
+	if (!d)
+		return NULL;
+
+	return container_of(d, struct aggregate_driver, driver);
+}
+
+int component_aggregate_register(struct device *parent,
+	struct aggregate_driver *adrv, struct component_match *match);
+void component_aggregate_unregister(struct device *parent,
+	struct aggregate_driver *adrv);
+
 void component_master_del(struct device *,
 	const struct component_master_ops *);
 
-struct component_match;
-
 int component_master_add_with_match(struct device *,
 	const struct component_master_ops *, struct component_match *);
 void component_match_add_release(struct device *master,
-- 
https://chromeos.dev


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

* [PATCH v2 03/34] component: Move struct aggregate_device out to header file
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 04/34] drm/msm: Migrate to aggregate driver Stephen Boyd
                   ` (32 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

This allows aggregate driver writers to use the device passed to their
probe/remove/shutdown functions properly instead of treating it as an
opaque pointer.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c  | 15 ---------------
 include/linux/component.h | 19 ++++++++++++++++---
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index d99e99cabb99..f49b48695c8f 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -62,21 +62,6 @@ struct component_match {
 	struct component_match_array *compare;
 };
 
-struct aggregate_device {
-	const struct component_master_ops *ops;
-	struct device *parent;
-	struct device dev;
-	struct component_match *match;
-	struct aggregate_driver *adrv;
-
-	int id;
-};
-
-static inline struct aggregate_device *to_aggregate_device(struct device *d)
-{
-	return container_of(d, struct aggregate_device, dev);
-}
-
 struct component {
 	struct list_head node;
 	struct aggregate_device *adev;
diff --git a/include/linux/component.h b/include/linux/component.h
index 95d1b23ede8a..e99cf8e910f0 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -5,6 +5,8 @@
 #include <linux/stddef.h>
 #include <linux/device.h>
 
+struct component_match;
+
 /**
  * struct component_ops - callbacks for component drivers
  *
@@ -39,8 +41,6 @@ void component_del(struct device *, const struct component_ops *);
 int component_bind_all(struct device *master, void *master_data);
 void component_unbind_all(struct device *master, void *master_data);
 
-struct aggregate_device;
-
 /**
  * struct component_master_ops - callback for the aggregate driver
  *
@@ -80,7 +80,20 @@ struct component_master_ops {
 	void (*unbind)(struct device *master);
 };
 
-struct component_match;
+struct aggregate_device {
+	const struct component_master_ops *ops;
+	struct device *parent;
+	struct device dev;
+	struct component_match *match;
+	struct aggregate_driver *adrv;
+
+	int id;
+};
+
+static inline struct aggregate_device *to_aggregate_device(struct device *d)
+{
+	return container_of(d, struct aggregate_device, dev);
+}
 
 /**
  * struct aggregate_driver - Aggregate driver (made up of other drivers)
-- 
https://chromeos.dev


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

* [PATCH v2 04/34] drm/msm: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (2 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 03/34] component: Move struct aggregate_device out to header file Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 05/34] component: Add {bind,unbind}_component() ops that take aggregate device Stephen Boyd
                   ` (31 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

The device lists are poorly ordered when the component device code is
used. This is because component_master_add_with_match() returns 0
regardless of component devices calling component_add() first. It can
really only fail if an allocation fails, in which case everything is
going bad and we're out of memory. The driver that registers the
aggregate driver, can succeed at probe and put the attached device on
the DPM lists before any of the component devices are probed and put on
the lists.

Within the component device framework this usually isn't that bad
because the real driver work is done at bind time via
component{,master}_ops::bind(). It becomes a problem when the driver
core, or host driver, wants to operate on the component device outside
of the bind/unbind functions, e.g. via 'remove' or 'shutdown'. The
driver core doesn't understand the relationship between the host device
and the component devices and could possibly try to operate on component
devices when they're already removed from the system or shut down.

Normally, device links or probe defer would reorder the lists and put
devices that depend on other devices in the lists at the correct
location, but with component devices this doesn't happen because this
information isn't expressed anywhere. Drivers simply succeed at
registering their component or the aggregate driver with the component
framework and wait for their bind() callback to be called once the other
components are ready. In summary, the drivers that make up the aggregate
driver can probe in any order.

This ordering problem becomes fairly obvious when shutting down the
device with a DSI controller connected to a DSI bridge that is
controlled via i2c. In this case, the msm display driver wants to tear
down the display pipeline on shutdown via msm_pdev_shutdown() by calling
drm_atomic_helper_shutdown(), and it can't do that unless the whole
display chain is still probed and active in the system. When a display
bridge is on i2c, the i2c device for the bridge will be created whenever
the i2c controller probes, which could be before or after the msm
display driver probes. If the i2c controller probes after the display
driver, then the i2c controller will be shutdown before the display
controller during system wide shutdown and thus i2c transactions will
stop working before the display pipeline is shut down. This means we'll
have the display bridge trying to access an i2c bus that's shut down
because drm_atomic_helper_shutdown() is trying to disable the bridge
after the bridge is off.

The solution is to make the aggregate driver into a real struct driver
that is bound to a device when the other component devices have all
probed. Now that the component driver code is a proper bus, we can
simply register an aggregate driver with that bus via
component_aggregate_register() and then attach the shutdown hook to that
driver to be sure that the shutdown for the display pipeline is called
before any of the component device driver shutdown hooks are called.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/msm/msm_drv.c | 46 +++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 2e6fc185e54d..efbcae6e585f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1324,19 +1324,35 @@ static int add_gpu_components(struct device *dev,
 	return 0;
 }
 
-static int msm_drm_bind(struct device *dev)
+static int msm_drm_bind(struct aggregate_device *adev)
 {
-	return msm_drm_init(dev, &msm_driver);
+	return msm_drm_init(adev->parent, &msm_driver);
 }
 
-static void msm_drm_unbind(struct device *dev)
+static void msm_drm_unbind(struct aggregate_device *adev)
 {
-	msm_drm_uninit(dev);
+	msm_drm_uninit(adev->parent);
+}
+
+static void msm_drm_shutdown(struct aggregate_device *adev)
+{
+	struct drm_device *drm = platform_get_drvdata(to_platform_device(adev->parent));
+	struct msm_drm_private *priv = drm ? drm->dev_private : NULL;
+
+	if (!priv || !priv->kms)
+		return;
+
+	drm_atomic_helper_shutdown(drm);
 }
 
-static const struct component_master_ops msm_drm_ops = {
-	.bind = msm_drm_bind,
-	.unbind = msm_drm_unbind,
+static struct aggregate_driver msm_drm_aggregate_driver = {
+	.probe = msm_drm_bind,
+	.remove = msm_drm_unbind,
+	.shutdown = msm_drm_shutdown,
+	.driver = {
+		.name	= "msm_drm",
+		.owner	= THIS_MODULE,
+	},
 };
 
 /*
@@ -1365,7 +1381,7 @@ static int msm_pdev_probe(struct platform_device *pdev)
 	if (ret)
 		goto fail;
 
-	ret = component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
+	ret = component_aggregate_register(&pdev->dev, &msm_drm_aggregate_driver, match);
 	if (ret)
 		goto fail;
 
@@ -1378,23 +1394,12 @@ static int msm_pdev_probe(struct platform_device *pdev)
 
 static int msm_pdev_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &msm_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &msm_drm_aggregate_driver);
 	of_platform_depopulate(&pdev->dev);
 
 	return 0;
 }
 
-static void msm_pdev_shutdown(struct platform_device *pdev)
-{
-	struct drm_device *drm = platform_get_drvdata(pdev);
-	struct msm_drm_private *priv = drm ? drm->dev_private : NULL;
-
-	if (!priv || !priv->kms)
-		return;
-
-	drm_atomic_helper_shutdown(drm);
-}
-
 static const struct of_device_id dt_match[] = {
 	{ .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
 	{ .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 },
@@ -1410,7 +1415,6 @@ MODULE_DEVICE_TABLE(of, dt_match);
 static struct platform_driver msm_platform_driver = {
 	.probe      = msm_pdev_probe,
 	.remove     = msm_pdev_remove,
-	.shutdown   = msm_pdev_shutdown,
 	.driver     = {
 		.name   = "msm",
 		.of_match_table = dt_match,
-- 
https://chromeos.dev


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

* [PATCH v2 05/34] component: Add {bind,unbind}_component() ops that take aggregate device
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (3 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 04/34] drm/msm: Migrate to aggregate driver Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API Stephen Boyd
                   ` (30 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter

We'd like to get more device model features in the component framework
so let's pass the struct aggregate_device pointer instead of the parent
device pointer to the component binding functions. This will allow
drivers to inspect and control things related to the aggregate device in
case they need it, and they'll always be able to get back to the device
they were using before by using the 'parent' member of the aggregate
device struct.

Suggested-by: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c  | 14 +++++++++++---
 include/linux/component.h | 22 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index f49b48695c8f..a6dd33d0ddeb 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -707,8 +707,13 @@ static void component_unbind(struct component *component,
 {
 	WARN_ON(!component->bound);
 
-	if (component->ops && component->ops->unbind)
-		component->ops->unbind(component->dev, adev->parent, data);
+	if (component->ops) {
+		if (component->ops->unbind)
+			component->ops->unbind(component->dev, adev->parent, data);
+		else if (component->ops->unbind_component)
+			component->ops->unbind_component(component->dev, adev, data);
+	}
+
 	component->bound = false;
 
 	/* Release all resources claimed in the binding of this component */
@@ -773,7 +778,10 @@ static int component_bind(struct component *component, struct aggregate_device *
 	dev_dbg(adev->parent, "binding %s (ops %ps)\n",
 		dev_name(component->dev), component->ops);
 
-	ret = component->ops->bind(component->dev, adev->parent, data);
+	if (component->ops->bind_component)
+		ret = component->ops->bind_component(component->dev, adev, data);
+	else
+		ret = component->ops->bind(component->dev, adev->parent, data);
 	if (!ret) {
 		component->bound = true;
 
diff --git a/include/linux/component.h b/include/linux/component.h
index e99cf8e910f0..d8dcbf9733da 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -6,6 +6,7 @@
 #include <linux/device.h>
 
 struct component_match;
+struct aggregate_device;
 
 /**
  * struct component_ops - callbacks for component drivers
@@ -19,18 +20,39 @@ struct component_ops {
 	 *
 	 * Called through component_bind_all() when the aggregate driver is
 	 * ready to bind the overall driver.
+	 *
+	 * Deprecated: Use bind_component() instead.
 	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @bind_component:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
+	int (*bind_component)(struct device *comp, struct aggregate_device *adev,
+			      void *aggregate_data);
 	/**
 	 * @unbind:
 	 *
 	 * Called through component_unbind_all() when the aggregate driver is
 	 * ready to bind the overall driver, or when component_bind_all() fails
 	 * part-ways through and needs to unbind some already bound components.
+	 *
+	 * Deprecated: Use unbind_component() instead.
 	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
+	/**
+	 * @unbind_component:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to unbind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
+	int (*unbind_component)(struct device *comp, struct aggregate_device *adev,
+				void *aggregate_data);
 };
 
 int component_add(struct device *, const struct component_ops *);
-- 
https://chromeos.dev


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

* [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (4 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 05/34] component: Add {bind,unbind}_component() ops that take aggregate device Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 22:28   ` kernel test robot
  2021-10-06 22:36   ` kernel test robot
  2021-10-06 19:37 ` [PATCH v2 07/34] drm/komeda: Migrate to aggregate driver Stephen Boyd
                   ` (29 subsequent siblings)
  35 siblings, 2 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Laurent Pinchart, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Similar to drm_of_component_probe() but using the new API that registers
a driver instead of an ops struct. This allows us to migrate the users
of drm_of_component_probe() to the new way of doing things.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/drm_of.c | 85 +++++++++++++++++++++++++++++++---------
 include/drm/drm_of.h     | 11 ++++++
 2 files changed, 77 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 997b8827fed2..58db65ad2770 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -99,30 +99,18 @@ void drm_of_component_match_add(struct device *master,
 }
 EXPORT_SYMBOL_GPL(drm_of_component_match_add);
 
-/**
- * drm_of_component_probe - Generic probe function for a component based master
- * @dev: master device containing the OF node
- * @compare_of: compare function used for matching components
- * @m_ops: component master ops to be used
- *
- * Parse the platform device OF node and bind all the components associated
- * with the master. Interface ports are added before the encoders in order to
- * satisfy their .bind requirements
- * See Documentation/devicetree/bindings/graph.txt for the bindings.
- *
- * Returns zero if successful, or one of the standard error codes if it fails.
- */
-int drm_of_component_probe(struct device *dev,
+static int _drm_of_component_probe(struct device *dev,
 			   int (*compare_of)(struct device *, void *),
-			   const struct component_master_ops *m_ops)
+			   struct component_match **matchptr)
 {
 	struct device_node *ep, *port, *remote;
-	struct component_match *match = NULL;
 	int i;
 
 	if (!dev->of_node)
 		return -EINVAL;
 
+	*matchptr = NULL;
+
 	/*
 	 * Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
 	 * called from encoder's .bind callbacks works as expected
@@ -133,7 +121,7 @@ int drm_of_component_probe(struct device *dev,
 			break;
 
 		if (of_device_is_available(port->parent))
-			drm_of_component_match_add(dev, &match, compare_of,
+			drm_of_component_match_add(dev, matchptr, compare_of,
 						   port);
 
 		of_node_put(port);
@@ -144,7 +132,7 @@ int drm_of_component_probe(struct device *dev,
 		return -ENODEV;
 	}
 
-	if (!match) {
+	if (!*matchptr) {
 		dev_err(dev, "no available port\n");
 		return -ENODEV;
 	}
@@ -174,17 +162,76 @@ int drm_of_component_probe(struct device *dev,
 				continue;
 			}
 
-			drm_of_component_match_add(dev, &match, compare_of,
+			drm_of_component_match_add(dev, matchptr, compare_of,
 						   remote);
 			of_node_put(remote);
 		}
 		of_node_put(port);
 	}
 
+	return 0;
+}
+
+/**
+ * drm_of_component_probe - Generic probe function for a component based master
+ * @dev: master device containing the OF node
+ * @compare_of: compare function used for matching components
+ * @m_ops: component master ops to be used
+ *
+ * Parse the platform device OF node and bind all the components associated
+ * with the master. Interface ports are added before the encoders in order to
+ * satisfy their .bind requirements
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ *
+ * Deprecated: Use drm_of_aggregate_probe() instead.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+static int drm_of_component_probe(struct device *dev,
+			   int (*compare_of)(struct device *, void *),
+			   const struct component_master_ops *m_ops)
+{
+
+	struct component_match *match;
+	int ret;
+
+	ret = _drm_of_component_probe(dev, compare_of, &match);
+	if (ret)
+		return ret;
+
 	return component_master_add_with_match(dev, m_ops, match);
 }
 EXPORT_SYMBOL(drm_of_component_probe);
 
+
+/**
+ * drm_of_aggregate_probe - Generic probe function for a component based aggregate host
+ * @dev: device containing the OF node
+ * @compare_of: compare function used for matching components
+ * @adrv: aggregate driver to be used
+ *
+ * Parse the platform device OF node and bind all the components associated
+ * with the aggregate device. Interface ports are added before the encoders in
+ * order to satisfy their .bind_component requirements
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+static int drm_of_aggregate_probe(struct device *dev,
+			   int (*compare_of)(struct device *, void *),
+			   struct aggregate_driver *adrv)
+{
+	struct component_match *match;
+	int ret;
+
+	ret = _drm_of_component_probe(dev, compare_of, &match);
+	if (ret)
+		return ret;
+
+	return component_aggregate_register(dev, adrv, match);
+}
+EXPORT_SYMBOL(drm_of_aggregate_probe);
+
 /*
  * drm_of_encoder_active_endpoint - return the active encoder endpoint
  * @node: device tree node containing encoder input ports
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index b9b093add92e..c3ec9b14df48 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -40,6 +40,9 @@ void drm_of_component_match_add(struct device *master,
 int drm_of_component_probe(struct device *dev,
 			   int (*compare_of)(struct device *, void *),
 			   const struct component_master_ops *m_ops);
+int drm_of_aggregate_probe(struct device *dev,
+			   int (*compare_of)(struct device *, void *),
+			   struct aggregate_driver *adrv);
 int drm_of_encoder_active_endpoint(struct device_node *node,
 				   struct drm_encoder *encoder,
 				   struct of_endpoint *endpoint);
@@ -78,6 +81,14 @@ drm_of_component_probe(struct device *dev,
 	return -EINVAL;
 }
 
+static inline int
+drm_of_aggregate_probe(struct device *dev,
+		       int (*compare_of)(struct device *, void *),
+		       struct aggregate_driver *adrv)
+{
+	return -EINVAL;
+}
+
 static inline int drm_of_encoder_active_endpoint(struct device_node *node,
 						 struct drm_encoder *encoder,
 						 struct of_endpoint *endpoint)
-- 
https://chromeos.dev


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

* [PATCH v2 07/34] drm/komeda: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (5 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 08/34] drm/arm/hdlcd: " Stephen Boyd
                   ` (28 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	James Qian Wang, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 .../gpu/drm/arm/display/komeda/komeda_drv.c   | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index e7933930a657..0463386a6ed2 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -25,8 +25,9 @@ struct komeda_dev *dev_to_mdev(struct device *dev)
 	return mdrv ? mdrv->mdev : NULL;
 }
 
-static void komeda_unbind(struct device *dev)
+static void komeda_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct komeda_drv *mdrv = dev_get_drvdata(dev);
 
 	if (!mdrv)
@@ -45,8 +46,9 @@ static void komeda_unbind(struct device *dev)
 	devm_kfree(dev, mdrv);
 }
 
-static int komeda_bind(struct device *dev)
+static int komeda_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct komeda_drv *mdrv;
 	int err;
 
@@ -87,9 +89,13 @@ static int komeda_bind(struct device *dev)
 	return err;
 }
 
-static const struct component_master_ops komeda_master_ops = {
-	.bind	= komeda_bind,
-	.unbind	= komeda_unbind,
+static struct aggregate_driver komeda_aggregate_driver = {
+	.probe	= komeda_bind,
+	.remove	= komeda_unbind,
+	.driver = {
+		.name  = "komeda_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int compare_of(struct device *dev, void *data)
@@ -129,12 +135,12 @@ static int komeda_platform_probe(struct platform_device *pdev)
 		komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 1);
 	}
 
-	return component_master_add_with_match(dev, &komeda_master_ops, match);
+	return component_aggregate_register(dev, &komeda_aggregate_driver, match);
 }
 
 static int komeda_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &komeda_master_ops);
+	component_aggregate_unregister(&pdev->dev, &komeda_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 08/34] drm/arm/hdlcd: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (6 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 07/34] drm/komeda: Migrate to aggregate driver Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 09/34] drm/malidp: " Stephen Boyd
                   ` (27 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Liviu Dudau,
	Daniel Vetter, Rafael J. Wysocki, Rob Clark, Russell King,
	Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 479c2422a2e0..8f3e5924042a 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -270,8 +270,9 @@ static const struct drm_driver hdlcd_driver = {
 	.minor = 0,
 };
 
-static int hdlcd_drm_bind(struct device *dev)
+static int hdlcd_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm;
 	struct hdlcd_drm_private *hdlcd;
 	int ret;
@@ -344,8 +345,9 @@ static int hdlcd_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void hdlcd_drm_unbind(struct device *dev)
+static void hdlcd_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct hdlcd_drm_private *hdlcd = drm->dev_private;
 
@@ -367,9 +369,13 @@ static void hdlcd_drm_unbind(struct device *dev)
 	drm_dev_put(drm);
 }
 
-static const struct component_master_ops hdlcd_master_ops = {
-	.bind		= hdlcd_drm_bind,
-	.unbind		= hdlcd_drm_unbind,
+static struct aggregate_driver hdlcd_aggregate_driver = {
+	.probe		= hdlcd_drm_bind,
+	.remove		= hdlcd_drm_unbind,
+	.driver		= {
+		.name 	= "hdlcd_drm",
+		.owner	= THIS_MODULE,
+	},
 };
 
 static int compare_dev(struct device *dev, void *data)
@@ -390,13 +396,12 @@ static int hdlcd_probe(struct platform_device *pdev)
 	drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
 	of_node_put(port);
 
-	return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
-					       match);
+	return component_aggregate_register(&pdev->dev, &hdlcd_aggregate_driver, match);
 }
 
 static int hdlcd_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &hdlcd_master_ops);
+	component_aggregate_unregister(&pdev->dev, &hdlcd_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 09/34] drm/malidp: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (7 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 08/34] drm/arm/hdlcd: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 10/34] drm/armada: " Stephen Boyd
                   ` (26 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Laurent Pinchart, Liviu Dudau, Daniel Vetter, Rafael J. Wysocki,
	Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

TODO: This can be updated to move the drm helper logic into the
aggregate driver shutdown op.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/arm/malidp_drv.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 78d15b04b105..e6ee4d1e3bb8 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -702,8 +702,9 @@ static int malidp_runtime_pm_resume(struct device *dev)
 	return 0;
 }
 
-static int malidp_bind(struct device *dev)
+static int malidp_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct resource *res;
 	struct drm_device *drm;
 	struct malidp_drm *malidp;
@@ -894,8 +895,9 @@ static int malidp_bind(struct device *dev)
 	return ret;
 }
 
-static void malidp_unbind(struct device *dev)
+static void malidp_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct malidp_drm *malidp = drm->dev_private;
 	struct malidp_hw_device *hwdev = malidp->dev;
@@ -921,9 +923,13 @@ static void malidp_unbind(struct device *dev)
 	of_reserved_mem_device_release(dev);
 }
 
-static const struct component_master_ops malidp_master_ops = {
-	.bind = malidp_bind,
-	.unbind = malidp_unbind,
+static struct aggregate_driver malidp_aggregate_driver = {
+	.probe = malidp_bind,
+	.remove = malidp_unbind,
+	.driver = {
+		.name = "malidp_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int malidp_compare_dev(struct device *dev, void *data)
@@ -949,13 +955,12 @@ static int malidp_platform_probe(struct platform_device *pdev)
 	drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
 				   port);
 	of_node_put(port);
-	return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
-					       match);
+	return component_aggregate_register(&pdev->dev, &malidp_aggregate_driver, match);
 }
 
 static int malidp_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &malidp_master_ops);
+	component_aggregate_unregister(&pdev->dev, &malidp_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 10/34] drm/armada: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (8 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 09/34] drm/malidp: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 11/34] drm/etnaviv: " Stephen Boyd
                   ` (25 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Russell King,
	Daniel Vetter, Rafael J. Wysocki, Rob Clark, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Russell King <linux@armlinux.org.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/armada/armada_drv.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 8e3e98f13db4..b3559363ea43 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -60,8 +60,9 @@ static const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
 	.atomic_commit		= drm_atomic_helper_commit,
 };
 
-static int armada_drm_bind(struct device *dev)
+static int armada_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct armada_private *priv;
 	struct resource *mem = NULL;
 	int ret, n;
@@ -159,8 +160,9 @@ static int armada_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void armada_drm_unbind(struct device *dev)
+static void armada_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct armada_private *priv = drm_to_armada_dev(drm);
 
@@ -202,9 +204,13 @@ static void armada_add_endpoints(struct device *dev,
 	}
 }
 
-static const struct component_master_ops armada_master_ops = {
-	.bind = armada_drm_bind,
-	.unbind = armada_drm_unbind,
+static struct aggregate_driver armada_aggregate_driver = {
+	.probe = armada_drm_bind,
+	.remove = armada_drm_unbind,
+	.driver = {
+		.name = "armada_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int armada_drm_probe(struct platform_device *pdev)
@@ -213,7 +219,7 @@ static int armada_drm_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	int ret;
 
-	ret = drm_of_component_probe(dev, compare_dev_name, &armada_master_ops);
+	ret = drm_of_aggregate_probe(dev, compare_dev_name, &armada_aggregate_driver);
 	if (ret != -EINVAL)
 		return ret;
 
@@ -240,13 +246,12 @@ static int armada_drm_probe(struct platform_device *pdev)
 		}
 	}
 
-	return component_master_add_with_match(&pdev->dev, &armada_master_ops,
-					       match);
+	return component_aggregate_register(&pdev->dev, &armada_aggregate_driver, match);
 }
 
 static int armada_drm_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &armada_master_ops);
+	component_aggregate_unregister(&pdev->dev, &armada_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 11/34] drm/etnaviv: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (9 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 10/34] drm/armada: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 12/34] drm/kirin: " Stephen Boyd
                   ` (24 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Lucas Stach,
	Russell King, Christian Gmeiner, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Russell King <linux+etnaviv@armlinux.org.uk>
Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 7dcc6392792d..95d1e518ff13 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -494,8 +494,9 @@ static const struct drm_driver etnaviv_drm_driver = {
 /*
  * Platform driver:
  */
-static int etnaviv_bind(struct device *dev)
+static int etnaviv_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct etnaviv_drm_private *priv;
 	struct drm_device *drm;
 	int ret;
@@ -552,8 +553,9 @@ static int etnaviv_bind(struct device *dev)
 	return ret;
 }
 
-static void etnaviv_unbind(struct device *dev)
+static void etnaviv_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct etnaviv_drm_private *priv = drm->dev_private;
 
@@ -569,9 +571,13 @@ static void etnaviv_unbind(struct device *dev)
 	drm_dev_put(drm);
 }
 
-static const struct component_master_ops etnaviv_master_ops = {
-	.bind = etnaviv_bind,
-	.unbind = etnaviv_unbind,
+static struct aggregate_driver etnaviv_aggregate_driver = {
+	.probe = etnaviv_bind,
+	.remove = etnaviv_unbind,
+	.driver = {
+		.name = "etnaviv_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int compare_of(struct device *dev, void *data)
@@ -609,12 +615,12 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
 			component_match_add(dev, &match, compare_str, names[i]);
 	}
 
-	return component_master_add_with_match(dev, &etnaviv_master_ops, match);
+	return component_aggregate_register(dev, &etnaviv_aggregate_driver, match);
 }
 
 static int etnaviv_pdev_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &etnaviv_master_ops);
+	component_aggregate_unregister(&pdev->dev, &etnaviv_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 12/34] drm/kirin: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (10 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 11/34] drm/etnaviv: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 13/34] drm/exynos: " Stephen Boyd
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Xinliang Liu,
	Tian Tao, John Stultz, Xinwei Kong, Chen Feng, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Tian Tao <tiantao6@hisilicon.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
Cc: Chen Feng <puck.chen@hisilicon.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c   | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 98ae9a48f3fe..00d47c784cbb 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -217,8 +217,9 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev)
 	return 0;
 }
 
-static int kirin_drm_bind(struct device *dev)
+static int kirin_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct kirin_drm_data *driver_data;
 	struct drm_device *drm_dev;
 	int ret;
@@ -253,8 +254,9 @@ static int kirin_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void kirin_drm_unbind(struct device *dev)
+static void kirin_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm_dev);
@@ -262,9 +264,13 @@ static void kirin_drm_unbind(struct device *dev)
 	drm_dev_put(drm_dev);
 }
 
-static const struct component_master_ops kirin_drm_ops = {
-	.bind = kirin_drm_bind,
-	.unbind = kirin_drm_unbind,
+static struct aggregate_driver kirin_drm_aggregate_driver = {
+	.probe = kirin_drm_bind,
+	.remove = kirin_drm_unbind,
+	.driver = {
+		.name = "kirin_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int kirin_drm_platform_probe(struct platform_device *pdev)
@@ -281,12 +287,12 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
 	drm_of_component_match_add(dev, &match, compare_of, remote);
 	of_node_put(remote);
 
-	return component_master_add_with_match(dev, &kirin_drm_ops, match);
+	return component_aggregate_register(dev, &kirin_drm_aggregate_driver, match);
 }
 
 static int kirin_drm_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &kirin_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &kirin_drm_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 13/34] drm/exynos: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (11 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 12/34] drm/kirin: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:37 ` [PATCH v2 14/34] drm/imx: " Stephen Boyd
                   ` (22 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Inki Dae <inki.dae@samsung.com>
Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Cc: Seung-Woo Kim <sw0312.kim@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/exynos/exynos_drm_drv.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index d8f1cf4d6b69..dcb52ec2bd35 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -253,8 +253,9 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
 	return match ?: ERR_PTR(-ENODEV);
 }
 
-static int exynos_drm_bind(struct device *dev)
+static int exynos_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct exynos_drm_private *private;
 	struct drm_encoder *encoder;
 	struct drm_device *drm;
@@ -330,8 +331,9 @@ static int exynos_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void exynos_drm_unbind(struct device *dev)
+static void exynos_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -350,9 +352,13 @@ static void exynos_drm_unbind(struct device *dev)
 	drm_dev_put(drm);
 }
 
-static const struct component_master_ops exynos_drm_ops = {
-	.bind		= exynos_drm_bind,
-	.unbind		= exynos_drm_unbind,
+static struct aggregate_driver exynos_drm_aggregate_driver = {
+	.probe		= exynos_drm_bind,
+	.remove		= exynos_drm_unbind,
+	.driver		= {
+		.name	= "exynos_drm",
+		.owner	= THIS_MODULE,
+	},
 };
 
 static int exynos_drm_platform_probe(struct platform_device *pdev)
@@ -365,13 +371,12 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
 	if (IS_ERR(match))
 		return PTR_ERR(match);
 
-	return component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
-					       match);
+	return component_aggregate_register(&pdev->dev, &exynos_drm_aggregate_driver, match);
 }
 
 static int exynos_drm_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &exynos_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &exynos_drm_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 14/34] drm/imx: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (12 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 13/34] drm/exynos: " Stephen Boyd
@ 2021-10-06 19:37 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 15/34] drm/ingenic: " Stephen Boyd
                   ` (21 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Philipp Zabel,
	Daniel Vetter, Rafael J. Wysocki, Rob Clark, Russell King,
	Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/imx/imx-drm-core.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 9558e9e1b431..dbf5cca5201d 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -198,8 +198,9 @@ static int compare_of(struct device *dev, void *data)
 	return dev->of_node == np;
 }
 
-static int imx_drm_bind(struct device *dev)
+static int imx_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm;
 	int ret;
 
@@ -266,8 +267,9 @@ static int imx_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void imx_drm_unbind(struct device *dev)
+static void imx_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -281,14 +283,18 @@ static void imx_drm_unbind(struct device *dev)
 	dev_set_drvdata(dev, NULL);
 }
 
-static const struct component_master_ops imx_drm_ops = {
-	.bind = imx_drm_bind,
-	.unbind = imx_drm_unbind,
+static struct aggregate_driver imx_drm_aggregate_driver = {
+	.probe = imx_drm_bind,
+	.remove = imx_drm_unbind,
+	.driver = {
+		.name = "imx_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
-	int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops);
+	int ret = drm_of_aggregate_probe(&pdev->dev, compare_of, &imx_drm_aggregate_driver);
 
 	if (!ret)
 		ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
@@ -298,7 +304,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &imx_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &imx_drm_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 15/34] drm/ingenic: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (13 preceding siblings ...)
  2021-10-06 19:37 ` [PATCH v2 14/34] drm/imx: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-07 21:29   ` Paul Cercueil
  2021-10-06 19:38 ` [PATCH v2 16/34] drm/mcde: " Stephen Boyd
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Paul Cercueil,
	Daniel Vetter, Rafael J. Wysocki, Rob Clark, Russell King,
	Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

TODO: Move the helpers to PM in aggregate driver hooks.

Cc: Paul Cercueil <paul@crapouillou.net>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 24 +++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index a5df1c8d34cd..058b7bfe5610 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1150,8 +1150,10 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
 	return ret;
 }
 
-static int ingenic_drm_bind_with_components(struct device *dev)
+static int ingenic_drm_bind_with_components(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
+
 	return ingenic_drm_bind(dev, true);
 }
 
@@ -1174,9 +1176,19 @@ static void ingenic_drm_unbind(struct device *dev)
 	drm_atomic_helper_shutdown(&priv->drm);
 }
 
-static const struct component_master_ops ingenic_master_ops = {
-	.bind = ingenic_drm_bind_with_components,
-	.unbind = ingenic_drm_unbind,
+static void ingenic_aggregate_remove(struct aggregate_device *adev)
+{
+	struct device *dev = adev->parent;
+	ingenic_drm_unbind(dev);
+}
+
+static struct aggregate_driver ingenic_aggregate_driver = {
+	.probe = ingenic_drm_bind_with_components,
+	.remove = ingenic_aggregate_remove,
+	.driver = {
+		.name = "ingenic_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int ingenic_drm_probe(struct platform_device *pdev)
@@ -1196,7 +1208,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
 	drm_of_component_match_add(dev, &match, compare_of, np);
 	of_node_put(np);
 
-	return component_master_add_with_match(dev, &ingenic_master_ops, match);
+	return component_aggregate_register(dev, &ingenic_aggregate_driver, match);
 }
 
 static int ingenic_drm_remove(struct platform_device *pdev)
@@ -1206,7 +1218,7 @@ static int ingenic_drm_remove(struct platform_device *pdev)
 	if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
 		ingenic_drm_unbind(dev);
 	else
-		component_master_del(dev, &ingenic_master_ops);
+		component_aggregate_unregister(dev, &ingenic_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 16/34] drm/mcde: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (14 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 15/34] drm/ingenic: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 17/34] drm/mediatek: " Stephen Boyd
                   ` (19 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/mcde/mcde_drv.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
index e60566a5739c..84fcfe77540e 100644
--- a/drivers/gpu/drm/mcde/mcde_drv.c
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -215,8 +215,9 @@ static const struct drm_driver mcde_drm_driver = {
 	DRM_GEM_CMA_DRIVER_OPS,
 };
 
-static int mcde_drm_bind(struct device *dev)
+static int mcde_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 	int ret;
 
@@ -247,8 +248,9 @@ static int mcde_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void mcde_drm_unbind(struct device *dev)
+static void mcde_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -256,9 +258,13 @@ static void mcde_drm_unbind(struct device *dev)
 	component_unbind_all(drm->dev, drm);
 }
 
-static const struct component_master_ops mcde_drm_comp_ops = {
-	.bind = mcde_drm_bind,
-	.unbind = mcde_drm_unbind,
+static struct aggregate_driver mcde_drm_comp_driver = {
+	.probe = mcde_drm_bind,
+	.remove = mcde_drm_unbind,
+	.driver = {
+		.name = "mcde_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static struct platform_driver *const mcde_component_drivers[] = {
@@ -421,7 +427,7 @@ static int mcde_probe(struct platform_device *pdev)
 	 * Perform an invasive reset of the MCDE and all blocks by
 	 * cutting the power to the subsystem, then bring it back up
 	 * later when we enable the display as a result of
-	 * component_master_add_with_match().
+	 * component_aggregate_register().
 	 */
 	ret = regulator_disable(mcde->epod);
 	if (ret) {
@@ -431,8 +437,7 @@ static int mcde_probe(struct platform_device *pdev)
 	/* Wait 50 ms so we are sure we cut the power */
 	usleep_range(50000, 70000);
 
-	ret = component_master_add_with_match(&pdev->dev, &mcde_drm_comp_ops,
-					      match);
+	ret = component_aggregate_register(&pdev->dev, &mcde_drm_comp_driver, match);
 	if (ret) {
 		dev_err(dev, "failed to add component master\n");
 		/*
@@ -461,7 +466,7 @@ static int mcde_remove(struct platform_device *pdev)
 	struct drm_device *drm = platform_get_drvdata(pdev);
 	struct mcde *mcde = to_mcde(drm);
 
-	component_master_del(&pdev->dev, &mcde_drm_comp_ops);
+	component_aggregate_unregister(&pdev->dev, &mcde_drm_comp_driver);
 	clk_disable_unprepare(mcde->mcde_clk);
 	regulator_disable(mcde->vana);
 	regulator_disable(mcde->epod);
-- 
https://chromeos.dev


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

* [PATCH v2 17/34] drm/mediatek: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (15 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 16/34] drm/mcde: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 18/34] drm/meson: " Stephen Boyd
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Chun-Kuang Hu,
	Philipp Zabel, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index aec39724ebeb..a3f27b8c9769 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -348,8 +348,9 @@ static int compare_of(struct device *dev, void *data)
 	return dev->of_node == data;
 }
 
-static int mtk_drm_bind(struct device *dev)
+static int mtk_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mtk_drm_private *private = dev_get_drvdata(dev);
 	struct drm_device *drm;
 	int ret;
@@ -380,8 +381,9 @@ static int mtk_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void mtk_drm_unbind(struct device *dev)
+static void mtk_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mtk_drm_private *private = dev_get_drvdata(dev);
 
 	drm_dev_unregister(private->drm);
@@ -391,9 +393,13 @@ static void mtk_drm_unbind(struct device *dev)
 	private->drm = NULL;
 }
 
-static const struct component_master_ops mtk_drm_ops = {
-	.bind		= mtk_drm_bind,
-	.unbind		= mtk_drm_unbind,
+static struct aggregate_driver mtk_drm_aggregate_driver = {
+	.probe		= mtk_drm_bind,
+	.remove		= mtk_drm_unbind,
+	.driver		= {
+		.name	= "mtk_drm",
+		.owner	= THIS_MODULE,
+	},
 };
 
 static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
@@ -593,7 +599,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, private);
 
-	ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
+	ret = component_aggregate_register(dev, &mtk_drm_aggregate_driver, match);
 	if (ret)
 		goto err_pm;
 
@@ -616,7 +622,7 @@ static int mtk_drm_remove(struct platform_device *pdev)
 	struct mtk_drm_private *private = platform_get_drvdata(pdev);
 	int i;
 
-	component_master_del(&pdev->dev, &mtk_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &mtk_drm_aggregate_driver);
 	pm_runtime_disable(&pdev->dev);
 	of_node_put(private->mutex_node);
 	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
-- 
https://chromeos.dev


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

* [PATCH v2 18/34] drm/meson: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (16 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 17/34] drm/mediatek: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 19/34] drm/omap: " Stephen Boyd
                   ` (17 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Neil Armstrong, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/meson/meson_drv.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index bc0d60df04ae..109fb9d057e3 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -357,13 +357,16 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
 	return ret;
 }
 
-static int meson_drv_bind(struct device *dev)
+static int meson_drv_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
+
 	return meson_drv_bind_master(dev, true);
 }
 
-static void meson_drv_unbind(struct device *dev)
+static void meson_drv_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct meson_drm *priv = dev_get_drvdata(dev);
 	struct drm_device *drm = priv->drm;
 
@@ -387,9 +390,13 @@ static void meson_drv_unbind(struct device *dev)
 	}
 }
 
-static const struct component_master_ops meson_drv_master_ops = {
-	.bind	= meson_drv_bind,
-	.unbind	= meson_drv_unbind,
+static struct aggregate_driver meson_aggregate_drv = {
+	.probe	= meson_drv_bind,
+	.remove	= meson_drv_unbind,
+	.driver = {
+		.name = "meson_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int __maybe_unused meson_drv_pm_suspend(struct device *dev)
@@ -503,9 +510,7 @@ static int meson_drv_probe(struct platform_device *pdev)
 	if (count) {
 		dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
 
-		return component_master_add_with_match(&pdev->dev,
-						       &meson_drv_master_ops,
-						       match);
+		return component_aggregate_register(&pdev->dev, &meson_aggregate_drv, match);
 	}
 
 	/* If no output endpoints were available, simply bail out */
-- 
https://chromeos.dev


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

* [PATCH v2 19/34] drm/omap: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (17 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 18/34] drm/meson: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 20/34] drm/rockchip: " Stephen Boyd
                   ` (16 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Tomi Valkeinen, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Tomi Valkeinen <tomba@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/omapdrm/dss/dss.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index d6a5862b4dbf..6a6ae2786d7a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1304,8 +1304,9 @@ static const struct soc_device_attribute dss_soc_devices[] = {
 	{ /* sentinel */ }
 };
 
-static int dss_bind(struct device *dev)
+static int dss_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct dss_device *dss = dev_get_drvdata(dev);
 	struct platform_device *drm_pdev;
 	struct dss_pdata pdata;
@@ -1339,9 +1340,13 @@ static void dss_unbind(struct device *dev)
 	component_unbind_all(dev, NULL);
 }
 
-static const struct component_master_ops dss_component_ops = {
-	.bind = dss_bind,
-	.unbind = dss_unbind,
+static struct aggregate_driver dss_aggregate_driver = {
+	.probe = dss_bind,
+	.remove = dss_unbind,
+	.driver = {
+		.name = "dss_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int dss_component_compare(struct device *dev, void *data)
@@ -1504,7 +1509,7 @@ static int dss_probe(struct platform_device *pdev)
 	cmatch.match = &match;
 	device_for_each_child(&pdev->dev, &cmatch, dss_add_child_component);
 
-	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
+	r = component_aggregate_register(&pdev->dev, &dss_aggregate_driver, match);
 	if (r)
 		goto err_of_depopulate;
 
@@ -1543,7 +1548,7 @@ static int dss_remove(struct platform_device *pdev)
 
 	of_platform_depopulate(&pdev->dev);
 
-	component_master_del(&pdev->dev, &dss_component_ops);
+	component_aggregate_unregister(&pdev->dev, &dss_aggregate_driver);
 
 	dss_debugfs_remove_file(dss->debugfs.clk);
 	dss_debugfs_remove_file(dss->debugfs.dss);
-- 
https://chromeos.dev


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

* [PATCH v2 20/34] drm/rockchip: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (18 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 19/34] drm/omap: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 21/34] drm/sti: " Stephen Boyd
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Sandy Huang,
	Heiko Stübner, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Sandy Huang <hjc@rock-chips.com>
Cc: "Heiko Stübner" <heiko@sntech.de>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index bfba9793d238..cc63222c3ad0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -109,8 +109,9 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
 	iommu_domain_free(private->domain);
 }
 
-static int rockchip_drm_bind(struct device *dev)
+static int rockchip_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm_dev;
 	struct rockchip_drm_private *private;
 	int ret;
@@ -186,8 +187,9 @@ static int rockchip_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void rockchip_drm_unbind(struct device *dev)
+static void rockchip_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm_dev);
@@ -342,9 +344,13 @@ static struct component_match *rockchip_drm_match_add(struct device *dev)
 	return match ?: ERR_PTR(-ENODEV);
 }
 
-static const struct component_master_ops rockchip_drm_ops = {
-	.bind = rockchip_drm_bind,
-	.unbind = rockchip_drm_unbind,
+static struct aggregate_driver rockchip_aggregate_driver = {
+	.probe = rockchip_drm_bind,
+	.remove = rockchip_drm_unbind,
+	.driver = {
+		.name = "rockchip_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int rockchip_drm_platform_of_probe(struct device *dev)
@@ -415,7 +421,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
 	if (IS_ERR(match))
 		return PTR_ERR(match);
 
-	ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);
+	ret = component_aggregate_register(dev, &rockchip_aggregate_driver, match);
 	if (ret < 0) {
 		rockchip_drm_match_remove(dev);
 		return ret;
@@ -426,7 +432,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
 
 static int rockchip_drm_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &rockchip_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &rockchip_aggregate_driver);
 
 	rockchip_drm_match_remove(&pdev->dev);
 
-- 
https://chromeos.dev


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

* [PATCH v2 21/34] drm/sti: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (19 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 20/34] drm/rockchip: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 22/34] drm/sun4i: " Stephen Boyd
                   ` (14 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Benjamin Gaignard, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/sti/sti_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index c7efb43b83ee..b277cc679154 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -182,8 +182,9 @@ static void sti_cleanup(struct drm_device *ddev)
 	ddev->dev_private = NULL;
 }
 
-static int sti_bind(struct device *dev)
+static int sti_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *ddev;
 	int ret;
 
@@ -216,8 +217,9 @@ static int sti_bind(struct device *dev)
 	return ret;
 }
 
-static void sti_unbind(struct device *dev)
+static void sti_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *ddev = dev_get_drvdata(dev);
 
 	drm_dev_unregister(ddev);
@@ -225,9 +227,13 @@ static void sti_unbind(struct device *dev)
 	drm_dev_put(ddev);
 }
 
-static const struct component_master_ops sti_ops = {
-	.bind = sti_bind,
-	.unbind = sti_unbind,
+static struct aggregate_driver sti_aggregate_driver = {
+	.probe = sti_bind,
+	.remove = sti_unbind,
+	.driver = {
+		.name = "sti_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int sti_platform_probe(struct platform_device *pdev)
@@ -249,12 +255,12 @@ static int sti_platform_probe(struct platform_device *pdev)
 		child_np = of_get_next_available_child(node, child_np);
 	}
 
-	return component_master_add_with_match(dev, &sti_ops, match);
+	return component_aggregate_register(dev, &sti_aggregate_driver, match);
 }
 
 static int sti_platform_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &sti_ops);
+	component_aggregate_unregister(&pdev->dev, &sti_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 22/34] drm/sun4i: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (20 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 21/34] drm/sti: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 23/34] drm/tilcdc: " Stephen Boyd
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Maxime Ripard,
	Chen-Yu Tsai, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Maxime Ripard <mripard@kernel.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 54dd562e294c..700f5e32eaf7 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -56,8 +56,9 @@ static const struct drm_driver sun4i_drv_driver = {
 	DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create),
 };
 
-static int sun4i_drv_bind(struct device *dev)
+static int sun4i_drv_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm;
 	struct sun4i_drv *drv;
 	int ret;
@@ -125,8 +126,9 @@ static int sun4i_drv_bind(struct device *dev)
 	return ret;
 }
 
-static void sun4i_drv_unbind(struct device *dev)
+static void sun4i_drv_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -140,9 +142,13 @@ static void sun4i_drv_unbind(struct device *dev)
 	drm_dev_put(drm);
 }
 
-static const struct component_master_ops sun4i_drv_master_ops = {
-	.bind	= sun4i_drv_bind,
-	.unbind	= sun4i_drv_unbind,
+static struct aggregate_driver sun4i_aggregate_driver = {
+	.probe	= sun4i_drv_bind,
+	.remove	= sun4i_drv_unbind,
+	.driver = {
+		.name = "sun4i_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static bool sun4i_drv_node_is_connector(struct device_node *node)
@@ -398,16 +404,14 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 	}
 
 	if (count)
-		return component_master_add_with_match(&pdev->dev,
-						       &sun4i_drv_master_ops,
-						       match);
-	else
-		return 0;
+		return component_aggregate_register(&pdev->dev, &sun4i_aggregate_driver, match);
+
+	return 0;
 }
 
 static int sun4i_drv_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &sun4i_drv_master_ops);
+	component_aggregate_unregister(&pdev->dev, &sun4i_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 23/34] drm/tilcdc: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (21 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 22/34] drm/sun4i: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 24/34] drm/vc4: " Stephen Boyd
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Jyri Sarha,
	Tomi Valkeinen, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Jyri Sarha <jyri.sarha@iki.fi>
Cc: Tomi Valkeinen <tomba@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 6b03f89a98d4..d5c6567eec8d 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -531,13 +531,16 @@ static const struct dev_pm_ops tilcdc_pm_ops = {
 /*
  * Platform driver:
  */
-static int tilcdc_bind(struct device *dev)
+static int tilcdc_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
+
 	return tilcdc_init(&tilcdc_driver, dev);
 }
 
-static void tilcdc_unbind(struct device *dev)
+static void tilcdc_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *ddev = dev_get_drvdata(dev);
 
 	/* Check if a subcomponent has already triggered the unloading. */
@@ -547,9 +550,13 @@ static void tilcdc_unbind(struct device *dev)
 	tilcdc_fini(dev_get_drvdata(dev));
 }
 
-static const struct component_master_ops tilcdc_comp_ops = {
-	.bind = tilcdc_bind,
-	.unbind = tilcdc_unbind,
+static struct aggregate_driver tilcdc_aggregate_driver = {
+	.probe = tilcdc_bind,
+	.remove = tilcdc_unbind,
+	.driver = {
+		.name = "tilcdc_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int tilcdc_pdev_probe(struct platform_device *pdev)
@@ -566,12 +573,9 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
 	ret = tilcdc_get_external_components(&pdev->dev, &match);
 	if (ret < 0)
 		return ret;
-	else if (ret == 0)
+	if (ret == 0)
 		return tilcdc_init(&tilcdc_driver, &pdev->dev);
-	else
-		return component_master_add_with_match(&pdev->dev,
-						       &tilcdc_comp_ops,
-						       match);
+	return component_aggregate_register(&pdev->dev, &tilcdc_aggregate_driver, match);
 }
 
 static int tilcdc_pdev_remove(struct platform_device *pdev)
@@ -581,10 +585,10 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
 	ret = tilcdc_get_external_components(&pdev->dev, NULL);
 	if (ret < 0)
 		return ret;
-	else if (ret == 0)
+	if (ret == 0)
 		tilcdc_fini(platform_get_drvdata(pdev));
 	else
-		component_master_del(&pdev->dev, &tilcdc_comp_ops);
+		component_aggregate_unregister(&pdev->dev, &tilcdc_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 24/34] drm/vc4: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (22 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 23/34] drm/tilcdc: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 25/34] drm/zte: " Stephen Boyd
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Emma Anholt,
	Maxime Ripard, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Emma Anholt <emma@anholt.net>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/vc4/vc4_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index f6c16c5aee68..bccbde7a2f59 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -214,8 +214,9 @@ static void vc4_match_add_drivers(struct device *dev,
 	}
 }
 
-static int vc4_drm_bind(struct device *dev)
+static int vc4_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm;
 	struct vc4_dev *vc4;
@@ -286,8 +287,9 @@ static int vc4_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void vc4_drm_unbind(struct device *dev)
+static void vc4_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -295,9 +297,13 @@ static void vc4_drm_unbind(struct device *dev)
 	drm_atomic_helper_shutdown(drm);
 }
 
-static const struct component_master_ops vc4_drm_ops = {
-	.bind = vc4_drm_bind,
-	.unbind = vc4_drm_unbind,
+static struct aggregate_driver vc4_aggregate_driver = {
+	.probe = vc4_drm_bind,
+	.remove = vc4_drm_unbind,
+	.driver = {
+		.name = "vc4_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 /*
@@ -328,12 +334,12 @@ static int vc4_platform_drm_probe(struct platform_device *pdev)
 	vc4_match_add_drivers(dev, &match,
 			      component_drivers, ARRAY_SIZE(component_drivers));
 
-	return component_master_add_with_match(dev, &vc4_drm_ops, match);
+	return component_aggregate_register(dev, &vc4_aggregate_driver, match);
 }
 
 static int vc4_platform_drm_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &vc4_drm_ops);
+	component_aggregate_unregister(&pdev->dev, &vc4_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 25/34] drm/zte: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (23 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 24/34] drm/vc4: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 26/34] iommu/mtk: " Stephen Boyd
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/zte/zx_drm_drv.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
index 064056503ebb..b46f677ea51d 100644
--- a/drivers/gpu/drm/zte/zx_drm_drv.c
+++ b/drivers/gpu/drm/zte/zx_drm_drv.c
@@ -45,8 +45,9 @@ static const struct drm_driver zx_drm_driver = {
 	.minor = 0,
 };
 
-static int zx_drm_bind(struct device *dev)
+static int zx_drm_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm;
 	int ret;
 
@@ -97,8 +98,9 @@ static int zx_drm_bind(struct device *dev)
 	return ret;
 }
 
-static void zx_drm_unbind(struct device *dev)
+static void zx_drm_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_device *drm = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm);
@@ -110,9 +112,13 @@ static void zx_drm_unbind(struct device *dev)
 	drm_dev_put(drm);
 }
 
-static const struct component_master_ops zx_drm_master_ops = {
-	.bind = zx_drm_bind,
-	.unbind = zx_drm_unbind,
+static struct aggregate_driver zx_aggregate_driver = {
+	.probe = zx_drm_bind,
+	.remove = zx_drm_unbind,
+	.driver = {
+		.name = "zx_drm",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int compare_of(struct device *dev, void *data)
@@ -135,12 +141,12 @@ static int zx_drm_probe(struct platform_device *pdev)
 	for_each_available_child_of_node(parent, child)
 		component_match_add(dev, &match, compare_of, child);
 
-	return component_master_add_with_match(dev, &zx_drm_master_ops, match);
+	return component_aggregate_register(dev, &zx_aggregate_driver, match);
 }
 
 static int zx_drm_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &zx_drm_master_ops);
+	component_aggregate_unregister(&pdev->dev, &zx_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 26/34] iommu/mtk: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (24 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 25/34] drm/zte: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 27/34] mei: " Stephen Boyd
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Yong Wu,
	Joerg Roedel, Will Deacon, Daniel Vetter, Rafael J. Wysocki,
	Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Yong Wu <yong.wu@mediatek.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/iommu/mtk_iommu.c    | 14 +++++++++-----
 drivers/iommu/mtk_iommu.h    |  6 ++++--
 drivers/iommu/mtk_iommu_v1.c | 14 +++++++++-----
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d837adfd1da5..8b303c388a9b 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -750,9 +750,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 	return 0;
 }
 
-static const struct component_master_ops mtk_iommu_com_ops = {
-	.bind		= mtk_iommu_bind,
-	.unbind		= mtk_iommu_unbind,
+static struct aggregate_driver mtk_iommu_aggregate_driver = {
+	.probe		= mtk_iommu_bind,
+	.remove		= mtk_iommu_unbind,
+	.driver		= {
+		.name	= "mtk_iommu_agg",
+		.owner	= THIS_MODULE,
+	},
 };
 
 static int mtk_iommu_probe(struct platform_device *pdev)
@@ -893,7 +897,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 			goto out_list_del;
 	}
 
-	ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+	ret = component_aggregate_register(dev, &mtk_iommu_aggregate_driver, match);
 	if (ret)
 		goto out_bus_set_null;
 	return ret;
@@ -926,7 +930,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 	device_link_remove(data->smicomm_dev, &pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	devm_free_irq(&pdev->dev, data->irq, data);
-	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
+	component_aggregate_unregister(&pdev->dev, &mtk_iommu_aggregate_driver);
 	return 0;
 }
 
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index f81fa8862ed0..064fd4f4eade 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -94,15 +94,17 @@ static inline void release_of(struct device *dev, void *data)
 	of_node_put(data);
 }
 
-static inline int mtk_iommu_bind(struct device *dev)
+static inline int mtk_iommu_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mtk_iommu_data *data = dev_get_drvdata(dev);
 
 	return component_bind_all(dev, &data->larb_imu);
 }
 
-static inline void mtk_iommu_unbind(struct device *dev)
+static inline void mtk_iommu_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mtk_iommu_data *data = dev_get_drvdata(dev);
 
 	component_unbind_all(dev, &data->larb_imu);
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index be22fcf988ce..5fb29058a165 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -534,9 +534,13 @@ static const struct of_device_id mtk_iommu_of_ids[] = {
 	{}
 };
 
-static const struct component_master_ops mtk_iommu_com_ops = {
-	.bind		= mtk_iommu_bind,
-	.unbind		= mtk_iommu_unbind,
+static struct aggregate_driver mtk_iommu_aggregate_driver = {
+	.probe		= mtk_iommu_bind,
+	.remove		= mtk_iommu_unbind,
+	.driver		= {
+		.name	= "mtk_iommu_agg",
+		.owner	= THIS_MODULE,
+	},
 };
 
 static int mtk_iommu_probe(struct platform_device *pdev)
@@ -624,7 +628,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 			goto out_dev_unreg;
 	}
 
-	ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+	ret = component_aggregate_register(dev, &mtk_iommu_aggregate_driver, match);
 	if (ret)
 		goto out_bus_set_null;
 	return ret;
@@ -650,7 +654,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->bclk);
 	devm_free_irq(&pdev->dev, data->irq, data);
-	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
+	component_aggregate_unregister(&pdev->dev, &mtk_iommu_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 27/34] mei: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (25 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 26/34] iommu/mtk: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 28/34] power: supply: ab8500: " Stephen Boyd
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Tomas Winkler,
	Arnd Bergmann, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Tomas Winkler <tomas.winkler@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index ec2a4fce8581..79dcc02277d2 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -732,8 +732,9 @@ static const struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.close_hdcp_session = mei_hdcp_close_session,
 };
 
-static int mei_component_master_bind(struct device *dev)
+static int mei_component_master_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mei_cl_device *cldev = to_mei_cl_device(dev);
 	struct i915_hdcp_comp_master *comp_master =
 						mei_cldev_get_drvdata(cldev);
@@ -749,8 +750,9 @@ static int mei_component_master_bind(struct device *dev)
 	return 0;
 }
 
-static void mei_component_master_unbind(struct device *dev)
+static void mei_component_master_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct mei_cl_device *cldev = to_mei_cl_device(dev);
 	struct i915_hdcp_comp_master *comp_master =
 						mei_cldev_get_drvdata(cldev);
@@ -759,9 +761,13 @@ static void mei_component_master_unbind(struct device *dev)
 	component_unbind_all(dev, comp_master);
 }
 
-static const struct component_master_ops mei_component_master_ops = {
-	.bind = mei_component_master_bind,
-	.unbind = mei_component_master_unbind,
+static struct aggregate_driver mei_aggregate_driver = {
+	.probe = mei_component_master_bind,
+	.remove = mei_component_master_unbind,
+	.driver = {
+		.name = "mei_agg",
+		.owner = THIS_MODULE,
+	},
 };
 
 /**
@@ -826,9 +832,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
 	}
 
 	mei_cldev_set_drvdata(cldev, comp_master);
-	ret = component_master_add_with_match(&cldev->dev,
-					      &mei_component_master_ops,
-					      master_match);
+	ret = component_aggregate_register(&cldev->dev, &mei_aggregate_driver, master_match);
 	if (ret < 0) {
 		dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
 		goto err_exit;
@@ -850,7 +854,7 @@ static void mei_hdcp_remove(struct mei_cl_device *cldev)
 						mei_cldev_get_drvdata(cldev);
 	int ret;
 
-	component_master_del(&cldev->dev, &mei_component_master_ops);
+	component_aggregate_unregister(&cldev->dev, &mei_aggregate_driver);
 	kfree(comp_master);
 	mei_cldev_set_drvdata(cldev, NULL);
 
-- 
https://chromeos.dev


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

* [PATCH v2 28/34] power: supply: ab8500: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (26 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 27/34] mei: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-13 16:24   ` Sebastian Reichel
  2021-10-06 19:38 ` [PATCH v2 29/34] fbdev: omap2: " Stephen Boyd
                   ` (7 subsequent siblings)
  35 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Sebastian Reichel, linux-pm, Daniel Vetter, Rafael J. Wysocki,
	Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Sebastian Reichel <sre@kernel.org>
Cc: <linux-pm@vger.kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/power/supply/ab8500_charger.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 15eadaf46f14..52d4105e28f2 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -3312,8 +3312,9 @@ static const struct power_supply_desc ab8500_usb_chg_desc = {
 	.get_property	= ab8500_charger_usb_get_property,
 };
 
-static int ab8500_charger_bind(struct device *dev)
+static int ab8500_charger_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct ab8500_charger *di = dev_get_drvdata(dev);
 	int ch_stat;
 	int ret;
@@ -3354,8 +3355,9 @@ static int ab8500_charger_bind(struct device *dev)
 	return 0;
 }
 
-static void ab8500_charger_unbind(struct device *dev)
+static void ab8500_charger_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct ab8500_charger *di = dev_get_drvdata(dev);
 	int ret;
 
@@ -3380,9 +3382,13 @@ static void ab8500_charger_unbind(struct device *dev)
 	component_unbind_all(dev, di);
 }
 
-static const struct component_master_ops ab8500_charger_comp_ops = {
-	.bind = ab8500_charger_bind,
-	.unbind = ab8500_charger_unbind,
+static struct aggregate_driver ab8500_charger_aggregate_driver = {
+	.probe = ab8500_charger_bind,
+	.remove = ab8500_charger_unbind,
+	.driver = {
+		.name = "ab8500_charger_agg",
+		.owner = THIS_MODULE,
+	},
 };
 
 static struct platform_driver *const ab8500_charger_component_drivers[] = {
@@ -3663,9 +3669,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	}
 
 
-	ret = component_master_add_with_match(&pdev->dev,
-					      &ab8500_charger_comp_ops,
-					      match);
+	ret = component_aggregate_register(&pdev->dev, &ab8500_charger_aggregate_driver, match);
 	if (ret) {
 		dev_err(dev, "failed to add component master\n");
 		goto free_notifier;
@@ -3688,7 +3692,7 @@ static int ab8500_charger_remove(struct platform_device *pdev)
 {
 	struct ab8500_charger *di = platform_get_drvdata(pdev);
 
-	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
+	component_aggregate_unregister(&pdev->dev, &ab8500_charger_aggregate_driver);
 
 	usb_unregister_notifier(di->usb_phy, &di->nb);
 	usb_put_phy(di->usb_phy);
-- 
https://chromeos.dev


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

* [PATCH v2 29/34] fbdev: omap2: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (27 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 28/34] power: supply: ab8500: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 30/34] sound: hdac: " Stephen Boyd
                   ` (6 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, linux-omap,
	linux-fbdev, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: <linux-omap@vger.kernel.org>
Cc: <linux-fbdev@vger.kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/video/fbdev/omap2/omapfb/dss/dss.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c
index a6b1c1598040..f12663c39ceb 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/dss.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c
@@ -1067,8 +1067,9 @@ static int dss_video_pll_probe(struct platform_device *pdev)
 }
 
 /* DSS HW IP initialisation */
-static int dss_bind(struct device *dev)
+static int dss_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *dss_mem;
 	u32 rev;
@@ -1167,8 +1168,9 @@ static int dss_bind(struct device *dev)
 	return r;
 }
 
-static void dss_unbind(struct device *dev)
+static void dss_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct platform_device *pdev = to_platform_device(dev);
 
 	dss_initialized = false;
@@ -1188,9 +1190,13 @@ static void dss_unbind(struct device *dev)
 	dss_put_clocks();
 }
 
-static const struct component_master_ops dss_component_ops = {
-	.bind = dss_bind,
-	.unbind = dss_unbind,
+static struct aggregate_driver dss_aggregate_driver = {
+	.probe = dss_bind,
+	.remove = dss_unbind,
+	.driver = {
+		.name = "dss_fbdev",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int dss_component_compare(struct device *dev, void *data)
@@ -1225,7 +1231,7 @@ static int dss_probe(struct platform_device *pdev)
 	/* add all the child devices as components */
 	device_for_each_child(&pdev->dev, &match, dss_add_child_component);
 
-	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
+	r = component_aggregate_register(&pdev->dev, &dss_aggregate_driver, match);
 	if (r)
 		return r;
 
@@ -1234,7 +1240,7 @@ static int dss_probe(struct platform_device *pdev)
 
 static int dss_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &dss_component_ops);
+	component_aggregate_unregister(&pdev->dev, &dss_aggregate_driver);
 	return 0;
 }
 
-- 
https://chromeos.dev


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

* [PATCH v2 30/34] sound: hdac: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (28 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 29/34] fbdev: omap2: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 31/34] ASoC: codecs: wcd938x: " Stephen Boyd
                   ` (5 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Jaroslav Kysela, Takashi Iwai, Kai Vehmanen, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 sound/hda/hdac_component.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
index bb37e7e0bd79..9e4dab97f485 100644
--- a/sound/hda/hdac_component.c
+++ b/sound/hda/hdac_component.c
@@ -181,8 +181,9 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
 }
 EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
 
-static int hdac_component_master_bind(struct device *dev)
+static int hdac_component_master_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_audio_component *acomp = hdac_get_acomp(dev);
 	int ret;
 
@@ -222,8 +223,9 @@ static int hdac_component_master_bind(struct device *dev)
 	return ret;
 }
 
-static void hdac_component_master_unbind(struct device *dev)
+static void hdac_component_master_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct drm_audio_component *acomp = hdac_get_acomp(dev);
 
 	if (acomp->audio_ops && acomp->audio_ops->master_unbind)
@@ -233,9 +235,13 @@ static void hdac_component_master_unbind(struct device *dev)
 	WARN_ON(acomp->ops || acomp->dev);
 }
 
-static const struct component_master_ops hdac_component_master_ops = {
-	.bind = hdac_component_master_bind,
-	.unbind = hdac_component_master_unbind,
+static struct aggregate_driver hdac_aggregate_driver = {
+	.probe = hdac_component_master_bind,
+	.remove = hdac_component_master_unbind,
+	.driver = {
+		.name = "hdac_agg",
+		.owner = THIS_MODULE,
+	},
 };
 
 /**
@@ -303,8 +309,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
 	devres_add(dev, acomp);
 
 	component_match_add_typed(dev, &match, match_master, bus);
-	ret = component_master_add_with_match(dev, &hdac_component_master_ops,
-					      match);
+	ret = component_aggregate_register(dev, &hdac_aggregate_driver, match);
 	if (ret < 0)
 		goto out_err;
 
@@ -344,7 +349,7 @@ int snd_hdac_acomp_exit(struct hdac_bus *bus)
 	bus->display_power_active = 0;
 	bus->display_power_status = 0;
 
-	component_master_del(dev, &hdac_component_master_ops);
+	component_aggregate_unregister(dev, &hdac_aggregate_driver);
 
 	bus->audio_component = NULL;
 	devres_destroy(dev, hdac_acomp_release, NULL, NULL);
-- 
https://chromeos.dev


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

* [PATCH v2 31/34] ASoC: codecs: wcd938x: Migrate to aggregate driver
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (29 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 30/34] sound: hdac: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-07 12:35   ` Mark Brown
  2021-10-06 19:38 ` [PATCH v2 32/34] component: Get rid of drm_of_component_probe() Stephen Boyd
                   ` (4 subsequent siblings)
  35 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Mark Brown,
	Jaroslav Kysela, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Use an aggregate driver instead of component ops so that we can get
proper driver probe ordering of the aggregate device with respect to all
the component devices that make up the aggregate device.

Cc: Mark Brown <broonie@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 sound/soc/codecs/wcd938x.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index f0daf8defcf1..6033de7f57ef 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -4316,8 +4316,9 @@ static struct snd_soc_dai_driver wcd938x_dais[] = {
 	},
 };
 
-static int wcd938x_bind(struct device *dev)
+static int wcd938x_bind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
 	int ret;
 
@@ -4400,8 +4401,9 @@ static int wcd938x_bind(struct device *dev)
 
 }
 
-static void wcd938x_unbind(struct device *dev)
+static void wcd938x_unbind(struct aggregate_device *adev)
 {
+	struct device *dev = adev->parent;
 	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
 
 	device_link_remove(dev, wcd938x->txdev);
@@ -4411,9 +4413,13 @@ static void wcd938x_unbind(struct device *dev)
 	component_unbind_all(dev, wcd938x);
 }
 
-static const struct component_master_ops wcd938x_comp_ops = {
-	.bind   = wcd938x_bind,
-	.unbind = wcd938x_unbind,
+static struct aggregate_driver wcd938x_aggregate_driver = {
+	.probe	= wcd938x_bind,
+	.remove	= wcd938x_unbind,
+	.driver	= {
+		.name = "wcd938x_snd",
+		.owner = THIS_MODULE,
+	},
 };
 
 static int wcd938x_compare_of(struct device *dev, void *data)
@@ -4482,7 +4488,7 @@ static int wcd938x_probe(struct platform_device *pdev)
 
 	wcd938x_reset(wcd938x);
 
-	ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match);
+	ret = component_aggregate_register(dev, &wcd938x_aggregate_driver, match);
 	if (ret)
 		return ret;
 
@@ -4498,7 +4504,7 @@ static int wcd938x_probe(struct platform_device *pdev)
 
 static int wcd938x_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &wcd938x_comp_ops);
+	component_aggregate_unregister(&pdev->dev, &wcd938x_aggregate_driver);
 
 	return 0;
 }
-- 
https://chromeos.dev


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

* [PATCH v2 32/34] component: Get rid of drm_of_component_probe()
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (30 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 31/34] ASoC: codecs: wcd938x: " Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 19:38 ` [PATCH v2 33/34] component: Remove component_master_ops and friends Stephen Boyd
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Laurent Pinchart, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

There aren't any users anymore so drop it.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/gpu/drm/drm_of.c | 87 +++++++++-------------------------------
 include/drm/drm_of.h     | 12 ------
 2 files changed, 20 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 58db65ad2770..78fe2b809872 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -99,18 +99,30 @@ void drm_of_component_match_add(struct device *master,
 }
 EXPORT_SYMBOL_GPL(drm_of_component_match_add);
 
-static int _drm_of_component_probe(struct device *dev,
-			   int (*compare_of)(struct device *, void *),
-			   struct component_match **matchptr)
+/**
+ * drm_of_aggregate_probe - Generic probe function for a component based aggregate host
+ * @dev: device containing the OF node
+ * @compare_of: compare function used for matching components
+ * @adrv: aggregate driver to be used
+ *
+ * Parse the platform device OF node and bind all the components associated
+ * with the aggregate device. Interface ports are added before the encoders in
+ * order to satisfy their .bind_component requirements
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+static int drm_of_aggregate_probe(struct device *dev,
+				  int (*compare_of)(struct device *, void *),
+				  struct aggregate_driver *adrv)
 {
 	struct device_node *ep, *port, *remote;
+	struct component_match *match = NULL;
 	int i;
 
 	if (!dev->of_node)
 		return -EINVAL;
 
-	*matchptr = NULL;
-
 	/*
 	 * Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
 	 * called from encoder's .bind callbacks works as expected
@@ -121,7 +133,7 @@ static int _drm_of_component_probe(struct device *dev,
 			break;
 
 		if (of_device_is_available(port->parent))
-			drm_of_component_match_add(dev, matchptr, compare_of,
+			drm_of_component_match_add(dev, &match, compare_of,
 						   port);
 
 		of_node_put(port);
@@ -132,7 +144,7 @@ static int _drm_of_component_probe(struct device *dev,
 		return -ENODEV;
 	}
 
-	if (!*matchptr) {
+	if (!match) {
 		dev_err(dev, "no available port\n");
 		return -ENODEV;
 	}
@@ -162,72 +174,13 @@ static int _drm_of_component_probe(struct device *dev,
 				continue;
 			}
 
-			drm_of_component_match_add(dev, matchptr, compare_of,
+			drm_of_component_match_add(dev, &match, compare_of,
 						   remote);
 			of_node_put(remote);
 		}
 		of_node_put(port);
 	}
 
-	return 0;
-}
-
-/**
- * drm_of_component_probe - Generic probe function for a component based master
- * @dev: master device containing the OF node
- * @compare_of: compare function used for matching components
- * @m_ops: component master ops to be used
- *
- * Parse the platform device OF node and bind all the components associated
- * with the master. Interface ports are added before the encoders in order to
- * satisfy their .bind requirements
- * See Documentation/devicetree/bindings/graph.txt for the bindings.
- *
- * Deprecated: Use drm_of_aggregate_probe() instead.
- *
- * Returns zero if successful, or one of the standard error codes if it fails.
- */
-static int drm_of_component_probe(struct device *dev,
-			   int (*compare_of)(struct device *, void *),
-			   const struct component_master_ops *m_ops)
-{
-
-	struct component_match *match;
-	int ret;
-
-	ret = _drm_of_component_probe(dev, compare_of, &match);
-	if (ret)
-		return ret;
-
-	return component_master_add_with_match(dev, m_ops, match);
-}
-EXPORT_SYMBOL(drm_of_component_probe);
-
-
-/**
- * drm_of_aggregate_probe - Generic probe function for a component based aggregate host
- * @dev: device containing the OF node
- * @compare_of: compare function used for matching components
- * @adrv: aggregate driver to be used
- *
- * Parse the platform device OF node and bind all the components associated
- * with the aggregate device. Interface ports are added before the encoders in
- * order to satisfy their .bind_component requirements
- * See Documentation/devicetree/bindings/graph.txt for the bindings.
- *
- * Returns zero if successful, or one of the standard error codes if it fails.
- */
-static int drm_of_aggregate_probe(struct device *dev,
-			   int (*compare_of)(struct device *, void *),
-			   struct aggregate_driver *adrv)
-{
-	struct component_match *match;
-	int ret;
-
-	ret = _drm_of_component_probe(dev, compare_of, &match);
-	if (ret)
-		return ret;
-
 	return component_aggregate_register(dev, adrv, match);
 }
 EXPORT_SYMBOL(drm_of_aggregate_probe);
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index c3ec9b14df48..447568992294 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -7,7 +7,6 @@
 #include <drm/drm_bridge.h>
 #endif
 
-struct component_master_ops;
 struct component_match;
 struct device;
 struct drm_device;
@@ -37,9 +36,6 @@ void drm_of_component_match_add(struct device *master,
 				struct component_match **matchptr,
 				int (*compare)(struct device *, void *),
 				struct device_node *node);
-int drm_of_component_probe(struct device *dev,
-			   int (*compare_of)(struct device *, void *),
-			   const struct component_master_ops *m_ops);
 int drm_of_aggregate_probe(struct device *dev,
 			   int (*compare_of)(struct device *, void *),
 			   struct aggregate_driver *adrv);
@@ -73,14 +69,6 @@ drm_of_component_match_add(struct device *master,
 {
 }
 
-static inline int
-drm_of_component_probe(struct device *dev,
-		       int (*compare_of)(struct device *, void *),
-		       const struct component_master_ops *m_ops)
-{
-	return -EINVAL;
-}
-
 static inline int
 drm_of_aggregate_probe(struct device *dev,
 		       int (*compare_of)(struct device *, void *),
-- 
https://chromeos.dev


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

* [PATCH v2 33/34] component: Remove component_master_ops and friends
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (31 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 32/34] component: Get rid of drm_of_component_probe() Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-06 23:19   ` kernel test robot
  2021-10-06 19:38 ` [PATCH v2 34/34] component: Remove all references to 'master' Stephen Boyd
                   ` (2 subsequent siblings)
  35 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

The struct is unused now so drop it along with the functions that use
it.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c  | 109 +++-----------------------------------
 drivers/gpu/drm/drm_drv.c |   2 +-
 include/linux/component.h |  45 ----------------
 3 files changed, 8 insertions(+), 148 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index a6dd33d0ddeb..939862b25b10 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -140,18 +140,12 @@ static void component_master_debugfs_del(struct aggregate_device *m)
 
 #endif
 
-struct aggregate_bus_find_data {
-	const struct component_master_ops *ops;
-	struct device *parent;
-};
-
 static int aggregate_bus_find_match(struct device *dev, const void *_data)
 {
 	struct aggregate_device *adev = to_aggregate_device(dev);
-	const struct aggregate_bus_find_data *data = _data;
+	const struct device *parent = _data;
 
-	if (adev->parent == data->parent &&
-	    (!data->ops || adev->ops == data->ops))
+	if (adev->parent == parent)
 		return 1;
 
 	return 0;
@@ -496,16 +490,11 @@ static struct bus_type aggregate_bus_type = {
 };
 
 /* Callers take ownership of return value, should call put_device() */
-static struct aggregate_device *__aggregate_find(struct device *parent,
-	const struct component_master_ops *ops)
+static struct aggregate_device *__aggregate_find(struct device *parent)
 {
 	struct device *dev;
-	struct aggregate_bus_find_data data = {
-		.ops = ops,
-		.parent = parent,
-	};
 
-	dev = bus_find_device(&aggregate_bus_type, NULL, &data,
+	dev = bus_find_device(&aggregate_bus_type, NULL, parent,
 			      aggregate_bus_find_match);
 
 	return dev ? to_aggregate_device(dev) : NULL;
@@ -523,7 +512,7 @@ static void aggregate_driver_unregister(struct aggregate_driver *adrv)
 }
 
 static struct aggregate_device *aggregate_device_add(struct device *parent,
-	const struct component_master_ops *ops, struct aggregate_driver *adrv,
+	struct aggregate_driver *adrv,
 	struct component_match *match)
 {
 	struct aggregate_device *adev;
@@ -564,54 +553,6 @@ static struct aggregate_device *aggregate_device_add(struct device *parent,
 	return adev;
 }
 
-/**
- * component_master_add_with_match - register an aggregate driver
- * @parent: parent device of the aggregate driver
- * @ops: callbacks for the aggregate driver
- * @match: component match list for the aggregate driver
- *
- * Registers a new aggregate driver consisting of the components added to @match
- * by calling one of the component_match_add() functions. Once all components in
- * @match are available, it will be assembled by calling
- * &component_master_ops.bind from @ops. Must be unregistered by calling
- * component_master_del().
- *
- * Deprecated: Use component_aggregate_register() instead.
- */
-int component_master_add_with_match(struct device *parent,
-	const struct component_master_ops *ops,
-	struct component_match *match)
-{
-	struct aggregate_driver *adrv;
-	struct aggregate_device *adev;
-	int ret = 0;
-
-	adrv = kzalloc(sizeof(*adrv), GFP_KERNEL);
-	if (!adrv)
-		return -ENOMEM;
-
-	adev = aggregate_device_add(parent, ops, adrv, match);
-	if (IS_ERR(adev)) {
-		ret = PTR_ERR(adev);
-		goto err;
-	}
-
-	adrv->probe = component_probe_bind;
-	adrv->remove = component_remove_unbind;
-	adrv->driver.owner = THIS_MODULE;
-	adrv->driver.name = dev_name(&adev->dev);
-
-	ret = aggregate_driver_register(adrv);
-	if (!ret)
-		return 0;
-
-	put_device(&adev->dev);
-err:
-	kfree(adrv);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(component_master_add_with_match);
-
 /**
  * component_aggregate_register - register an aggregate driver
  * @parent: parent device of the aggregate driver
@@ -640,42 +581,6 @@ int component_aggregate_register(struct device *parent,
 }
 EXPORT_SYMBOL_GPL(component_aggregate_register);
 
-/**
- * component_master_del - unregister an aggregate driver
- * @parent: parent device of the aggregate driver
- * @ops: callbacks for the aggregate driver
- *
- * Unregisters an aggregate driver registered with
- * component_master_add_with_match(). If necessary the aggregate driver is first
- * disassembled by calling &component_master_ops.unbind from @ops.
- *
- * Deprecated: Use component_aggregate_unregister() instead.
- */
-void component_master_del(struct device *parent,
-	const struct component_master_ops *ops)
-{
-	struct aggregate_device *adev;
-	struct aggregate_driver *adrv;
-	struct device_driver *drv;
-
-	mutex_lock(&component_mutex);
-	adev = __aggregate_find(parent, ops);
-	mutex_unlock(&component_mutex);
-
-	if (adev) {
-		drv = adev->dev.driver;
-		if (drv) {
-			adrv = to_aggregate_driver(drv);
-			aggregate_driver_unregister(adrv);
-			kfree(adrv);
-		}
-
-		device_unregister(&adev->dev);
-	}
-	put_device(&adev->dev);
-}
-EXPORT_SYMBOL_GPL(component_master_del);
-
 /**
  * component_aggregate_unregister - unregister an aggregate driver
  * @parent: parent device of the aggregate driver
@@ -727,7 +632,7 @@ static void component_unbind(struct component *component,
  *
  * Unbinds all components of the aggregate device by passing @data to their
  * &component_ops.unbind functions. Should be called from
- * &component_master_ops.unbind.
+ * &aggregate_driver.remove.
  */
 void component_unbind_all(struct device *parent, void *data)
 {
@@ -815,7 +720,7 @@ static int component_bind(struct component *component, struct aggregate_device *
  *
  * Binds all components of the aggregate @dev by passing @data to their
  * &component_ops.bind functions. Should be called from
- * &component_master_ops.bind.
+ * &aggregate_driver.probe.
  */
 int component_bind_all(struct device *parent, void *data)
 {
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a5097467ba5..d188fa26bb1b 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -544,7 +544,7 @@ static void drm_fs_inode_free(struct inode *inode)
  * following guidelines apply:
  *
  *  - The entire device initialization procedure should be run from the
- *    &component_master_ops.master_bind callback, starting with
+ *    &aggregate_driver.probe callback, starting with
  *    devm_drm_dev_alloc(), then binding all components with
  *    component_bind_all() and finishing with drm_dev_register().
  *
diff --git a/include/linux/component.h b/include/linux/component.h
index d8dcbf9733da..07fe481d4e3b 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -63,47 +63,7 @@ void component_del(struct device *, const struct component_ops *);
 int component_bind_all(struct device *master, void *master_data);
 void component_unbind_all(struct device *master, void *master_data);
 
-/**
- * struct component_master_ops - callback for the aggregate driver
- *
- * Aggregate drivers are registered with component_master_add_with_match() and
- * unregistered with component_master_del().
- */
-struct component_master_ops {
-	/**
-	 * @bind:
-	 *
-	 * Called when all components or the aggregate driver, as specified in
-	 * the match list passed to component_master_add_with_match(), are
-	 * ready. Usually there are 3 steps to bind an aggregate driver:
-	 *
-	 * 1. Allocate a structure for the aggregate driver.
-	 *
-	 * 2. Bind all components to the aggregate driver by calling
-	 *    component_bind_all() with the aggregate driver structure as opaque
-	 *    pointer data.
-	 *
-	 * 3. Register the aggregate driver with the subsystem to publish its
-	 *    interfaces.
-	 *
-	 * Note that the lifetime of the aggregate driver does not align with
-	 * any of the underlying &struct device instances. Therefore devm cannot
-	 * be used and all resources acquired or allocated in this callback must
-	 * be explicitly released in the @unbind callback.
-	 */
-	int (*bind)(struct device *master);
-	/**
-	 * @unbind:
-	 *
-	 * Called when either the aggregate driver, using
-	 * component_master_del(), or one of its components, using
-	 * component_del(), is unregistered.
-	 */
-	void (*unbind)(struct device *master);
-};
-
 struct aggregate_device {
-	const struct component_master_ops *ops;
 	struct device *parent;
 	struct device dev;
 	struct component_match *match;
@@ -171,11 +131,6 @@ int component_aggregate_register(struct device *parent,
 void component_aggregate_unregister(struct device *parent,
 	struct aggregate_driver *adrv);
 
-void component_master_del(struct device *,
-	const struct component_master_ops *);
-
-int component_master_add_with_match(struct device *,
-	const struct component_master_ops *, struct component_match *);
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
-- 
https://chromeos.dev


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

* [PATCH v2 34/34] component: Remove all references to 'master'
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (32 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 33/34] component: Remove component_master_ops and friends Stephen Boyd
@ 2021-10-06 19:38 ` Stephen Boyd
  2021-10-07 10:16 ` [PATCH v2 00/34] component: Make into an aggregate bus Andrzej Hajda
       [not found] ` <CAHp75VdLg-rBjCDGEwgkY6QDbFGW0of4SjSmp08FXXRN_raQtQ@mail.gmail.com>
  35 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-06 19:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Remove all references to 'master' in the code now that we've migrated
all the users of the ops structure to the aggregate driver.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Saravana Kannan <saravanak@google.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/base/component.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index 939862b25b10..75323d35773c 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -1,11 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Componentized device handling.
- *
- * This is work in progress.  We gather up the component devices into a list,
- * and bind them when instructed.  At the moment, we're specific to the DRM
- * subsystem, and only handles one master device, but this doesn't have to be
- * the case.
  */
 #include <linux/component.h>
 #include <linux/device.h>
@@ -119,23 +114,23 @@ static int __init component_debug_init(void)
 
 core_initcall(component_debug_init);
 
-static void component_master_debugfs_add(struct aggregate_device *m)
+static void component_debugfs_add(struct aggregate_device *m)
 {
 	debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m,
 			    &component_devices_fops);
 }
 
-static void component_master_debugfs_del(struct aggregate_device *m)
+static void component_debugfs_del(struct aggregate_device *m)
 {
 	debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir));
 }
 
 #else
 
-static void component_master_debugfs_add(struct aggregate_device *m)
+static void component_debugfs_add(struct aggregate_device *m)
 { }
 
-static void component_master_debugfs_del(struct aggregate_device *m)
+static void component_debugfs_del(struct aggregate_device *m)
 { }
 
 #endif
@@ -343,7 +338,7 @@ EXPORT_SYMBOL(component_match_add_release);
  * @compare_typed: compare function to match against all typed components
  * @compare_data: opaque pointer passed to the @compare function
  *
- * Adds a new component match to the list stored in @matchptr, which the @master
+ * Adds a new component match to the list stored in @matchptr, which the
  * aggregate driver needs to function. The list of component matches pointed to
  * by @matchptr must be initialized to NULL before adding the first match. This
  * only matches against components added with component_add_typed().
@@ -367,7 +362,7 @@ static void free_aggregate_device(struct aggregate_device *adev)
 	struct component_match *match = adev->match;
 	int i;
 
-	component_master_debugfs_del(adev);
+	component_debugfs_del(adev);
 
 	if (match) {
 		for (i = 0; i < match->num; i++) {
@@ -548,7 +543,7 @@ static struct aggregate_device *aggregate_device_add(struct device *parent,
 		return ERR_PTR(ret);
 	}
 
-	component_master_debugfs_add(adev);
+	component_debugfs_add(adev);
 
 	return adev;
 }
-- 
https://chromeos.dev


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

* Re: [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
  2021-10-06 19:37 ` [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API Stephen Boyd
@ 2021-10-06 22:28   ` kernel test robot
  2021-10-06 22:36   ` kernel test robot
  1 sibling, 0 replies; 60+ messages in thread
From: kernel test robot @ 2021-10-06 22:28 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman
  Cc: llvm, kbuild-all, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Laurent Pinchart, Daniel Vetter, Rafael J. Wysocki,
	Rob Clark, Russell King

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

Hi Stephen,

I love your patch! Perhaps something to improve:

[auto build test WARNING on e4e737bb5c170df6135a127739a9e6148ee3da82]

url:    https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
base:   e4e737bb5c170df6135a127739a9e6148ee3da82
config: hexagon-randconfig-r041-20211006 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8de4fafdac42c316be0fc23e4176e13043031a38
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
        git checkout 8de4fafdac42c316be0fc23e4176e13043031a38
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:32:
>> include/drm/drm_of.h:45:14: warning: declaration of 'struct aggregate_driver' will not be visible outside of this function [-Wvisibility]
                              struct aggregate_driver *adrv);
                                     ^
   1 warning generated.


vim +45 include/drm/drm_of.h

    30	
    31	#ifdef CONFIG_OF
    32	uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
    33				    struct device_node *port);
    34	uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
    35					    struct device_node *port);
    36	void drm_of_component_match_add(struct device *master,
    37					struct component_match **matchptr,
    38					int (*compare)(struct device *, void *),
    39					struct device_node *node);
    40	int drm_of_component_probe(struct device *dev,
    41				   int (*compare_of)(struct device *, void *),
    42				   const struct component_master_ops *m_ops);
    43	int drm_of_aggregate_probe(struct device *dev,
    44				   int (*compare_of)(struct device *, void *),
  > 45				   struct aggregate_driver *adrv);
    46	int drm_of_encoder_active_endpoint(struct device_node *node,
    47					   struct drm_encoder *encoder,
    48					   struct of_endpoint *endpoint);
    49	int drm_of_find_panel_or_bridge(const struct device_node *np,
    50					int port, int endpoint,
    51					struct drm_panel **panel,
    52					struct drm_bridge **bridge);
    53	int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
    54						  const struct device_node *port2);
    55	#else
    56	static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
    57						  struct device_node *port)
    58	{
    59		return 0;
    60	}
    61	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24816 bytes --]

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

* Re: [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
  2021-10-06 19:37 ` [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API Stephen Boyd
  2021-10-06 22:28   ` kernel test robot
@ 2021-10-06 22:36   ` kernel test robot
  1 sibling, 0 replies; 60+ messages in thread
From: kernel test robot @ 2021-10-06 22:36 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman
  Cc: kbuild-all, linux-kernel, linux-arm-msm, dri-devel, freedreno,
	Laurent Pinchart, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

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

Hi Stephen,

I love your patch! Perhaps something to improve:

[auto build test WARNING on e4e737bb5c170df6135a127739a9e6148ee3da82]

url:    https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
base:   e4e737bb5c170df6135a127739a9e6148ee3da82
config: s390-randconfig-r044-20211006 (attached as .config)
compiler: s390-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8de4fafdac42c316be0fc23e4176e13043031a38
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
        git checkout 8de4fafdac42c316be0fc23e4176e13043031a38
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=s390 SHELL=/bin/bash drivers/gpu/drm/bridge/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/bridge/chipone-icn6211.c:7:
>> include/drm/drm_of.h:45:35: warning: 'struct aggregate_driver' declared inside parameter list will not be visible outside of this definition or declaration
      45 |                            struct aggregate_driver *adrv);
         |                                   ^~~~~~~~~~~~~~~~


vim +45 include/drm/drm_of.h

    30	
    31	#ifdef CONFIG_OF
    32	uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
    33				    struct device_node *port);
    34	uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
    35					    struct device_node *port);
    36	void drm_of_component_match_add(struct device *master,
    37					struct component_match **matchptr,
    38					int (*compare)(struct device *, void *),
    39					struct device_node *node);
    40	int drm_of_component_probe(struct device *dev,
    41				   int (*compare_of)(struct device *, void *),
    42				   const struct component_master_ops *m_ops);
    43	int drm_of_aggregate_probe(struct device *dev,
    44				   int (*compare_of)(struct device *, void *),
  > 45				   struct aggregate_driver *adrv);
    46	int drm_of_encoder_active_endpoint(struct device_node *node,
    47					   struct drm_encoder *encoder,
    48					   struct of_endpoint *endpoint);
    49	int drm_of_find_panel_or_bridge(const struct device_node *np,
    50					int port, int endpoint,
    51					struct drm_panel **panel,
    52					struct drm_bridge **bridge);
    53	int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
    54						  const struct device_node *port2);
    55	#else
    56	static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
    57						  struct device_node *port)
    58	{
    59		return 0;
    60	}
    61	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28649 bytes --]

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
@ 2021-10-06 22:42   ` kernel test robot
  2021-10-07  3:07   ` Saravana Kannan
  2021-10-07  5:37   ` Greg Kroah-Hartman
  2 siblings, 0 replies; 60+ messages in thread
From: kernel test robot @ 2021-10-06 22:42 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman
  Cc: llvm, kbuild-all, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

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

Hi Stephen,

I love your patch! Yet something to improve:

[auto build test ERROR on e4e737bb5c170df6135a127739a9e6148ee3da82]

url:    https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
base:   e4e737bb5c170df6135a127739a9e6148ee3da82
config: hexagon-randconfig-r045-20211006 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b7f12127fd97fe811eaf9600a6677fb1cbb66554
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
        git checkout b7f12127fd97fe811eaf9600a6677fb1cbb66554
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/base/component.c:509:13: error: incompatible function pointer types initializing 'void (*)(struct device *)' with an expression of type 'int (struct device *)' [-Werror,-Wincompatible-function-pointer-types]
           .remove         = aggregate_driver_remove,
                             ^~~~~~~~~~~~~~~~~~~~~~~
   1 error generated.


vim +509 drivers/base/component.c

   504	
   505	static struct bus_type aggregate_bus_type = {
   506		.name		= "aggregate",
   507		.match		= aggregate_device_match,
   508		.probe		= aggregate_driver_probe,
 > 509		.remove		= aggregate_driver_remove,
   510		.shutdown	= aggregate_driver_shutdown,
   511	};
   512	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34531 bytes --]

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

* Re: [PATCH v2 33/34] component: Remove component_master_ops and friends
  2021-10-06 19:38 ` [PATCH v2 33/34] component: Remove component_master_ops and friends Stephen Boyd
@ 2021-10-06 23:19   ` kernel test robot
  0 siblings, 0 replies; 60+ messages in thread
From: kernel test robot @ 2021-10-06 23:19 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman
  Cc: llvm, kbuild-all, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

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

Hi Stephen,

I love your patch! Yet something to improve:

[auto build test ERROR on e4e737bb5c170df6135a127739a9e6148ee3da82]

url:    https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
base:   e4e737bb5c170df6135a127739a9e6148ee3da82
config: hexagon-randconfig-r045-20211006 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b2ecd8598795ffcc3d4e766c4c4cc93865f3ff33
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200
        git checkout b2ecd8598795ffcc3d4e766c4c4cc93865f3ff33
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/base/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/base/component.c:412:15: error: no member named 'ops' in 'struct aggregate_device'
           return adev->ops->bind(adev->parent);
                  ~~~~  ^
   drivers/base/component.c:417:8: error: no member named 'ops' in 'struct aggregate_device'
           adev->ops->unbind(adev->parent);
           ~~~~  ^
   drivers/base/component.c:488:13: error: incompatible function pointer types initializing 'void (*)(struct device *)' with an expression of type 'int (struct device *)' [-Werror,-Wincompatible-function-pointer-types]
           .remove         = aggregate_driver_remove,
                             ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/base/component.c:540:8: error: no member named 'ops' in 'struct aggregate_device'
           adev->ops = ops;
           ~~~~  ^
>> drivers/base/component.c:540:14: error: use of undeclared identifier 'ops'
           adev->ops = ops;
                       ^
>> drivers/base/component.c:572:50: error: too many arguments to function call, expected 3, have 4
           adev = aggregate_device_add(parent, NULL, adrv, match);
                  ~~~~~~~~~~~~~~~~~~~~                     ^~~~~
   drivers/base/component.c:514:33: note: 'aggregate_device_add' declared here
   static struct aggregate_device *aggregate_device_add(struct device *parent,
                                   ^
>> drivers/base/component.c:599:34: error: too many arguments to function call, expected single argument 'parent', have 2 arguments
           adev = __aggregate_find(parent, NULL);
                  ~~~~~~~~~~~~~~~~         ^~~~
   include/linux/stddef.h:8:14: note: expanded from macro 'NULL'
   #define NULL ((void *)0)
                ^~~~~~~~~~~
   drivers/base/component.c:493:33: note: '__aggregate_find' declared here
   static struct aggregate_device *__aggregate_find(struct device *parent)
                                   ^
   drivers/base/component.c:645:34: error: too many arguments to function call, expected single argument 'parent', have 2 arguments
           adev = __aggregate_find(parent, NULL);
                  ~~~~~~~~~~~~~~~~         ^~~~
   include/linux/stddef.h:8:14: note: expanded from macro 'NULL'
   #define NULL ((void *)0)
                ^~~~~~~~~~~
   drivers/base/component.c:493:33: note: '__aggregate_find' declared here
   static struct aggregate_device *__aggregate_find(struct device *parent)
                                   ^
   drivers/base/component.c:734:34: error: too many arguments to function call, expected single argument 'parent', have 2 arguments
           adev = __aggregate_find(parent, NULL);
                  ~~~~~~~~~~~~~~~~         ^~~~
   include/linux/stddef.h:8:14: note: expanded from macro 'NULL'
   #define NULL ((void *)0)
                ^~~~~~~~~~~
   drivers/base/component.c:493:33: note: '__aggregate_find' declared here
   static struct aggregate_device *__aggregate_find(struct device *parent)
                                   ^
   9 errors generated.


vim +412 drivers/base/component.c

b7f12127fd97fe Stephen Boyd 2021-10-06  408  
b7f12127fd97fe Stephen Boyd 2021-10-06  409  /* TODO: Remove once all aggregate drivers use component_aggregate_register() */
b7f12127fd97fe Stephen Boyd 2021-10-06  410  static int component_probe_bind(struct aggregate_device *adev)
b7f12127fd97fe Stephen Boyd 2021-10-06  411  {
b7f12127fd97fe Stephen Boyd 2021-10-06 @412  	return adev->ops->bind(adev->parent);
b7f12127fd97fe Stephen Boyd 2021-10-06  413  }
b7f12127fd97fe Stephen Boyd 2021-10-06  414  
b7f12127fd97fe Stephen Boyd 2021-10-06  415  static void component_remove_unbind(struct aggregate_device *adev)
b7f12127fd97fe Stephen Boyd 2021-10-06  416  {
b7f12127fd97fe Stephen Boyd 2021-10-06  417  	adev->ops->unbind(adev->parent);
b7f12127fd97fe Stephen Boyd 2021-10-06  418  }
b7f12127fd97fe Stephen Boyd 2021-10-06  419  
b7f12127fd97fe Stephen Boyd 2021-10-06  420  static int aggregate_driver_probe(struct device *dev)
b7f12127fd97fe Stephen Boyd 2021-10-06  421  {
b7f12127fd97fe Stephen Boyd 2021-10-06  422  	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
b7f12127fd97fe Stephen Boyd 2021-10-06  423  	struct aggregate_device *adev = to_aggregate_device(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  424  	bool modern = adrv->probe != component_probe_bind;
b7f12127fd97fe Stephen Boyd 2021-10-06  425  	int ret;
b7f12127fd97fe Stephen Boyd 2021-10-06  426  
b7f12127fd97fe Stephen Boyd 2021-10-06  427  	/* Only do runtime PM when drivers migrate */
b7f12127fd97fe Stephen Boyd 2021-10-06  428  	if (modern) {
b7f12127fd97fe Stephen Boyd 2021-10-06  429  		pm_runtime_get_noresume(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  430  		pm_runtime_set_active(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  431  		pm_runtime_enable(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  432  	}
b7f12127fd97fe Stephen Boyd 2021-10-06  433  
b7f12127fd97fe Stephen Boyd 2021-10-06  434  	mutex_lock(&component_mutex);
b7f12127fd97fe Stephen Boyd 2021-10-06  435  	if (devres_open_group(adev->parent, NULL, GFP_KERNEL)) {
b7f12127fd97fe Stephen Boyd 2021-10-06  436  		ret = adrv->probe(adev);
b7f12127fd97fe Stephen Boyd 2021-10-06  437  		if (ret)
b7f12127fd97fe Stephen Boyd 2021-10-06  438  			devres_release_group(adev->parent, NULL);
b7f12127fd97fe Stephen Boyd 2021-10-06  439  	} else {
b7f12127fd97fe Stephen Boyd 2021-10-06  440  		ret = -ENOMEM;
b7f12127fd97fe Stephen Boyd 2021-10-06  441  	}
b7f12127fd97fe Stephen Boyd 2021-10-06  442  	mutex_unlock(&component_mutex);
b7f12127fd97fe Stephen Boyd 2021-10-06  443  
b7f12127fd97fe Stephen Boyd 2021-10-06  444  	if (ret && modern) {
b7f12127fd97fe Stephen Boyd 2021-10-06  445  		pm_runtime_disable(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  446  		pm_runtime_set_suspended(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  447  		pm_runtime_put_noidle(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  448  	}
b7f12127fd97fe Stephen Boyd 2021-10-06  449  
b7f12127fd97fe Stephen Boyd 2021-10-06  450  	return ret;
b7f12127fd97fe Stephen Boyd 2021-10-06  451  }
b7f12127fd97fe Stephen Boyd 2021-10-06  452  
b7f12127fd97fe Stephen Boyd 2021-10-06  453  static int aggregate_driver_remove(struct device *dev)
b7f12127fd97fe Stephen Boyd 2021-10-06  454  {
b7f12127fd97fe Stephen Boyd 2021-10-06  455  	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
b7f12127fd97fe Stephen Boyd 2021-10-06  456  	struct aggregate_device *adev = to_aggregate_device(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  457  	bool modern = adrv->remove != component_remove_unbind;
b7f12127fd97fe Stephen Boyd 2021-10-06  458  
b7f12127fd97fe Stephen Boyd 2021-10-06  459  	/* Only do runtime PM when drivers migrate */
b7f12127fd97fe Stephen Boyd 2021-10-06  460  	if (modern)
b7f12127fd97fe Stephen Boyd 2021-10-06  461  		pm_runtime_get_sync(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  462  	adrv->remove(to_aggregate_device(dev));
b7f12127fd97fe Stephen Boyd 2021-10-06  463  	devres_release_group(adev->parent, NULL);
b7f12127fd97fe Stephen Boyd 2021-10-06  464  	if (!modern)
b7f12127fd97fe Stephen Boyd 2021-10-06  465  		return 0;
b7f12127fd97fe Stephen Boyd 2021-10-06  466  
b7f12127fd97fe Stephen Boyd 2021-10-06  467  	pm_runtime_put_noidle(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  468  
b7f12127fd97fe Stephen Boyd 2021-10-06  469  	pm_runtime_disable(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  470  	pm_runtime_set_suspended(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  471  	pm_runtime_put_noidle(dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  472  
b7f12127fd97fe Stephen Boyd 2021-10-06  473  	return 0;
b7f12127fd97fe Stephen Boyd 2021-10-06  474  }
b7f12127fd97fe Stephen Boyd 2021-10-06  475  
b7f12127fd97fe Stephen Boyd 2021-10-06  476  static void aggregate_driver_shutdown(struct device *dev)
b7f12127fd97fe Stephen Boyd 2021-10-06  477  {
b7f12127fd97fe Stephen Boyd 2021-10-06  478  	const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
b7f12127fd97fe Stephen Boyd 2021-10-06  479  
b7f12127fd97fe Stephen Boyd 2021-10-06  480  	if (adrv && adrv->shutdown)
b7f12127fd97fe Stephen Boyd 2021-10-06  481  		adrv->shutdown(to_aggregate_device(dev));
b7f12127fd97fe Stephen Boyd 2021-10-06  482  }
b7f12127fd97fe Stephen Boyd 2021-10-06  483  
b7f12127fd97fe Stephen Boyd 2021-10-06  484  static struct bus_type aggregate_bus_type = {
b7f12127fd97fe Stephen Boyd 2021-10-06  485  	.name		= "aggregate",
b7f12127fd97fe Stephen Boyd 2021-10-06  486  	.match		= aggregate_device_match,
b7f12127fd97fe Stephen Boyd 2021-10-06  487  	.probe		= aggregate_driver_probe,
b7f12127fd97fe Stephen Boyd 2021-10-06  488  	.remove		= aggregate_driver_remove,
b7f12127fd97fe Stephen Boyd 2021-10-06  489  	.shutdown	= aggregate_driver_shutdown,
b7f12127fd97fe Stephen Boyd 2021-10-06  490  };
b7f12127fd97fe Stephen Boyd 2021-10-06  491  
b7f12127fd97fe Stephen Boyd 2021-10-06  492  /* Callers take ownership of return value, should call put_device() */
b2ecd8598795ff Stephen Boyd 2021-10-06  493  static struct aggregate_device *__aggregate_find(struct device *parent)
b7f12127fd97fe Stephen Boyd 2021-10-06  494  {
b7f12127fd97fe Stephen Boyd 2021-10-06  495  	struct device *dev;
b7f12127fd97fe Stephen Boyd 2021-10-06  496  
b2ecd8598795ff Stephen Boyd 2021-10-06  497  	dev = bus_find_device(&aggregate_bus_type, NULL, parent,
b7f12127fd97fe Stephen Boyd 2021-10-06  498  			      aggregate_bus_find_match);
b7f12127fd97fe Stephen Boyd 2021-10-06  499  
b7f12127fd97fe Stephen Boyd 2021-10-06  500  	return dev ? to_aggregate_device(dev) : NULL;
b7f12127fd97fe Stephen Boyd 2021-10-06  501  }
b7f12127fd97fe Stephen Boyd 2021-10-06  502  
b7f12127fd97fe Stephen Boyd 2021-10-06  503  static int aggregate_driver_register(struct aggregate_driver *adrv)
b7f12127fd97fe Stephen Boyd 2021-10-06  504  {
b7f12127fd97fe Stephen Boyd 2021-10-06  505  	adrv->driver.bus = &aggregate_bus_type;
b7f12127fd97fe Stephen Boyd 2021-10-06  506  	return driver_register(&adrv->driver);
b7f12127fd97fe Stephen Boyd 2021-10-06  507  }
b7f12127fd97fe Stephen Boyd 2021-10-06  508  
b7f12127fd97fe Stephen Boyd 2021-10-06  509  static void aggregate_driver_unregister(struct aggregate_driver *adrv)
b7f12127fd97fe Stephen Boyd 2021-10-06  510  {
b7f12127fd97fe Stephen Boyd 2021-10-06  511  	driver_unregister(&adrv->driver);
b7f12127fd97fe Stephen Boyd 2021-10-06  512  }
b7f12127fd97fe Stephen Boyd 2021-10-06  513  
b7f12127fd97fe Stephen Boyd 2021-10-06  514  static struct aggregate_device *aggregate_device_add(struct device *parent,
b2ecd8598795ff Stephen Boyd 2021-10-06  515  	struct aggregate_driver *adrv,
6955b58254c2bc Russell King 2014-04-19  516  	struct component_match *match)
2a41e6070dd7ef Russell King 2014-01-10  517  {
0b7b1dfac42590 Stephen Boyd 2021-10-06  518  	struct aggregate_device *adev;
0b7b1dfac42590 Stephen Boyd 2021-10-06  519  	int ret, id;
2a41e6070dd7ef Russell King 2014-01-10  520  
6955b58254c2bc Russell King 2014-04-19  521  	/* Reallocate the match array for its true size */
82769cc671b6dd Stephen Boyd 2021-05-19  522  	ret = component_match_realloc(match, match->num);
ce657b1cddf1f8 Russell King 2015-11-17  523  	if (ret)
b7f12127fd97fe Stephen Boyd 2021-10-06  524  		return ERR_PTR(ret);
6955b58254c2bc Russell King 2014-04-19  525  
0b7b1dfac42590 Stephen Boyd 2021-10-06  526  	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
0b7b1dfac42590 Stephen Boyd 2021-10-06  527  	if (!adev)
b7f12127fd97fe Stephen Boyd 2021-10-06  528  		return ERR_PTR(-ENOMEM);
2a41e6070dd7ef Russell King 2014-01-10  529  
0b7b1dfac42590 Stephen Boyd 2021-10-06  530  	id = ida_alloc(&aggregate_ida, GFP_KERNEL);
0b7b1dfac42590 Stephen Boyd 2021-10-06  531  	if (id < 0) {
0b7b1dfac42590 Stephen Boyd 2021-10-06  532  		kfree(adev);
b7f12127fd97fe Stephen Boyd 2021-10-06  533  		return ERR_PTR(id);
0b7b1dfac42590 Stephen Boyd 2021-10-06  534  	}
0b7b1dfac42590 Stephen Boyd 2021-10-06  535  
0b7b1dfac42590 Stephen Boyd 2021-10-06  536  	adev->id = id;
0b7b1dfac42590 Stephen Boyd 2021-10-06  537  	adev->parent = parent;
b7f12127fd97fe Stephen Boyd 2021-10-06  538  	adev->dev.bus = &aggregate_bus_type;
b7f12127fd97fe Stephen Boyd 2021-10-06  539  	adev->dev.release = aggregate_device_release;
0b7b1dfac42590 Stephen Boyd 2021-10-06 @540  	adev->ops = ops;
0b7b1dfac42590 Stephen Boyd 2021-10-06  541  	adev->match = match;
b7f12127fd97fe Stephen Boyd 2021-10-06  542  	adev->adrv = adrv;
0b7b1dfac42590 Stephen Boyd 2021-10-06  543  	dev_set_name(&adev->dev, "aggregate%d", id);
2a41e6070dd7ef Russell King 2014-01-10  544  
b7f12127fd97fe Stephen Boyd 2021-10-06  545  	ret = device_register(&adev->dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  546  	if (ret) {
b7f12127fd97fe Stephen Boyd 2021-10-06  547  		put_device(&adev->dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  548  		return ERR_PTR(ret);
b7f12127fd97fe Stephen Boyd 2021-10-06  549  	}
b7f12127fd97fe Stephen Boyd 2021-10-06  550  
0b7b1dfac42590 Stephen Boyd 2021-10-06  551  	component_master_debugfs_add(adev);
2a41e6070dd7ef Russell King 2014-01-10  552  
b7f12127fd97fe Stephen Boyd 2021-10-06  553  	return adev;
b7f12127fd97fe Stephen Boyd 2021-10-06  554  }
2a41e6070dd7ef Russell King 2014-01-10  555  
b7f12127fd97fe Stephen Boyd 2021-10-06  556  /**
b7f12127fd97fe Stephen Boyd 2021-10-06  557   * component_aggregate_register - register an aggregate driver
b7f12127fd97fe Stephen Boyd 2021-10-06  558   * @parent: parent device of the aggregate driver
b7f12127fd97fe Stephen Boyd 2021-10-06  559   * @adrv: aggregate driver to register
b7f12127fd97fe Stephen Boyd 2021-10-06  560   *
b7f12127fd97fe Stephen Boyd 2021-10-06  561   * Registers a new aggregate driver consisting of the components added to @adrv.match
b7f12127fd97fe Stephen Boyd 2021-10-06  562   * by calling one of the component_match_add() functions. Once all components in
b7f12127fd97fe Stephen Boyd 2021-10-06  563   * @match are available, the aggregate driver will be assembled by calling
b7f12127fd97fe Stephen Boyd 2021-10-06  564   * &adrv.bind. Must be unregistered by calling component_aggregate_unregister().
b7f12127fd97fe Stephen Boyd 2021-10-06  565   */
b7f12127fd97fe Stephen Boyd 2021-10-06  566  int component_aggregate_register(struct device *parent,
b7f12127fd97fe Stephen Boyd 2021-10-06  567  	struct aggregate_driver *adrv, struct component_match *match)
b7f12127fd97fe Stephen Boyd 2021-10-06  568  {
b7f12127fd97fe Stephen Boyd 2021-10-06  569  	struct aggregate_device *adev;
b7f12127fd97fe Stephen Boyd 2021-10-06  570  	int ret;
b7f12127fd97fe Stephen Boyd 2021-10-06  571  
b7f12127fd97fe Stephen Boyd 2021-10-06 @572  	adev = aggregate_device_add(parent, NULL, adrv, match);
b7f12127fd97fe Stephen Boyd 2021-10-06  573  	if (IS_ERR(adev))
b7f12127fd97fe Stephen Boyd 2021-10-06  574  		return PTR_ERR(adev);
b7f12127fd97fe Stephen Boyd 2021-10-06  575  
b7f12127fd97fe Stephen Boyd 2021-10-06  576  	ret = aggregate_driver_register(adrv);
b7f12127fd97fe Stephen Boyd 2021-10-06  577  	if (ret)
b7f12127fd97fe Stephen Boyd 2021-10-06  578  		put_device(&adev->dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  579  
b7f12127fd97fe Stephen Boyd 2021-10-06  580  	return ret;
b7f12127fd97fe Stephen Boyd 2021-10-06  581  }
b7f12127fd97fe Stephen Boyd 2021-10-06  582  EXPORT_SYMBOL_GPL(component_aggregate_register);
b7f12127fd97fe Stephen Boyd 2021-10-06  583  
b7f12127fd97fe Stephen Boyd 2021-10-06  584  /**
b7f12127fd97fe Stephen Boyd 2021-10-06  585   * component_aggregate_unregister - unregister an aggregate driver
b7f12127fd97fe Stephen Boyd 2021-10-06  586   * @parent: parent device of the aggregate driver
b7f12127fd97fe Stephen Boyd 2021-10-06  587   * @adrv: registered aggregate driver
b7f12127fd97fe Stephen Boyd 2021-10-06  588   *
b7f12127fd97fe Stephen Boyd 2021-10-06  589   * Unregisters an aggregate driver registered with
b7f12127fd97fe Stephen Boyd 2021-10-06  590   * component_aggregate_register(). If necessary the aggregate driver is first
b7f12127fd97fe Stephen Boyd 2021-10-06  591   * disassembled.
b7f12127fd97fe Stephen Boyd 2021-10-06  592   */
b7f12127fd97fe Stephen Boyd 2021-10-06  593  void component_aggregate_unregister(struct device *parent,
b7f12127fd97fe Stephen Boyd 2021-10-06  594  	struct aggregate_driver *adrv)
b7f12127fd97fe Stephen Boyd 2021-10-06  595  {
b7f12127fd97fe Stephen Boyd 2021-10-06  596  	struct aggregate_device *adev;
b7f12127fd97fe Stephen Boyd 2021-10-06  597  
b7f12127fd97fe Stephen Boyd 2021-10-06  598  	mutex_lock(&component_mutex);
b7f12127fd97fe Stephen Boyd 2021-10-06 @599  	adev = __aggregate_find(parent, NULL);
b7f12127fd97fe Stephen Boyd 2021-10-06  600  	mutex_unlock(&component_mutex);
b7f12127fd97fe Stephen Boyd 2021-10-06  601  
b7f12127fd97fe Stephen Boyd 2021-10-06  602  	if (adev)
b7f12127fd97fe Stephen Boyd 2021-10-06  603  		device_unregister(&adev->dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  604  	put_device(&adev->dev);
b7f12127fd97fe Stephen Boyd 2021-10-06  605  
b7f12127fd97fe Stephen Boyd 2021-10-06  606  	aggregate_driver_unregister(adrv);
b7f12127fd97fe Stephen Boyd 2021-10-06  607  }
b7f12127fd97fe Stephen Boyd 2021-10-06  608  EXPORT_SYMBOL_GPL(component_aggregate_unregister);
b7f12127fd97fe Stephen Boyd 2021-10-06  609  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34531 bytes --]

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

* Re: [PATCH v2 01/34] component: Introduce struct aggregate_device
  2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
@ 2021-10-07  1:17   ` Laurent Pinchart
  2021-10-07 18:36     ` Stephen Boyd
  2021-10-13 12:22   ` Daniel Vetter
  1 sibling, 1 reply; 60+ messages in thread
From: Laurent Pinchart @ 2021-10-07  1:17 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Hi Stephen,

Thank you for the patch.

On Wed, Oct 06, 2021 at 12:37:46PM -0700, Stephen Boyd wrote:
> Replace 'struct master' with 'struct aggregate_device' and then rename
> 'master' to 'adev' everywhere in the code. While we're here, put a
> struct device inside the aggregate device so that we can register it
> with a bus_type in the next patch.

Not "while at it" please. The signal to noise ratio is very high here.
Adding the struct device in the structure is the important change that
needs to be properly reviewed and discussed, the rename is noise. You're
even adding an IDA and an id without mentioning it at all in the commit
message. This should be split in two patches, you can decide whether to
perform the rename at the bottom or top of the series (it would be more
logical to group all renames together though, there's currently one in
01/34 and one in 34/34, so please group them both at the top or bottom).

> The diff is large but that's because this is mostly a rename, where
> sometimes 'master' is replaced with 'adev' and other times it is
> replaced with 'parent' to indicate that the struct device that was being
> used is actually the parent of the aggregate device and driver.
> 
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>  drivers/base/component.c  | 250 ++++++++++++++++++++------------------
>  include/linux/component.h |   2 +-
>  2 files changed, 134 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index 5e79299f6c3f..0a41bbe14981 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -9,6 +9,7 @@
>   */
>  #include <linux/component.h>
>  #include <linux/device.h>
> +#include <linux/idr.h>
>  #include <linux/kref.h>
>  #include <linux/list.h>
>  #include <linux/mutex.h>
> @@ -58,18 +59,21 @@ struct component_match {
>  	struct component_match_array *compare;
>  };
>  
> -struct master {
> +struct aggregate_device {
>  	struct list_head node;
>  	bool bound;
>  
>  	const struct component_master_ops *ops;
>  	struct device *parent;
> +	struct device dev;
>  	struct component_match *match;
> +
> +	int id;
>  };
>  
>  struct component {
>  	struct list_head node;
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	bool bound;
>  
>  	const struct component_ops *ops;
> @@ -79,7 +83,9 @@ struct component {
>  
>  static DEFINE_MUTEX(component_mutex);
>  static LIST_HEAD(component_list);
> -static LIST_HEAD(masters);
> +static LIST_HEAD(aggregate_devices);
> +
> +static DEFINE_IDA(aggregate_ida);
>  
>  #ifdef CONFIG_DEBUG_FS
>  
> @@ -87,12 +93,12 @@ static struct dentry *component_debugfs_dir;
>  
>  static int component_devices_show(struct seq_file *s, void *data)
>  {
> -	struct master *m = s->private;
> +	struct aggregate_device *m = s->private;
>  	struct component_match *match = m->match;
>  	size_t i;
>  
>  	mutex_lock(&component_mutex);
> -	seq_printf(s, "%-40s %20s\n", "master name", "status");
> +	seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
>  	seq_puts(s, "-------------------------------------------------------------\n");
>  	seq_printf(s, "%-40s %20s\n\n",
>  		   dev_name(m->parent), m->bound ? "bound" : "not bound");
> @@ -122,46 +128,46 @@ static int __init component_debug_init(void)
>  
>  core_initcall(component_debug_init);
>  
> -static void component_master_debugfs_add(struct master *m)
> +static void component_master_debugfs_add(struct aggregate_device *m)
>  {
>  	debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m,
>  			    &component_devices_fops);
>  }
>  
> -static void component_master_debugfs_del(struct master *m)
> +static void component_master_debugfs_del(struct aggregate_device *m)
>  {
>  	debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir));
>  }
>  
>  #else
>  
> -static void component_master_debugfs_add(struct master *m)
> +static void component_master_debugfs_add(struct aggregate_device *m)
>  { }
>  
> -static void component_master_debugfs_del(struct master *m)
> +static void component_master_debugfs_del(struct aggregate_device *m)
>  { }
>  
>  #endif
>  
> -static struct master *__master_find(struct device *parent,
> +static struct aggregate_device *__aggregate_find(struct device *parent,
>  	const struct component_master_ops *ops)
>  {
> -	struct master *m;
> +	struct aggregate_device *m;
>  
> -	list_for_each_entry(m, &masters, node)
> +	list_for_each_entry(m, &aggregate_devices, node)
>  		if (m->parent == parent && (!ops || m->ops == ops))
>  			return m;
>  
>  	return NULL;
>  }
>  
> -static struct component *find_component(struct master *master,
> +static struct component *find_component(struct aggregate_device *adev,
>  	struct component_match_array *mc)
>  {
>  	struct component *c;
>  
>  	list_for_each_entry(c, &component_list, node) {
> -		if (c->master && c->master != master)
> +		if (c->adev && c->adev != adev)
>  			continue;
>  
>  		if (mc->compare && mc->compare(c->dev, mc->data))
> @@ -175,101 +181,102 @@ static struct component *find_component(struct master *master,
>  	return NULL;
>  }
>  
> -static int find_components(struct master *master)
> +static int find_components(struct aggregate_device *adev)
>  {
> -	struct component_match *match = master->match;
> +	struct component_match *match = adev->match;
>  	size_t i;
>  	int ret = 0;
>  
>  	/*
>  	 * Scan the array of match functions and attach
> -	 * any components which are found to this master.
> +	 * any components which are found to this adev.
>  	 */
>  	for (i = 0; i < match->num; i++) {
>  		struct component_match_array *mc = &match->compare[i];
>  		struct component *c;
>  
> -		dev_dbg(master->parent, "Looking for component %zu\n", i);
> +		dev_dbg(adev->parent, "Looking for component %zu\n", i);
>  
>  		if (match->compare[i].component)
>  			continue;
>  
> -		c = find_component(master, mc);
> +		c = find_component(adev, mc);
>  		if (!c) {
>  			ret = -ENXIO;
>  			break;
>  		}
>  
> -		dev_dbg(master->parent, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
> +		dev_dbg(adev->parent, "found component %s, duplicate %u\n",
> +			dev_name(c->dev), !!c->adev);
>  
> -		/* Attach this component to the master */
> -		match->compare[i].duplicate = !!c->master;
> +		/* Attach this component to the adev */
> +		match->compare[i].duplicate = !!c->adev;
>  		match->compare[i].component = c;
> -		c->master = master;
> +		c->adev = adev;
>  	}
>  	return ret;
>  }
>  
> -/* Detach component from associated master */
> -static void remove_component(struct master *master, struct component *c)
> +/* Detach component from associated aggregate_device */
> +static void remove_component(struct aggregate_device *adev, struct component *c)
>  {
>  	size_t i;
>  
> -	/* Detach the component from this master. */
> -	for (i = 0; i < master->match->num; i++)
> -		if (master->match->compare[i].component == c)
> -			master->match->compare[i].component = NULL;
> +	/* Detach the component from this adev. */
> +	for (i = 0; i < adev->match->num; i++)
> +		if (adev->match->compare[i].component == c)
> +			adev->match->compare[i].component = NULL;
>  }
>  
>  /*
> - * Try to bring up a master.  If component is NULL, we're interested in
> - * this master, otherwise it's a component which must be present to try
> - * and bring up the master.
> + * Try to bring up an aggregate device.  If component is NULL, we're interested
> + * in this aggregate device, otherwise it's a component which must be present
> + * to try and bring up the aggregate device.
>   *
>   * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
>   */
> -static int try_to_bring_up_master(struct master *master,
> +static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
>  	struct component *component)
>  {
>  	int ret;
>  
> -	dev_dbg(master->parent, "trying to bring up master\n");
> +	dev_dbg(adev->parent, "trying to bring up adev\n");
>  
> -	if (find_components(master)) {
> -		dev_dbg(master->parent, "master has incomplete components\n");
> +	if (find_components(adev)) {
> +		dev_dbg(adev->parent, "master has incomplete components\n");
>  		return 0;
>  	}
>  
> -	if (component && component->master != master) {
> -		dev_dbg(master->parent, "master is not for this component (%s)\n",
> +	if (component && component->adev != adev) {
> +		dev_dbg(adev->parent, "master is not for this component (%s)\n",
>  			dev_name(component->dev));
>  		return 0;
>  	}
>  
> -	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
> +	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
>  		return -ENOMEM;
>  
>  	/* Found all components */
> -	ret = master->ops->bind(master->parent);
> +	ret = adev->ops->bind(adev->parent);
>  	if (ret < 0) {
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  		if (ret != -EPROBE_DEFER)
> -			dev_info(master->parent, "master bind failed: %d\n", ret);
> +			dev_info(adev->parent, "adev bind failed: %d\n", ret);
>  		return ret;
>  	}
>  
> -	master->bound = true;
> +	adev->bound = true;
>  	return 1;
>  }
>  
>  static int try_to_bring_up_masters(struct component *component)
>  {
> -	struct master *m;
> +	struct aggregate_device *adev;
>  	int ret = 0;
>  
> -	list_for_each_entry(m, &masters, node) {
> -		if (!m->bound) {
> -			ret = try_to_bring_up_master(m, component);
> +	list_for_each_entry(adev, &aggregate_devices, node) {
> +		if (!adev->bound) {
> +			ret = try_to_bring_up_aggregate_device(adev, component);
>  			if (ret != 0)
>  				break;
>  		}
> @@ -278,12 +285,12 @@ static int try_to_bring_up_masters(struct component *component)
>  	return ret;
>  }
>  
> -static void take_down_master(struct master *master)
> +static void take_down_aggregate_device(struct aggregate_device *adev)
>  {
> -	if (master->bound) {
> -		master->ops->unbind(master->parent);
> -		devres_release_group(master->parent, NULL);
> -		master->bound = false;
> +	if (adev->bound) {
> +		adev->ops->unbind(adev->parent);
> +		devres_release_group(adev->parent, NULL);
> +		adev->bound = false;
>  	}
>  }
>  
> @@ -324,7 +331,7 @@ static int component_match_realloc(struct component_match *match, size_t num)
>  	return 0;
>  }
>  
> -static void __component_match_add(struct device *master,
> +static void __component_match_add(struct device *parent,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *),
> @@ -344,7 +351,7 @@ static void __component_match_add(struct device *master,
>  			return;
>  		}
>  
> -		devres_add(master, match);
> +		devres_add(parent, match);
>  
>  		*matchptr = match;
>  	}
> @@ -370,13 +377,13 @@ static void __component_match_add(struct device *master,
>  
>  /**
>   * component_match_add_release - add a component match entry with release callback
> - * @master: device with the aggregate driver
> + * @parent: parent device of the aggregate driver
>   * @matchptr: pointer to the list of component matches
>   * @release: release function for @compare_data
>   * @compare: compare function to match against all components
>   * @compare_data: opaque pointer passed to the @compare function
>   *
> - * Adds a new component match to the list stored in @matchptr, which the @master
> + * Adds a new component match to the list stored in @matchptr, which the
>   * aggregate driver needs to function. The list of component matches pointed to
>   * by @matchptr must be initialized to NULL before adding the first match. This
>   * only matches against components added with component_add().
> @@ -388,19 +395,19 @@ static void __component_match_add(struct device *master,
>   *
>   * See also component_match_add() and component_match_add_typed().
>   */
> -void component_match_add_release(struct device *master,
> +void component_match_add_release(struct device *parent,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *), void *compare_data)
>  {
> -	__component_match_add(master, matchptr, release, compare, NULL,
> +	__component_match_add(parent, matchptr, release, compare, NULL,
>  			      compare_data);
>  }
>  EXPORT_SYMBOL(component_match_add_release);
>  
>  /**
>   * component_match_add_typed - add a component match entry for a typed component
> - * @master: device with the aggregate driver
> + * @parent: parent device of the aggregate driver
>   * @matchptr: pointer to the list of component matches
>   * @compare_typed: compare function to match against all typed components
>   * @compare_data: opaque pointer passed to the @compare function
> @@ -415,32 +422,33 @@ EXPORT_SYMBOL(component_match_add_release);
>   *
>   * See also component_match_add_release() and component_match_add_typed().
>   */
> -void component_match_add_typed(struct device *master,
> +void component_match_add_typed(struct device *parent,
>  	struct component_match **matchptr,
>  	int (*compare_typed)(struct device *, int, void *), void *compare_data)
>  {
> -	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> +	__component_match_add(parent, matchptr, NULL, NULL, compare_typed,
>  			      compare_data);
>  }
>  EXPORT_SYMBOL(component_match_add_typed);
>  
> -static void free_master(struct master *master)
> +static void free_aggregate_device(struct aggregate_device *adev)
>  {
> -	struct component_match *match = master->match;
> +	struct component_match *match = adev->match;
>  	int i;
>  
> -	component_master_debugfs_del(master);
> -	list_del(&master->node);
> +	component_master_debugfs_del(adev);
> +	list_del(&adev->node);
>  
>  	if (match) {
>  		for (i = 0; i < match->num; i++) {
>  			struct component *c = match->compare[i].component;
>  			if (c)
> -				c->master = NULL;
> +				c->adev = NULL;
>  		}
>  	}
>  
> -	kfree(master);
> +	ida_free(&aggregate_ida, adev->id);
> +	kfree(adev);
>  }
>  
>  /**
> @@ -459,31 +467,39 @@ int component_master_add_with_match(struct device *parent,
>  	const struct component_master_ops *ops,
>  	struct component_match *match)
>  {
> -	struct master *master;
> -	int ret;
> +	struct aggregate_device *adev;
> +	int ret, id;
>  
>  	/* Reallocate the match array for its true size */
>  	ret = component_match_realloc(match, match->num);
>  	if (ret)
>  		return ret;
>  
> -	master = kzalloc(sizeof(*master), GFP_KERNEL);
> -	if (!master)
> +	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
> +	if (!adev)
>  		return -ENOMEM;
>  
> -	master->parent = parent;
> -	master->ops = ops;
> -	master->match = match;
> +	id = ida_alloc(&aggregate_ida, GFP_KERNEL);
> +	if (id < 0) {
> +		kfree(adev);
> +		return id;
> +	}
> +
> +	adev->id = id;
> +	adev->parent = parent;
> +	adev->ops = ops;
> +	adev->match = match;
> +	dev_set_name(&adev->dev, "aggregate%d", id);
>  
> -	component_master_debugfs_add(master);
> -	/* Add to the list of available masters. */
> +	component_master_debugfs_add(adev);
> +	/* Add to the list of available aggregate devices. */
>  	mutex_lock(&component_mutex);
> -	list_add(&master->node, &masters);
> +	list_add(&adev->node, &aggregate_devices);
>  
> -	ret = try_to_bring_up_master(master, NULL);
> +	ret = try_to_bring_up_aggregate_device(adev, NULL);
>  
>  	if (ret < 0)
> -		free_master(master);
> +		free_aggregate_device(adev);
>  
>  	mutex_unlock(&component_mutex);
>  
> @@ -503,25 +519,25 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
>  void component_master_del(struct device *parent,
>  	const struct component_master_ops *ops)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  
>  	mutex_lock(&component_mutex);
> -	master = __master_find(parent, ops);
> -	if (master) {
> -		take_down_master(master);
> -		free_master(master);
> +	adev = __aggregate_find(parent, ops);
> +	if (adev) {
> +		take_down_aggregate_device(adev);
> +		free_aggregate_device(adev);
>  	}
>  	mutex_unlock(&component_mutex);
>  }
>  EXPORT_SYMBOL_GPL(component_master_del);
>  
>  static void component_unbind(struct component *component,
> -	struct master *master, void *data)
> +	struct aggregate_device *adev, void *data)
>  {
>  	WARN_ON(!component->bound);
>  
>  	if (component->ops && component->ops->unbind)
> -		component->ops->unbind(component->dev, master->parent, data);
> +		component->ops->unbind(component->dev, adev->parent, data);
>  	component->bound = false;
>  
>  	/* Release all resources claimed in the binding of this component */
> @@ -539,26 +555,26 @@ static void component_unbind(struct component *component,
>   */
>  void component_unbind_all(struct device *parent, void *data)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	struct component *c;
>  	size_t i;
>  
>  	WARN_ON(!mutex_is_locked(&component_mutex));
>  
> -	master = __master_find(parent, NULL);
> -	if (!master)
> +	adev = __aggregate_find(parent, NULL);
> +	if (!adev)
>  		return;
>  
>  	/* Unbind components in reverse order */
> -	for (i = master->match->num; i--; )
> -		if (!master->match->compare[i].duplicate) {
> -			c = master->match->compare[i].component;
> -			component_unbind(c, master, data);
> +	for (i = adev->match->num; i--; )
> +		if (!adev->match->compare[i].duplicate) {
> +			c = adev->match->compare[i].component;
> +			component_unbind(c, adev, data);
>  		}
>  }
>  EXPORT_SYMBOL_GPL(component_unbind_all);
>  
> -static int component_bind(struct component *component, struct master *master,
> +static int component_bind(struct component *component, struct aggregate_device *adev,
>  	void *data)
>  {
>  	int ret;
> @@ -568,7 +584,7 @@ static int component_bind(struct component *component, struct master *master,
>  	 * This allows us to roll-back a failed component without
>  	 * affecting anything else.
>  	 */
> -	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
> +	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
>  		return -ENOMEM;
>  
>  	/*
> @@ -577,14 +593,14 @@ static int component_bind(struct component *component, struct master *master,
>  	 * at the appropriate moment.
>  	 */
>  	if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  		return -ENOMEM;
>  	}
>  
> -	dev_dbg(master->parent, "binding %s (ops %ps)\n",
> +	dev_dbg(adev->parent, "binding %s (ops %ps)\n",
>  		dev_name(component->dev), component->ops);
>  
> -	ret = component->ops->bind(component->dev, master->parent, data);
> +	ret = component->ops->bind(component->dev, adev->parent, data);
>  	if (!ret) {
>  		component->bound = true;
>  
> @@ -595,16 +611,16 @@ static int component_bind(struct component *component, struct master *master,
>  		 * can clean those resources up independently.
>  		 */
>  		devres_close_group(component->dev, NULL);
> -		devres_remove_group(master->parent, NULL);
> +		devres_remove_group(adev->parent, NULL);
>  
> -		dev_info(master->parent, "bound %s (ops %ps)\n",
> +		dev_info(adev->parent, "bound %s (ops %ps)\n",
>  			 dev_name(component->dev), component->ops);
>  	} else {
>  		devres_release_group(component->dev, NULL);
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  
>  		if (ret != -EPROBE_DEFER)
> -			dev_err(master->parent, "failed to bind %s (ops %ps): %d\n",
> +			dev_err(adev->parent, "failed to bind %s (ops %ps): %d\n",
>  				dev_name(component->dev), component->ops, ret);
>  	}
>  
> @@ -622,31 +638,31 @@ static int component_bind(struct component *component, struct master *master,
>   */
>  int component_bind_all(struct device *parent, void *data)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	struct component *c;
>  	size_t i;
>  	int ret = 0;
>  
>  	WARN_ON(!mutex_is_locked(&component_mutex));
>  
> -	master = __master_find(parent, NULL);
> -	if (!master)
> +	adev = __aggregate_find(parent, NULL);
> +	if (!adev)
>  		return -EINVAL;
>  
>  	/* Bind components in match order */
> -	for (i = 0; i < master->match->num; i++)
> -		if (!master->match->compare[i].duplicate) {
> -			c = master->match->compare[i].component;
> -			ret = component_bind(c, master, data);
> +	for (i = 0; i < adev->match->num; i++)
> +		if (!adev->match->compare[i].duplicate) {
> +			c = adev->match->compare[i].component;
> +			ret = component_bind(c, adev, data);
>  			if (ret)
>  				break;
>  		}
>  
>  	if (ret != 0) {
>  		for (; i > 0; i--)
> -			if (!master->match->compare[i - 1].duplicate) {
> -				c = master->match->compare[i - 1].component;
> -				component_unbind(c, master, data);
> +			if (!adev->match->compare[i - 1].duplicate) {
> +				c = adev->match->compare[i - 1].component;
> +				component_unbind(c, adev, data);
>  			}
>  	}
>  
> @@ -675,8 +691,8 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
>  
>  	ret = try_to_bring_up_masters(component);
>  	if (ret < 0) {
> -		if (component->master)
> -			remove_component(component->master, component);
> +		if (component->adev)
> +			remove_component(component->adev, component);
>  		list_del(&component->node);
>  
>  		kfree(component);
> @@ -757,9 +773,9 @@ void component_del(struct device *dev, const struct component_ops *ops)
>  			break;
>  		}
>  
> -	if (component && component->master) {
> -		take_down_master(component->master);
> -		remove_component(component->master, component);
> +	if (component && component->adev) {
> +		take_down_aggregate_device(component->adev);
> +		remove_component(component->adev, component);
>  	}
>  
>  	mutex_unlock(&component_mutex);
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 16de18f473d7..71bfc3862633 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -41,7 +41,7 @@ void component_del(struct device *, const struct component_ops *);
>  int component_bind_all(struct device *master, void *master_data);
>  void component_unbind_all(struct device *master, void *master_data);
>  
> -struct master;
> +struct aggregate_device;
>  
>  /**
>   * struct component_master_ops - callback for the aggregate driver

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
  2021-10-06 22:42   ` kernel test robot
@ 2021-10-07  3:07   ` Saravana Kannan
  2021-10-07 18:40     ` Stephen Boyd
  2021-10-07  5:37   ` Greg Kroah-Hartman
  2 siblings, 1 reply; 60+ messages in thread
From: Saravana Kannan @ 2021-10-07  3:07 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
>
> The component driver only provides 'bind' and 'unbind' callbacks to tell
> the host driver that it is time to assemble the aggregate driver now
> that all the components have probed. The component driver model doesn't
> attempt to resolve runtime PM or suspend/resume ordering, and explicitly
> mentions this in the code. This lack of support leads to some pretty
> gnarly usages of the 'prepare' and 'complete' power management hooks in
> drivers that host the aggregate device, and it fully breaks down when
> faced with ordering shutdown between the various components, the
> aggregate driver, and the host driver that registers the whole thing.
>
> In a concrete example, the MSM display driver at drivers/gpu/drm/msm is
> using 'prepare' and 'complete' to call the drm helpers
> drm_mode_config_helper_suspend() and drm_mode_config_helper_resume()
> respectively, so that it can move the aggregate driver suspend/resume
> callbacks to be before and after the components that make up the drm
> device call any suspend/resume hooks they have. This only works as long
> as the component devices don't do anything in their own 'prepare' and
> 'complete' callbacks. If they did, then the ordering would be incorrect
> and we would be doing something in the component drivers before the
> aggregate driver could do anything. Yuck!
>
> Similarly, when trying to add shutdown support to the MSM driver we run
> across a problem where we're trying to shutdown the drm device via
> drm_atomic_helper_shutdown(), but some of the devices in the encoder
> chain have already been shutdown. This time, the component devices
> aren't the problem (although they could be if they did anything in their
> shutdown callbacks), but there's a DSI to eDP bridge in the encoder
> chain that has already been shutdown before the driver hosting the
> aggregate device runs shutdown. The ordering of driver probe is like
> this:
>
>  1. msm_pdev_probe() (host driver)
>  2. DSI bridge
>  3. aggregate bind
>
> When it comes to shutdown we have this order:
>
>  1. DSI bridge
>  2. msm_pdev_shutdown() (host driver)
>
> and so the bridge is already off, but we want to communicate to it to
> turn things off on the display during msm_pdev_shutdown(). Double yuck!
> Unfortunately, this time we can't split shutdown into multiple phases
> and swap msm_pdev_shutdown() with the DSI bridge.
>
> Let's make the component driver into an actual device driver that has
> probe/remove/shutdown functions. The driver will only be bound to the
> aggregate device once all component drivers have called component_add()
> to indicate they're ready to assemble the aggregate driver. This allows
> us to attach shutdown logic (and in the future runtime PM logic) to the
> aggregate driver so that it runs the hooks in the correct order.
>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>  drivers/base/component.c  | 454 +++++++++++++++++++++++++++-----------
>  include/linux/component.h |  62 +++++-
>  2 files changed, 381 insertions(+), 135 deletions(-)
>
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index 0a41bbe14981..d99e99cabb99 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -15,6 +15,9 @@
>  #include <linux/mutex.h>
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "base.h"
>
>  /**
>   * DOC: overview
> @@ -38,8 +41,8 @@
>   *
>   * Aggregate drivers first assemble a component match list of what they need
>   * using component_match_add(). This is then registered as an aggregate driver
> - * using component_master_add_with_match(), and unregistered using
> - * component_master_del().
> + * using component_aggregate_register(), and unregistered using
> + * component_aggregate_unregister().
>   */
>
>  struct component;
> @@ -60,17 +63,20 @@ struct component_match {
>  };
>
>  struct aggregate_device {
> -       struct list_head node;
> -       bool bound;
> -
>         const struct component_master_ops *ops;
>         struct device *parent;
>         struct device dev;
>         struct component_match *match;
> +       struct aggregate_driver *adrv;
>
>         int id;
>  };
>
> +static inline struct aggregate_device *to_aggregate_device(struct device *d)
> +{
> +       return container_of(d, struct aggregate_device, dev);
> +}
> +
>  struct component {
>         struct list_head node;
>         struct aggregate_device *adev;
> @@ -79,11 +85,11 @@ struct component {
>         const struct component_ops *ops;
>         int subcomponent;
>         struct device *dev;
> +       struct device_link *link;
>  };
>
>  static DEFINE_MUTEX(component_mutex);
>  static LIST_HEAD(component_list);
> -static LIST_HEAD(aggregate_devices);
>
>  static DEFINE_IDA(aggregate_ida);
>
> @@ -101,7 +107,7 @@ static int component_devices_show(struct seq_file *s, void *data)
>         seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
>         seq_puts(s, "-------------------------------------------------------------\n");
>         seq_printf(s, "%-40s %20s\n\n",
> -                  dev_name(m->parent), m->bound ? "bound" : "not bound");
> +                  dev_name(m->parent), m->dev.driver ? "bound" : "not bound");
>
>         seq_printf(s, "%-40s %20s\n", "device name", "status");
>         seq_puts(s, "-------------------------------------------------------------\n");
> @@ -149,16 +155,21 @@ static void component_master_debugfs_del(struct aggregate_device *m)
>
>  #endif
>
> -static struct aggregate_device *__aggregate_find(struct device *parent,
> -       const struct component_master_ops *ops)
> +struct aggregate_bus_find_data {
> +       const struct component_master_ops *ops;
> +       struct device *parent;
> +};
> +
> +static int aggregate_bus_find_match(struct device *dev, const void *_data)
>  {
> -       struct aggregate_device *m;
> +       struct aggregate_device *adev = to_aggregate_device(dev);
> +       const struct aggregate_bus_find_data *data = _data;
>
> -       list_for_each_entry(m, &aggregate_devices, node)
> -               if (m->parent == parent && (!ops || m->ops == ops))
> -                       return m;
> +       if (adev->parent == data->parent &&
> +           (!data->ops || adev->ops == data->ops))
> +               return 1;
>
> -       return NULL;
> +       return 0;
>  }
>
>  static struct component *find_component(struct aggregate_device *adev,
> @@ -185,7 +196,6 @@ static int find_components(struct aggregate_device *adev)
>  {
>         struct component_match *match = adev->match;
>         size_t i;
> -       int ret = 0;
>
>         /*
>          * Scan the array of match functions and attach
> @@ -194,6 +204,7 @@ static int find_components(struct aggregate_device *adev)
>         for (i = 0; i < match->num; i++) {
>                 struct component_match_array *mc = &match->compare[i];
>                 struct component *c;
> +               bool duplicate;
>
>                 dev_dbg(adev->parent, "Looking for component %zu\n", i);
>
> @@ -201,20 +212,27 @@ static int find_components(struct aggregate_device *adev)
>                         continue;
>
>                 c = find_component(adev, mc);
> -               if (!c) {
> -                       ret = -ENXIO;
> -                       break;
> -               }
> +               if (!c)
> +                       return 0;
>
> +               duplicate = !!c->adev;
>                 dev_dbg(adev->parent, "found component %s, duplicate %u\n",
> -                       dev_name(c->dev), !!c->adev);
> +                       dev_name(c->dev), duplicate);
>
>                 /* Attach this component to the adev */
> -               match->compare[i].duplicate = !!c->adev;
> +               match->compare[i].duplicate = duplicate;
>                 match->compare[i].component = c;
> +               if (duplicate)
> +                       continue;
> +
> +               /* Matches put in component_del() */
> +               get_device(&adev->dev);
> +               c->link = device_link_add(&adev->dev, c->dev,
> +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);

Remove the STATELESS flag and you'll get a bunch of other stuff done for free:
1. The aggregate device would get force unbound when the component
devices unbind.
2. You don't need to explicitly keep track of and delete the link. If
either of the devices get deleted, it'll get deleted automatically.
3. It will avoid useless probe attempts of the aggregate device before
all the component devices are probed.

-Saravana

>                 c->adev = adev;
>         }
> -       return ret;
> +
> +       return 1;
>  }
>
>  /* Detach component from associated aggregate_device */
> @@ -228,72 +246,6 @@ static void remove_component(struct aggregate_device *adev, struct component *c)
>                         adev->match->compare[i].component = NULL;
>  }
>
> -/*
> - * Try to bring up an aggregate device.  If component is NULL, we're interested
> - * in this aggregate device, otherwise it's a component which must be present
> - * to try and bring up the aggregate device.
> - *
> - * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
> - */
> -static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
> -       struct component *component)
> -{
> -       int ret;
> -
> -       dev_dbg(adev->parent, "trying to bring up adev\n");
> -
> -       if (find_components(adev)) {
> -               dev_dbg(adev->parent, "master has incomplete components\n");
> -               return 0;
> -       }
> -
> -       if (component && component->adev != adev) {
> -               dev_dbg(adev->parent, "master is not for this component (%s)\n",
> -                       dev_name(component->dev));
> -               return 0;
> -       }
> -
> -       if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
> -               return -ENOMEM;
> -
> -       /* Found all components */
> -       ret = adev->ops->bind(adev->parent);
> -       if (ret < 0) {
> -               devres_release_group(adev->parent, NULL);
> -               if (ret != -EPROBE_DEFER)
> -                       dev_info(adev->parent, "adev bind failed: %d\n", ret);
> -               return ret;
> -       }
> -
> -       adev->bound = true;
> -       return 1;
> -}
> -
> -static int try_to_bring_up_masters(struct component *component)
> -{
> -       struct aggregate_device *adev;
> -       int ret = 0;
> -
> -       list_for_each_entry(adev, &aggregate_devices, node) {
> -               if (!adev->bound) {
> -                       ret = try_to_bring_up_aggregate_device(adev, component);
> -                       if (ret != 0)
> -                               break;
> -               }
> -       }
> -
> -       return ret;
> -}
> -
> -static void take_down_aggregate_device(struct aggregate_device *adev)
> -{
> -       if (adev->bound) {
> -               adev->ops->unbind(adev->parent);
> -               devres_release_group(adev->parent, NULL);
> -               adev->bound = false;
> -       }
> -}
> -
>  static void devm_component_match_release(struct device *parent, void *res)
>  {
>         struct component_match *match = res;
> @@ -437,7 +389,6 @@ static void free_aggregate_device(struct aggregate_device *adev)
>         int i;
>
>         component_master_debugfs_del(adev);
> -       list_del(&adev->node);
>
>         if (match) {
>                 for (i = 0; i < match->num; i++) {
> @@ -451,20 +402,143 @@ static void free_aggregate_device(struct aggregate_device *adev)
>         kfree(adev);
>  }
>
> -/**
> - * component_master_add_with_match - register an aggregate driver
> - * @parent: parent device of the aggregate driver
> - * @ops: callbacks for the aggregate driver
> - * @match: component match list for the aggregate driver
> - *
> - * Registers a new aggregate driver consisting of the components added to @match
> - * by calling one of the component_match_add() functions. Once all components in
> - * @match are available, it will be assembled by calling
> - * &component_master_ops.bind from @ops. Must be unregistered by calling
> - * component_master_del().
> - */
> -int component_master_add_with_match(struct device *parent,
> -       const struct component_master_ops *ops,
> +static void aggregate_device_release(struct device *dev)
> +{
> +       struct aggregate_device *adev = to_aggregate_device(dev);
> +
> +       free_aggregate_device(adev);
> +}
> +
> +static int aggregate_device_match(struct device *dev, struct device_driver *drv)
> +{
> +       const struct aggregate_driver *adrv = to_aggregate_driver(drv);
> +       struct aggregate_device *adev = to_aggregate_device(dev);
> +       int ret;
> +
> +       /* Is this driver associated with this device */
> +       if (adrv != adev->adrv)
> +               return 0;
> +
> +       /* Should we start to assemble? */
> +       mutex_lock(&component_mutex);
> +       ret = find_components(adev);
> +       mutex_unlock(&component_mutex);
> +
> +       return ret;
> +}
> +
> +/* TODO: Remove once all aggregate drivers use component_aggregate_register() */
> +static int component_probe_bind(struct aggregate_device *adev)
> +{
> +       return adev->ops->bind(adev->parent);
> +}
> +
> +static void component_remove_unbind(struct aggregate_device *adev)
> +{
> +       adev->ops->unbind(adev->parent);
> +}
> +
> +static int aggregate_driver_probe(struct device *dev)
> +{
> +       const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
> +       struct aggregate_device *adev = to_aggregate_device(dev);
> +       bool modern = adrv->probe != component_probe_bind;
> +       int ret;
> +
> +       /* Only do runtime PM when drivers migrate */
> +       if (modern) {
> +               pm_runtime_get_noresume(dev);
> +               pm_runtime_set_active(dev);
> +               pm_runtime_enable(dev);
> +       }
> +
> +       mutex_lock(&component_mutex);
> +       if (devres_open_group(adev->parent, NULL, GFP_KERNEL)) {
> +               ret = adrv->probe(adev);
> +               if (ret)
> +                       devres_release_group(adev->parent, NULL);
> +       } else {
> +               ret = -ENOMEM;
> +       }
> +       mutex_unlock(&component_mutex);
> +
> +       if (ret && modern) {
> +               pm_runtime_disable(dev);
> +               pm_runtime_set_suspended(dev);
> +               pm_runtime_put_noidle(dev);
> +       }
> +
> +       return ret;
> +}
> +
> +static int aggregate_driver_remove(struct device *dev)
> +{
> +       const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
> +       struct aggregate_device *adev = to_aggregate_device(dev);
> +       bool modern = adrv->remove != component_remove_unbind;
> +
> +       /* Only do runtime PM when drivers migrate */
> +       if (modern)
> +               pm_runtime_get_sync(dev);
> +       adrv->remove(to_aggregate_device(dev));
> +       devres_release_group(adev->parent, NULL);
> +       if (!modern)
> +               return 0;
> +
> +       pm_runtime_put_noidle(dev);
> +
> +       pm_runtime_disable(dev);
> +       pm_runtime_set_suspended(dev);
> +       pm_runtime_put_noidle(dev);
> +
> +       return 0;
> +}
> +
> +static void aggregate_driver_shutdown(struct device *dev)
> +{
> +       const struct aggregate_driver *adrv = to_aggregate_driver(dev->driver);
> +
> +       if (adrv && adrv->shutdown)
> +               adrv->shutdown(to_aggregate_device(dev));
> +}
> +
> +static struct bus_type aggregate_bus_type = {
> +       .name           = "aggregate",
> +       .match          = aggregate_device_match,
> +       .probe          = aggregate_driver_probe,
> +       .remove         = aggregate_driver_remove,
> +       .shutdown       = aggregate_driver_shutdown,
> +};
> +
> +/* Callers take ownership of return value, should call put_device() */
> +static struct aggregate_device *__aggregate_find(struct device *parent,
> +       const struct component_master_ops *ops)
> +{
> +       struct device *dev;
> +       struct aggregate_bus_find_data data = {
> +               .ops = ops,
> +               .parent = parent,
> +       };
> +
> +       dev = bus_find_device(&aggregate_bus_type, NULL, &data,
> +                             aggregate_bus_find_match);
> +
> +       return dev ? to_aggregate_device(dev) : NULL;
> +}
> +
> +static int aggregate_driver_register(struct aggregate_driver *adrv)
> +{
> +       adrv->driver.bus = &aggregate_bus_type;
> +       return driver_register(&adrv->driver);
> +}
> +
> +static void aggregate_driver_unregister(struct aggregate_driver *adrv)
> +{
> +       driver_unregister(&adrv->driver);
> +}
> +
> +static struct aggregate_device *aggregate_device_add(struct device *parent,
> +       const struct component_master_ops *ops, struct aggregate_driver *adrv,
>         struct component_match *match)
>  {
>         struct aggregate_device *adev;
> @@ -473,40 +547,114 @@ int component_master_add_with_match(struct device *parent,
>         /* Reallocate the match array for its true size */
>         ret = component_match_realloc(match, match->num);
>         if (ret)
> -               return ret;
> +               return ERR_PTR(ret);
>
>         adev = kzalloc(sizeof(*adev), GFP_KERNEL);
>         if (!adev)
> -               return -ENOMEM;
> +               return ERR_PTR(-ENOMEM);
>
>         id = ida_alloc(&aggregate_ida, GFP_KERNEL);
>         if (id < 0) {
>                 kfree(adev);
> -               return id;
> +               return ERR_PTR(id);
>         }
>
>         adev->id = id;
>         adev->parent = parent;
> +       adev->dev.bus = &aggregate_bus_type;
> +       adev->dev.release = aggregate_device_release;
>         adev->ops = ops;
>         adev->match = match;
> +       adev->adrv = adrv;
>         dev_set_name(&adev->dev, "aggregate%d", id);
>
> +       ret = device_register(&adev->dev);
> +       if (ret) {
> +               put_device(&adev->dev);
> +               return ERR_PTR(ret);
> +       }
> +
>         component_master_debugfs_add(adev);
> -       /* Add to the list of available aggregate devices. */
> -       mutex_lock(&component_mutex);
> -       list_add(&adev->node, &aggregate_devices);
>
> -       ret = try_to_bring_up_aggregate_device(adev, NULL);
> +       return adev;
> +}
> +
> +/**
> + * component_master_add_with_match - register an aggregate driver
> + * @parent: parent device of the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + * @match: component match list for the aggregate driver
> + *
> + * Registers a new aggregate driver consisting of the components added to @match
> + * by calling one of the component_match_add() functions. Once all components in
> + * @match are available, it will be assembled by calling
> + * &component_master_ops.bind from @ops. Must be unregistered by calling
> + * component_master_del().
> + *
> + * Deprecated: Use component_aggregate_register() instead.
> + */
> +int component_master_add_with_match(struct device *parent,
> +       const struct component_master_ops *ops,
> +       struct component_match *match)
> +{
> +       struct aggregate_driver *adrv;
> +       struct aggregate_device *adev;
> +       int ret = 0;
> +
> +       adrv = kzalloc(sizeof(*adrv), GFP_KERNEL);
> +       if (!adrv)
> +               return -ENOMEM;
>
> -       if (ret < 0)
> -               free_aggregate_device(adev);
> +       adev = aggregate_device_add(parent, ops, adrv, match);
> +       if (IS_ERR(adev)) {
> +               ret = PTR_ERR(adev);
> +               goto err;
> +       }
>
> -       mutex_unlock(&component_mutex);
> +       adrv->probe = component_probe_bind;
> +       adrv->remove = component_remove_unbind;
> +       adrv->driver.owner = THIS_MODULE;
> +       adrv->driver.name = dev_name(&adev->dev);
> +
> +       ret = aggregate_driver_register(adrv);
> +       if (!ret)
> +               return 0;
>
> -       return ret < 0 ? ret : 0;
> +       put_device(&adev->dev);
> +err:
> +       kfree(adrv);
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(component_master_add_with_match);
>
> +/**
> + * component_aggregate_register - register an aggregate driver
> + * @parent: parent device of the aggregate driver
> + * @adrv: aggregate driver to register
> + *
> + * Registers a new aggregate driver consisting of the components added to @adrv.match
> + * by calling one of the component_match_add() functions. Once all components in
> + * @match are available, the aggregate driver will be assembled by calling
> + * &adrv.bind. Must be unregistered by calling component_aggregate_unregister().
> + */
> +int component_aggregate_register(struct device *parent,
> +       struct aggregate_driver *adrv, struct component_match *match)
> +{
> +       struct aggregate_device *adev;
> +       int ret;
> +
> +       adev = aggregate_device_add(parent, NULL, adrv, match);
> +       if (IS_ERR(adev))
> +               return PTR_ERR(adev);
> +
> +       ret = aggregate_driver_register(adrv);
> +       if (ret)
> +               put_device(&adev->dev);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(component_aggregate_register);
> +
>  /**
>   * component_master_del - unregister an aggregate driver
>   * @parent: parent device of the aggregate driver
> @@ -515,22 +663,60 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
>   * Unregisters an aggregate driver registered with
>   * component_master_add_with_match(). If necessary the aggregate driver is first
>   * disassembled by calling &component_master_ops.unbind from @ops.
> + *
> + * Deprecated: Use component_aggregate_unregister() instead.
>   */
>  void component_master_del(struct device *parent,
>         const struct component_master_ops *ops)
>  {
>         struct aggregate_device *adev;
> +       struct aggregate_driver *adrv;
> +       struct device_driver *drv;
>
>         mutex_lock(&component_mutex);
>         adev = __aggregate_find(parent, ops);
> +       mutex_unlock(&component_mutex);
> +
>         if (adev) {
> -               take_down_aggregate_device(adev);
> -               free_aggregate_device(adev);
> +               drv = adev->dev.driver;
> +               if (drv) {
> +                       adrv = to_aggregate_driver(drv);
> +                       aggregate_driver_unregister(adrv);
> +                       kfree(adrv);
> +               }
> +
> +               device_unregister(&adev->dev);
>         }
> -       mutex_unlock(&component_mutex);
> +       put_device(&adev->dev);
>  }
>  EXPORT_SYMBOL_GPL(component_master_del);
>
> +/**
> + * component_aggregate_unregister - unregister an aggregate driver
> + * @parent: parent device of the aggregate driver
> + * @adrv: registered aggregate driver
> + *
> + * Unregisters an aggregate driver registered with
> + * component_aggregate_register(). If necessary the aggregate driver is first
> + * disassembled.
> + */
> +void component_aggregate_unregister(struct device *parent,
> +       struct aggregate_driver *adrv)
> +{
> +       struct aggregate_device *adev;
> +
> +       mutex_lock(&component_mutex);
> +       adev = __aggregate_find(parent, NULL);
> +       mutex_unlock(&component_mutex);
> +
> +       if (adev)
> +               device_unregister(&adev->dev);
> +       put_device(&adev->dev);
> +
> +       aggregate_driver_unregister(adrv);
> +}
> +EXPORT_SYMBOL_GPL(component_aggregate_unregister);
> +
>  static void component_unbind(struct component *component,
>         struct aggregate_device *adev, void *data)
>  {
> @@ -571,6 +757,8 @@ void component_unbind_all(struct device *parent, void *data)
>                         c = adev->match->compare[i].component;
>                         component_unbind(c, adev, data);
>                 }
> +
> +       put_device(&adev->dev);
>  }
>  EXPORT_SYMBOL_GPL(component_unbind_all);
>
> @@ -665,6 +853,7 @@ int component_bind_all(struct device *parent, void *data)
>                                 component_unbind(c, adev, data);
>                         }
>         }
> +       put_device(&adev->dev);
>
>         return ret;
>  }
> @@ -674,7 +863,6 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
>         int subcomponent)
>  {
>         struct component *component;
> -       int ret;
>
>         component = kzalloc(sizeof(*component), GFP_KERNEL);
>         if (!component)
> @@ -688,18 +876,10 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
>
>         mutex_lock(&component_mutex);
>         list_add_tail(&component->node, &component_list);
> -
> -       ret = try_to_bring_up_masters(component);
> -       if (ret < 0) {
> -               if (component->adev)
> -                       remove_component(component->adev, component);
> -               list_del(&component->node);
> -
> -               kfree(component);
> -       }
>         mutex_unlock(&component_mutex);
>
> -       return ret < 0 ? ret : 0;
> +       /* Try to bind */
> +       return bus_rescan_devices(&aggregate_bus_type);
>  }
>
>  /**
> @@ -763,6 +943,7 @@ EXPORT_SYMBOL_GPL(component_add);
>   */
>  void component_del(struct device *dev, const struct component_ops *ops)
>  {
> +       struct aggregate_device *adev = NULL;
>         struct component *c, *component = NULL;
>
>         mutex_lock(&component_mutex);
> @@ -774,13 +955,26 @@ void component_del(struct device *dev, const struct component_ops *ops)
>                 }
>
>         if (component && component->adev) {
> -               take_down_aggregate_device(component->adev);
> -               remove_component(component->adev, component);
> +               adev = component->adev;
> +               remove_component(adev, component);
>         }
>
>         mutex_unlock(&component_mutex);
>
> +       if (adev) {
> +               /* Force unbind */
> +               device_driver_detach(&adev->dev);
> +               device_link_del(component->link);
> +               put_device(&adev->dev);
> +       }
> +
>         WARN_ON(!component);
>         kfree(component);
>  }
>  EXPORT_SYMBOL_GPL(component_del);
> +
> +static int __init aggregate_bus_init(void)
> +{
> +       return bus_register(&aggregate_bus_type);
> +}
> +postcore_initcall(aggregate_bus_init);
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 71bfc3862633..95d1b23ede8a 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -3,9 +3,7 @@
>  #define COMPONENT_H
>
>  #include <linux/stddef.h>
> -
> -
> -struct device;
> +#include <linux/device.h>
>
>  /**
>   * struct component_ops - callbacks for component drivers
> @@ -82,11 +80,65 @@ struct component_master_ops {
>         void (*unbind)(struct device *master);
>  };
>
> +struct component_match;
> +
> +/**
> + * struct aggregate_driver - Aggregate driver (made up of other drivers)
> + * @driver: device driver
> + * @match: component match list
> + */
> +struct aggregate_driver {
> +       /**
> +        * @probe:
> +        *
> +        * Called when all components or the aggregate driver, as specified in
> +        * the @match list are
> +        * ready. Usually there are 3 steps to bind an aggregate driver:
> +        *
> +        * 1. Allocate a struct aggregate_driver.
> +        *
> +        * 2. Bind all components to the aggregate driver by calling
> +        *    component_bind_all() with the aggregate driver structure as opaque
> +        *    pointer data.
> +        *
> +        * 3. Register the aggregate driver with the subsystem to publish its
> +        *    interfaces.
> +        */
> +       int (*probe)(struct aggregate_device *adev);
> +       /**
> +        * @remove:
> +        *
> +        * Called when either the aggregate driver, using
> +        * component_aggregate_unregister(), or one of its components, using
> +        * component_del(), is unregistered.
> +        */
> +       void (*remove)(struct aggregate_device *adev);
> +       /**
> +        * @shutdown:
> +        *
> +        * Called when the system is shutting down.
> +        */
> +       void (*shutdown)(struct aggregate_device *adev);
> +
> +       struct device_driver    driver;
> +};
> +
> +static inline struct aggregate_driver *to_aggregate_driver(struct device_driver *d)
> +{
> +       if (!d)
> +               return NULL;
> +
> +       return container_of(d, struct aggregate_driver, driver);
> +}
> +
> +int component_aggregate_register(struct device *parent,
> +       struct aggregate_driver *adrv, struct component_match *match);
> +void component_aggregate_unregister(struct device *parent,
> +       struct aggregate_driver *adrv);
> +
>  void component_master_del(struct device *,
>         const struct component_master_ops *);
>
> -struct component_match;
> -
>  int component_master_add_with_match(struct device *,
>         const struct component_master_ops *, struct component_match *);
>  void component_match_add_release(struct device *master,
> --
> https://chromeos.dev
>

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
  2021-10-06 22:42   ` kernel test robot
  2021-10-07  3:07   ` Saravana Kannan
@ 2021-10-07  5:37   ` Greg Kroah-Hartman
  2021-10-07 20:42     ` Stephen Boyd
  2 siblings, 1 reply; 60+ messages in thread
From: Greg Kroah-Hartman @ 2021-10-07  5:37 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

On Wed, Oct 06, 2021 at 12:37:47PM -0700, Stephen Boyd wrote:
> The component driver only provides 'bind' and 'unbind' callbacks to tell
> the host driver that it is time to assemble the aggregate driver now
> that all the components have probed. The component driver model doesn't
> attempt to resolve runtime PM or suspend/resume ordering, and explicitly
> mentions this in the code. This lack of support leads to some pretty
> gnarly usages of the 'prepare' and 'complete' power management hooks in
> drivers that host the aggregate device, and it fully breaks down when
> faced with ordering shutdown between the various components, the
> aggregate driver, and the host driver that registers the whole thing.
> 
> In a concrete example, the MSM display driver at drivers/gpu/drm/msm is
> using 'prepare' and 'complete' to call the drm helpers
> drm_mode_config_helper_suspend() and drm_mode_config_helper_resume()
> respectively, so that it can move the aggregate driver suspend/resume
> callbacks to be before and after the components that make up the drm
> device call any suspend/resume hooks they have. This only works as long
> as the component devices don't do anything in their own 'prepare' and
> 'complete' callbacks. If they did, then the ordering would be incorrect
> and we would be doing something in the component drivers before the
> aggregate driver could do anything. Yuck!
> 
> Similarly, when trying to add shutdown support to the MSM driver we run
> across a problem where we're trying to shutdown the drm device via
> drm_atomic_helper_shutdown(), but some of the devices in the encoder
> chain have already been shutdown. This time, the component devices
> aren't the problem (although they could be if they did anything in their
> shutdown callbacks), but there's a DSI to eDP bridge in the encoder
> chain that has already been shutdown before the driver hosting the
> aggregate device runs shutdown. The ordering of driver probe is like
> this:
> 
>  1. msm_pdev_probe() (host driver)
>  2. DSI bridge
>  3. aggregate bind
> 
> When it comes to shutdown we have this order:
> 
>  1. DSI bridge
>  2. msm_pdev_shutdown() (host driver)
> 
> and so the bridge is already off, but we want to communicate to it to
> turn things off on the display during msm_pdev_shutdown(). Double yuck!
> Unfortunately, this time we can't split shutdown into multiple phases
> and swap msm_pdev_shutdown() with the DSI bridge.
> 
> Let's make the component driver into an actual device driver that has
> probe/remove/shutdown functions. The driver will only be bound to the
> aggregate device once all component drivers have called component_add()
> to indicate they're ready to assemble the aggregate driver. This allows
> us to attach shutdown logic (and in the future runtime PM logic) to the
> aggregate driver so that it runs the hooks in the correct order.

Why are you creating a new bus type and not using the auxiliary bus
instead?

You have seen Documentation/driver-api/auxiliary_bus.rst, right?

thanks,

greg k-h

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

* Re: [PATCH v2 00/34] component: Make into an aggregate bus
  2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
                   ` (33 preceding siblings ...)
  2021-10-06 19:38 ` [PATCH v2 34/34] component: Remove all references to 'master' Stephen Boyd
@ 2021-10-07 10:16 ` Andrzej Hajda
  2021-10-07 20:46   ` Stephen Boyd
       [not found] ` <CAHp75VdLg-rBjCDGEwgkY6QDbFGW0of4SjSmp08FXXRN_raQtQ@mail.gmail.com>
  35 siblings, 1 reply; 60+ messages in thread
From: Andrzej Hajda @ 2021-10-07 10:16 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Arnd Bergmann,
	Benjamin Gaignard, Chen Feng, Chen-Yu Tsai, Christian Gmeiner,
	Chun-Kuang Hu, Daniel Vetter, Emma Anholt, Heiko Stübner,
	Inki Dae, James Qian Wang, Jaroslav Kysela, Joerg Roedel,
	John Stultz, Joonyoung Shim, Jyri Sarha, Kai Vehmanen,
	Kyungmin Park, Laurent Pinchart, linux-fbdev, linux-omap,
	linux-pm, Liviu Dudau, Lucas Stach, Mark Brown, Maxime Ripard,
	Neil Armstrong, Paul Cercueil, Philipp Zabel, Rafael J. Wysocki,
	Rob Clark, Russell King, Russell King, Russell King, Sandy Huang,
	Saravana Kannan, Sebastian Reichel, Seung-Woo Kim, Takashi Iwai,
	Tian Tao, Tomas Winkler, Tomi Valkeinen, Will Deacon,
	Xinliang Liu, Xinwei Kong, Yong Wu

Hi Stephen,

On 06.10.2021 21:37, Stephen Boyd wrote:
> This series is from discussion we had on reordering the device lists for
> drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put
> the aggregate device onto and then we probe the aggregate device once
> all the components are probed and call component_add(). The probe/remove
> hooks are where the bind/unbind calls go, and then a shutdown hook is
> added that can be used to shutdown the drm display pipeline at the right
> time.
> 
> This works for me on my sc7180 board. I no longer get a warning from i2c
> at shutdown that we're trying to make an i2c transaction after the i2c
> bus has been shutdown. There's more work to do on the msm drm driver to
> extract component device resources like clks, regulators, etc. out of
> the component bind function into the driver probe but I wanted to move
> everything over now in other component drivers before tackling that
> problem.


As I understand you have DSI host with i2c-controlled DSI bridge. And 
there is an issue that bridge is shutdown before msmdrm. Your solution 
is to 'adjust' device order on pm list.
I had similar issue and solved it locally by adding notification from 
DSI bridge to DSI host that is has to be removed: mipi_dsi_detach, this 
notification escalates in DSI host to component_del and this allow to 
react properly.

Advantages:
- it is local (only involves DSI host and DSI device),
- it does not depend on PM internals,
- it can be used in other scenarios as well - unbinding DSI device driver

Disadvantage:
- It is DSI specific (but this is your case), I have advertised some 
time ago more general approach [1][2].

[1]: https://static.sched.com/hosted_files/osseu18/0f/deferred_problem.pdf
[2]: https://lwn.net/Articles/625454/


Regards
Andrzej

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

* Re: [PATCH v2 00/34] component: Make into an aggregate bus
       [not found] ` <CAHp75VdLg-rBjCDGEwgkY6QDbFGW0of4SjSmp08FXXRN_raQtQ@mail.gmail.com>
@ 2021-10-07 12:33   ` Andrzej Hajda
  0 siblings, 0 replies; 60+ messages in thread
From: Andrzej Hajda @ 2021-10-07 12:33 UTC (permalink / raw)
  To: Andy Shevchenko, Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Arnd Bergmann, Benjamin Gaignard, Chen Feng,
	Chen-Yu Tsai, Christian Gmeiner, Chun-Kuang Hu, Daniel Vetter,
	Emma Anholt, Heiko Stübner, Inki Dae, James Qian Wang,
	Jaroslav Kysela, Joerg Roedel, John Stultz, Joonyoung Shim,
	Jyri Sarha, Kai Vehmanen, Kyungmin Park, Laurent Pinchart,
	linux-fbdev, linux-omap, linux-pm, Liviu Dudau, Lucas Stach,
	Mark Brown, Maxime Ripard, Neil Armstrong, Paul Cercueil,
	Philipp Zabel, Rafael J. Wysocki, Rob Clark, Russell King,
	Russell King, Russell King, Sandy Huang, Saravana Kannan,
	Sebastian Reichel, Seung-Woo Kim, Takashi Iwai, Tian Tao,
	Tomas Winkler, Tomi Valkeinen, Will Deacon, Xinliang Liu,
	Xinwei Kong, Yong Wu

On 07.10.2021 13:22, Andy Shevchenko wrote:
> 
> 
> On Wednesday, October 6, 2021, Stephen Boyd <swboyd@chromium.org 
> <mailto:swboyd@chromium.org>> wrote:
> 
>     This series is from discussion we had on reordering the device lists for
>     drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put
>     the aggregate device onto and then we probe the aggregate device once
>     all the components are probed and call component_add(). The probe/remove
>     hooks are where the bind/unbind calls go, and then a shutdown hook is
>     added that can be used to shutdown the drm display pipeline at the right
>     time.
> 
>     This works for me on my sc7180 board. I no longer get a warning from i2c
>     at shutdown that we're trying to make an i2c transaction after the i2c
>     bus has been shutdown. There's more work to do on the msm drm driver to
>     extract component device resources like clks, regulators, etc. out of
>     the component bind function into the driver probe but I wanted to move
>     everything over now in other component drivers before tackling that
>     problem.
> 
>     I'll definitely be sending a v3 so this is partially a request for
>     testing to shake out any more problems. Tested-by tags would be
>     appreciated,
>     and Acked-by/Reviewed-by tags too. I sent this to gregkh which may be
>     incorrect but I don't know what better tree to send it all through.
>     Maybe drm?
> 
>     I'll be faster at resending this next time, sorry for the long delay!
> 
> 
> Yet another avoidance of mathematically proven device dependency graph...
> 
> 
> Can we actually find and ask a mathematician to look into the problem 
> and suggest real solution instead of all these ugly hacks: deferred 
> probe (ugliest hack, how it even came into kernel?), component 
> framework, custom approaches on how to see if devices are in the system 
> (ASoC hack).

Master of Science in Math is OK? :)
The solution is simple - topological sort - this is what PM device list 
does, but it is possible only if there are no circular dependencies.

And in this case we have circular dependency.
In such case the solution in case of initialization is to split it to 
two phases - probe/bind (component framework), probe/attach (DSI bus) 
and it works. But PM still relies on topological sort. To make PM 
working with circular deps you can try to extend PM somehow (maybe 
replace list of devices with list of pairs (device, phase) ??? ), or to 
add notifiers to frameworks allowing providers to informs its consumers 
about state change. The latter approach I have advertised several times, 
even on OSS.

[1]: https://static.sched.com/hosted_files/osseu18/0f/deferred_problem.pdf
[2]: https://lwn.net/Articles/625454/


Regards
Andrzej


> 
>     Changes since v1
>     (https://lore.kernel.org/r/20210520002519.3538432-1-swboyd@chromium.org
>     <https://lore.kernel.org/r/20210520002519.3538432-1-swboyd@chromium.org>):
>       - Use devlink to connect components to the aggregate device
>       - Don't set the registering device as a parent of the aggregate device
>       - New patch for bind_component/unbind_component ops that takes the
>         aggregate device
>       - Convert all drivers in the tree to use the aggregate driver approach
>       - Allow one aggregate driver to be used for multiple aggregate devices
> 
>     [1]
>     https://lore.kernel.org/r/20210508074118.1621729-1-swboyd@chromium.org
>     <https://lore.kernel.org/r/20210508074118.1621729-1-swboyd@chromium.org>
> 
>     Stephen Boyd (34):
>        component: Introduce struct aggregate_device
>        component: Introduce the aggregate bus_type
>        component: Move struct aggregate_device out to header file
>        drm/msm: Migrate to aggregate driver
>        component: Add {bind,unbind}_component() ops that take aggregate
>          device
>        drm/of: Add a drm_of_aggregate_probe() API
>        drm/komeda: Migrate to aggregate driver
>        drm/arm/hdlcd: Migrate to aggregate driver
>        drm/malidp: Migrate to aggregate driver
>        drm/armada: Migrate to aggregate driver
>        drm/etnaviv: Migrate to aggregate driver
>        drm/kirin: Migrate to aggregate driver
>        drm/exynos: Migrate to aggregate driver
>        drm/imx: Migrate to aggregate driver
>        drm/ingenic: Migrate to aggregate driver
>        drm/mcde: Migrate to aggregate driver
>        drm/mediatek: Migrate to aggregate driver
>        drm/meson: Migrate to aggregate driver
>        drm/omap: Migrate to aggregate driver
>        drm/rockchip: Migrate to aggregate driver
>        drm/sti: Migrate to aggregate driver
>        drm/sun4i: Migrate to aggregate driver
>        drm/tilcdc: Migrate to aggregate driver
>        drm/vc4: Migrate to aggregate driver
>        drm/zte: Migrate to aggregate driver
>        iommu/mtk: Migrate to aggregate driver
>        mei: Migrate to aggregate driver
>        power: supply: ab8500: Migrate to aggregate driver
>        fbdev: omap2: Migrate to aggregate driver
>        sound: hdac: Migrate to aggregate driver
>        ASoC: codecs: wcd938x: Migrate to aggregate driver
>        component: Get rid of drm_of_component_probe()
>        component: Remove component_master_ops and friends
>        component: Remove all references to 'master'
> 
>     Cc: Arnd Bergmann <arnd@arndb.de <mailto:arnd@arndb.de>>
>     Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org
>     <mailto:benjamin.gaignard@linaro.org>>
>     Cc: Chen Feng <puck.chen@hisilicon.com <mailto:puck.chen@hisilicon.com>>
>     Cc: Chen-Yu Tsai <wens@csie.org <mailto:wens@csie.org>>
>     Cc: Christian Gmeiner <christian.gmeiner@gmail.com
>     <mailto:christian.gmeiner@gmail.com>>
>     Cc: Chun-Kuang Hu <chunkuang.hu@kernel.org
>     <mailto:chunkuang.hu@kernel.org>>
>     Cc: Daniel Vetter <daniel.vetter@ffwll.ch
>     <mailto:daniel.vetter@ffwll.ch>>
>     Cc: Emma Anholt <emma@anholt.net <mailto:emma@anholt.net>>
>     Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org
>     <mailto:gregkh@linuxfoundation.org>>
>     Cc: "Heiko Stübner" <heiko@sntech.de <mailto:heiko@sntech.de>>
>     Cc: Inki Dae <inki.dae@samsung.com <mailto:inki.dae@samsung.com>>
>     Cc: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com
>     <mailto:james.qian.wang@arm.com>>
>     Cc: Jaroslav Kysela <perex@perex.cz <mailto:perex@perex.cz>>
>     Cc: Joerg Roedel <joro@8bytes.org <mailto:joro@8bytes.org>>
>     Cc: John Stultz <john.stultz@linaro.org <mailto:john.stultz@linaro.org>>
>     Cc: Joonyoung Shim <jy0922.shim@samsung.com
>     <mailto:jy0922.shim@samsung.com>>
>     Cc: Jyri Sarha <jyri.sarha@iki.fi <mailto:jyri.sarha@iki.fi>>
>     Cc: Kai Vehmanen <kai.vehmanen@linux.intel.com
>     <mailto:kai.vehmanen@linux.intel.com>>
>     Cc: Kyungmin Park <kyungmin.park@samsung.com
>     <mailto:kyungmin.park@samsung.com>>
>     Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com
>     <mailto:laurent.pinchart@ideasonboard.com>>
>     Cc: <linux-fbdev@vger.kernel.org <mailto:linux-fbdev@vger.kernel.org>>
>     Cc: <linux-omap@vger.kernel.org <mailto:linux-omap@vger.kernel.org>>
>     Cc: <linux-pm@vger.kernel.org <mailto:linux-pm@vger.kernel.org>>
>     Cc: Liviu Dudau <liviu.dudau@arm.com <mailto:liviu.dudau@arm.com>>
>     Cc: Lucas Stach <l.stach@pengutronix.de <mailto:l.stach@pengutronix.de>>
>     Cc: Mark Brown <broonie@kernel.org <mailto:broonie@kernel.org>>
>     Cc: Maxime Ripard <mripard@kernel.org <mailto:mripard@kernel.org>>
>     Cc: Neil Armstrong <narmstrong@baylibre.com
>     <mailto:narmstrong@baylibre.com>>
>     Cc: Paul Cercueil <paul@crapouillou.net <mailto:paul@crapouillou.net>>
>     Cc: Philipp Zabel <p.zabel@pengutronix.de
>     <mailto:p.zabel@pengutronix.de>>
>     Cc: "Rafael J. Wysocki" <rafael@kernel.org <mailto:rafael@kernel.org>>
>     Cc: Rob Clark <robdclark@gmail.com <mailto:robdclark@gmail.com>>
>     Cc: Russell King <linux@armlinux.org.uk <mailto:linux@armlinux.org.uk>>
>     Cc: Russell King <linux+etnaviv@armlinux.org.uk
>     <mailto:linux+etnaviv@armlinux.org.uk>>
>     Cc: Russell King <rmk+kernel@arm.linux.org.uk
>     <mailto:rmk+kernel@arm.linux.org.uk>>
>     Cc: Sandy Huang <hjc@rock-chips.com <mailto:hjc@rock-chips.com>>
>     Cc: Saravana Kannan <saravanak@google.com <mailto:saravanak@google.com>>
>     Cc: Sebastian Reichel <sre@kernel.org <mailto:sre@kernel.org>>
>     Cc: Seung-Woo Kim <sw0312.kim@samsung.com
>     <mailto:sw0312.kim@samsung.com>>
>     Cc: Takashi Iwai <tiwai@suse.com <mailto:tiwai@suse.com>>
>     Cc: Tian Tao <tiantao6@hisilicon.com <mailto:tiantao6@hisilicon.com>>
>     Cc: Tomas Winkler <tomas.winkler@intel.com
>     <mailto:tomas.winkler@intel.com>>
>     Cc: Tomi Valkeinen <tomba@kernel.org <mailto:tomba@kernel.org>>
>     Cc: Will Deacon <will@kernel.org <mailto:will@kernel.org>>
>     Cc: Xinliang Liu <xinliang.liu@linaro.org
>     <mailto:xinliang.liu@linaro.org>>
>     Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com
>     <mailto:kong.kongxinwei@hisilicon.com>>
>     Cc: Yong Wu <yong.wu@mediatek.com <mailto:yong.wu@mediatek.com>>
> 
>       drivers/base/component.c                      | 555 +++++++++++-------
>       .../gpu/drm/arm/display/komeda/komeda_drv.c   |  20 +-
>       drivers/gpu/drm/arm/hdlcd_drv.c               |  21 +-
>       drivers/gpu/drm/arm/malidp_drv.c              |  21 +-
>       drivers/gpu/drm/armada/armada_drv.c           |  23 +-
>       drivers/gpu/drm/drm_drv.c                     |   2 +-
>       drivers/gpu/drm/drm_of.c                      |  20 +-
>       drivers/gpu/drm/etnaviv/etnaviv_drv.c         |  20 +-
>       drivers/gpu/drm/exynos/exynos_drm_drv.c       |  21 +-
>       .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c   |  20 +-
>       drivers/gpu/drm/imx/imx-drm-core.c            |  20 +-
>       drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |  24 +-
>       drivers/gpu/drm/mcde/mcde_drv.c               |  23 +-
>       drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  20 +-
>       drivers/gpu/drm/meson/meson_drv.c             |  21 +-
>       drivers/gpu/drm/msm/msm_drv.c                 |  46 +-
>       drivers/gpu/drm/omapdrm/dss/dss.c             |  17 +-
>       drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |  20 +-
>       drivers/gpu/drm/sti/sti_drv.c                 |  20 +-
>       drivers/gpu/drm/sun4i/sun4i_drv.c             |  26 +-
>       drivers/gpu/drm/tilcdc/tilcdc_drv.c           |  28 +-
>       drivers/gpu/drm/vc4/vc4_drv.c                 |  20 +-
>       drivers/gpu/drm/zte/zx_drm_drv.c              |  20 +-
>       drivers/iommu/mtk_iommu.c                     |  14 +-
>       drivers/iommu/mtk_iommu.h                     |   6 +-
>       drivers/iommu/mtk_iommu_v1.c                  |  14 +-
>       drivers/misc/mei/hdcp/mei_hdcp.c              |  22 +-
>       drivers/power/supply/ab8500_charger.c         |  22 +-
>       drivers/video/fbdev/omap2/omapfb/dss/dss.c    |  20 +-
>       include/drm/drm_of.h                          |   9 +-
>       include/linux/component.h                     |  92 ++-
>       sound/hda/hdac_component.c                    |  21 +-
>       sound/soc/codecs/wcd938x.c                    |  20 +-
>       33 files changed, 780 insertions(+), 488 deletions(-)
> 
> 
>     base-commit: e4e737bb5c170df6135a127739a9e6148ee3da82
>     -- 
>     https://chromeos.dev <https://chromeos.dev>
> 
> 
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
> 


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

* Re: [PATCH v2 31/34] ASoC: codecs: wcd938x: Migrate to aggregate driver
  2021-10-06 19:38 ` [PATCH v2 31/34] ASoC: codecs: wcd938x: " Stephen Boyd
@ 2021-10-07 12:35   ` Mark Brown
  0 siblings, 0 replies; 60+ messages in thread
From: Mark Brown @ 2021-10-07 12:35 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Jaroslav Kysela, Daniel Vetter, Rafael J. Wysocki,
	Rob Clark, Russell King, Saravana Kannan

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

On Wed, Oct 06, 2021 at 12:38:16PM -0700, Stephen Boyd wrote:
> Use an aggregate driver instead of component ops so that we can get
> proper driver probe ordering of the aggregate device with respect to all
> the component devices that make up the aggregate device.

Acked-by: Mark Brown <broonie@kernel.org>

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

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

* Re: [PATCH v2 01/34] component: Introduce struct aggregate_device
  2021-10-07  1:17   ` Laurent Pinchart
@ 2021-10-07 18:36     ` Stephen Boyd
  0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-07 18:36 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Quoting Laurent Pinchart (2021-10-06 18:17:25)
> Hi Stephen,
>
> Thank you for the patch.
>
> On Wed, Oct 06, 2021 at 12:37:46PM -0700, Stephen Boyd wrote:
> > Replace 'struct master' with 'struct aggregate_device' and then rename
> > 'master' to 'adev' everywhere in the code. While we're here, put a
> > struct device inside the aggregate device so that we can register it
> > with a bus_type in the next patch.
>
> Not "while at it" please. The signal to noise ratio is very high here.
> Adding the struct device in the structure is the important change that
> needs to be properly reviewed and discussed, the rename is noise. You're
> even adding an IDA and an id without mentioning it at all in the commit
> message. This should be split in two patches, you can decide whether to
> perform the rename at the bottom or top of the series (it would be more
> logical to group all renames together though, there's currently one in
> 01/34 and one in 34/34, so please group them both at the top or bottom).

Got it. I will split the rename from this change and let things lie
until I change that line.

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-07  3:07   ` Saravana Kannan
@ 2021-10-07 18:40     ` Stephen Boyd
  2021-10-07 20:11       ` Stephen Boyd
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-07 18:40 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

Quoting Saravana Kannan (2021-10-06 20:07:11)
> On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > index 0a41bbe14981..d99e99cabb99 100644
> > --- a/drivers/base/component.c
> > +++ b/drivers/base/component.c
[...]
> > +                       continue;
> > +
> > +               /* Matches put in component_del() */
> > +               get_device(&adev->dev);
> > +               c->link = device_link_add(&adev->dev, c->dev,
> > +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
>
> Remove the STATELESS flag and you'll get a bunch of other stuff done for free:

I tried that and it didn't work for me. The aggregate device never
probed and I was left with no display. Let me see if I can reproduce it
with logging to provide more details.

> 1. The aggregate device would get force unbound when the component
> devices unbind.
> 2. You don't need to explicitly keep track of and delete the link. If
> either of the devices get deleted, it'll get deleted automatically.
> 3. It will avoid useless probe attempts of the aggregate device before
> all the component devices are probed.
>

I don't think point 3 is happening right now. We only try to probe the
aggregate device once all components probe.

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-07 18:40     ` Stephen Boyd
@ 2021-10-07 20:11       ` Stephen Boyd
  2021-10-08  1:10         ` Saravana Kannan
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-07 20:11 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

Quoting Stephen Boyd (2021-10-07 11:40:07)
> Quoting Saravana Kannan (2021-10-06 20:07:11)
> > On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > > index 0a41bbe14981..d99e99cabb99 100644
> > > --- a/drivers/base/component.c
> > > +++ b/drivers/base/component.c
> [...]
> > > +                       continue;
> > > +
> > > +               /* Matches put in component_del() */
> > > +               get_device(&adev->dev);
> > > +               c->link = device_link_add(&adev->dev, c->dev,
> > > +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
> >
> > Remove the STATELESS flag and you'll get a bunch of other stuff done for free:
>
> I tried that and it didn't work for me. The aggregate device never
> probed and I was left with no display. Let me see if I can reproduce it
> with logging to provide more details.

This patch fixes it (whitespace damaged sorry).

----8<----
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 65042c9f8a42..43cac9ed70b7 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -202,7 +202,7 @@ static int find_components(struct aggregate_device *adev)
 		/* Matches put in component_del() */
 		get_device(&adev->dev);
 		c->link = device_link_add(&adev->dev, c->dev,
-					  DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+					  DL_FLAG_PM_RUNTIME);
 		c->adev = adev;
 	}

@@ -749,7 +749,9 @@ static int __component_add(struct device *dev,
const struct component_ops *ops,
 	mutex_unlock(&component_mutex);

 	/* Try to bind */
-	return bus_rescan_devices(&aggregate_bus_type);
+	bus_rescan_devices(&aggregate_bus_type);
+
+	return 0;
 }

 /**


The important part is ignoring the return value of bus_rescan_devices().
It's a cycle problem. The last component is probing and calling
component_add() in its probe function. The call to component_add() is
trying to probe the aggregate device now that all components are added.
But when it tries to probe the aggregate device it sees that a supplier,
which is this component calling compnent_add(), hasn't been probed yet,
so it returns -EPROBE_DEFER. That is passed up to the component and it
defers probe.

I don't think the component device cares at all about the aggregate
device being able to probe or not. We should be able to ignore the
return value of bus_rescan_devices() in component_add(). I'll add a
comment to the code here so it's more obvious.

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-07  5:37   ` Greg Kroah-Hartman
@ 2021-10-07 20:42     ` Stephen Boyd
  2021-10-14 13:27       ` Daniel Vetter
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-07 20:42 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Daniel Vetter,
	Rafael J. Wysocki, Rob Clark, Russell King, Saravana Kannan

Quoting Greg Kroah-Hartman (2021-10-06 22:37:40)
> On Wed, Oct 06, 2021 at 12:37:47PM -0700, Stephen Boyd wrote:
> >
> > Let's make the component driver into an actual device driver that has
> > probe/remove/shutdown functions. The driver will only be bound to the
> > aggregate device once all component drivers have called component_add()
> > to indicate they're ready to assemble the aggregate driver. This allows
> > us to attach shutdown logic (and in the future runtime PM logic) to the
> > aggregate driver so that it runs the hooks in the correct order.
>
> Why are you creating a new bus type and not using the auxiliary bus
> instead?
>
> You have seen Documentation/driver-api/auxiliary_bus.rst, right?
>

Nope, but I read it now. Thanks for the pointer.

My read of it is that the auxiliary bus is a way to slice up a single IP
block into multiple devices and then have drivers attach to those
different "pieces" of the IP. It avoids polluting the platform bus with
devices that don't belong on the platform bus because they are sub
components of a larger IP block that sits on the platform bus.

The aggregate bus is solving the reverse problem. It is rounding up a
collection of IP blocks that live on some bus (platform, i2c, spi,
whatever) and presenting them as a single aggregate device (sound card,
display card, whatever) whenever all the component devices call
component_add(). For example, we don't want to do operations on the
entire display pipeline until all the devices that make up the display
are probed and drivers are attached. I suppose the aggregate_device in
this patch series has a 1:1 relationship with the drm class_type that
makes up /sys/class/drm/cardN but there's also a couple sound users and
a power_supply user so I don't know the equivalent there.

Long term, maybe all of this component code could be placed directly
into the driver core? That's probably even more invasive of a change but
I imagine we could make device links with component_add() as we're
already doing with these patches and then have driver core call some
class function pointer when all the links are probed. That would
handle the 'bind/probe' callback for the aggregate device but it won't
handle the component_bind_all() path where we call bind_component() for
each component device that makes up the aggregate device. Maybe we can
add even more devices for the components and then call probe there too.

Sorry that's a long-winded non-answer. I don't think they're solving the
same problem so using the same bus type looks wrong. We'd have to take
two different paths depending on what type of device it is (aggregate
vs. auxiliary) so there's not much of anything that is shared code-wise.

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

* Re: [PATCH v2 00/34] component: Make into an aggregate bus
  2021-10-07 10:16 ` [PATCH v2 00/34] component: Make into an aggregate bus Andrzej Hajda
@ 2021-10-07 20:46   ` Stephen Boyd
  2021-10-13 12:14     ` Daniel Vetter
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-07 20:46 UTC (permalink / raw)
  To: Andrzej Hajda, Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-msm, dri-devel, freedreno, Arnd Bergmann,
	Benjamin Gaignard, Chen Feng, Chen-Yu Tsai, Christian Gmeiner,
	Chun-Kuang Hu, Daniel Vetter, Emma Anholt, Heiko Stübner,
	Inki Dae, James Qian Wang, Jaroslav Kysela, Joerg Roedel,
	John Stultz, Joonyoung Shim, Jyri Sarha, Kai Vehmanen,
	Kyungmin Park, Laurent Pinchart, linux-fbdev, linux-omap,
	linux-pm, Liviu Dudau, Lucas Stach, Mark Brown, Maxime Ripard,
	Neil Armstrong, Paul Cercueil, Philipp Zabel, Rafael J. Wysocki,
	Rob Clark, Russell King, Russell King, Russell King, Sandy Huang,
	Saravana Kannan, Sebastian Reichel, Seung-Woo Kim, Takashi Iwai,
	Tian Tao, Tomas Winkler, Tomi Valkeinen, Will Deacon,
	Xinliang Liu, Xinwei Kong, Yong Wu

Quoting Andrzej Hajda (2021-10-07 03:16:27)
> Hi Stephen,
>
> On 06.10.2021 21:37, Stephen Boyd wrote:
> > This series is from discussion we had on reordering the device lists for
> > drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put
> > the aggregate device onto and then we probe the aggregate device once
> > all the components are probed and call component_add(). The probe/remove
> > hooks are where the bind/unbind calls go, and then a shutdown hook is
> > added that can be used to shutdown the drm display pipeline at the right
> > time.
> >
> > This works for me on my sc7180 board. I no longer get a warning from i2c
> > at shutdown that we're trying to make an i2c transaction after the i2c
> > bus has been shutdown. There's more work to do on the msm drm driver to
> > extract component device resources like clks, regulators, etc. out of
> > the component bind function into the driver probe but I wanted to move
> > everything over now in other component drivers before tackling that
> > problem.
>
>
> As I understand you have DSI host with i2c-controlled DSI bridge. And
> there is an issue that bridge is shutdown before msmdrm. Your solution
> is to 'adjust' device order on pm list.
> I had similar issue and solved it locally by adding notification from
> DSI bridge to DSI host that is has to be removed: mipi_dsi_detach, this
> notification escalates in DSI host to component_del and this allow to
> react properly.
>
> Advantages:
> - it is local (only involves DSI host and DSI device),
> - it does not depend on PM internals,
> - it can be used in other scenarios as well - unbinding DSI device driver
>
> Disadvantage:
> - It is DSI specific (but this is your case), I have advertised some
> time ago more general approach [1][2].
>
> [1]: https://static.sched.com/hosted_files/osseu18/0f/deferred_problem.pdf
> [2]: https://lwn.net/Articles/625454/
>

I think these are all points for or against using the component code in
general? Maybe you can send patches that you think can solve the problem
I'm experiencing and we can review them on the list.

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

* Re: [PATCH v2 15/34] drm/ingenic: Migrate to aggregate driver
  2021-10-06 19:38 ` [PATCH v2 15/34] drm/ingenic: " Stephen Boyd
@ 2021-10-07 21:29   ` Paul Cercueil
  0 siblings, 0 replies; 60+ messages in thread
From: Paul Cercueil @ 2021-10-07 21:29 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Hi Stephen,

Le mer., oct. 6 2021 at 12:38:00 -0700, Stephen Boyd 
<swboyd@chromium.org> a écrit :
> Use an aggregate driver instead of component ops so that we can get
> proper driver probe ordering of the aggregate device with respect to 
> all
> the component devices that make up the aggregate device.
> 
> TODO: Move the helpers to PM in aggregate driver hooks.
> 
> Cc: Paul Cercueil <paul@crapouillou.net>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>  drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 24 
> +++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
> b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> index a5df1c8d34cd..058b7bfe5610 100644
> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> @@ -1150,8 +1150,10 @@ static int ingenic_drm_bind(struct device 
> *dev, bool has_components)
>  	return ret;
>  }
> 
> -static int ingenic_drm_bind_with_components(struct device *dev)
> +static int ingenic_drm_bind_with_components(struct aggregate_device 
> *adev)
>  {
> +	struct device *dev = adev->parent;
> +
>  	return ingenic_drm_bind(dev, true);
>  }
> 
> @@ -1174,9 +1176,19 @@ static void ingenic_drm_unbind(struct device 
> *dev)
>  	drm_atomic_helper_shutdown(&priv->drm);
>  }
> 
> -static const struct component_master_ops ingenic_master_ops = {
> -	.bind = ingenic_drm_bind_with_components,
> -	.unbind = ingenic_drm_unbind,
> +static void ingenic_aggregate_remove(struct aggregate_device *adev)
> +{
> +	struct device *dev = adev->parent;

Space here.

With that:

Acked-by: Paul Cercueil <paul@crapouillou.net>

Cheers,
-Paul

> +	ingenic_drm_unbind(dev);
> +}
> +
> +static struct aggregate_driver ingenic_aggregate_driver = {
> +	.probe = ingenic_drm_bind_with_components,
> +	.remove = ingenic_aggregate_remove,
> +	.driver = {
> +		.name = "ingenic_drm",
> +		.owner = THIS_MODULE,
> +	},
>  };
> 
>  static int ingenic_drm_probe(struct platform_device *pdev)
> @@ -1196,7 +1208,7 @@ static int ingenic_drm_probe(struct 
> platform_device *pdev)
>  	drm_of_component_match_add(dev, &match, compare_of, np);
>  	of_node_put(np);
> 
> -	return component_master_add_with_match(dev, &ingenic_master_ops, 
> match);
> +	return component_aggregate_register(dev, &ingenic_aggregate_driver, 
> match);
>  }
> 
>  static int ingenic_drm_remove(struct platform_device *pdev)
> @@ -1206,7 +1218,7 @@ static int ingenic_drm_remove(struct 
> platform_device *pdev)
>  	if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
>  		ingenic_drm_unbind(dev);
>  	else
> -		component_master_del(dev, &ingenic_master_ops);
> +		component_aggregate_unregister(dev, &ingenic_aggregate_driver);
> 
>  	return 0;
>  }
> --
> https://chromeos.dev
> 



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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-07 20:11       ` Stephen Boyd
@ 2021-10-08  1:10         ` Saravana Kannan
  2021-10-08  1:24           ` Stephen Boyd
  0 siblings, 1 reply; 60+ messages in thread
From: Saravana Kannan @ 2021-10-08  1:10 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

On Thu, Oct 7, 2021 at 1:11 PM Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Stephen Boyd (2021-10-07 11:40:07)
> > Quoting Saravana Kannan (2021-10-06 20:07:11)
> > > On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > > > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > > > index 0a41bbe14981..d99e99cabb99 100644
> > > > --- a/drivers/base/component.c
> > > > +++ b/drivers/base/component.c
> > [...]
> > > > +                       continue;
> > > > +
> > > > +               /* Matches put in component_del() */
> > > > +               get_device(&adev->dev);
> > > > +               c->link = device_link_add(&adev->dev, c->dev,
> > > > +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
> > >
> > > Remove the STATELESS flag and you'll get a bunch of other stuff done for free:
> >
> > I tried that and it didn't work for me. The aggregate device never
> > probed and I was left with no display. Let me see if I can reproduce it
> > with logging to provide more details.
>
> This patch fixes it (whitespace damaged sorry).

Not sure why you have to trigger an explicit rescan, but instead of
this patch below, you could also try setting this flag instead?
DL_FLAG_AUTOPROBE_CONSUMER

-Saravana

>
> ----8<----
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index 65042c9f8a42..43cac9ed70b7 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -202,7 +202,7 @@ static int find_components(struct aggregate_device *adev)
>                 /* Matches put in component_del() */
>                 get_device(&adev->dev);
>                 c->link = device_link_add(&adev->dev, c->dev,
> -                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
> +                                         DL_FLAG_PM_RUNTIME);
>                 c->adev = adev;
>         }
>
> @@ -749,7 +749,9 @@ static int __component_add(struct device *dev,
> const struct component_ops *ops,
>         mutex_unlock(&component_mutex);
>
>         /* Try to bind */
> -       return bus_rescan_devices(&aggregate_bus_type);
> +       bus_rescan_devices(&aggregate_bus_type);
> +
> +       return 0;
>  }
>
>  /**
>
>
> The important part is ignoring the return value of bus_rescan_devices().
> It's a cycle problem. The last component is probing and calling
> component_add() in its probe function. The call to component_add() is
> trying to probe the aggregate device now that all components are added.
> But when it tries to probe the aggregate device it sees that a supplier,
> which is this component calling compnent_add(), hasn't been probed yet,
> so it returns -EPROBE_DEFER. That is passed up to the component and it
> defers probe.
>
> I don't think the component device cares at all about the aggregate
> device being able to probe or not. We should be able to ignore the
> return value of bus_rescan_devices() in component_add(). I'll add a
> comment to the code here so it's more obvious.

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-08  1:10         ` Saravana Kannan
@ 2021-10-08  1:24           ` Stephen Boyd
  2021-10-08  1:32             ` Saravana Kannan
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2021-10-08  1:24 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

Quoting Saravana Kannan (2021-10-07 18:10:24)
> On Thu, Oct 7, 2021 at 1:11 PM Stephen Boyd <swboyd@chromium.org> wrote:
> >
> > Quoting Stephen Boyd (2021-10-07 11:40:07)
> > > Quoting Saravana Kannan (2021-10-06 20:07:11)
> > > > On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > > > > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > > > > index 0a41bbe14981..d99e99cabb99 100644
> > > > > --- a/drivers/base/component.c
> > > > > +++ b/drivers/base/component.c
> > > [...]
> > > > > +                       continue;
> > > > > +
> > > > > +               /* Matches put in component_del() */
> > > > > +               get_device(&adev->dev);
> > > > > +               c->link = device_link_add(&adev->dev, c->dev,
> > > > > +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
> > > >
> > > > Remove the STATELESS flag and you'll get a bunch of other stuff done for free:
> > >
> > > I tried that and it didn't work for me. The aggregate device never
> > > probed and I was left with no display. Let me see if I can reproduce it
> > > with logging to provide more details.
> >
> > This patch fixes it (whitespace damaged sorry).
>
> Not sure why you have to trigger an explicit rescan, but instead of
> this patch below, you could also try setting this flag instead?
> DL_FLAG_AUTOPROBE_CONSUMER
>

I'd rather not conflate component driver probe with component_add()
being called. It's simpler if that is the case, i.e. all component
drivers are calling component_add() in their driver probe routine, but I
don't know if that's always true. I did this poor audit of the kernel

$ git grep -p \[^_]component_add | grep \.c=  | grep -v probe
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c=static int
amdgpu_dm_audio_init(struct amdgpu_device *adev)
drivers/gpu/drm/i915/display/intel_audio.c=static void
i915_audio_component_init(struct drm_i915_private *dev_priv)
drivers/gpu/drm/i915/display/intel_hdcp.c=void
intel_hdcp_component_init(struct drm_i915_private *dev_priv)
drivers/gpu/drm/nouveau/dispnv50/disp.c=nv50_audio_component_init(struct
nouveau_drm *drm)
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c=static int
dw_mipi_dsi_rockchip_host_attach(void *priv_data,
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c=static int
dw_mipi_dsi_dphy_init(struct phy *phy)
drivers/gpu/drm/vc4/vc4_dsi.c=static int vc4_dsi_host_attach(struct
mipi_dsi_host *host,

and then peeking at rockchip above I see that component_add() is called
in the mipi dsi attach ops and then I got lost trying to figure out
where it ends up. Maybe it is still in some probe call?

Anyway, I think we still have to do a rescan so that we can try to bind
the aggregate device. Is there a better API to use for that?

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-08  1:24           ` Stephen Boyd
@ 2021-10-08  1:32             ` Saravana Kannan
  2021-10-08  1:37               ` Stephen Boyd
  0 siblings, 1 reply; 60+ messages in thread
From: Saravana Kannan @ 2021-10-08  1:32 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

On Thu, Oct 7, 2021 at 6:24 PM Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Saravana Kannan (2021-10-07 18:10:24)
> > On Thu, Oct 7, 2021 at 1:11 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > >
> > > Quoting Stephen Boyd (2021-10-07 11:40:07)
> > > > Quoting Saravana Kannan (2021-10-06 20:07:11)
> > > > > On Wed, Oct 6, 2021 at 12:38 PM Stephen Boyd <swboyd@chromium.org> wrote:
> > > > > > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > > > > > index 0a41bbe14981..d99e99cabb99 100644
> > > > > > --- a/drivers/base/component.c
> > > > > > +++ b/drivers/base/component.c
> > > > [...]
> > > > > > +                       continue;
> > > > > > +
> > > > > > +               /* Matches put in component_del() */
> > > > > > +               get_device(&adev->dev);
> > > > > > +               c->link = device_link_add(&adev->dev, c->dev,
> > > > > > +                                         DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
> > > > >
> > > > > Remove the STATELESS flag and you'll get a bunch of other stuff done for free:
> > > >
> > > > I tried that and it didn't work for me. The aggregate device never
> > > > probed and I was left with no display. Let me see if I can reproduce it
> > > > with logging to provide more details.
> > >
> > > This patch fixes it (whitespace damaged sorry).
> >
> > Not sure why you have to trigger an explicit rescan, but instead of
> > this patch below, you could also try setting this flag instead?
> > DL_FLAG_AUTOPROBE_CONSUMER
> >
>
> I'd rather not conflate component driver probe with component_add()
> being called. It's simpler if that is the case, i.e. all component
> drivers are calling component_add() in their driver probe routine, but I
> don't know if that's always true. I did this poor audit of the kernel
>
> $ git grep -p \[^_]component_add | grep \.c=  | grep -v probe
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c=static int
> amdgpu_dm_audio_init(struct amdgpu_device *adev)
> drivers/gpu/drm/i915/display/intel_audio.c=static void
> i915_audio_component_init(struct drm_i915_private *dev_priv)
> drivers/gpu/drm/i915/display/intel_hdcp.c=void
> intel_hdcp_component_init(struct drm_i915_private *dev_priv)
> drivers/gpu/drm/nouveau/dispnv50/disp.c=nv50_audio_component_init(struct
> nouveau_drm *drm)
> drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c=static int
> dw_mipi_dsi_rockchip_host_attach(void *priv_data,
> drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c=static int
> dw_mipi_dsi_dphy_init(struct phy *phy)
> drivers/gpu/drm/vc4/vc4_dsi.c=static int vc4_dsi_host_attach(struct
> mipi_dsi_host *host,
>
> and then peeking at rockchip above I see that component_add() is called
> in the mipi dsi attach ops and then I got lost trying to figure out
> where it ends up. Maybe it is still in some probe call?
>
> Anyway, I think we still have to do a rescan so that we can try to bind
> the aggregate device. Is there a better API to use for that?

If you know the exact device, you could call device_attach()? That's
what bus_rescan_devices() eventually calls, but you skip the
unnecessary looping over all the other devices.

-Saravana

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-08  1:32             ` Saravana Kannan
@ 2021-10-08  1:37               ` Stephen Boyd
  0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-08  1:37 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King

Quoting Saravana Kannan (2021-10-07 18:32:20)
> On Thu, Oct 7, 2021 at 6:24 PM Stephen Boyd <swboyd@chromium.org> wrote:
> >
> > Anyway, I think we still have to do a rescan so that we can try to bind
> > the aggregate device. Is there a better API to use for that?
>
> If you know the exact device, you could call device_attach()? That's
> what bus_rescan_devices() eventually calls, but you skip the
> unnecessary looping over all the other devices.
>

Unfortunately we don't know the device. At this point it's possible that
the aggregate device hasn't even been registered yet.

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

* Re: [PATCH v2 00/34] component: Make into an aggregate bus
  2021-10-07 20:46   ` Stephen Boyd
@ 2021-10-13 12:14     ` Daniel Vetter
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Vetter @ 2021-10-13 12:14 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Andrzej Hajda, Greg Kroah-Hartman, linux-kernel, linux-arm-msm,
	dri-devel, freedreno, Arnd Bergmann, Benjamin Gaignard,
	Chen Feng, Chen-Yu Tsai, Christian Gmeiner, Chun-Kuang Hu,
	Daniel Vetter, Emma Anholt, Heiko Stübner, Inki Dae,
	James Qian Wang, Jaroslav Kysela, Joerg Roedel, John Stultz,
	Joonyoung Shim, Jyri Sarha, Kai Vehmanen, Kyungmin Park,
	Laurent Pinchart, linux-fbdev, linux-omap, linux-pm, Liviu Dudau,
	Lucas Stach, Mark Brown, Maxime Ripard, Neil Armstrong,
	Paul Cercueil, Philipp Zabel, Rafael J. Wysocki, Rob Clark,
	Russell King, Russell King, Russell King, Sandy Huang,
	Saravana Kannan, Sebastian Reichel, Seung-Woo Kim, Takashi Iwai,
	Tian Tao, Tomas Winkler, Tomi Valkeinen, Will Deacon,
	Xinliang Liu, Xinwei Kong, Yong Wu

On Thu, Oct 07, 2021 at 04:46:22PM -0400, Stephen Boyd wrote:
> Quoting Andrzej Hajda (2021-10-07 03:16:27)
> > Hi Stephen,
> >
> > On 06.10.2021 21:37, Stephen Boyd wrote:
> > > This series is from discussion we had on reordering the device lists for
> > > drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put
> > > the aggregate device onto and then we probe the aggregate device once
> > > all the components are probed and call component_add(). The probe/remove
> > > hooks are where the bind/unbind calls go, and then a shutdown hook is
> > > added that can be used to shutdown the drm display pipeline at the right
> > > time.
> > >
> > > This works for me on my sc7180 board. I no longer get a warning from i2c
> > > at shutdown that we're trying to make an i2c transaction after the i2c
> > > bus has been shutdown. There's more work to do on the msm drm driver to
> > > extract component device resources like clks, regulators, etc. out of
> > > the component bind function into the driver probe but I wanted to move
> > > everything over now in other component drivers before tackling that
> > > problem.
> >
> >
> > As I understand you have DSI host with i2c-controlled DSI bridge. And
> > there is an issue that bridge is shutdown before msmdrm. Your solution
> > is to 'adjust' device order on pm list.
> > I had similar issue and solved it locally by adding notification from
> > DSI bridge to DSI host that is has to be removed: mipi_dsi_detach, this
> > notification escalates in DSI host to component_del and this allow to
> > react properly.
> >
> > Advantages:
> > - it is local (only involves DSI host and DSI device),
> > - it does not depend on PM internals,
> > - it can be used in other scenarios as well - unbinding DSI device driver
> >
> > Disadvantage:
> > - It is DSI specific (but this is your case), I have advertised some
> > time ago more general approach [1][2].
> >
> > [1]: https://static.sched.com/hosted_files/osseu18/0f/deferred_problem.pdf
> > [2]: https://lwn.net/Articles/625454/
> >
> 
> I think these are all points for or against using the component code in
> general? Maybe you can send patches that you think can solve the problem
> I'm experiencing and we can review them on the list.

Yeah I think this is entirely orthogonal. If you use component, then
component should provide a way to handle this.

If you use something else, like drm_bridge or dsi or whatever, then that
part should provide a solution to stage stuff correctly and handle all the
ordering.

Now there's a bunch of drivers which mix up component with bridge use and
hilarity ensues, but since there's no real effort to fix that I think it's
toally fine to just improve component.c meanwhile.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH v2 01/34] component: Introduce struct aggregate_device
  2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
  2021-10-07  1:17   ` Laurent Pinchart
@ 2021-10-13 12:22   ` Daniel Vetter
  2021-10-13 19:49     ` Stephen Boyd
  1 sibling, 1 reply; 60+ messages in thread
From: Daniel Vetter @ 2021-10-13 12:22 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

On Wed, Oct 06, 2021 at 12:37:46PM -0700, Stephen Boyd wrote:
> Replace 'struct master' with 'struct aggregate_device' and then rename
> 'master' to 'adev' everywhere in the code. While we're here, put a
> struct device inside the aggregate device so that we can register it
> with a bus_type in the next patch.
> 
> The diff is large but that's because this is mostly a rename, where
> sometimes 'master' is replaced with 'adev' and other times it is
> replaced with 'parent' to indicate that the struct device that was being
> used is actually the parent of the aggregate device and driver.
> 
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>

This adds device model stuff, please cc Greg KH and ask him to review
this. Maybe also an ack from Rafael would be good whether this makes
sense.

Once we have that I think we can then go&collect acks/review for all the
driver changes and get this sorted. Thanks a lot for pushing this forward.
-Daniel

> ---
>  drivers/base/component.c  | 250 ++++++++++++++++++++------------------
>  include/linux/component.h |   2 +-
>  2 files changed, 134 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index 5e79299f6c3f..0a41bbe14981 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -9,6 +9,7 @@
>   */
>  #include <linux/component.h>
>  #include <linux/device.h>
> +#include <linux/idr.h>
>  #include <linux/kref.h>
>  #include <linux/list.h>
>  #include <linux/mutex.h>
> @@ -58,18 +59,21 @@ struct component_match {
>  	struct component_match_array *compare;
>  };
>  
> -struct master {
> +struct aggregate_device {
>  	struct list_head node;
>  	bool bound;
>  
>  	const struct component_master_ops *ops;
>  	struct device *parent;
> +	struct device dev;
>  	struct component_match *match;
> +
> +	int id;
>  };
>  
>  struct component {
>  	struct list_head node;
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	bool bound;
>  
>  	const struct component_ops *ops;
> @@ -79,7 +83,9 @@ struct component {
>  
>  static DEFINE_MUTEX(component_mutex);
>  static LIST_HEAD(component_list);
> -static LIST_HEAD(masters);
> +static LIST_HEAD(aggregate_devices);
> +
> +static DEFINE_IDA(aggregate_ida);
>  
>  #ifdef CONFIG_DEBUG_FS
>  
> @@ -87,12 +93,12 @@ static struct dentry *component_debugfs_dir;
>  
>  static int component_devices_show(struct seq_file *s, void *data)
>  {
> -	struct master *m = s->private;
> +	struct aggregate_device *m = s->private;
>  	struct component_match *match = m->match;
>  	size_t i;
>  
>  	mutex_lock(&component_mutex);
> -	seq_printf(s, "%-40s %20s\n", "master name", "status");
> +	seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
>  	seq_puts(s, "-------------------------------------------------------------\n");
>  	seq_printf(s, "%-40s %20s\n\n",
>  		   dev_name(m->parent), m->bound ? "bound" : "not bound");
> @@ -122,46 +128,46 @@ static int __init component_debug_init(void)
>  
>  core_initcall(component_debug_init);
>  
> -static void component_master_debugfs_add(struct master *m)
> +static void component_master_debugfs_add(struct aggregate_device *m)
>  {
>  	debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m,
>  			    &component_devices_fops);
>  }
>  
> -static void component_master_debugfs_del(struct master *m)
> +static void component_master_debugfs_del(struct aggregate_device *m)
>  {
>  	debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir));
>  }
>  
>  #else
>  
> -static void component_master_debugfs_add(struct master *m)
> +static void component_master_debugfs_add(struct aggregate_device *m)
>  { }
>  
> -static void component_master_debugfs_del(struct master *m)
> +static void component_master_debugfs_del(struct aggregate_device *m)
>  { }
>  
>  #endif
>  
> -static struct master *__master_find(struct device *parent,
> +static struct aggregate_device *__aggregate_find(struct device *parent,
>  	const struct component_master_ops *ops)
>  {
> -	struct master *m;
> +	struct aggregate_device *m;
>  
> -	list_for_each_entry(m, &masters, node)
> +	list_for_each_entry(m, &aggregate_devices, node)
>  		if (m->parent == parent && (!ops || m->ops == ops))
>  			return m;
>  
>  	return NULL;
>  }
>  
> -static struct component *find_component(struct master *master,
> +static struct component *find_component(struct aggregate_device *adev,
>  	struct component_match_array *mc)
>  {
>  	struct component *c;
>  
>  	list_for_each_entry(c, &component_list, node) {
> -		if (c->master && c->master != master)
> +		if (c->adev && c->adev != adev)
>  			continue;
>  
>  		if (mc->compare && mc->compare(c->dev, mc->data))
> @@ -175,101 +181,102 @@ static struct component *find_component(struct master *master,
>  	return NULL;
>  }
>  
> -static int find_components(struct master *master)
> +static int find_components(struct aggregate_device *adev)
>  {
> -	struct component_match *match = master->match;
> +	struct component_match *match = adev->match;
>  	size_t i;
>  	int ret = 0;
>  
>  	/*
>  	 * Scan the array of match functions and attach
> -	 * any components which are found to this master.
> +	 * any components which are found to this adev.
>  	 */
>  	for (i = 0; i < match->num; i++) {
>  		struct component_match_array *mc = &match->compare[i];
>  		struct component *c;
>  
> -		dev_dbg(master->parent, "Looking for component %zu\n", i);
> +		dev_dbg(adev->parent, "Looking for component %zu\n", i);
>  
>  		if (match->compare[i].component)
>  			continue;
>  
> -		c = find_component(master, mc);
> +		c = find_component(adev, mc);
>  		if (!c) {
>  			ret = -ENXIO;
>  			break;
>  		}
>  
> -		dev_dbg(master->parent, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
> +		dev_dbg(adev->parent, "found component %s, duplicate %u\n",
> +			dev_name(c->dev), !!c->adev);
>  
> -		/* Attach this component to the master */
> -		match->compare[i].duplicate = !!c->master;
> +		/* Attach this component to the adev */
> +		match->compare[i].duplicate = !!c->adev;
>  		match->compare[i].component = c;
> -		c->master = master;
> +		c->adev = adev;
>  	}
>  	return ret;
>  }
>  
> -/* Detach component from associated master */
> -static void remove_component(struct master *master, struct component *c)
> +/* Detach component from associated aggregate_device */
> +static void remove_component(struct aggregate_device *adev, struct component *c)
>  {
>  	size_t i;
>  
> -	/* Detach the component from this master. */
> -	for (i = 0; i < master->match->num; i++)
> -		if (master->match->compare[i].component == c)
> -			master->match->compare[i].component = NULL;
> +	/* Detach the component from this adev. */
> +	for (i = 0; i < adev->match->num; i++)
> +		if (adev->match->compare[i].component == c)
> +			adev->match->compare[i].component = NULL;
>  }
>  
>  /*
> - * Try to bring up a master.  If component is NULL, we're interested in
> - * this master, otherwise it's a component which must be present to try
> - * and bring up the master.
> + * Try to bring up an aggregate device.  If component is NULL, we're interested
> + * in this aggregate device, otherwise it's a component which must be present
> + * to try and bring up the aggregate device.
>   *
>   * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
>   */
> -static int try_to_bring_up_master(struct master *master,
> +static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
>  	struct component *component)
>  {
>  	int ret;
>  
> -	dev_dbg(master->parent, "trying to bring up master\n");
> +	dev_dbg(adev->parent, "trying to bring up adev\n");
>  
> -	if (find_components(master)) {
> -		dev_dbg(master->parent, "master has incomplete components\n");
> +	if (find_components(adev)) {
> +		dev_dbg(adev->parent, "master has incomplete components\n");
>  		return 0;
>  	}
>  
> -	if (component && component->master != master) {
> -		dev_dbg(master->parent, "master is not for this component (%s)\n",
> +	if (component && component->adev != adev) {
> +		dev_dbg(adev->parent, "master is not for this component (%s)\n",
>  			dev_name(component->dev));
>  		return 0;
>  	}
>  
> -	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
> +	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
>  		return -ENOMEM;
>  
>  	/* Found all components */
> -	ret = master->ops->bind(master->parent);
> +	ret = adev->ops->bind(adev->parent);
>  	if (ret < 0) {
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  		if (ret != -EPROBE_DEFER)
> -			dev_info(master->parent, "master bind failed: %d\n", ret);
> +			dev_info(adev->parent, "adev bind failed: %d\n", ret);
>  		return ret;
>  	}
>  
> -	master->bound = true;
> +	adev->bound = true;
>  	return 1;
>  }
>  
>  static int try_to_bring_up_masters(struct component *component)
>  {
> -	struct master *m;
> +	struct aggregate_device *adev;
>  	int ret = 0;
>  
> -	list_for_each_entry(m, &masters, node) {
> -		if (!m->bound) {
> -			ret = try_to_bring_up_master(m, component);
> +	list_for_each_entry(adev, &aggregate_devices, node) {
> +		if (!adev->bound) {
> +			ret = try_to_bring_up_aggregate_device(adev, component);
>  			if (ret != 0)
>  				break;
>  		}
> @@ -278,12 +285,12 @@ static int try_to_bring_up_masters(struct component *component)
>  	return ret;
>  }
>  
> -static void take_down_master(struct master *master)
> +static void take_down_aggregate_device(struct aggregate_device *adev)
>  {
> -	if (master->bound) {
> -		master->ops->unbind(master->parent);
> -		devres_release_group(master->parent, NULL);
> -		master->bound = false;
> +	if (adev->bound) {
> +		adev->ops->unbind(adev->parent);
> +		devres_release_group(adev->parent, NULL);
> +		adev->bound = false;
>  	}
>  }
>  
> @@ -324,7 +331,7 @@ static int component_match_realloc(struct component_match *match, size_t num)
>  	return 0;
>  }
>  
> -static void __component_match_add(struct device *master,
> +static void __component_match_add(struct device *parent,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *),
> @@ -344,7 +351,7 @@ static void __component_match_add(struct device *master,
>  			return;
>  		}
>  
> -		devres_add(master, match);
> +		devres_add(parent, match);
>  
>  		*matchptr = match;
>  	}
> @@ -370,13 +377,13 @@ static void __component_match_add(struct device *master,
>  
>  /**
>   * component_match_add_release - add a component match entry with release callback
> - * @master: device with the aggregate driver
> + * @parent: parent device of the aggregate driver
>   * @matchptr: pointer to the list of component matches
>   * @release: release function for @compare_data
>   * @compare: compare function to match against all components
>   * @compare_data: opaque pointer passed to the @compare function
>   *
> - * Adds a new component match to the list stored in @matchptr, which the @master
> + * Adds a new component match to the list stored in @matchptr, which the
>   * aggregate driver needs to function. The list of component matches pointed to
>   * by @matchptr must be initialized to NULL before adding the first match. This
>   * only matches against components added with component_add().
> @@ -388,19 +395,19 @@ static void __component_match_add(struct device *master,
>   *
>   * See also component_match_add() and component_match_add_typed().
>   */
> -void component_match_add_release(struct device *master,
> +void component_match_add_release(struct device *parent,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *), void *compare_data)
>  {
> -	__component_match_add(master, matchptr, release, compare, NULL,
> +	__component_match_add(parent, matchptr, release, compare, NULL,
>  			      compare_data);
>  }
>  EXPORT_SYMBOL(component_match_add_release);
>  
>  /**
>   * component_match_add_typed - add a component match entry for a typed component
> - * @master: device with the aggregate driver
> + * @parent: parent device of the aggregate driver
>   * @matchptr: pointer to the list of component matches
>   * @compare_typed: compare function to match against all typed components
>   * @compare_data: opaque pointer passed to the @compare function
> @@ -415,32 +422,33 @@ EXPORT_SYMBOL(component_match_add_release);
>   *
>   * See also component_match_add_release() and component_match_add_typed().
>   */
> -void component_match_add_typed(struct device *master,
> +void component_match_add_typed(struct device *parent,
>  	struct component_match **matchptr,
>  	int (*compare_typed)(struct device *, int, void *), void *compare_data)
>  {
> -	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> +	__component_match_add(parent, matchptr, NULL, NULL, compare_typed,
>  			      compare_data);
>  }
>  EXPORT_SYMBOL(component_match_add_typed);
>  
> -static void free_master(struct master *master)
> +static void free_aggregate_device(struct aggregate_device *adev)
>  {
> -	struct component_match *match = master->match;
> +	struct component_match *match = adev->match;
>  	int i;
>  
> -	component_master_debugfs_del(master);
> -	list_del(&master->node);
> +	component_master_debugfs_del(adev);
> +	list_del(&adev->node);
>  
>  	if (match) {
>  		for (i = 0; i < match->num; i++) {
>  			struct component *c = match->compare[i].component;
>  			if (c)
> -				c->master = NULL;
> +				c->adev = NULL;
>  		}
>  	}
>  
> -	kfree(master);
> +	ida_free(&aggregate_ida, adev->id);
> +	kfree(adev);
>  }
>  
>  /**
> @@ -459,31 +467,39 @@ int component_master_add_with_match(struct device *parent,
>  	const struct component_master_ops *ops,
>  	struct component_match *match)
>  {
> -	struct master *master;
> -	int ret;
> +	struct aggregate_device *adev;
> +	int ret, id;
>  
>  	/* Reallocate the match array for its true size */
>  	ret = component_match_realloc(match, match->num);
>  	if (ret)
>  		return ret;
>  
> -	master = kzalloc(sizeof(*master), GFP_KERNEL);
> -	if (!master)
> +	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
> +	if (!adev)
>  		return -ENOMEM;
>  
> -	master->parent = parent;
> -	master->ops = ops;
> -	master->match = match;
> +	id = ida_alloc(&aggregate_ida, GFP_KERNEL);
> +	if (id < 0) {
> +		kfree(adev);
> +		return id;
> +	}
> +
> +	adev->id = id;
> +	adev->parent = parent;
> +	adev->ops = ops;
> +	adev->match = match;
> +	dev_set_name(&adev->dev, "aggregate%d", id);
>  
> -	component_master_debugfs_add(master);
> -	/* Add to the list of available masters. */
> +	component_master_debugfs_add(adev);
> +	/* Add to the list of available aggregate devices. */
>  	mutex_lock(&component_mutex);
> -	list_add(&master->node, &masters);
> +	list_add(&adev->node, &aggregate_devices);
>  
> -	ret = try_to_bring_up_master(master, NULL);
> +	ret = try_to_bring_up_aggregate_device(adev, NULL);
>  
>  	if (ret < 0)
> -		free_master(master);
> +		free_aggregate_device(adev);
>  
>  	mutex_unlock(&component_mutex);
>  
> @@ -503,25 +519,25 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
>  void component_master_del(struct device *parent,
>  	const struct component_master_ops *ops)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  
>  	mutex_lock(&component_mutex);
> -	master = __master_find(parent, ops);
> -	if (master) {
> -		take_down_master(master);
> -		free_master(master);
> +	adev = __aggregate_find(parent, ops);
> +	if (adev) {
> +		take_down_aggregate_device(adev);
> +		free_aggregate_device(adev);
>  	}
>  	mutex_unlock(&component_mutex);
>  }
>  EXPORT_SYMBOL_GPL(component_master_del);
>  
>  static void component_unbind(struct component *component,
> -	struct master *master, void *data)
> +	struct aggregate_device *adev, void *data)
>  {
>  	WARN_ON(!component->bound);
>  
>  	if (component->ops && component->ops->unbind)
> -		component->ops->unbind(component->dev, master->parent, data);
> +		component->ops->unbind(component->dev, adev->parent, data);
>  	component->bound = false;
>  
>  	/* Release all resources claimed in the binding of this component */
> @@ -539,26 +555,26 @@ static void component_unbind(struct component *component,
>   */
>  void component_unbind_all(struct device *parent, void *data)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	struct component *c;
>  	size_t i;
>  
>  	WARN_ON(!mutex_is_locked(&component_mutex));
>  
> -	master = __master_find(parent, NULL);
> -	if (!master)
> +	adev = __aggregate_find(parent, NULL);
> +	if (!adev)
>  		return;
>  
>  	/* Unbind components in reverse order */
> -	for (i = master->match->num; i--; )
> -		if (!master->match->compare[i].duplicate) {
> -			c = master->match->compare[i].component;
> -			component_unbind(c, master, data);
> +	for (i = adev->match->num; i--; )
> +		if (!adev->match->compare[i].duplicate) {
> +			c = adev->match->compare[i].component;
> +			component_unbind(c, adev, data);
>  		}
>  }
>  EXPORT_SYMBOL_GPL(component_unbind_all);
>  
> -static int component_bind(struct component *component, struct master *master,
> +static int component_bind(struct component *component, struct aggregate_device *adev,
>  	void *data)
>  {
>  	int ret;
> @@ -568,7 +584,7 @@ static int component_bind(struct component *component, struct master *master,
>  	 * This allows us to roll-back a failed component without
>  	 * affecting anything else.
>  	 */
> -	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
> +	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
>  		return -ENOMEM;
>  
>  	/*
> @@ -577,14 +593,14 @@ static int component_bind(struct component *component, struct master *master,
>  	 * at the appropriate moment.
>  	 */
>  	if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  		return -ENOMEM;
>  	}
>  
> -	dev_dbg(master->parent, "binding %s (ops %ps)\n",
> +	dev_dbg(adev->parent, "binding %s (ops %ps)\n",
>  		dev_name(component->dev), component->ops);
>  
> -	ret = component->ops->bind(component->dev, master->parent, data);
> +	ret = component->ops->bind(component->dev, adev->parent, data);
>  	if (!ret) {
>  		component->bound = true;
>  
> @@ -595,16 +611,16 @@ static int component_bind(struct component *component, struct master *master,
>  		 * can clean those resources up independently.
>  		 */
>  		devres_close_group(component->dev, NULL);
> -		devres_remove_group(master->parent, NULL);
> +		devres_remove_group(adev->parent, NULL);
>  
> -		dev_info(master->parent, "bound %s (ops %ps)\n",
> +		dev_info(adev->parent, "bound %s (ops %ps)\n",
>  			 dev_name(component->dev), component->ops);
>  	} else {
>  		devres_release_group(component->dev, NULL);
> -		devres_release_group(master->parent, NULL);
> +		devres_release_group(adev->parent, NULL);
>  
>  		if (ret != -EPROBE_DEFER)
> -			dev_err(master->parent, "failed to bind %s (ops %ps): %d\n",
> +			dev_err(adev->parent, "failed to bind %s (ops %ps): %d\n",
>  				dev_name(component->dev), component->ops, ret);
>  	}
>  
> @@ -622,31 +638,31 @@ static int component_bind(struct component *component, struct master *master,
>   */
>  int component_bind_all(struct device *parent, void *data)
>  {
> -	struct master *master;
> +	struct aggregate_device *adev;
>  	struct component *c;
>  	size_t i;
>  	int ret = 0;
>  
>  	WARN_ON(!mutex_is_locked(&component_mutex));
>  
> -	master = __master_find(parent, NULL);
> -	if (!master)
> +	adev = __aggregate_find(parent, NULL);
> +	if (!adev)
>  		return -EINVAL;
>  
>  	/* Bind components in match order */
> -	for (i = 0; i < master->match->num; i++)
> -		if (!master->match->compare[i].duplicate) {
> -			c = master->match->compare[i].component;
> -			ret = component_bind(c, master, data);
> +	for (i = 0; i < adev->match->num; i++)
> +		if (!adev->match->compare[i].duplicate) {
> +			c = adev->match->compare[i].component;
> +			ret = component_bind(c, adev, data);
>  			if (ret)
>  				break;
>  		}
>  
>  	if (ret != 0) {
>  		for (; i > 0; i--)
> -			if (!master->match->compare[i - 1].duplicate) {
> -				c = master->match->compare[i - 1].component;
> -				component_unbind(c, master, data);
> +			if (!adev->match->compare[i - 1].duplicate) {
> +				c = adev->match->compare[i - 1].component;
> +				component_unbind(c, adev, data);
>  			}
>  	}
>  
> @@ -675,8 +691,8 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
>  
>  	ret = try_to_bring_up_masters(component);
>  	if (ret < 0) {
> -		if (component->master)
> -			remove_component(component->master, component);
> +		if (component->adev)
> +			remove_component(component->adev, component);
>  		list_del(&component->node);
>  
>  		kfree(component);
> @@ -757,9 +773,9 @@ void component_del(struct device *dev, const struct component_ops *ops)
>  			break;
>  		}
>  
> -	if (component && component->master) {
> -		take_down_master(component->master);
> -		remove_component(component->master, component);
> +	if (component && component->adev) {
> +		take_down_aggregate_device(component->adev);
> +		remove_component(component->adev, component);
>  	}
>  
>  	mutex_unlock(&component_mutex);
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 16de18f473d7..71bfc3862633 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -41,7 +41,7 @@ void component_del(struct device *, const struct component_ops *);
>  int component_bind_all(struct device *master, void *master_data);
>  void component_unbind_all(struct device *master, void *master_data);
>  
> -struct master;
> +struct aggregate_device;
>  
>  /**
>   * struct component_master_ops - callback for the aggregate driver
> -- 
> https://chromeos.dev
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH v2 28/34] power: supply: ab8500: Migrate to aggregate driver
  2021-10-06 19:38 ` [PATCH v2 28/34] power: supply: ab8500: " Stephen Boyd
@ 2021-10-13 16:24   ` Sebastian Reichel
  0 siblings, 0 replies; 60+ messages in thread
From: Sebastian Reichel @ 2021-10-13 16:24 UTC (permalink / raw)
  To: Stephen Boyd, Linus Walleij
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, linux-pm, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

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

Hi,

[+cc Linus Walleij (I guess we should add a MAINTAINERS entry for
the ab8500* power-supply drivers)]

On Wed, Oct 06, 2021 at 12:38:13PM -0700, Stephen Boyd wrote:
> Use an aggregate driver instead of component ops so that we can get
> proper driver probe ordering of the aggregate device with respect to all
> the component devices that make up the aggregate device.
> 
> Cc: Sebastian Reichel <sre@kernel.org>
> Cc: <linux-pm@vger.kernel.org>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---

Acked-by: Sebastian Reichel <sre@kernel.org>

-- Sebastian

>  drivers/power/supply/ab8500_charger.c | 22 +++++++++++++---------
>  1 file changed, 13 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
> index 15eadaf46f14..52d4105e28f2 100644
> --- a/drivers/power/supply/ab8500_charger.c
> +++ b/drivers/power/supply/ab8500_charger.c
> @@ -3312,8 +3312,9 @@ static const struct power_supply_desc ab8500_usb_chg_desc = {
>  	.get_property	= ab8500_charger_usb_get_property,
>  };
>  
> -static int ab8500_charger_bind(struct device *dev)
> +static int ab8500_charger_bind(struct aggregate_device *adev)
>  {
> +	struct device *dev = adev->parent;
>  	struct ab8500_charger *di = dev_get_drvdata(dev);
>  	int ch_stat;
>  	int ret;
> @@ -3354,8 +3355,9 @@ static int ab8500_charger_bind(struct device *dev)
>  	return 0;
>  }
>  
> -static void ab8500_charger_unbind(struct device *dev)
> +static void ab8500_charger_unbind(struct aggregate_device *adev)
>  {
> +	struct device *dev = adev->parent;
>  	struct ab8500_charger *di = dev_get_drvdata(dev);
>  	int ret;
>  
> @@ -3380,9 +3382,13 @@ static void ab8500_charger_unbind(struct device *dev)
>  	component_unbind_all(dev, di);
>  }
>  
> -static const struct component_master_ops ab8500_charger_comp_ops = {
> -	.bind = ab8500_charger_bind,
> -	.unbind = ab8500_charger_unbind,
> +static struct aggregate_driver ab8500_charger_aggregate_driver = {
> +	.probe = ab8500_charger_bind,
> +	.remove = ab8500_charger_unbind,
> +	.driver = {
> +		.name = "ab8500_charger_agg",
> +		.owner = THIS_MODULE,
> +	},
>  };
>  
>  static struct platform_driver *const ab8500_charger_component_drivers[] = {
> @@ -3663,9 +3669,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
>  	}
>  
>  
> -	ret = component_master_add_with_match(&pdev->dev,
> -					      &ab8500_charger_comp_ops,
> -					      match);
> +	ret = component_aggregate_register(&pdev->dev, &ab8500_charger_aggregate_driver, match);
>  	if (ret) {
>  		dev_err(dev, "failed to add component master\n");
>  		goto free_notifier;
> @@ -3688,7 +3692,7 @@ static int ab8500_charger_remove(struct platform_device *pdev)
>  {
>  	struct ab8500_charger *di = platform_get_drvdata(pdev);
>  
> -	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
> +	component_aggregate_unregister(&pdev->dev, &ab8500_charger_aggregate_driver);
>  
>  	usb_unregister_notifier(di->usb_phy, &di->nb);
>  	usb_put_phy(di->usb_phy);
> -- 
> https://chromeos.dev
> 

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

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

* Re: [PATCH v2 01/34] component: Introduce struct aggregate_device
  2021-10-13 12:22   ` Daniel Vetter
@ 2021-10-13 19:49     ` Stephen Boyd
  0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2021-10-13 19:49 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

Quoting Daniel Vetter (2021-10-13 05:22:23)
> On Wed, Oct 06, 2021 at 12:37:46PM -0700, Stephen Boyd wrote:
> > Replace 'struct master' with 'struct aggregate_device' and then rename
> > 'master' to 'adev' everywhere in the code. While we're here, put a
> > struct device inside the aggregate device so that we can register it
> > with a bus_type in the next patch.
> >
> > The diff is large but that's because this is mostly a rename, where
> > sometimes 'master' is replaced with 'adev' and other times it is
> > replaced with 'parent' to indicate that the struct device that was being
> > used is actually the parent of the aggregate device and driver.
> >
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > Cc: Rob Clark <robdclark@gmail.com>
> > Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > Cc: Saravana Kannan <saravanak@google.com>
> > Signed-off-by: Stephen Boyd <swboyd@chromium.org>
>
> This adds device model stuff, please cc Greg KH and ask him to review
> this. Maybe also an ack from Rafael would be good whether this makes
> sense.

I will explicitly Cc Greg on these component.c patches.

>
> Once we have that I think we can then go&collect acks/review for all the
> driver changes and get this sorted. Thanks a lot for pushing this forward.

I'll resend the series today. This one has some compilation problems
that I've fixed now.

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

* Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
  2021-10-07 20:42     ` Stephen Boyd
@ 2021-10-14 13:27       ` Daniel Vetter
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Vetter @ 2021-10-14 13:27 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Greg Kroah-Hartman, linux-kernel, linux-arm-msm, dri-devel,
	freedreno, Daniel Vetter, Rafael J. Wysocki, Rob Clark,
	Russell King, Saravana Kannan

On Thu, Oct 07, 2021 at 04:42:48PM -0400, Stephen Boyd wrote:
> Quoting Greg Kroah-Hartman (2021-10-06 22:37:40)
> > On Wed, Oct 06, 2021 at 12:37:47PM -0700, Stephen Boyd wrote:
> > >
> > > Let's make the component driver into an actual device driver that has
> > > probe/remove/shutdown functions. The driver will only be bound to the
> > > aggregate device once all component drivers have called component_add()
> > > to indicate they're ready to assemble the aggregate driver. This allows
> > > us to attach shutdown logic (and in the future runtime PM logic) to the
> > > aggregate driver so that it runs the hooks in the correct order.
> >
> > Why are you creating a new bus type and not using the auxiliary bus
> > instead?
> >
> > You have seen Documentation/driver-api/auxiliary_bus.rst, right?
> >
> 
> Nope, but I read it now. Thanks for the pointer.
> 
> My read of it is that the auxiliary bus is a way to slice up a single IP
> block into multiple devices and then have drivers attach to those
> different "pieces" of the IP. It avoids polluting the platform bus with
> devices that don't belong on the platform bus because they are sub
> components of a larger IP block that sits on the platform bus.
> 
> The aggregate bus is solving the reverse problem. It is rounding up a
> collection of IP blocks that live on some bus (platform, i2c, spi,
> whatever) and presenting them as a single aggregate device (sound card,
> display card, whatever) whenever all the component devices call
> component_add(). For example, we don't want to do operations on the
> entire display pipeline until all the devices that make up the display
> are probed and drivers are attached. I suppose the aggregate_device in
> this patch series has a 1:1 relationship with the drm class_type that
> makes up /sys/class/drm/cardN but there's also a couple sound users and
> a power_supply user so I don't know the equivalent there.
> 
> Long term, maybe all of this component code could be placed directly
> into the driver core? That's probably even more invasive of a change but
> I imagine we could make device links with component_add() as we're
> already doing with these patches and then have driver core call some
> class function pointer when all the links are probed. That would
> handle the 'bind/probe' callback for the aggregate device but it won't
> handle the component_bind_all() path where we call bind_component() for
> each component device that makes up the aggregate device. Maybe we can
> add even more devices for the components and then call probe there too.
> 
> Sorry that's a long-winded non-answer. I don't think they're solving the
> same problem so using the same bus type looks wrong. We'd have to take
> two different paths depending on what type of device it is (aggregate
> vs. auxiliary) so there's not much of anything that is shared code-wise.

Yeah component is the reverse of auxiliary, and right now a lot of
subsystems have their own hand-rolled version of this. I do hope that
component.c does become more of a standard (that's why it's in
drivers/base/), but I guess that's a bit tricky if the device model
maintainer hasn't seen it yet ...

Hopefully putting more proper device model concepts into it can fix this
problem :-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

end of thread, other threads:[~2021-10-14 13:27 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-06 19:37 [PATCH v2 00/34] component: Make into an aggregate bus Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 01/34] component: Introduce struct aggregate_device Stephen Boyd
2021-10-07  1:17   ` Laurent Pinchart
2021-10-07 18:36     ` Stephen Boyd
2021-10-13 12:22   ` Daniel Vetter
2021-10-13 19:49     ` Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 02/34] component: Introduce the aggregate bus_type Stephen Boyd
2021-10-06 22:42   ` kernel test robot
2021-10-07  3:07   ` Saravana Kannan
2021-10-07 18:40     ` Stephen Boyd
2021-10-07 20:11       ` Stephen Boyd
2021-10-08  1:10         ` Saravana Kannan
2021-10-08  1:24           ` Stephen Boyd
2021-10-08  1:32             ` Saravana Kannan
2021-10-08  1:37               ` Stephen Boyd
2021-10-07  5:37   ` Greg Kroah-Hartman
2021-10-07 20:42     ` Stephen Boyd
2021-10-14 13:27       ` Daniel Vetter
2021-10-06 19:37 ` [PATCH v2 03/34] component: Move struct aggregate_device out to header file Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 04/34] drm/msm: Migrate to aggregate driver Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 05/34] component: Add {bind,unbind}_component() ops that take aggregate device Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API Stephen Boyd
2021-10-06 22:28   ` kernel test robot
2021-10-06 22:36   ` kernel test robot
2021-10-06 19:37 ` [PATCH v2 07/34] drm/komeda: Migrate to aggregate driver Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 08/34] drm/arm/hdlcd: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 09/34] drm/malidp: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 10/34] drm/armada: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 11/34] drm/etnaviv: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 12/34] drm/kirin: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 13/34] drm/exynos: " Stephen Boyd
2021-10-06 19:37 ` [PATCH v2 14/34] drm/imx: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 15/34] drm/ingenic: " Stephen Boyd
2021-10-07 21:29   ` Paul Cercueil
2021-10-06 19:38 ` [PATCH v2 16/34] drm/mcde: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 17/34] drm/mediatek: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 18/34] drm/meson: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 19/34] drm/omap: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 20/34] drm/rockchip: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 21/34] drm/sti: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 22/34] drm/sun4i: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 23/34] drm/tilcdc: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 24/34] drm/vc4: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 25/34] drm/zte: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 26/34] iommu/mtk: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 27/34] mei: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 28/34] power: supply: ab8500: " Stephen Boyd
2021-10-13 16:24   ` Sebastian Reichel
2021-10-06 19:38 ` [PATCH v2 29/34] fbdev: omap2: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 30/34] sound: hdac: " Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 31/34] ASoC: codecs: wcd938x: " Stephen Boyd
2021-10-07 12:35   ` Mark Brown
2021-10-06 19:38 ` [PATCH v2 32/34] component: Get rid of drm_of_component_probe() Stephen Boyd
2021-10-06 19:38 ` [PATCH v2 33/34] component: Remove component_master_ops and friends Stephen Boyd
2021-10-06 23:19   ` kernel test robot
2021-10-06 19:38 ` [PATCH v2 34/34] component: Remove all references to 'master' Stephen Boyd
2021-10-07 10:16 ` [PATCH v2 00/34] component: Make into an aggregate bus Andrzej Hajda
2021-10-07 20:46   ` Stephen Boyd
2021-10-13 12:14     ` Daniel Vetter
     [not found] ` <CAHp75VdLg-rBjCDGEwgkY6QDbFGW0of4SjSmp08FXXRN_raQtQ@mail.gmail.com>
2021-10-07 12:33   ` Andrzej Hajda

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).