linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows
@ 2020-10-19 22:58 Daniel Scally
  2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
                   ` (10 more replies)
  0 siblings, 11 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Hello all

This series adds support to the ipu3-cio2 driver for fwnode connections
between cio2 and sensors to be defined via software_nodes. The final patch
in the series deals wholly with those changes - the preceding patches are
either supporting changes to accommodate that or incidental fixes along
the way:

1/9 adds a function to drivers/base/swnode.c unwinding arrays of software
nodes in reverse order

2/9 uses that function in lib/test_printf.c

3/9 fixes what seems to me to be a bug in the existing swnode.c code in
that software_node_get_next_child() does not increase the refcount of the
returned node (in contrast to, for example, of_get_next_child_node() which
does increase the count)

4/9 adds the fwnode_graph*() family of functions to the software_node
implementation

5/9 adds a T: entry to MAINTAINERS for the ipu3-cio2 driver

6/9 renames the ipu3-cio2.c file to ipu3-cio2-main.c and fixes Makefile
to accommodate that change

7/9 alters the ipu3-cio2 driver to check if the pci_dev's fwnode is a
software_node and pass flags to fwnode_graph_get_endpoint_by_id() if so

8/9 alters match_fwnode() in v4l2-async.c to additionally try to match on
a fwnode_handle's secondary if the primary doesn't match

9/9 alters the ipu3-cio2 driver to do the actual building of software_node
connections between the sensor devices and the cio2 device.

This is still not ready for integration - hence the RFC label - as there
is ongoing work to extend the ipu3-cio2 driver further to parse ACPI
to discover resources such as regulators and GPIOs that are defined there
in unusual ways and map them to the sensor devices so that their drivers
can consume them transparently through the usual frameworks. Given this
has changed quite extensively from v2 though, I wanted to submit it for
feedback at this point in case it needs further large scale change.

Thanks
Dan

Daniel Scally (8):
  software_node: Add helper function to unregister arrays of
    software_nodes ordered parent to child
  lib/test_printf.c: Use helper function to unwind array of
    software_nodes
  software_node: Fix failure to hold refcount in
    software_node_get_next_child
  ipu3-cio2: Add T: entry to MAINTAINERS
  ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from
    multiple sources files retaining ipu3-cio2 name
  ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in
    cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  media: v4l2-core: v4l2-async: Check possible match in match_fwnode
    based on sd->fwnode->secondary
  ipu3-cio2: Add functionality allowing software_node connections to
    sensors on platforms designed for Windows

Heikki Krogerus (1):
  software_node: Add support for fwnode_graph*() family of functions

 MAINTAINERS                                   |   2 +
 drivers/base/swnode.c                         | 143 +++++++-
 drivers/media/pci/intel/ipu3/Kconfig          |  18 +
 drivers/media/pci/intel/ipu3/Makefile         |   3 +
 drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
 drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
 .../ipu3/{ipu3-cio2.c => ipu3-cio2-main.c}    |  30 +-
 drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
 drivers/media/v4l2-core/v4l2-async.c          |   8 +
 include/linux/property.h                      |   1 +
 lib/test_printf.c                             |   4 +-
 11 files changed, 632 insertions(+), 7 deletions(-)
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
 rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (98%)

-- 
2.17.1


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

* [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-10-19 22:58 ` Daniel Scally
  2020-10-20  9:22   ` Andy Shevchenko
  2020-10-20 10:05   ` Sakari Ailus
  2020-10-19 22:58 ` [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Software nodes that are children of another software node should be
unregistered before their parent. To allow easy unregistering of an array
of software_nodes ordered parent to child, add a helper function to loop
over and unregister nodes in such an array in reverse order.

Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced.

 drivers/base/swnode.c    | 21 +++++++++++++++++++++
 include/linux/property.h |  1 +
 2 files changed, 22 insertions(+)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 010828fc7..f01b1cc61 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -727,6 +727,27 @@ void software_node_unregister_nodes(const struct software_node *nodes)
 }
 EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
 
+/**
+ * software_node_unregister_nodes_reverse - Unregister an array of software
+ * nodes in reverse order.
+ * @nodes: Array of software nodes to be unregistered.
+ *
+ * NOTE: The same warning applies as with software_node_unregister_nodes.
+ * Unless you are _sure_ that the array of nodes is ordered parent to child
+ * it is wiser to remove them individually in the correct order.
+ */
+void software_node_unregister_nodes_reverse(const struct software_node *nodes)
+{
+	unsigned int i = 0;
+
+	while (nodes[i].name)
+		i++;
+
+	while (i--)
+		software_node_unregister(&nodes[i]);
+}
+EXPORT_SYMBOL_GPL(software_node_unregister_nodes_reverse);
+
 /**
  * software_node_register_node_group - Register a group of software nodes
  * @node_group: NULL terminated array of software node pointers to be registered
diff --git a/include/linux/property.h b/include/linux/property.h
index 9f805c442..b6410258b 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -444,6 +444,7 @@ software_node_find_by_name(const struct software_node *parent,
 
 int software_node_register_nodes(const struct software_node *nodes);
 void software_node_unregister_nodes(const struct software_node *nodes);
+void software_node_unregister_nodes_reverse(const struct software_node *nodes);
 
 int software_node_register_node_group(const struct software_node **node_group);
 void software_node_unregister_node_group(const struct software_node **node_group);
-- 
2.17.1


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

* [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
@ 2020-10-19 22:58 ` Daniel Scally
  2020-10-20  7:23   ` Petr Mladek
  2020-10-20  9:20   ` Andy Shevchenko
  2020-10-19 22:58 ` [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child Daniel Scally
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Use the new software_node_unregister_nodes_reverse() function to
unwind this array in a cleaner way.

Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced.

 lib/test_printf.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/test_printf.c b/lib/test_printf.c
index 7ac87f18a..c63365570 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -644,9 +644,7 @@ static void __init fwnode_pointer(void)
 	test(second_name, "%pfwP", software_node_fwnode(&softnodes[1]));
 	test(third_name, "%pfwP", software_node_fwnode(&softnodes[2]));
 
-	software_node_unregister(&softnodes[2]);
-	software_node_unregister(&softnodes[1]);
-	software_node_unregister(&softnodes[0]);
+	software_node_unregister_nodes_reverse(softnodes);
 }
 
 static void __init
-- 
2.17.1


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

* [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
  2020-10-19 22:58 ` [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
@ 2020-10-19 22:58 ` Daniel Scally
  2020-10-20 12:44   ` Rafael J. Wysocki
  2020-10-20 13:31   ` Sakari Ailus
  2020-10-19 22:58 ` [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

The software_node_get_next_child() function currently does not hold a kref
to the child software_node; fix that.

Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the firmware node framework")
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- split out from the full software_node_graph*() patch

 drivers/base/swnode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index f01b1cc61..741149b90 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -450,7 +450,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
 		c = list_next_entry(c, entry);
 	else
 		c = list_first_entry(&p->children, struct swnode, entry);
-	return &c->fwnode;
+	return software_node_get(&c->fwnode);
 }
 
 static struct fwnode_handle *
-- 
2.17.1


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

* [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (2 preceding siblings ...)
  2020-10-19 22:58 ` [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child Daniel Scally
@ 2020-10-19 22:58 ` Daniel Scally
  2020-10-20  9:17   ` Andy Shevchenko
  2020-10-20 12:35   ` Sakari Ailus
  2020-10-19 22:58 ` [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
                   ` (6 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

This implements the remaining .graph_* callbacks in the
fwnode operations vector for the software nodes. That makes
the fwnode_graph*() functions available in the drivers also
when software nodes are used.

The implementation tries to mimic the "OF graph" as much as
possible, but there is no support for the "reg" device
property. The ports will need to have the index in their
name which starts with "port" (for example "port0", "port1",
...) and endpoints will use the index of the software node
that is given to them during creation. The port nodes can
also be grouped under a specially named "ports" subnode,
just like in DT, if necessary.

The remote-endpoints are reference properties under the
endpoint nodes that are named "remote-endpoint". 

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Co-developed-by: Daniel Scally <djrscally@gmail.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
changes in v3:
	- removed software_node_device_is_available
	- moved the change to software_node_get_next_child to a separate
	patch
	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
	instead of software_node_put()

changes in v2:
	- added software_node_device_is_available
	- altered software_node_get_next_child to get references
	- altered software_node_get_next_endpoint to release references
	to ports and avoid passing invalid combinations of swnodes to
	software_node_get_next_child
	- altered swnode_graph_find_next_port to release port rather than
	old
 drivers/base/swnode.c | 120 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 741149b90..3732530ce 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -536,6 +536,120 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
 	return 0;
 }
 
+static struct fwnode_handle *
+swnode_graph_find_next_port(const struct fwnode_handle *parent,
+			    struct fwnode_handle *port)
+{
+	struct fwnode_handle *old = port;
+
+	while ((port = software_node_get_next_child(parent, old))) {
+		if (!strncmp(to_swnode(port)->node->name, "port", 4))
+			return port;
+		fwnode_handle_put(port);
+		old = port;
+	}
+
+	return NULL;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
+				      struct fwnode_handle *endpoint)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	struct fwnode_handle *old = endpoint;
+	struct fwnode_handle *parent_of_old;
+	struct fwnode_handle *parent;
+	struct fwnode_handle *port;
+
+	if (!swnode)
+		return NULL;
+
+	if (endpoint) {
+		port = software_node_get_parent(endpoint);
+		parent = software_node_get_parent(port);
+	} else {
+		parent = software_node_get_named_child_node(fwnode, "ports");
+		if (!parent)
+			parent = software_node_get(&swnode->fwnode);
+
+		port = swnode_graph_find_next_port(parent, NULL);
+	}
+
+	for (; port; port = swnode_graph_find_next_port(parent, port)) {
+		if (old) {
+			parent_of_old = software_node_get_parent(old);
+
+			if (parent_of_old != port)
+				old = NULL;
+
+			fwnode_handle_put(parent_of_old);
+		}
+
+		endpoint = software_node_get_next_child(port, old);
+		fwnode_handle_put(old);
+		if (endpoint)
+			break;
+
+		fwnode_handle_put(port);
+	}
+
+	fwnode_handle_put(port);
+	fwnode_handle_put(parent);
+
+	return endpoint;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	const struct software_node_ref_args *ref;
+	const struct property_entry *prop;
+
+	if (!swnode)
+		return NULL;
+
+	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
+	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
+		return NULL;
+
+	ref = prop->pointer;
+
+	return software_node_get(software_node_fwnode(ref[0].node));
+}
+
+static struct fwnode_handle *
+software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	struct fwnode_handle *parent;
+
+	if (!strcmp(swnode->parent->node->name, "ports"))
+		parent = &swnode->parent->parent->fwnode;
+	else
+		parent = &swnode->parent->fwnode;
+
+	return software_node_get(parent);
+}
+
+static int
+software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
+				   struct fwnode_endpoint *endpoint)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	int ret;
+
+	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);
+	if (ret)
+		return ret;
+
+	endpoint->id = swnode->id;
+	endpoint->local_fwnode = fwnode;
+
+	return 0;
+}
+
 static const struct fwnode_operations software_node_ops = {
 	.get = software_node_get,
 	.put = software_node_put,
@@ -547,7 +661,11 @@ static const struct fwnode_operations software_node_ops = {
 	.get_parent = software_node_get_parent,
 	.get_next_child_node = software_node_get_next_child,
 	.get_named_child_node = software_node_get_named_child_node,
-	.get_reference_args = software_node_get_reference_args
+	.get_reference_args = software_node_get_reference_args,
+	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
+	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
+	.graph_get_port_parent = software_node_graph_get_port_parent,
+	.graph_parse_endpoint = software_node_graph_parse_endpoint,
 };
 
 /* -------------------------------------------------------------------------- */
-- 
2.17.1


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

* [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (3 preceding siblings ...)
  2020-10-19 22:58 ` [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
@ 2020-10-19 22:58 ` Daniel Scally
  2020-10-20  9:16   ` Andy Shevchenko
  2020-10-24  0:28   ` Laurent Pinchart
  2020-10-19 22:59 ` [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name Daniel Scally
                   ` (5 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:58 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Development for the ipu3-cio2 driver is taking place in media_tree, but
there's no T: entry in MAINTAINERS to denote that - rectify that oversight

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced.
	
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 43a025039..5d768d5ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8851,6 +8851,7 @@ M:	Bingbu Cao <bingbu.cao@intel.com>
 R:	Tianshu Qiu <tian.shu.qiu@intel.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
+T:	git git://linuxtv.org/media_tree.git
 F:	Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
 F:	drivers/media/pci/intel/ipu3/
 
-- 
2.17.1


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

* [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (4 preceding siblings ...)
  2020-10-19 22:58 ` [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
@ 2020-10-19 22:59 ` Daniel Scally
  2020-10-20  9:15   ` Andy Shevchenko
  2020-10-24  0:34   ` Laurent Pinchart
  2020-10-19 22:59 ` [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so Daniel Scally
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:59 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

ipu3-cio2 driver needs extending with multiple files; rename the main
source file and specify the renamed file in Makefile to accommodate that.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced

 drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
 drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
 2 files changed, 2 insertions(+)
 rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)

diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
index 98ddd5bea..b4e3266d9 100644
--- a/drivers/media/pci/intel/ipu3/Makefile
+++ b/drivers/media/pci/intel/ipu3/Makefile
@@ -1,2 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
+
+ipu3-cio2-y += ipu3-cio2-main.o
\ No newline at end of file
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
similarity index 100%
rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
-- 
2.17.1


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

* [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (5 preceding siblings ...)
  2020-10-19 22:59 ` [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name Daniel Scally
@ 2020-10-19 22:59 ` Daniel Scally
  2020-10-20  9:19   ` Andy Shevchenko
  2020-10-19 22:59 ` [RFC PATCH v3 8/9] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:59 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
only; that status being determined through the .device_is_available() op
of the device's fwnode. As software_nodes don't have that operation and
adding it is meaningless, we instead need to check if the device's fwnode
is a software_node and if so pass the appropriate flag to disable that
check

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced

 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 4e598e937..f68ef0f6b 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1466,6 +1466,7 @@ static const struct v4l2_async_notifier_operations cio2_async_ops = {
 
 static int cio2_parse_firmware(struct cio2_device *cio2)
 {
+	unsigned long allow_disabled;
 	unsigned int i;
 	int ret;
 
@@ -1474,11 +1475,15 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
 			.bus_type = V4L2_MBUS_CSI2_DPHY
 		};
 		struct sensor_async_subdev *s_asd = NULL;
+		struct fwnode_handle *fwnode;
 		struct fwnode_handle *ep;
 
+		fwnode = dev_fwnode(&cio2->pci_dev->dev);
+		allow_disabled = is_software_node(fwnode) ? FWNODE_GRAPH_DEVICE_DISABLED : 0;
+
 		ep = fwnode_graph_get_endpoint_by_id(
-			dev_fwnode(&cio2->pci_dev->dev), i, 0,
-			FWNODE_GRAPH_ENDPOINT_NEXT);
+			fwnode, i, 0,
+			FWNODE_GRAPH_ENDPOINT_NEXT | allow_disabled);
 
 		if (!ep)
 			continue;
-- 
2.17.1


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

* [RFC PATCH v3 8/9] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (6 preceding siblings ...)
  2020-10-19 22:59 ` [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so Daniel Scally
@ 2020-10-19 22:59 ` Daniel Scally
  2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:59 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Where the fwnode graph is comprised of software_nodes, these will be
assigned as the secondary to dev->fwnode. Check the v4l2_subdev's fwnode
for a secondary and attempt to match against it during match_fwnode() to
accommodate that possibility.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- patch introduced

 drivers/media/v4l2-core/v4l2-async.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index e3ab003a6..6486dbde7 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -87,6 +87,14 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 	if (sd->fwnode == asd->match.fwnode)
 		return true;
 
+	/*
+	 * Check the same situation for any possible secondary assigned to the
+	 * subdev's fwnode
+	 */
+	if ((!IS_ERR_OR_NULL(sd->fwnode->secondary)) &&
+	    sd->fwnode->secondary == asd->match.fwnode)
+		return true;
+
 	/*
 	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
 	 * endpoint or a device. If they're of the same type, there's no match.
-- 
2.17.1


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

* [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (7 preceding siblings ...)
  2020-10-19 22:59 ` [RFC PATCH v3 8/9] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
@ 2020-10-19 22:59 ` Daniel Scally
  2020-10-20  9:41   ` Andy Shevchenko
                     ` (2 more replies)
  2020-10-20  9:24 ` [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver " Andy Shevchenko
  2020-10-20 13:38 ` Rafael J. Wysocki
  10 siblings, 3 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-19 22:59 UTC (permalink / raw)
  To: linux-kernel, linux-media
  Cc: linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	andriy.shevchenko, sergey.senozhatsky, rostedt, pmladek, mchehab,
	tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Currently on platforms designed for Windows, connections between CIO2 and
sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
driver to compensate by building software_node connections, parsing the
connection properties from the sensor's SSDB buffer.

Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes in v3:
	- Rather than overwriting the device's primary fwnode, we now
	simply assign a secondary. Some of the preceding patches alter the
	existing driver code and v4l2 framework to allow for that.
	- Rather than reprobe() the sensor after connecting the devices in
	cio2-bridge we create the software_nodes right away. In this case,
	sensor drivers will have to defer probing until they detect that a
	fwnode graph is connecting them to the CIO2 device.
	- Error paths in connect_supported_devices() moved outside the
	loop
	- Replaced pr_*() with dev_*() throughout
	- Moved creation of software_node / property_entry arrays to stack
	- A lot of formatting changes.

 MAINTAINERS                                   |   1 +
 drivers/media/pci/intel/ipu3/Kconfig          |  18 +
 drivers/media/pci/intel/ipu3/Makefile         |   3 +-
 drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
 drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
 drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
 7 files changed, 472 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5d768d5ad..4c9c646c7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
 M:	Yong Zhi <yong.zhi@intel.com>
 M:	Sakari Ailus <sakari.ailus@linux.intel.com>
 M:	Bingbu Cao <bingbu.cao@intel.com>
+M:	Dan Scally <djrscally@gmail.com>
 R:	Tianshu Qiu <tian.shu.qiu@intel.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
index 82d7f17e6..d14cbceae 100644
--- a/drivers/media/pci/intel/ipu3/Kconfig
+++ b/drivers/media/pci/intel/ipu3/Kconfig
@@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
 	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
 	  connected camera.
 	  The module will be called ipu3-cio2.
+
+config CIO2_BRIDGE
+	bool "IPU3 CIO2 Sensors Bridge"
+	depends on VIDEO_IPU3_CIO2
+	help
+	  This extension provides an API for the ipu3-cio2 driver to create
+	  connections to cameras that are hidden in SSDB buffer in ACPI. It
+	  can be used to enable support for cameras in detachable / hybrid
+	  devices that ship with Windows.
+
+	  Say Y here if your device is a detachable / hybrid laptop that comes
+	  with Windows installed by the OEM, for example:
+
+	  	- Some Microsoft Surface models
+		- The Lenovo Miix line
+		- Dell 7285
+
+	  If in doubt, say N here.
diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
index b4e3266d9..933777e6e 100644
--- a/drivers/media/pci/intel/ipu3/Makefile
+++ b/drivers/media/pci/intel/ipu3/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
 
-ipu3-cio2-y += ipu3-cio2-main.o
\ No newline at end of file
+ipu3-cio2-y += ipu3-cio2-main.o
+ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
new file mode 100644
index 000000000..bbe072f04
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+// Author: Dan Scally <djrscally@gmail.com>
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/fwnode.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/property.h>
+#include <media/v4l2-subdev.h>
+
+#include "cio2-bridge.h"
+
+/*
+ * Extend this array with ACPI Hardware ID's of devices known to be
+ * working
+ */
+static const char * const supported_devices[] = {
+	"INT33BE",
+	"OVTI2680",
+};
+
+static struct software_node cio2_hid_node = { CIO2_HID };
+
+static struct cio2_bridge bridge;
+
+static const char * const port_names[] = {
+	"port0", "port1", "port2", "port3"
+};
+
+static const struct property_entry remote_endpoints[] = {
+	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, Sensor Property */
+			   &bridge.sensors[0].swnodes[SWNODE_CIO2_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, CIO2 Property */
+			   &bridge.sensors[0].swnodes[SWNODE_SENSOR_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[1].swnodes[SWNODE_CIO2_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[1].swnodes[SWNODE_SENSOR_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[2].swnodes[SWNODE_CIO2_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[2].swnodes[SWNODE_SENSOR_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[3].swnodes[SWNODE_CIO2_ENDPOINT]),
+	PROPERTY_ENTRY_REF("remote-endpoint",
+			   &bridge.sensors[3].swnodes[SWNODE_SENSOR_ENDPOINT]),
+};
+
+static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_handle *handle;
+	union acpi_object *obj;
+	acpi_status status;
+	int ret;
+
+	handle = ACPI_HANDLE(dev);
+
+	status = acpi_evaluate_object(handle, id, NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	obj = buffer.pointer;
+	if (!obj) {
+		dev_err(dev, "Couldn't locate ACPI buffer\n");
+		return -ENODEV;
+	}
+
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		dev_err(dev, "Couldn't read ACPI buffer\n");
+		ret = -ENODEV;
+		goto out_free_buff;
+	}
+
+	if (obj->buffer.length > size) {
+		dev_err(dev, "Given buffer is too small\n");
+		ret = -ENODEV;
+		goto out_free_buff;
+	}
+
+	memcpy(data, obj->buffer.pointer, obj->buffer.length);
+	ret = obj->buffer.length;
+
+out_free_buff:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static int get_acpi_ssdb_sensor_data(struct device *dev,
+				     struct sensor_bios_data *sensor)
+{
+	struct sensor_bios_data_packed sensor_data;
+	int ret;
+
+	ret = read_acpi_block(dev, "SSDB", &sensor_data, sizeof(sensor_data));
+	if (ret < 0)
+		return ret;
+
+	sensor->link = sensor_data.link;
+	sensor->lanes = sensor_data.lanes;
+	sensor->mclkspeed = sensor_data.mclkspeed;
+	sensor->degree = sensor_data.degree;
+
+	return 0;
+}
+
+static int create_fwnode_properties(struct sensor *sensor,
+				    struct sensor_bios_data *ssdb)
+{
+	struct property_entry *cio2_properties = sensor->cio2_properties;
+	struct property_entry *dev_properties = sensor->dev_properties;
+	struct property_entry *ep_properties = sensor->ep_properties;
+	int i;
+
+	/* device fwnode properties */
+	memset(dev_properties, 0, sizeof(struct property_entry) * 3);
+
+	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
+					       ssdb->mclkspeed);
+	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
+
+	/* endpoint fwnode properties */
+	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
+
+	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
+					   GFP_KERNEL);
+
+	if (!sensor->data_lanes)
+		return -ENOMEM;
+
+	for (i = 0; i < ssdb->lanes; i++)
+		sensor->data_lanes[i] = i + 1;
+
+	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
+	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
+							sensor->data_lanes,
+							ssdb->lanes);
+	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
+
+	/* cio2 endpoint props */
+	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
+
+	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
+							  sensor->data_lanes,
+							  ssdb->lanes);
+	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
+
+	return 0;
+}
+
+static int create_connection_swnodes(struct sensor *sensor,
+				     struct sensor_bios_data *ssdb)
+{
+	struct software_node *nodes = sensor->swnodes;
+
+	memset(nodes, 0, sizeof(struct software_node) * 6);
+
+	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
+					       sensor->dev_properties);
+	nodes[SWNODE_SENSOR_PORT] = NODE_PORT("port0",
+					      &nodes[SWNODE_SENSOR_HID]);
+	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT("endpoint0",
+						      &nodes[SWNODE_SENSOR_PORT],
+						      sensor->ep_properties);
+	nodes[SWNODE_CIO2_PORT] = NODE_PORT(port_names[ssdb->link],
+					    &cio2_hid_node);
+	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT("endpoint0",
+						    &nodes[SWNODE_CIO2_PORT],
+						    sensor->cio2_properties);
+
+	return 0;
+}
+
+static void cio2_bridge_unregister_sensors(void)
+{
+	struct sensor *sensor;
+	int i;
+
+	for (i = 0; i < bridge.n_sensors; i++) {
+		sensor = &bridge.sensors[i];
+
+		software_node_unregister_nodes_reverse(sensor->swnodes);
+
+		kfree(sensor->data_lanes);
+
+		put_device(sensor->dev);
+		acpi_dev_put(sensor->adev);
+	}
+}
+
+static int connect_supported_devices(struct pci_dev *cio2)
+{
+	struct sensor_bios_data ssdb;
+	struct fwnode_handle *fwnode;
+	struct acpi_device *adev;
+	struct sensor *sensor;
+	struct device *dev;
+	int i, ret;
+
+	ret = 0;
+	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
+		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
+		if (!adev)
+			continue;
+
+		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
+		if (!dev) {
+			ret = -EPROBE_DEFER;
+			goto err_rollback;
+		}
+
+		sensor = &bridge.sensors[bridge.n_sensors];
+		sensor->dev = dev;
+		sensor->adev = adev;
+
+		snprintf(sensor->name, ACPI_ID_LEN, "%s",
+			 supported_devices[i]);
+
+		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
+		if (ret)
+			goto err_free_dev;
+
+		ret = create_fwnode_properties(sensor, &ssdb);
+		if (ret)
+			goto err_free_dev;
+
+		ret = create_connection_swnodes(sensor, &ssdb);
+		if (ret)
+			goto err_free_dev;
+
+		ret = software_node_register_nodes(sensor->swnodes);
+		if (ret)
+			goto err_free_dev;
+
+		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
+		if (!fwnode) {
+			ret = -ENODEV;
+			goto err_free_swnodes;
+		}
+
+		set_secondary_fwnode(dev, fwnode);
+
+		dev_info(&cio2->dev, "Found supported device %s\n",
+			 supported_devices[i]);
+
+		bridge.n_sensors++;
+		continue;
+	}
+
+	return ret;
+
+err_free_swnodes:
+	software_node_unregister_nodes_reverse(sensor->swnodes);
+err_free_dev:
+	put_device(dev);
+err_rollback:
+	acpi_dev_put(adev);
+
+	/*
+	 * If an iteration of this loop results in -EPROBE_DEFER then
+	 * we need to roll back any sensors that were successfully
+	 * registered. Any other error and we'll skip that step, as
+	 * it seems better to have one successfully connected sensor.
+	 */
+
+	if (ret == -EPROBE_DEFER)
+		cio2_bridge_unregister_sensors();
+
+	return ret;
+}
+
+int cio2_bridge_build(struct pci_dev *cio2)
+{
+	struct fwnode_handle *fwnode;
+	int ret;
+
+	pci_dev_get(cio2);
+
+	ret = software_node_register(&cio2_hid_node);
+	if (ret < 0) {
+		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
+		goto err_put_cio2;
+	}
+
+	ret = connect_supported_devices(cio2);
+	if (ret == -EPROBE_DEFER)
+		goto err_unregister_cio2;
+
+	if (bridge.n_sensors == 0) {
+		ret = -EPROBE_DEFER;
+		goto err_unregister_cio2;
+	}
+
+	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
+
+	fwnode = software_node_fwnode(&cio2_hid_node);
+	if (!fwnode) {
+		dev_err(&cio2->dev,
+			"Error getting fwnode from cio2 software_node\n");
+		ret = -ENODEV;
+		goto err_unregister_sensors;
+	}
+
+	set_secondary_fwnode(&cio2->dev, fwnode);
+
+	return 0;
+
+err_unregister_sensors:
+	cio2_bridge_unregister_sensors();
+err_unregister_cio2:
+	software_node_unregister(&cio2_hid_node);
+err_put_cio2:
+	pci_dev_put(cio2);
+
+	return ret;
+}
+
+void cio2_bridge_burn(struct pci_dev *cio2)
+{
+	pci_dev_put(cio2);
+
+	cio2_bridge_unregister_sensors();
+
+	software_node_unregister(&cio2_hid_node);
+}
diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
new file mode 100644
index 000000000..077354ca8
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Author: Dan Scally <djrscally@gmail.com> */
+#ifndef __CIO2_BRIDGE_H
+#define __CIO2_BRIDGE_H
+
+#define MAX_CONNECTED_DEVICES			4
+#define SWNODE_SENSOR_HID			0
+#define SWNODE_SENSOR_PORT			1
+#define SWNODE_SENSOR_ENDPOINT			2
+#define SWNODE_CIO2_PORT			3
+#define SWNODE_CIO2_ENDPOINT			4
+#define SWNODE_NULL_TERMINATOR			5
+
+#define CIO2_HID				"INT343E"
+#define CIO2_PCI_ID				0x9d32
+
+#define ENDPOINT_SENSOR				0
+#define ENDPOINT_CIO2				1
+
+#define NODE_SENSOR(_HID, _PROPS)		\
+	((const struct software_node) {		\
+		.name = _HID,			\
+		.properties = _PROPS,		\
+	})
+
+#define NODE_PORT(_PORT, _SENSOR_NODE)		\
+	((const struct software_node) {		\
+		_PORT,				\
+		_SENSOR_NODE,			\
+	})
+
+#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
+	((const struct software_node) {		\
+		_EP,				\
+		_PORT,				\
+		_PROPS,				\
+	})
+
+struct sensor {
+	char name[ACPI_ID_LEN];
+	struct device *dev;
+	struct acpi_device *adev;
+	struct software_node swnodes[6];
+	struct property_entry dev_properties[3];
+	struct property_entry ep_properties[4];
+	struct property_entry cio2_properties[3];
+	u32 *data_lanes;
+};
+
+struct cio2_bridge {
+	int n_sensors;
+	struct sensor sensors[MAX_CONNECTED_DEVICES];
+};
+
+/* Data representation as it is in ACPI SSDB buffer */
+struct sensor_bios_data_packed {
+	u8 version;
+	u8 sku;
+	u8 guid_csi2[16];
+	u8 devfunction;
+	u8 bus;
+	u32 dphylinkenfuses;
+	u32 clockdiv;
+	u8 link;
+	u8 lanes;
+	u32 csiparams[10];
+	u32 maxlanespeed;
+	u8 sensorcalibfileidx;
+	u8 sensorcalibfileidxInMBZ[3];
+	u8 romtype;
+	u8 vcmtype;
+	u8 platforminfo;
+	u8 platformsubinfo;
+	u8 flash;
+	u8 privacyled;
+	u8 degree;
+	u8 mipilinkdefined;
+	u32 mclkspeed;
+	u8 controllogicid;
+	u8 reserved1[3];
+	u8 mclkport;
+	u8 reserved2[13];
+} __packed__;
+
+/* Fields needed by bridge driver */
+struct sensor_bios_data {
+	struct device *dev;
+	u8 link;
+	u8 lanes;
+	u8 degree;
+	u32 mclkspeed;
+};
+
+#endif
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index f68ef0f6b..827457110 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
 static int cio2_pci_probe(struct pci_dev *pci_dev,
 			  const struct pci_device_id *id)
 {
+	struct fwnode_handle *endpoint;
 	struct cio2_device *cio2;
 	int r;
 
+	/*
+	 * On some platforms no connections to sensors are defined in firmware,
+	 * if the device has no endpoints then we can try to build those as
+	 * software_nodes parsed from SSDB.
+	 *
+	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
+	 * but not yet ready for use (either not attached to the i2c bus yet,
+	 * or not done probing themselves).
+	 */
+
+	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&pci_dev->dev), NULL);
+	if (!endpoint) {
+		r = cio2_bridge_build(pci_dev);
+		if (r)
+			return r;
+	}
+
 	cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL);
 	if (!cio2)
 		return -ENOMEM;
@@ -1825,6 +1843,9 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
 {
 	struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
 
+	if (is_software_node(dev_fwnode(&pci_dev->dev)))
+		cio2_bridge_burn(pci_dev);
+
 	media_device_unregister(&cio2->media_dev);
 	v4l2_async_notifier_unregister(&cio2->notifier);
 	v4l2_async_notifier_cleanup(&cio2->notifier);
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
index 549b08f88..80a081d7e 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
@@ -436,4 +436,13 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
 	return container_of(vq, struct cio2_queue, vbq);
 }
 
+#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
+	int cio2_bridge_build(struct pci_dev *cio2);
+	void cio2_bridge_burn(struct pci_dev *cio2);
+#else
+
+	int cio2_bridge_build(struct pci_dev *cio2) { return 0; }
+	void cio2_bridge_burn(struct pci_dev *cio2) { }
+#endif
+
 #endif
-- 
2.17.1


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

* Re: [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-10-19 22:58 ` [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
@ 2020-10-20  7:23   ` Petr Mladek
  2020-10-20  9:20   ` Andy Shevchenko
  1 sibling, 0 replies; 82+ messages in thread
From: Petr Mladek @ 2020-10-20  7:23 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus,
	yong.zhi, rafael, gregkh, kitakar, dan.carpenter

On Mon 2020-10-19 23:58:56, Daniel Scally wrote:
> Use the new software_node_unregister_nodes_reverse() function to
> unwind this array in a cleaner way.
> 
> Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

If the new API gets accepted:

Acked-by: Petr Mladek <pmladek@suse.com>

Best Regards,
Petr

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

* Re: [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name
  2020-10-19 22:59 ` [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name Daniel Scally
@ 2020-10-20  9:15   ` Andy Shevchenko
  2020-10-20 20:41     ` Dan Scally
  2020-10-24  0:34   ` Laurent Pinchart
  1 sibling, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:15 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:59:00PM +0100, Daniel Scally wrote:
> ipu3-cio2 driver needs extending with multiple files; rename the main
> source file and specify the renamed file in Makefile to accommodate that.

Suggested-by?

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
after addressing below comment.

> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- patch introduced
> 
>  drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
>  drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
>  2 files changed, 2 insertions(+)
>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)
> 
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 98ddd5bea..b4e3266d9 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,2 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +
> +ipu3-cio2-y += ipu3-cio2-main.o
> \ No newline at end of file

Don't forget to add \n at the end of above line.

> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> similarity index 100%
> rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
> rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS
  2020-10-19 22:58 ` [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
@ 2020-10-20  9:16   ` Andy Shevchenko
  2020-10-24  0:28   ` Laurent Pinchart
  1 sibling, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:16 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:58:59PM +0100, Daniel Scally wrote:
> Development for the ipu3-cio2 driver is taking place in media_tree, but
> there's no T: entry in MAINTAINERS to denote that - rectify that oversight

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- patch introduced.
> 	
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 43a025039..5d768d5ad 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8851,6 +8851,7 @@ M:	Bingbu Cao <bingbu.cao@intel.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> +T:	git git://linuxtv.org/media_tree.git
>  F:	Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
>  F:	drivers/media/pci/intel/ipu3/
>  
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions
  2020-10-19 22:58 ` [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
@ 2020-10-20  9:17   ` Andy Shevchenko
  2020-10-20 12:35   ` Sakari Ailus
  1 sibling, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:17 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:58:58PM +0100, Daniel Scally wrote:
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> This implements the remaining .graph_* callbacks in the
> fwnode operations vector for the software nodes. That makes
> the fwnode_graph*() functions available in the drivers also
> when software nodes are used.
> 
> The implementation tries to mimic the "OF graph" as much as
> possible, but there is no support for the "reg" device
> property. The ports will need to have the index in their
> name which starts with "port" (for example "port0", "port1",
> ...) and endpoints will use the index of the software node
> that is given to them during creation. The port nodes can
> also be grouped under a specially named "ports" subnode,
> just like in DT, if necessary.
> 
> The remote-endpoints are reference properties under the
> endpoint nodes that are named "remote-endpoint". 

FWIW,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Co-developed-by: Daniel Scally <djrscally@gmail.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> changes in v3:
> 	- removed software_node_device_is_available
> 	- moved the change to software_node_get_next_child to a separate
> 	patch
> 	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
> 	instead of software_node_put()
> 
> changes in v2:
> 	- added software_node_device_is_available
> 	- altered software_node_get_next_child to get references
> 	- altered software_node_get_next_endpoint to release references
> 	to ports and avoid passing invalid combinations of swnodes to
> 	software_node_get_next_child
> 	- altered swnode_graph_find_next_port to release port rather than
> 	old
>  drivers/base/swnode.c | 120 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 119 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 741149b90..3732530ce 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -536,6 +536,120 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
>  	return 0;
>  }
>  
> +static struct fwnode_handle *
> +swnode_graph_find_next_port(const struct fwnode_handle *parent,
> +			    struct fwnode_handle *port)
> +{
> +	struct fwnode_handle *old = port;
> +
> +	while ((port = software_node_get_next_child(parent, old))) {
> +		if (!strncmp(to_swnode(port)->node->name, "port", 4))
> +			return port;
> +		fwnode_handle_put(port);
> +		old = port;
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
> +				      struct fwnode_handle *endpoint)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	struct fwnode_handle *old = endpoint;
> +	struct fwnode_handle *parent_of_old;
> +	struct fwnode_handle *parent;
> +	struct fwnode_handle *port;
> +
> +	if (!swnode)
> +		return NULL;
> +
> +	if (endpoint) {
> +		port = software_node_get_parent(endpoint);
> +		parent = software_node_get_parent(port);
> +	} else {
> +		parent = software_node_get_named_child_node(fwnode, "ports");
> +		if (!parent)
> +			parent = software_node_get(&swnode->fwnode);
> +
> +		port = swnode_graph_find_next_port(parent, NULL);
> +	}
> +
> +	for (; port; port = swnode_graph_find_next_port(parent, port)) {
> +		if (old) {
> +			parent_of_old = software_node_get_parent(old);
> +
> +			if (parent_of_old != port)
> +				old = NULL;
> +
> +			fwnode_handle_put(parent_of_old);
> +		}
> +
> +		endpoint = software_node_get_next_child(port, old);
> +		fwnode_handle_put(old);
> +		if (endpoint)
> +			break;
> +
> +		fwnode_handle_put(port);
> +	}
> +
> +	fwnode_handle_put(port);
> +	fwnode_handle_put(parent);
> +
> +	return endpoint;
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	const struct software_node_ref_args *ref;
> +	const struct property_entry *prop;
> +
> +	if (!swnode)
> +		return NULL;
> +
> +	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
> +	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
> +		return NULL;
> +
> +	ref = prop->pointer;
> +
> +	return software_node_get(software_node_fwnode(ref[0].node));
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	struct fwnode_handle *parent;
> +
> +	if (!strcmp(swnode->parent->node->name, "ports"))
> +		parent = &swnode->parent->parent->fwnode;
> +	else
> +		parent = &swnode->parent->fwnode;
> +
> +	return software_node_get(parent);
> +}
> +
> +static int
> +software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> +				   struct fwnode_endpoint *endpoint)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	int ret;
> +
> +	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);
> +	if (ret)
> +		return ret;
> +
> +	endpoint->id = swnode->id;
> +	endpoint->local_fwnode = fwnode;
> +
> +	return 0;
> +}
> +
>  static const struct fwnode_operations software_node_ops = {
>  	.get = software_node_get,
>  	.put = software_node_put,
> @@ -547,7 +661,11 @@ static const struct fwnode_operations software_node_ops = {
>  	.get_parent = software_node_get_parent,
>  	.get_next_child_node = software_node_get_next_child,
>  	.get_named_child_node = software_node_get_named_child_node,
> -	.get_reference_args = software_node_get_reference_args
> +	.get_reference_args = software_node_get_reference_args,
> +	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
> +	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
> +	.graph_get_port_parent = software_node_graph_get_port_parent,
> +	.graph_parse_endpoint = software_node_graph_parse_endpoint,
>  };
>  
>  /* -------------------------------------------------------------------------- */
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-19 22:59 ` [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so Daniel Scally
@ 2020-10-20  9:19   ` Andy Shevchenko
  2020-10-20 12:06     ` Sakari Ailus
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:19 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> only; that status being determined through the .device_is_available() op
> of the device's fwnode. As software_nodes don't have that operation and
> adding it is meaningless, we instead need to check if the device's fwnode
> is a software_node and if so pass the appropriate flag to disable that
> check

Period.

I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-10-19 22:58 ` [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
  2020-10-20  7:23   ` Petr Mladek
@ 2020-10-20  9:20   ` Andy Shevchenko
  1 sibling, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:20 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:58:56PM +0100, Daniel Scally wrote:
> Use the new software_node_unregister_nodes_reverse() function to
> unwind this array in a cleaner way.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- patch introduced.
> 
>  lib/test_printf.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/lib/test_printf.c b/lib/test_printf.c
> index 7ac87f18a..c63365570 100644
> --- a/lib/test_printf.c
> +++ b/lib/test_printf.c
> @@ -644,9 +644,7 @@ static void __init fwnode_pointer(void)
>  	test(second_name, "%pfwP", software_node_fwnode(&softnodes[1]));
>  	test(third_name, "%pfwP", software_node_fwnode(&softnodes[2]));
>  
> -	software_node_unregister(&softnodes[2]);
> -	software_node_unregister(&softnodes[1]);
> -	software_node_unregister(&softnodes[0]);
> +	software_node_unregister_nodes_reverse(softnodes);
>  }
>  
>  static void __init
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
@ 2020-10-20  9:22   ` Andy Shevchenko
  2020-10-20 10:05   ` Sakari Ailus
  1 sibling, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:22 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> Software nodes that are children of another software node should be
> unregistered before their parent. To allow easy unregistering of an array
> of software_nodes ordered parent to child, add a helper function to loop
> over and unregister nodes in such an array in reverse order.

> Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>

For all patches Andriy -> Andy (email stays as above!).

...

> +/**
> + * software_node_unregister_nodes_reverse - Unregister an array of software
> + * nodes in reverse order.

Can you shrink this to one line?

Something like dropping ' in reverse order.' and adding it below...

> + * @nodes: Array of software nodes to be unregistered.
> + *

...like here to explain reversed order?

> + * NOTE: The same warning applies as with software_node_unregister_nodes.

software_node_unregister_nodes()

> + * Unless you are _sure_ that the array of nodes is ordered parent to child
> + * it is wiser to remove them individually in the correct order.
> + */
> +void software_node_unregister_nodes_reverse(const struct software_node *nodes)
> +{
> +	unsigned int i = 0;
> +
> +	while (nodes[i].name)
> +		i++;
> +
> +	while (i--)
> +		software_node_unregister(&nodes[i]);
> +}

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (8 preceding siblings ...)
  2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-10-20  9:24 ` Andy Shevchenko
  2020-10-20 13:38 ` Rafael J. Wysocki
  10 siblings, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:24 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:58:54PM +0100, Daniel Scally wrote:
> Hello all
> 
> This series adds support to the ipu3-cio2 driver for fwnode connections
> between cio2 and sensors to be defined via software_nodes. The final patch
> in the series deals wholly with those changes - the preceding patches are
> either supporting changes to accommodate that or incidental fixes along
> the way:
> 
> 1/9 adds a function to drivers/base/swnode.c unwinding arrays of software
> nodes in reverse order
> 
> 2/9 uses that function in lib/test_printf.c
> 
> 3/9 fixes what seems to me to be a bug in the existing swnode.c code in
> that software_node_get_next_child() does not increase the refcount of the
> returned node (in contrast to, for example, of_get_next_child_node() which
> does increase the count)
> 
> 4/9 adds the fwnode_graph*() family of functions to the software_node
> implementation
> 
> 5/9 adds a T: entry to MAINTAINERS for the ipu3-cio2 driver
> 
> 6/9 renames the ipu3-cio2.c file to ipu3-cio2-main.c and fixes Makefile
> to accommodate that change
> 
> 7/9 alters the ipu3-cio2 driver to check if the pci_dev's fwnode is a
> software_node and pass flags to fwnode_graph_get_endpoint_by_id() if so
> 
> 8/9 alters match_fwnode() in v4l2-async.c to additionally try to match on
> a fwnode_handle's secondary if the primary doesn't match
> 
> 9/9 alters the ipu3-cio2 driver to do the actual building of software_node
> connections between the sensor devices and the cio2 device.

Thanks!
I have mostly cosmetic comments.

> This is still not ready for integration - hence the RFC label - as there
> is ongoing work to extend the ipu3-cio2 driver further to parse ACPI
> to discover resources such as regulators and GPIOs that are defined there
> in unusual ways and map them to the sensor devices so that their drivers
> can consume them transparently through the usual frameworks. Given this
> has changed quite extensively from v2 though, I wanted to submit it for
> feedback at this point in case it needs further large scale change.

From my point of view it's a good start to drop RFC from next version
(RFC v3 -> v1). But let's wait couple of weeks for people to comment (now is a
second week of merge window, not everybody looking into the mailing lists).

> Daniel Scally (8):
>   software_node: Add helper function to unregister arrays of
>     software_nodes ordered parent to child
>   lib/test_printf.c: Use helper function to unwind array of
>     software_nodes
>   software_node: Fix failure to hold refcount in
>     software_node_get_next_child
>   ipu3-cio2: Add T: entry to MAINTAINERS
>   ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from
>     multiple sources files retaining ipu3-cio2 name
>   ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in
>     cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
>   media: v4l2-core: v4l2-async: Check possible match in match_fwnode
>     based on sd->fwnode->secondary
>   ipu3-cio2: Add functionality allowing software_node connections to
>     sensors on platforms designed for Windows
> 
> Heikki Krogerus (1):
>   software_node: Add support for fwnode_graph*() family of functions
> 
>  MAINTAINERS                                   |   2 +
>  drivers/base/swnode.c                         | 143 +++++++-
>  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
>  drivers/media/pci/intel/ipu3/Makefile         |   3 +
>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
>  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
>  .../ipu3/{ipu3-cio2.c => ipu3-cio2-main.c}    |  30 +-
>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
>  drivers/media/v4l2-core/v4l2-async.c          |   8 +
>  include/linux/property.h                      |   1 +
>  lib/test_printf.c                             |   4 +-
>  11 files changed, 632 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (98%)
> 
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-10-20  9:41   ` Andy Shevchenko
  2020-10-21 22:05     ` Daniel Scally
  2020-10-24  1:24   ` Laurent Pinchart
  2020-10-24 15:14   ` Sakari Ailus
  2 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20  9:41 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> Currently on platforms designed for Windows, connections between CIO2 and
> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> driver to compensate by building software_node connections, parsing the
> connection properties from the sensor's SSDB buffer.

...

> +	  	- Some Microsoft Surface models

Perhaps an example? Like '(e.g. Surface Book)'

> +		- The Lenovo Miix line

Ditto.

> +		- Dell 7285

...

> +#include <linux/acpi.h>
> +#include <linux/device.h>

> +#include <linux/fwnode.h>

This is implied by property.h, no need to have an explicit inclusion.

> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/property.h>
> +#include <media/v4l2-subdev.h>

...

> +static const char * const port_names[] = {
> +	"port0", "port1", "port2", "port3"

+ comma.

> +};

...

> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct acpi_handle *handle;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret;
> +
> +	handle = ACPI_HANDLE(dev);
> +
> +	status = acpi_evaluate_object(handle, id, NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(dev, "Couldn't locate ACPI buffer\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(dev, "Couldn't read ACPI buffer\n");

"not an ACPI buffer"

> +		ret = -ENODEV;

> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > size) {
> +		dev_err(dev, "Given buffer is too small\n");

> +		ret = -ENODEV;

-EINVAL?

> +		goto out_free_buff;
> +	}
> +
> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> +	ret = obj->buffer.length;
> +
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}

...

> +	/* device fwnode properties */
> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);

3 -> sizeof(...) ?
Same Q to other similar cases.

...

> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
> +					   GFP_KERNEL);

Perhaps one line?

> +

Redundant blank line.

> +	if (!sensor->data_lanes)
> +		return -ENOMEM;

...

> +static int connect_supported_devices(struct pci_dev *cio2)
> +{
> +	struct sensor_bios_data ssdb;
> +	struct fwnode_handle *fwnode;
> +	struct acpi_device *adev;
> +	struct sensor *sensor;
> +	struct device *dev;
> +	int i, ret;
> +
> +	ret = 0;
> +	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> +		if (!adev)
> +			continue;
> +
> +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
> +		if (!dev) {
> +			ret = -EPROBE_DEFER;
> +			goto err_rollback;
> +		}
> +
> +		sensor = &bridge.sensors[bridge.n_sensors];
> +		sensor->dev = dev;
> +		sensor->adev = adev;

> +		snprintf(sensor->name, ACPI_ID_LEN, "%s",
> +			 supported_devices[i]);

One line?

> +		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_fwnode_properties(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_connection_swnodes(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = software_node_register_nodes(sensor->swnodes);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> +		if (!fwnode) {
> +			ret = -ENODEV;
> +			goto err_free_swnodes;
> +		}
> +
> +		set_secondary_fwnode(dev, fwnode);

> +		dev_info(&cio2->dev, "Found supported device %s\n",
> +			 supported_devices[i]);

One line?

(In both cases you can use temporary variable to keep supported_devices[i])

> +		bridge.n_sensors++;
> +		continue;
> +	}
> +
> +	return ret;
> +
> +err_free_swnodes:
> +	software_node_unregister_nodes_reverse(sensor->swnodes);
> +err_free_dev:
> +	put_device(dev);
> +err_rollback:
> +	acpi_dev_put(adev);
> +
> +	/*
> +	 * If an iteration of this loop results in -EPROBE_DEFER then
> +	 * we need to roll back any sensors that were successfully
> +	 * registered. Any other error and we'll skip that step, as
> +	 * it seems better to have one successfully connected sensor.
> +	 */
> +
> +	if (ret == -EPROBE_DEFER)
> +		cio2_bridge_unregister_sensors();
> +
> +	return ret;
> +}
> +
> +int cio2_bridge_build(struct pci_dev *cio2)
> +{

	struct device *dev = &cio2->dev;

will help to clean the code below.

> +	struct fwnode_handle *fwnode;
> +	int ret;
> +
> +	pci_dev_get(cio2);
> +
> +	ret = software_node_register(&cio2_hid_node);
> +	if (ret < 0) {
> +		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
> +		goto err_put_cio2;
> +	}
> +
> +	ret = connect_supported_devices(cio2);
> +	if (ret == -EPROBE_DEFER)
> +		goto err_unregister_cio2;
> +
> +	if (bridge.n_sensors == 0) {
> +		ret = -EPROBE_DEFER;
> +		goto err_unregister_cio2;
> +	}
> +
> +	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
> +
> +	fwnode = software_node_fwnode(&cio2_hid_node);
> +	if (!fwnode) {

> +		dev_err(&cio2->dev,
> +			"Error getting fwnode from cio2 software_node\n");

One line (after above change)

> +		ret = -ENODEV;
> +		goto err_unregister_sensors;
> +	}
> +
> +	set_secondary_fwnode(&cio2->dev, fwnode);
> +
> +	return 0;
> +
> +err_unregister_sensors:
> +	cio2_bridge_unregister_sensors();
> +err_unregister_cio2:
> +	software_node_unregister(&cio2_hid_node);
> +err_put_cio2:
> +	pci_dev_put(cio2);
> +
> +	return ret;
> +}
> +
> +void cio2_bridge_burn(struct pci_dev *cio2)
> +{
> +	pci_dev_put(cio2);
> +
> +	cio2_bridge_unregister_sensors();
> +
> +	software_node_unregister(&cio2_hid_node);
> +}

I would rather name them like
build -> init / register / ...
burn -> clean / unregister / ...

...

> +#ifndef __CIO2_BRIDGE_H
> +#define __CIO2_BRIDGE_H

Missed inclusion that defines struct software_nodes type.

And so on. This file is consumer of some types and you need either to include
corresponding headers, or provide a forward declarations (for example, no need
to include device.h or acpi.h AFAICS).

> +#define MAX_CONNECTED_DEVICES			4
> +#define SWNODE_SENSOR_HID			0
> +#define SWNODE_SENSOR_PORT			1
> +#define SWNODE_SENSOR_ENDPOINT			2
> +#define SWNODE_CIO2_PORT			3
> +#define SWNODE_CIO2_ENDPOINT			4
> +#define SWNODE_NULL_TERMINATOR			5
> +
> +#define CIO2_HID				"INT343E"
> +#define CIO2_PCI_ID				0x9d32
> +
> +#define ENDPOINT_SENSOR				0
> +#define ENDPOINT_CIO2				1
> +
> +#define NODE_SENSOR(_HID, _PROPS)		\
> +	((const struct software_node) {		\
> +		.name = _HID,			\
> +		.properties = _PROPS,		\
> +	})
> +
> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> +	((const struct software_node) {		\
> +		_PORT,				\
> +		_SENSOR_NODE,			\
> +	})
> +
> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> +	((const struct software_node) {		\
> +		_EP,				\
> +		_PORT,				\
> +		_PROPS,				\
> +	})
> +
> +struct sensor {
> +	char name[ACPI_ID_LEN];
> +	struct device *dev;
> +	struct acpi_device *adev;
> +	struct software_node swnodes[6];
> +	struct property_entry dev_properties[3];
> +	struct property_entry ep_properties[4];
> +	struct property_entry cio2_properties[3];
> +	u32 *data_lanes;
> +};
> +
> +struct cio2_bridge {
> +	int n_sensors;
> +	struct sensor sensors[MAX_CONNECTED_DEVICES];
> +};
> +
> +/* Data representation as it is in ACPI SSDB buffer */
> +struct sensor_bios_data_packed {
> +	u8 version;
> +	u8 sku;
> +	u8 guid_csi2[16];
> +	u8 devfunction;
> +	u8 bus;
> +	u32 dphylinkenfuses;
> +	u32 clockdiv;
> +	u8 link;
> +	u8 lanes;
> +	u32 csiparams[10];
> +	u32 maxlanespeed;
> +	u8 sensorcalibfileidx;
> +	u8 sensorcalibfileidxInMBZ[3];
> +	u8 romtype;
> +	u8 vcmtype;
> +	u8 platforminfo;
> +	u8 platformsubinfo;
> +	u8 flash;
> +	u8 privacyled;
> +	u8 degree;
> +	u8 mipilinkdefined;
> +	u32 mclkspeed;
> +	u8 controllogicid;
> +	u8 reserved1[3];
> +	u8 mclkport;
> +	u8 reserved2[13];
> +} __packed__;
> +
> +/* Fields needed by bridge driver */
> +struct sensor_bios_data {
> +	struct device *dev;
> +	u8 link;
> +	u8 lanes;
> +	u8 degree;
> +	u32 mclkspeed;
> +};

...

> +	/*
> +	 * On some platforms no connections to sensors are defined in firmware,
> +	 * if the device has no endpoints then we can try to build those as
> +	 * software_nodes parsed from SSDB.
> +	 *
> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
> +	 * but not yet ready for use (either not attached to the i2c bus yet,
> +	 * or not done probing themselves).
> +	 */
> +
> +	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&pci_dev->dev), NULL);
> +	if (!endpoint) {
> +		r = cio2_bridge_build(pci_dev);
> +		if (r)
> +			return r;
> +	}
> +
>  	cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL);
>  	if (!cio2)
>  		return -ENOMEM;
> @@ -1825,6 +1843,9 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
>  {
>  	struct cio2_device *cio2 = pci_get_drvdata(pci_dev);

> +	if (is_software_node(dev_fwnode(&pci_dev->dev)))

Can we use the same check as for _build call above?

> +		cio2_bridge_burn(pci_dev);

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
  2020-10-20  9:22   ` Andy Shevchenko
@ 2020-10-20 10:05   ` Sakari Ailus
  2020-10-20 11:01     ` Andy Shevchenko
  2020-10-20 22:52     ` Dan Scally
  1 sibling, 2 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 10:05 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

Hi Daniel, Andy,

On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> Software nodes that are children of another software node should be
> unregistered before their parent. To allow easy unregistering of an array
> of software_nodes ordered parent to child, add a helper function to loop
> over and unregister nodes in such an array in reverse order.
> 
> Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- patch introduced.
> 
>  drivers/base/swnode.c    | 21 +++++++++++++++++++++
>  include/linux/property.h |  1 +
>  2 files changed, 22 insertions(+)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 010828fc7..f01b1cc61 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -727,6 +727,27 @@ void software_node_unregister_nodes(const struct software_node *nodes)
>  }
>  EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
>  
> +/**
> + * software_node_unregister_nodes_reverse - Unregister an array of software
> + * nodes in reverse order.
> + * @nodes: Array of software nodes to be unregistered.
> + *
> + * NOTE: The same warning applies as with software_node_unregister_nodes.
> + * Unless you are _sure_ that the array of nodes is ordered parent to child
> + * it is wiser to remove them individually in the correct order.

Could the default order in software_node_unregister_nodes() be reversed
instead? There are no users so this should be easy to change.

Doing this only one way may require enforcing the registration order in
software_node_register_nodes(), but the end result would be safer.

What do you think?

-- 
Regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-20 10:05   ` Sakari Ailus
@ 2020-10-20 11:01     ` Andy Shevchenko
  2020-10-20 11:02       ` Andy Shevchenko
  2020-10-20 11:04       ` Heikki Krogerus
  2020-10-20 22:52     ` Dan Scally
  1 sibling, 2 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20 11:01 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Daniel Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On Tue, Oct 20, 2020 at 01:05:10PM +0300, Sakari Ailus wrote:
> On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> > Software nodes that are children of another software node should be
> > unregistered before their parent. To allow easy unregistering of an array
> > of software_nodes ordered parent to child, add a helper function to loop
> > over and unregister nodes in such an array in reverse order.

...

> > + * software_node_unregister_nodes_reverse - Unregister an array of software
> > + * nodes in reverse order.
> > + * @nodes: Array of software nodes to be unregistered.
> > + *
> > + * NOTE: The same warning applies as with software_node_unregister_nodes.
> > + * Unless you are _sure_ that the array of nodes is ordered parent to child
> > + * it is wiser to remove them individually in the correct order.
> 
> Could the default order in software_node_unregister_nodes() be reversed
> instead? There are no users so this should be easy to change.
> 
> Doing this only one way may require enforcing the registration order in
> software_node_register_nodes(), but the end result would be safer.
> 
> What do you think?

Will work for me (I would also hear Heikki).

But in such case let's change the order of
software_node_unregister_node_group() for the sake of consistency.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-20 11:01     ` Andy Shevchenko
@ 2020-10-20 11:02       ` Andy Shevchenko
  2020-10-20 11:04       ` Heikki Krogerus
  1 sibling, 0 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-20 11:02 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Daniel Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On Tue, Oct 20, 2020 at 02:01:55PM +0300, Andy Shevchenko wrote:
> On Tue, Oct 20, 2020 at 01:05:10PM +0300, Sakari Ailus wrote:
> > On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> > > Software nodes that are children of another software node should be
> > > unregistered before their parent. To allow easy unregistering of an array
> > > of software_nodes ordered parent to child, add a helper function to loop
> > > over and unregister nodes in such an array in reverse order.
> 
> ...
> 
> > > + * software_node_unregister_nodes_reverse - Unregister an array of software
> > > + * nodes in reverse order.
> > > + * @nodes: Array of software nodes to be unregistered.
> > > + *
> > > + * NOTE: The same warning applies as with software_node_unregister_nodes.
> > > + * Unless you are _sure_ that the array of nodes is ordered parent to child
> > > + * it is wiser to remove them individually in the correct order.
> > 
> > Could the default order in software_node_unregister_nodes() be reversed
> > instead? There are no users so this should be easy to change.
> > 
> > Doing this only one way may require enforcing the registration order in
> > software_node_register_nodes(), but the end result would be safer.
> > 
> > What do you think?
> 
> Will work for me (I would also hear Heikki).
> 
> But in such case let's change the order of
> software_node_unregister_node_group() for the sake of consistency.

But either way we will need a note to describe the ordering.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-20 11:01     ` Andy Shevchenko
  2020-10-20 11:02       ` Andy Shevchenko
@ 2020-10-20 11:04       ` Heikki Krogerus
  1 sibling, 0 replies; 82+ messages in thread
From: Heikki Krogerus @ 2020-10-20 11:04 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sakari Ailus, Daniel Scally, linux-kernel, linux-media,
	linux.walleij, prabhakar.mahadev-lad.rj, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On Tue, Oct 20, 2020 at 02:01:55PM +0300, Andy Shevchenko wrote:
> On Tue, Oct 20, 2020 at 01:05:10PM +0300, Sakari Ailus wrote:
> > On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> > > Software nodes that are children of another software node should be
> > > unregistered before their parent. To allow easy unregistering of an array
> > > of software_nodes ordered parent to child, add a helper function to loop
> > > over and unregister nodes in such an array in reverse order.
> 
> ...
> 
> > > + * software_node_unregister_nodes_reverse - Unregister an array of software
> > > + * nodes in reverse order.
> > > + * @nodes: Array of software nodes to be unregistered.
> > > + *
> > > + * NOTE: The same warning applies as with software_node_unregister_nodes.
> > > + * Unless you are _sure_ that the array of nodes is ordered parent to child
> > > + * it is wiser to remove them individually in the correct order.
> > 
> > Could the default order in software_node_unregister_nodes() be reversed
> > instead? There are no users so this should be easy to change.
> > 
> > Doing this only one way may require enforcing the registration order in
> > software_node_register_nodes(), but the end result would be safer.
> > 
> > What do you think?
> 
> Will work for me (I would also hear Heikki).

Sounds reasonable to me.

thanks,

-- 
heikki

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-20  9:19   ` Andy Shevchenko
@ 2020-10-20 12:06     ` Sakari Ailus
  2020-10-20 19:56       ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 12:06 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Hi Andy,

On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> > fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> > only; that status being determined through the .device_is_available() op
> > of the device's fwnode. As software_nodes don't have that operation and
> > adding it is meaningless, we instead need to check if the device's fwnode
> > is a software_node and if so pass the appropriate flag to disable that
> > check
> 
> Period.
> 
> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().

The device availability test is actually there for a reason. Some firmware
implementations put all the potential devices in the tables and only one
(of some) of them are available.

Could this be implemented so that if the node is a software node, then get
its parent and then see if that is available?

I guess that could be implemented in software node ops. Any opinions?

-- 
Kind regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions
  2020-10-19 22:58 ` [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
  2020-10-20  9:17   ` Andy Shevchenko
@ 2020-10-20 12:35   ` Sakari Ailus
  2020-10-20 13:32     ` Sakari Ailus
  1 sibling, 1 reply; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 12:35 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

Hi Daniel, Heikki,

Thanks for the patch.

On Mon, Oct 19, 2020 at 11:58:58PM +0100, Daniel Scally wrote:
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> This implements the remaining .graph_* callbacks in the
> fwnode operations vector for the software nodes. That makes
> the fwnode_graph*() functions available in the drivers also
> when software nodes are used.
> 
> The implementation tries to mimic the "OF graph" as much as
> possible, but there is no support for the "reg" device
> property. The ports will need to have the index in their
> name which starts with "port" (for example "port0", "port1",
> ...) and endpoints will use the index of the software node
> that is given to them during creation. The port nodes can
> also be grouped under a specially named "ports" subnode,
> just like in DT, if necessary.
> 
> The remote-endpoints are reference properties under the
> endpoint nodes that are named "remote-endpoint". 
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Co-developed-by: Daniel Scally <djrscally@gmail.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> changes in v3:
> 	- removed software_node_device_is_available
> 	- moved the change to software_node_get_next_child to a separate
> 	patch
> 	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
> 	instead of software_node_put()
> 
> changes in v2:
> 	- added software_node_device_is_available
> 	- altered software_node_get_next_child to get references
> 	- altered software_node_get_next_endpoint to release references
> 	to ports and avoid passing invalid combinations of swnodes to
> 	software_node_get_next_child
> 	- altered swnode_graph_find_next_port to release port rather than
> 	old
>  drivers/base/swnode.c | 120 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 119 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 741149b90..3732530ce 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -536,6 +536,120 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
>  	return 0;
>  }
>  
> +static struct fwnode_handle *
> +swnode_graph_find_next_port(const struct fwnode_handle *parent,
> +			    struct fwnode_handle *port)
> +{
> +	struct fwnode_handle *old = port;
> +
> +	while ((port = software_node_get_next_child(parent, old))) {

software_node_get_next_child() doesn't drop the reference of the old child
nor gets a reference to the returned node. Should it?

The function to get a named child node does.

It'd be nice if this was aligned. Or am I missing something?

This isn't really a comment on this patch though.

-- 
Kind regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-19 22:58 ` [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child Daniel Scally
@ 2020-10-20 12:44   ` Rafael J. Wysocki
  2020-10-20 13:31   ` Sakari Ailus
  1 sibling, 0 replies; 82+ messages in thread
From: Rafael J. Wysocki @ 2020-10-20 12:44 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Linux Kernel Mailing List, Linux Media Mailing List,
	linux.walleij, prabhakar.mahadev-lad.rj, Heikki Krogerus,
	Dmitry Torokhov, Laurent Pinchart, Kieran Bingham, Jacopo Mondi,
	Rob Herring, David Miller, Rasmus Villemoes, Andy Shevchenko,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, tian.shu.qiu, Bingbu Cao, Sakari Ailus,
	yong.zhi, Rafael J. Wysocki, Greg Kroah-Hartman, kitakar,
	dan.carpenter

On Tue, Oct 20, 2020 at 12:59 AM Daniel Scally <djrscally@gmail.com> wrote:
>
> The software_node_get_next_child() function currently does not hold a kref
> to the child software_node; fix that.
>
> Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the firmware node framework")
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
>         - split out from the full software_node_graph*() patch
>
>  drivers/base/swnode.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index f01b1cc61..741149b90 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -450,7 +450,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>                 c = list_next_entry(c, entry);
>         else
>                 c = list_first_entry(&p->children, struct swnode, entry);
> -       return &c->fwnode;
> +       return software_node_get(&c->fwnode);
>  }
>
>  static struct fwnode_handle *
> --

This should be sent as a separate fix AFAICS.

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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-19 22:58 ` [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child Daniel Scally
  2020-10-20 12:44   ` Rafael J. Wysocki
@ 2020-10-20 13:31   ` Sakari Ailus
  2020-10-20 23:25     ` Dan Scally
  1 sibling, 1 reply; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 13:31 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Daniel,

On Mon, Oct 19, 2020 at 11:58:57PM +0100, Daniel Scally wrote:
> The software_node_get_next_child() function currently does not hold a kref
> to the child software_node; fix that.
> 
> Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the firmware node framework")
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- split out from the full software_node_graph*() patch
> 
>  drivers/base/swnode.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index f01b1cc61..741149b90 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -450,7 +450,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>  		c = list_next_entry(c, entry);
>  	else
>  		c = list_first_entry(&p->children, struct swnode, entry);
> -	return &c->fwnode;
> +	return software_node_get(&c->fwnode);

I believe similarly, the function should drop the reference to the previous
node, and not expect the caller to do this. The OF equivalent does the
same.

>  }
>  
>  static struct fwnode_handle *

-- 
Kind regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions
  2020-10-20 12:35   ` Sakari Ailus
@ 2020-10-20 13:32     ` Sakari Ailus
  0 siblings, 0 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 13:32 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Daniel Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Tue, Oct 20, 2020 at 03:35:56PM +0300, Sakari Ailus wrote:
> Hi Daniel, Heikki,
> 
> Thanks for the patch.
> 
> On Mon, Oct 19, 2020 at 11:58:58PM +0100, Daniel Scally wrote:
> > From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > 
> > This implements the remaining .graph_* callbacks in the
> > fwnode operations vector for the software nodes. That makes
> > the fwnode_graph*() functions available in the drivers also
> > when software nodes are used.
> > 
> > The implementation tries to mimic the "OF graph" as much as
> > possible, but there is no support for the "reg" device
> > property. The ports will need to have the index in their
> > name which starts with "port" (for example "port0", "port1",
> > ...) and endpoints will use the index of the software node
> > that is given to them during creation. The port nodes can
> > also be grouped under a specially named "ports" subnode,
> > just like in DT, if necessary.
> > 
> > The remote-endpoints are reference properties under the
> > endpoint nodes that are named "remote-endpoint". 
> > 
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > Co-developed-by: Daniel Scally <djrscally@gmail.com>
> > Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > ---
> > changes in v3:
> > 	- removed software_node_device_is_available
> > 	- moved the change to software_node_get_next_child to a separate
> > 	patch
> > 	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
> > 	instead of software_node_put()
> > 
> > changes in v2:
> > 	- added software_node_device_is_available
> > 	- altered software_node_get_next_child to get references
> > 	- altered software_node_get_next_endpoint to release references
> > 	to ports and avoid passing invalid combinations of swnodes to
> > 	software_node_get_next_child
> > 	- altered swnode_graph_find_next_port to release port rather than
> > 	old
> >  drivers/base/swnode.c | 120 +++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 119 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> > index 741149b90..3732530ce 100644
> > --- a/drivers/base/swnode.c
> > +++ b/drivers/base/swnode.c
> > @@ -536,6 +536,120 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
> >  	return 0;
> >  }
> >  
> > +static struct fwnode_handle *
> > +swnode_graph_find_next_port(const struct fwnode_handle *parent,
> > +			    struct fwnode_handle *port)
> > +{
> > +	struct fwnode_handle *old = port;
> > +
> > +	while ((port = software_node_get_next_child(parent, old))) {
> 
> software_node_get_next_child() doesn't drop the reference of the old child
> nor gets a reference to the returned node. Should it?
> 
> The function to get a named child node does.
> 
> It'd be nice if this was aligned. Or am I missing something?
> 
> This isn't really a comment on this patch though.

I didn't get this patch to my @linux.intel.com account so I guess it's our
mail servers again...

Anyway, please see my comments on that and ignore this one.

-- 
Sakari Ailus

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

* Re: [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (9 preceding siblings ...)
  2020-10-20  9:24 ` [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver " Andy Shevchenko
@ 2020-10-20 13:38 ` Rafael J. Wysocki
  2020-10-21 20:59   ` Daniel Scally
  10 siblings, 1 reply; 82+ messages in thread
From: Rafael J. Wysocki @ 2020-10-20 13:38 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Linux Kernel Mailing List, Linux Media Mailing List,
	prabhakar.mahadev-lad.rj, Heikki Krogerus, Dmitry Torokhov,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, Rob Herring,
	David Miller, Rasmus Villemoes, Andy Shevchenko,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, tian.shu.qiu, Bingbu Cao, Sakari Ailus,
	yong.zhi, Rafael J. Wysocki, Greg Kroah-Hartman, kitakar,
	dan.carpenter, Linus Walleij

[Fix the Linus Walleij's address.]

On Tue, Oct 20, 2020 at 12:59 AM Daniel Scally <djrscally@gmail.com> wrote:
>
> Hello all
>
> This series adds support to the ipu3-cio2 driver for fwnode connections
> between cio2 and sensors to be defined via software_nodes. The final patch
> in the series deals wholly with those changes - the preceding patches are
> either supporting changes to accommodate that or incidental fixes along
> the way:
>
> 1/9 adds a function to drivers/base/swnode.c unwinding arrays of software
> nodes in reverse order
>
> 2/9 uses that function in lib/test_printf.c
>
> 3/9 fixes what seems to me to be a bug in the existing swnode.c code in
> that software_node_get_next_child() does not increase the refcount of the
> returned node (in contrast to, for example, of_get_next_child_node() which
> does increase the count)
>
> 4/9 adds the fwnode_graph*() family of functions to the software_node
> implementation
>
> 5/9 adds a T: entry to MAINTAINERS for the ipu3-cio2 driver
>
> 6/9 renames the ipu3-cio2.c file to ipu3-cio2-main.c and fixes Makefile
> to accommodate that change
>
> 7/9 alters the ipu3-cio2 driver to check if the pci_dev's fwnode is a
> software_node and pass flags to fwnode_graph_get_endpoint_by_id() if so
>
> 8/9 alters match_fwnode() in v4l2-async.c to additionally try to match on
> a fwnode_handle's secondary if the primary doesn't match
>
> 9/9 alters the ipu3-cio2 driver to do the actual building of software_node
> connections between the sensor devices and the cio2 device.
>
> This is still not ready for integration - hence the RFC label - as there
> is ongoing work to extend the ipu3-cio2 driver further to parse ACPI
> to discover resources such as regulators and GPIOs that are defined there
> in unusual ways and map them to the sensor devices so that their drivers
> can consume them transparently through the usual frameworks. Given this
> has changed quite extensively from v2 though, I wanted to submit it for
> feedback at this point in case it needs further large scale change.

I would appreciate it if you posted the next version of this series
(all patches) to linux-acpi@vger.kernel.org for easier review.

Thanks!

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-20 12:06     ` Sakari Ailus
@ 2020-10-20 19:56       ` Dan Scally
  2020-10-20 22:49         ` Sakari Ailus
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-20 19:56 UTC (permalink / raw)
  To: Sakari Ailus, Andy Shevchenko
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Hi Sakari

On 20/10/2020 13:06, Sakari Ailus wrote:
> Hi Andy,
>
> On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
>> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
>>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
>>> only; that status being determined through the .device_is_available() op
>>> of the device's fwnode. As software_nodes don't have that operation and
>>> adding it is meaningless, we instead need to check if the device's fwnode
>>> is a software_node and if so pass the appropriate flag to disable that
>>> check
>> Period.
>>
>> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
> The device availability test is actually there for a reason. Some firmware
> implementations put all the potential devices in the tables and only one
> (of some) of them are available.
>
> Could this be implemented so that if the node is a software node, then get
> its parent and then see if that is available?
>
> I guess that could be implemented in software node ops. Any opinions?
Actually when considering the cio2 device, it seems that
set_secondary_fwnode() actually overwrites the _primary_, given
fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
this wouldn't work.

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

* Re: [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name
  2020-10-20  9:15   ` Andy Shevchenko
@ 2020-10-20 20:41     ` Dan Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-20 20:41 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On 20/10/2020 10:15, Andy Shevchenko wrote:
> On Mon, Oct 19, 2020 at 11:59:00PM +0100, Daniel Scally wrote:
>> ipu3-cio2 driver needs extending with multiple files; rename the main
>> source file and specify the renamed file in Makefile to accommodate that.
> Suggested-by?
Oops - yes of course, will add that next version.
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> after addressing below comment.
>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes in v3:
>> 	- patch introduced
>>
>>  drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
>>  drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
>>  2 files changed, 2 insertions(+)
>>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)
>>
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index 98ddd5bea..b4e3266d9 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -1,2 +1,4 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>> +
>> +ipu3-cio2-y += ipu3-cio2-main.o
>> \ No newline at end of file
> Don't forget to add \n at the end of above line.
>
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> similarity index 100%
>> rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
>> rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> -- 
>> 2.17.1
>>

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-20 19:56       ` Dan Scally
@ 2020-10-20 22:49         ` Sakari Ailus
  2020-10-20 22:55           ` Dan Scally
  2020-10-24  0:39           ` Laurent Pinchart
  0 siblings, 2 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-20 22:49 UTC (permalink / raw)
  To: Dan Scally
  Cc: Andy Shevchenko, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Hi Dan,

On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
> Hi Sakari
> 
> On 20/10/2020 13:06, Sakari Ailus wrote:
> > Hi Andy,
> >
> > On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
> >> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> >>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> >>> only; that status being determined through the .device_is_available() op
> >>> of the device's fwnode. As software_nodes don't have that operation and
> >>> adding it is meaningless, we instead need to check if the device's fwnode
> >>> is a software_node and if so pass the appropriate flag to disable that
> >>> check
> >> Period.
> >>
> >> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
> > The device availability test is actually there for a reason. Some firmware
> > implementations put all the potential devices in the tables and only one
> > (of some) of them are available.
> >
> > Could this be implemented so that if the node is a software node, then get
> > its parent and then see if that is available?
> >
> > I guess that could be implemented in software node ops. Any opinions?
> Actually when considering the cio2 device, it seems that
> set_secondary_fwnode() actually overwrites the _primary_, given
> fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
> this wouldn't work.

Ouch. I wonder when this happens --- have you checked what's the primary
there? I guess it might be if it's a PCI device without the corresponding
ACPI device node?

I remember you had an is_available implementation that just returned true
for software nodes in an early version of the set? I think it would still
be a lesser bad in this case.

-- 
Regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-20 10:05   ` Sakari Ailus
  2020-10-20 11:01     ` Andy Shevchenko
@ 2020-10-20 22:52     ` Dan Scally
  2020-10-21  9:40       ` Andy Shevchenko
  1 sibling, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-20 22:52 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

Hi Sakari

On 20/10/2020 11:05, Sakari Ailus wrote:
> Hi Daniel, Andy,
>
> On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
>> Software nodes that are children of another software node should be
>> unregistered before their parent. To allow easy unregistering of an array
>> of software_nodes ordered parent to child, add a helper function to loop
>> over and unregister nodes in such an array in reverse order.
>>
>> Suggested-by: Andriy Shevchenko <andriy.shevchenko@linux.intel.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes in v3:
>> 	- patch introduced.
>>
>>  drivers/base/swnode.c    | 21 +++++++++++++++++++++
>>  include/linux/property.h |  1 +
>>  2 files changed, 22 insertions(+)
>>
>> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
>> index 010828fc7..f01b1cc61 100644
>> --- a/drivers/base/swnode.c
>> +++ b/drivers/base/swnode.c
>> @@ -727,6 +727,27 @@ void software_node_unregister_nodes(const struct software_node *nodes)
>>  }
>>  EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
>>  
>> +/**
>> + * software_node_unregister_nodes_reverse - Unregister an array of software
>> + * nodes in reverse order.
>> + * @nodes: Array of software nodes to be unregistered.
>> + *
>> + * NOTE: The same warning applies as with software_node_unregister_nodes.
>> + * Unless you are _sure_ that the array of nodes is ordered parent to child
>> + * it is wiser to remove them individually in the correct order.
> Could the default order in software_node_unregister_nodes() be reversed
> instead? There are no users so this should be easy to change.
>
> Doing this only one way may require enforcing the registration order in
> software_node_register_nodes(), but the end result would be safer.
>
> What do you think?

Yeah fine by me. We can just use software_node_to_swnode(node->parent)
within software_node_unregister_nodes() to check that children come
after their parents have already been processed. I'll add a patch to do
that in the next version of this series, and another changing the
ordering of software_node_unregister_node_group() as Andy suggests for
consistency.


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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-20 22:49         ` Sakari Ailus
@ 2020-10-20 22:55           ` Dan Scally
  2020-10-24  0:39           ` Laurent Pinchart
  1 sibling, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-20 22:55 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Andy Shevchenko, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

Hi Sakari

On 20/10/2020 23:49, Sakari Ailus wrote:
> Hi Dan,
>
> On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
>> Hi Sakari
>>
>> On 20/10/2020 13:06, Sakari Ailus wrote:
>>> Hi Andy,
>>>
>>> On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
>>>> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
>>>>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
>>>>> only; that status being determined through the .device_is_available() op
>>>>> of the device's fwnode. As software_nodes don't have that operation and
>>>>> adding it is meaningless, we instead need to check if the device's fwnode
>>>>> is a software_node and if so pass the appropriate flag to disable that
>>>>> check
>>>> Period.
>>>>
>>>> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
>>> The device availability test is actually there for a reason. Some firmware
>>> implementations put all the potential devices in the tables and only one
>>> (of some) of them are available.
>>>
>>> Could this be implemented so that if the node is a software node, then get
>>> its parent and then see if that is available?
>>>
>>> I guess that could be implemented in software node ops. Any opinions?
>> Actually when considering the cio2 device, it seems that
>> set_secondary_fwnode() actually overwrites the _primary_, given
>> fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
>> this wouldn't work.
> Ouch. I wonder when this happens --- have you checked what's the primary
> there? I guess it might be if it's a PCI device without the corresponding
> ACPI device node?
Yes; it's null, and I think that diagnosis is correct.
> I remember you had an is_available implementation that just returned true
> for software nodes in an early version of the set? I think it would still
> be a lesser bad in this case.
Yep - I can put that back in and just drop this patch then; fine for me.

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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-20 13:31   ` Sakari Ailus
@ 2020-10-20 23:25     ` Dan Scally
  2020-10-21  9:33       ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-20 23:25 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Sakari

On 20/10/2020 14:31, Sakari Ailus wrote:
> Hi Daniel,
>
> On Mon, Oct 19, 2020 at 11:58:57PM +0100, Daniel Scally wrote:
>> The software_node_get_next_child() function currently does not hold a kref
>> to the child software_node; fix that.
>>
>> Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the firmware node framework")
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes in v3:
>> 	- split out from the full software_node_graph*() patch
>>
>>  drivers/base/swnode.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
>> index f01b1cc61..741149b90 100644
>> --- a/drivers/base/swnode.c
>> +++ b/drivers/base/swnode.c
>> @@ -450,7 +450,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>>  		c = list_next_entry(c, entry);
>>  	else
>>  		c = list_first_entry(&p->children, struct swnode, entry);
>> -	return &c->fwnode;
>> +	return software_node_get(&c->fwnode);
> I believe similarly, the function should drop the reference to the previous
> node, and not expect the caller to do this. The OF equivalent does the
> same.

I think I prefer it this way myself, since the alternative is having to
explicitly call *_node_get() on a returned child if you want to keep it
but also keep iterating. But I agree that it's important to take a
consistent approach. I'll add that too; this will mean
swnode_graph_find_next_port() and
software_node_graph_get_next_endpoint() in patch 4 of this series will
need changing slightly to square away their references.


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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-20 23:25     ` Dan Scally
@ 2020-10-21  9:33       ` Andy Shevchenko
  2020-10-21  9:37         ` Sakari Ailus
  2020-10-21  9:56         ` Dan Scally
  0 siblings, 2 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-21  9:33 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Wed, Oct 21, 2020 at 12:25:28AM +0100, Dan Scally wrote:
> On 20/10/2020 14:31, Sakari Ailus wrote:
> > On Mon, Oct 19, 2020 at 11:58:57PM +0100, Daniel Scally wrote:

> >> +	return software_node_get(&c->fwnode);
> > I believe similarly, the function should drop the reference to the previous
> > node, and not expect the caller to do this. The OF equivalent does the
> > same.
> 
> I think I prefer it this way myself, since the alternative is having to
> explicitly call *_node_get() on a returned child if you want to keep it
> but also keep iterating. But I agree that it's important to take a
> consistent approach. I'll add that too; this will mean
> swnode_graph_find_next_port() and
> software_node_graph_get_next_endpoint() in patch 4 of this series will
> need changing slightly to square away their references.

What about ACPI case? Does it square?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-21  9:33       ` Andy Shevchenko
@ 2020-10-21  9:37         ` Sakari Ailus
  2020-10-21  9:56         ` Dan Scally
  1 sibling, 0 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-21  9:37 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

On Wed, Oct 21, 2020 at 12:33:21PM +0300, Andy Shevchenko wrote:
> On Wed, Oct 21, 2020 at 12:25:28AM +0100, Dan Scally wrote:
> > On 20/10/2020 14:31, Sakari Ailus wrote:
> > > On Mon, Oct 19, 2020 at 11:58:57PM +0100, Daniel Scally wrote:
> 
> > >> +	return software_node_get(&c->fwnode);
> > > I believe similarly, the function should drop the reference to the previous
> > > node, and not expect the caller to do this. The OF equivalent does the
> > > same.
> > 
> > I think I prefer it this way myself, since the alternative is having to
> > explicitly call *_node_get() on a returned child if you want to keep it
> > but also keep iterating. But I agree that it's important to take a
> > consistent approach. I'll add that too; this will mean
> > swnode_graph_find_next_port() and
> > software_node_graph_get_next_endpoint() in patch 4 of this series will
> > need changing slightly to square away their references.
> 
> What about ACPI case? Does it square?

In ACPI, we seem to assume these nodes are always there and thus don't need
reference counting.

-- 
Sakari Ailus

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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-20 22:52     ` Dan Scally
@ 2020-10-21  9:40       ` Andy Shevchenko
  2020-10-21  9:54         ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-21  9:40 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On Tue, Oct 20, 2020 at 11:52:56PM +0100, Dan Scally wrote:
> On 20/10/2020 11:05, Sakari Ailus wrote:
> > On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
> >> Software nodes that are children of another software node should be
> >> unregistered before their parent. To allow easy unregistering of an array
> >> of software_nodes ordered parent to child, add a helper function to loop
> >> over and unregister nodes in such an array in reverse order.

...

> >> + * software_node_unregister_nodes_reverse - Unregister an array of software
> >> + * nodes in reverse order.
> >> + * @nodes: Array of software nodes to be unregistered.
> >> + *
> >> + * NOTE: The same warning applies as with software_node_unregister_nodes.
> >> + * Unless you are _sure_ that the array of nodes is ordered parent to child
> >> + * it is wiser to remove them individually in the correct order.
> > Could the default order in software_node_unregister_nodes() be reversed
> > instead? There are no users so this should be easy to change.
> >
> > Doing this only one way may require enforcing the registration order in
> > software_node_register_nodes(), but the end result would be safer.
> >
> > What do you think?
> 
> Yeah fine by me. We can just use software_node_to_swnode(node->parent)
> within software_node_unregister_nodes() to check that children come
> after their parents have already been processed. I'll add a patch to do
> that in the next version of this series, and another changing the
> ordering of software_node_unregister_node_group() as Andy suggests for
> consistency.

I remember it was a big discussion between Rafael, Heikki and Greg KH about
child-parent release in kobjects. That ended up with few patches to device
object handling along with one that reversed the order of swnode unregistering
in test_printf.c. So here is the question who is maintaining the order: a kref
(via kobject) or a caller?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child
  2020-10-21  9:40       ` Andy Shevchenko
@ 2020-10-21  9:54         ` Dan Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-21  9:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sakari Ailus, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On 21/10/2020 10:40, Andy Shevchenko wrote:
> On Tue, Oct 20, 2020 at 11:52:56PM +0100, Dan Scally wrote:
>> On 20/10/2020 11:05, Sakari Ailus wrote:
>>> On Mon, Oct 19, 2020 at 11:58:55PM +0100, Daniel Scally wrote:
>>>> Software nodes that are children of another software node should be
>>>> unregistered before their parent. To allow easy unregistering of an array
>>>> of software_nodes ordered parent to child, add a helper function to loop
>>>> over and unregister nodes in such an array in reverse order.
> ...
>
>>>> + * software_node_unregister_nodes_reverse - Unregister an array of software
>>>> + * nodes in reverse order.
>>>> + * @nodes: Array of software nodes to be unregistered.
>>>> + *
>>>> + * NOTE: The same warning applies as with software_node_unregister_nodes.
>>>> + * Unless you are _sure_ that the array of nodes is ordered parent to child
>>>> + * it is wiser to remove them individually in the correct order.
>>> Could the default order in software_node_unregister_nodes() be reversed
>>> instead? There are no users so this should be easy to change.
>>>
>>> Doing this only one way may require enforcing the registration order in
>>> software_node_register_nodes(), but the end result would be safer.
>>>
>>> What do you think?
>> Yeah fine by me. We can just use software_node_to_swnode(node->parent)
>> within software_node_unregister_nodes() to check that children come
>> after their parents have already been processed. I'll add a patch to do
>> that in the next version of this series, and another changing the
>> ordering of software_node_unregister_node_group() as Andy suggests for
>> consistency.
> I remember it was a big discussion between Rafael, Heikki and Greg KH about
> child-parent release in kobjects. That ended up with few patches to device
> object handling along with one that reversed the order of swnode unregistering
> in test_printf.c. So here is the question who is maintaining the order: a kref
> (via kobject) or a caller?
I would expect the caller to maintain the order correctly, and just have
the register() function validate that the ordering is good and complain
if not.

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

* Re: [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child
  2020-10-21  9:33       ` Andy Shevchenko
  2020-10-21  9:37         ` Sakari Ailus
@ 2020-10-21  9:56         ` Dan Scally
  1 sibling, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-21  9:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sakari Ailus, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter


On 21/10/2020 10:33, Andy Shevchenko wrote:
> On Wed, Oct 21, 2020 at 12:25:28AM +0100, Dan Scally wrote:
>> On 20/10/2020 14:31, Sakari Ailus wrote:
>>> On Mon, Oct 19, 2020 at 11:58:57PM +0100, Daniel Scally wrote:
>>>> +	return software_node_get(&c->fwnode);
>>> I believe similarly, the function should drop the reference to the previous
>>> node, and not expect the caller to do this. The OF equivalent does the
>>> same.
>> I think I prefer it this way myself, since the alternative is having to
>> explicitly call *_node_get() on a returned child if you want to keep it
>> but also keep iterating. But I agree that it's important to take a
>> consistent approach. I'll add that too; this will mean
>> swnode_graph_find_next_port() and
>> software_node_graph_get_next_endpoint() in patch 4 of this series will
>> need changing slightly to square away their references.
> What about ACPI case? Does it square?
ACPI version doesn't handle references at all; neither puts() the old
nor gets() the new child node.

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

* Re: [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows
  2020-10-20 13:38 ` Rafael J. Wysocki
@ 2020-10-21 20:59   ` Daniel Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-21 20:59 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Linux Media Mailing List,
	prabhakar.mahadev-lad.rj, Heikki Krogerus, Dmitry Torokhov,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, Rob Herring,
	David Miller, Rasmus Villemoes, Andy Shevchenko,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, tian.shu.qiu, Bingbu Cao, Sakari Ailus,
	yong.zhi, Greg Kroah-Hartman, kitakar, dan.carpenter,
	Linus Walleij

On 20/10/2020 14:38, Rafael J. Wysocki wrote:
> [Fix the Linus Walleij's address.]
Thanks - much appreciated
> On Tue, Oct 20, 2020 at 12:59 AM Daniel Scally <djrscally@gmail.com> wrote:
>> Hello all
>>
>> This series adds support to the ipu3-cio2 driver for fwnode connections
>> between cio2 and sensors to be defined via software_nodes. The final patch
>> in the series deals wholly with those changes - the preceding patches are
>> either supporting changes to accommodate that or incidental fixes along
>> the way:
>>
>> 1/9 adds a function to drivers/base/swnode.c unwinding arrays of software
>> nodes in reverse order
>>
>> 2/9 uses that function in lib/test_printf.c
>>
>> 3/9 fixes what seems to me to be a bug in the existing swnode.c code in
>> that software_node_get_next_child() does not increase the refcount of the
>> returned node (in contrast to, for example, of_get_next_child_node() which
>> does increase the count)
>>
>> 4/9 adds the fwnode_graph*() family of functions to the software_node
>> implementation
>>
>> 5/9 adds a T: entry to MAINTAINERS for the ipu3-cio2 driver
>>
>> 6/9 renames the ipu3-cio2.c file to ipu3-cio2-main.c and fixes Makefile
>> to accommodate that change
>>
>> 7/9 alters the ipu3-cio2 driver to check if the pci_dev's fwnode is a
>> software_node and pass flags to fwnode_graph_get_endpoint_by_id() if so
>>
>> 8/9 alters match_fwnode() in v4l2-async.c to additionally try to match on
>> a fwnode_handle's secondary if the primary doesn't match
>>
>> 9/9 alters the ipu3-cio2 driver to do the actual building of software_node
>> connections between the sensor devices and the cio2 device.
>>
>> This is still not ready for integration - hence the RFC label - as there
>> is ongoing work to extend the ipu3-cio2 driver further to parse ACPI
>> to discover resources such as regulators and GPIOs that are defined there
>> in unusual ways and map them to the sensor devices so that their drivers
>> can consume them transparently through the usual frameworks. Given this
>> has changed quite extensively from v2 though, I wanted to submit it for
>> feedback at this point in case it needs further large scale change.
> I would appreciate it if you posted the next version of this series
> (all patches) to linux-acpi@vger.kernel.org for easier review.
>
> Thanks!
Sure thing, I'll make sure to add that list to next version

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-20  9:41   ` Andy Shevchenko
@ 2020-10-21 22:05     ` Daniel Scally
  2020-10-22 13:40       ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Daniel Scally @ 2020-10-21 22:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

Hi Andy

On 20/10/2020 10:41, Andy Shevchenko wrote:
>> +	  	- Some Microsoft Surface models
> Perhaps an example? Like '(e.g. Surface Book)'
>
>> +		- The Lenovo Miix line
> Ditto.
Sure - I'll list them.
>> +static const char * const port_names[] = {
>> +	"port0", "port1", "port2", "port3"
> + comma.
I think 4 ports is the maximum for CIO2 device, so this shouldn't ever
get extended?
>> +	/* device fwnode properties */
>> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);
> 3 -> sizeof(...) ?
> Same Q to other similar cases.
Whoops, of course, that was stupid in hindsight!
>> +	if (is_software_node(dev_fwnode(&pci_dev->dev)))
> Can we use the same check as for _build call above?

And just set a flag in struct cio2? sure.


For all the other comments; ack - I'll make those changes for the next
version


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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-21 22:05     ` Daniel Scally
@ 2020-10-22 13:40       ` Andy Shevchenko
  2020-10-23 10:06         ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-22 13:40 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	Linux Media Mailing List, linux.walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto,
	dan.carpenter

On Thu, Oct 22, 2020 at 3:59 PM Daniel Scally <djrscally@gmail.com> wrote:
> On 20/10/2020 10:41, Andy Shevchenko wrote:

...

> >> +static const char * const port_names[] = {
> >> +    "port0", "port1", "port2", "port3"
> > + comma.
> I think 4 ports is the maximum for CIO2 device, so this shouldn't ever
> get extended?

It's better for at least teaching purposes (if anybody takes this
driver as an example for anything) if you have really believe that no
new generation will have more than that.

...

> >> +    if (is_software_node(dev_fwnode(&pci_dev->dev)))
> > Can we use the same check as for _build call above?
>
> And just set a flag in struct cio2? sure.

I meant can we use exact conditional w/o any additional flags added?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-22 13:40       ` Andy Shevchenko
@ 2020-10-23 10:06         ` Dan Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-23 10:06 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	Linux Media Mailing List, linus.walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto,
	dan.carpenter

On 22/10/2020 14:40, Andy Shevchenko wrote:
> On Thu, Oct 22, 2020 at 3:59 PM Daniel Scally <djrscally@gmail.com> wrote:
>> On 20/10/2020 10:41, Andy Shevchenko wrote:
> ...
>
>>>> +static const char * const port_names[] = {
>>>> +    "port0", "port1", "port2", "port3"
>>> + comma.
>> I think 4 ports is the maximum for CIO2 device, so this shouldn't ever
>> get extended?
> It's better for at least teaching purposes (if anybody takes this
> driver as an example for anything) if you have really believe that no
> new generation will have more than that.

Yeah fair point - it's added


>>>> +    if (is_software_node(dev_fwnode(&pci_dev->dev)))
>>> Can we use the same check as for _build call above?
>> And just set a flag in struct cio2? sure.
> I meant can we use exact conditional w/o any additional flags added?
Oh I see. Erm...I can't think of a way to do that immediately; checking
for the fwnode graph's presence will of course pass if it's defined in
ACPI too. Let me think about it

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

* Re: [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS
  2020-10-19 22:58 ` [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
  2020-10-20  9:16   ` Andy Shevchenko
@ 2020-10-24  0:28   ` Laurent Pinchart
  1 sibling, 0 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24  0:28 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Daniel,

Thank you for the patch.

On Mon, Oct 19, 2020 at 11:58:59PM +0100, Daniel Scally wrote:
> Development for the ipu3-cio2 driver is taking place in media_tree, but
> there's no T: entry in MAINTAINERS to denote that - rectify that oversight
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

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

> ---
> Changes in v3:
> 	- patch introduced.
> 	
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 43a025039..5d768d5ad 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8851,6 +8851,7 @@ M:	Bingbu Cao <bingbu.cao@intel.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> +T:	git git://linuxtv.org/media_tree.git
>  F:	Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
>  F:	drivers/media/pci/intel/ipu3/

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name
  2020-10-19 22:59 ` [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name Daniel Scally
  2020-10-20  9:15   ` Andy Shevchenko
@ 2020-10-24  0:34   ` Laurent Pinchart
  1 sibling, 0 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24  0:34 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Daniel,

Thank you for the patch.

On Mon, Oct 19, 2020 at 11:59:00PM +0100, Daniel Scally wrote:
> ipu3-cio2 driver needs extending with multiple files; rename the main
> source file and specify the renamed file in Makefile to accommodate that.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- patch introduced
> 
>  drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
>  drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
>  2 files changed, 2 insertions(+)
>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)
> 
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 98ddd5bea..b4e3266d9 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,2 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +
> +ipu3-cio2-y += ipu3-cio2-main.o
> \ No newline at end of file

I would have sworn the usual naming for this kind of case was -drv.c,
but it seems -main.c is more common (I've probably been mistaken by
focussing quite a bit on drivers/gpu/drm/ in the past few years).
-core.c wins over both though :-) Anyway, enough bikeshedding, with the
newline fixed,

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

> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> similarity index 100%
> rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
> rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-20 22:49         ` Sakari Ailus
  2020-10-20 22:55           ` Dan Scally
@ 2020-10-24  0:39           ` Laurent Pinchart
  2020-10-24 14:29             ` Sakari Ailus
  1 sibling, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24  0:39 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Dan Scally, Andy Shevchenko, linux-kernel, linux-media,
	linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	sergey.senozhatsky, rostedt, pmladek, mchehab, tian.shu.qiu,
	bingbu.cao, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Sakari

On Wed, Oct 21, 2020 at 01:49:10AM +0300, Sakari Ailus wrote:
> On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
> > On 20/10/2020 13:06, Sakari Ailus wrote:
> > > On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
> > >> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> > >>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> > >>> only; that status being determined through the .device_is_available() op
> > >>> of the device's fwnode. As software_nodes don't have that operation and
> > >>> adding it is meaningless, we instead need to check if the device's fwnode
> > >>> is a software_node and if so pass the appropriate flag to disable that
> > >>> check
> > >> Period.
> > >>
> > >> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
> > > The device availability test is actually there for a reason. Some firmware
> > > implementations put all the potential devices in the tables and only one
> > > (of some) of them are available.
> > >
> > > Could this be implemented so that if the node is a software node, then get
> > > its parent and then see if that is available?
> > >
> > > I guess that could be implemented in software node ops. Any opinions?
> > Actually when considering the cio2 device, it seems that
> > set_secondary_fwnode() actually overwrites the _primary_, given
> > fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
> > this wouldn't work.
> 
> Ouch. I wonder when this happens --- have you checked what's the primary
> there? I guess it might be if it's a PCI device without the corresponding
> ACPI device node?
> 
> I remember you had an is_available implementation that just returned true
> for software nodes in an early version of the set? I think it would still
> be a lesser bad in this case.

How about the following ?

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 81bd01ed4042..ea44ba846299 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -706,9 +706,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
 /**
  * fwnode_device_is_available - check if a device is available for use
  * @fwnode: Pointer to the fwnode of the device.
+ *
+ * For fwnode node types that don't implement the .device_is_available()
+ * operation, such as software nodes, this function returns true.
  */
 bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
 {
+	if (!fwnode_has_op(fwnode, device_is_available))
+		return true;
 	return fwnode_call_bool_op(fwnode, device_is_available);
 }
 EXPORT_SYMBOL_GPL(fwnode_device_is_available);

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-10-20  9:41   ` Andy Shevchenko
@ 2020-10-24  1:24   ` Laurent Pinchart
  2020-10-24  8:50     ` Dan Scally
  2020-10-24 15:11     ` Sakari Ailus
  2020-10-24 15:14   ` Sakari Ailus
  2 siblings, 2 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24  1:24 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Daniel,

Thank you for the patch.

On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> Currently on platforms designed for Windows, connections between CIO2 and
> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> driver to compensate by building software_node connections, parsing the
> connection properties from the sensor's SSDB buffer.
> 
> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- Rather than overwriting the device's primary fwnode, we now
> 	simply assign a secondary. Some of the preceding patches alter the
> 	existing driver code and v4l2 framework to allow for that.
> 	- Rather than reprobe() the sensor after connecting the devices in
> 	cio2-bridge we create the software_nodes right away. In this case,
> 	sensor drivers will have to defer probing until they detect that a
> 	fwnode graph is connecting them to the CIO2 device.
> 	- Error paths in connect_supported_devices() moved outside the
> 	loop
> 	- Replaced pr_*() with dev_*() throughout
> 	- Moved creation of software_node / property_entry arrays to stack
> 	- A lot of formatting changes.
> 
>  MAINTAINERS                                   |   1 +
>  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
>  drivers/media/pci/intel/ipu3/Makefile         |   3 +-
>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
>  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
>  7 files changed, 472 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5d768d5ad..4c9c646c7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>  M:	Yong Zhi <yong.zhi@intel.com>
>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>  M:	Bingbu Cao <bingbu.cao@intel.com>
> +M:	Dan Scally <djrscally@gmail.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 82d7f17e6..d14cbceae 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>  	  connected camera.
>  	  The module will be called ipu3-cio2.
> +
> +config CIO2_BRIDGE
> +	bool "IPU3 CIO2 Sensors Bridge"
> +	depends on VIDEO_IPU3_CIO2
> +	help
> +	  This extension provides an API for the ipu3-cio2 driver to create
> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> +	  can be used to enable support for cameras in detachable / hybrid
> +	  devices that ship with Windows.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM, for example:
> +
> +	  	- Some Microsoft Surface models
> +		- The Lenovo Miix line
> +		- Dell 7285
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index b4e3266d9..933777e6e 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>  
> -ipu3-cio2-y += ipu3-cio2-main.o
> \ No newline at end of file
> +ipu3-cio2-y += ipu3-cio2-main.o
> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> new file mode 100644
> index 000000000..bbe072f04
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> @@ -0,0 +1,327 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Author: Dan Scally <djrscally@gmail.com>
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/fwnode.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/property.h>
> +#include <media/v4l2-subdev.h>
> +
> +#include "cio2-bridge.h"
> +
> +/*
> + * Extend this array with ACPI Hardware ID's of devices known to be
> + * working
> + */
> +static const char * const supported_devices[] = {
> +	"INT33BE",
> +	"OVTI2680",
> +};
> +
> +static struct software_node cio2_hid_node = { CIO2_HID };
> +
> +static struct cio2_bridge bridge;

While there shouldn't be more than one CIO2 instance, we try to develop
drivers in a way that avoids global per-device variables. Could all this
be allocated dynamically, with the pointer returned by
cio2_bridge_build() and stored in the cio2_device structure ?

> +
> +static const char * const port_names[] = {
> +	"port0", "port1", "port2", "port3"
> +};
> +
> +static const struct property_entry remote_endpoints[] = {
> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, Sensor Property */
> +			   &bridge.sensors[0].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, CIO2 Property */
> +			   &bridge.sensors[0].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[1].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[1].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[2].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[2].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[3].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[3].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +};

For the same reason, I would move this to the sensor structure (with two
property_entry per sensor). That will simplify the code below, avoiding
indexing this array with bridge.n_sensors * 2.

> +
> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)

To avoid potential future namespace classes, I'd advise naming the
functions with a cio2_bridge_ prefix, even the static ones.

And maybe cio2_bridge_read_acpi_buffer(), as this function reads a
buffer ?

> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct acpi_handle *handle;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret;
> +
> +	handle = ACPI_HANDLE(dev);
> +
> +	status = acpi_evaluate_object(handle, id, NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(dev, "Couldn't locate ACPI buffer\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(dev, "Couldn't read ACPI buffer\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > size) {
> +		dev_err(dev, "Given buffer is too small\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> +	ret = obj->buffer.length;
> +
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int get_acpi_ssdb_sensor_data(struct device *dev,
> +				     struct sensor_bios_data *sensor)
> +{
> +	struct sensor_bios_data_packed sensor_data;
> +	int ret;
> +
> +	ret = read_acpi_block(dev, "SSDB", &sensor_data, sizeof(sensor_data));
> +	if (ret < 0)
> +		return ret;
> +
> +	sensor->link = sensor_data.link;
> +	sensor->lanes = sensor_data.lanes;
> +	sensor->mclkspeed = sensor_data.mclkspeed;
> +	sensor->degree = sensor_data.degree;

How about storing a sensor_bios_data_packed inside sensor_bios_data ?
That will avoid copying fields individually, with manual addition of
extra fields as they become useful. Usage of the sensor_bios_data
structure would turn from sensor->degree to sensor->ssdb.degree, which
is slightly longer, but I think more maintainable.

> +
> +	return 0;
> +}
> +
> +static int create_fwnode_properties(struct sensor *sensor,
> +				    struct sensor_bios_data *ssdb)
> +{
> +	struct property_entry *cio2_properties = sensor->cio2_properties;
> +	struct property_entry *dev_properties = sensor->dev_properties;
> +	struct property_entry *ep_properties = sensor->ep_properties;
> +	int i;

i never takes negative values, you can make it an unsigned int. Same for
other occurrences below.

> +
> +	/* device fwnode properties */
> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);

I would memset() bridge to 0 in one go and avoid individual memsets. And
if you allocate it with kzalloc() it will be initialized to 0.

> +
> +	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
> +					       ssdb->mclkspeed);
> +	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
> +
> +	/* endpoint fwnode properties */
> +	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
> +
> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
> +					   GFP_KERNEL);

Given that there can't be more than 4 data lanes, how about turning
data_lanes into an array with 4 entries, to avoid the dynamic allocation
? You will have to validate ssdb->lanes in connect_supported_devices(),
to make sure not to overflow the array. This and the next function can
then be turned into void functions.

> +
> +	if (!sensor->data_lanes)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < ssdb->lanes; i++)
> +		sensor->data_lanes[i] = i + 1;
> +
> +	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
> +	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> +							sensor->data_lanes,
> +							ssdb->lanes);
> +	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
> +
> +	/* cio2 endpoint props */
> +	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
> +
> +	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> +							  sensor->data_lanes,
> +							  ssdb->lanes);
> +	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
> +
> +	return 0;
> +}
> +
> +static int create_connection_swnodes(struct sensor *sensor,
> +				     struct sensor_bios_data *ssdb)
> +{
> +	struct software_node *nodes = sensor->swnodes;
> +
> +	memset(nodes, 0, sizeof(struct software_node) * 6);
> +
> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> +					       sensor->dev_properties);
> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT("port0",
> +					      &nodes[SWNODE_SENSOR_HID]);
> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> +						      &nodes[SWNODE_SENSOR_PORT],
> +						      sensor->ep_properties);
> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(port_names[ssdb->link],
> +					    &cio2_hid_node);
> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> +						    &nodes[SWNODE_CIO2_PORT],
> +						    sensor->cio2_properties);
> +
> +	return 0;
> +}
> +
> +static void cio2_bridge_unregister_sensors(void)
> +{
> +	struct sensor *sensor;
> +	int i;
> +
> +	for (i = 0; i < bridge.n_sensors; i++) {
> +		sensor = &bridge.sensors[i];
> +
> +		software_node_unregister_nodes_reverse(sensor->swnodes);
> +
> +		kfree(sensor->data_lanes);
> +
> +		put_device(sensor->dev);
> +		acpi_dev_put(sensor->adev);
> +	}
> +}
> +
> +static int connect_supported_devices(struct pci_dev *cio2)
> +{
> +	struct sensor_bios_data ssdb;
> +	struct fwnode_handle *fwnode;
> +	struct acpi_device *adev;
> +	struct sensor *sensor;
> +	struct device *dev;
> +	int i, ret;
> +
> +	ret = 0;

You can initialize ret to 0 when declaring the variable.

> +	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);

What if there are multiple sensor of the same model ?

> +		if (!adev)
> +			continue;
> +

Does acpi_dev_get_first_match_dev() skip disabled devices (as reported
by _STA) ?

> +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
> +		if (!dev) {
> +			ret = -EPROBE_DEFER;
> +			goto err_rollback;
> +		}
> +
> +		sensor = &bridge.sensors[bridge.n_sensors];
> +		sensor->dev = dev;
> +		sensor->adev = adev;
> +
> +		snprintf(sensor->name, ACPI_ID_LEN, "%s",
> +			 supported_devices[i]);

How about strlcpy() ?

> +
> +		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_fwnode_properties(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_connection_swnodes(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = software_node_register_nodes(sensor->swnodes);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> +		if (!fwnode) {
> +			ret = -ENODEV;
> +			goto err_free_swnodes;
> +		}
> +
> +		set_secondary_fwnode(dev, fwnode);

I wonder if we could avoid depending on the I2C device being created by
getting the fwnode from adev, and setting ->secondary manually. adev
would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.

> +
> +		dev_info(&cio2->dev, "Found supported device %s\n",
> +			 supported_devices[i]);
> +
> +		bridge.n_sensors++;
> +		continue;
> +	}
> +
> +	return ret;
> +
> +err_free_swnodes:
> +	software_node_unregister_nodes_reverse(sensor->swnodes);
> +err_free_dev:
> +	put_device(dev);
> +err_rollback:
> +	acpi_dev_put(adev);

I think you'll leak sensor->data_lanes here. It won't be a problem if
you don't allocate it manually, as proposed above. I however wonder if
error handling couldn't be simplified by increasing bridge.n_sensors
earlier, and skipping cleanup in cio2_bridge_unregister_sensors() for
the fields that haven't been initialized (for instance kfree() is a
no-op on NULL pointers, so that's already handled).

> +
> +	/*
> +	 * If an iteration of this loop results in -EPROBE_DEFER then
> +	 * we need to roll back any sensors that were successfully
> +	 * registered. Any other error and we'll skip that step, as
> +	 * it seems better to have one successfully connected sensor.
> +	 */
> +
> +	if (ret == -EPROBE_DEFER)
> +		cio2_bridge_unregister_sensors();
> +
> +	return ret;
> +}
> +
> +int cio2_bridge_build(struct pci_dev *cio2)
> +{
> +	struct fwnode_handle *fwnode;
> +	int ret;
> +
> +	pci_dev_get(cio2);
> +
> +	ret = software_node_register(&cio2_hid_node);
> +	if (ret < 0) {
> +		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
> +		goto err_put_cio2;
> +	}
> +
> +	ret = connect_supported_devices(cio2);
> +	if (ret == -EPROBE_DEFER)
> +		goto err_unregister_cio2;
> +
> +	if (bridge.n_sensors == 0) {
> +		ret = -EPROBE_DEFER;
> +		goto err_unregister_cio2;
> +	}
> +
> +	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
> +
> +	fwnode = software_node_fwnode(&cio2_hid_node);
> +	if (!fwnode) {
> +		dev_err(&cio2->dev,
> +			"Error getting fwnode from cio2 software_node\n");
> +		ret = -ENODEV;
> +		goto err_unregister_sensors;
> +	}
> +
> +	set_secondary_fwnode(&cio2->dev, fwnode);
> +
> +	return 0;
> +
> +err_unregister_sensors:
> +	cio2_bridge_unregister_sensors();
> +err_unregister_cio2:
> +	software_node_unregister(&cio2_hid_node);
> +err_put_cio2:
> +	pci_dev_put(cio2);
> +
> +	return ret;
> +}
> +
> +void cio2_bridge_burn(struct pci_dev *cio2)

Interesting function name :-) I like the creativity, but I think
consistency with the rest of the kernel code should unfortunately be
favoured.

> +{
> +	pci_dev_put(cio2);
> +
> +	cio2_bridge_unregister_sensors();
> +
> +	software_node_unregister(&cio2_hid_node);
> +}
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> new file mode 100644
> index 000000000..077354ca8
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> @@ -0,0 +1,94 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#ifndef __CIO2_BRIDGE_H
> +#define __CIO2_BRIDGE_H
> +
> +#define MAX_CONNECTED_DEVICES			4
> +#define SWNODE_SENSOR_HID			0
> +#define SWNODE_SENSOR_PORT			1
> +#define SWNODE_SENSOR_ENDPOINT			2
> +#define SWNODE_CIO2_PORT			3
> +#define SWNODE_CIO2_ENDPOINT			4
> +#define SWNODE_NULL_TERMINATOR			5
> +
> +#define CIO2_HID				"INT343E"
> +#define CIO2_PCI_ID				0x9d32
> +
> +#define ENDPOINT_SENSOR				0
> +#define ENDPOINT_CIO2				1
> +
> +#define NODE_SENSOR(_HID, _PROPS)		\
> +	((const struct software_node) {		\
> +		.name = _HID,			\
> +		.properties = _PROPS,		\
> +	})
> +
> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> +	((const struct software_node) {		\
> +		_PORT,				\
> +		_SENSOR_NODE,			\
> +	})
> +
> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> +	((const struct software_node) {		\
> +		_EP,				\
> +		_PORT,				\
> +		_PROPS,				\
> +	})
> +
> +struct sensor {

That's a very common name, prone to namespace clashes. How about naming
it cio2_sensor ?

> +	char name[ACPI_ID_LEN];
> +	struct device *dev;
> +	struct acpi_device *adev;
> +	struct software_node swnodes[6];
> +	struct property_entry dev_properties[3];
> +	struct property_entry ep_properties[4];
> +	struct property_entry cio2_properties[3];
> +	u32 *data_lanes;
> +};
> +
> +struct cio2_bridge {
> +	int n_sensors;

This can never be negative, I would make it an unsigned int.

> +	struct sensor sensors[MAX_CONNECTED_DEVICES];
> +};
> +
> +/* Data representation as it is in ACPI SSDB buffer */
> +struct sensor_bios_data_packed {

Similarly as above, I'd use a cio2_ prefix, and I think you can drop the
_packed suffix. How about naming it cio2_sensor_ssdb_data (or even just
cio2_sensor_ssdb) to make it clearer that it contains the SSDB data ?

> +	u8 version;
> +	u8 sku;
> +	u8 guid_csi2[16];
> +	u8 devfunction;
> +	u8 bus;
> +	u32 dphylinkenfuses;
> +	u32 clockdiv;
> +	u8 link;
> +	u8 lanes;
> +	u32 csiparams[10];
> +	u32 maxlanespeed;
> +	u8 sensorcalibfileidx;
> +	u8 sensorcalibfileidxInMBZ[3];
> +	u8 romtype;
> +	u8 vcmtype;
> +	u8 platforminfo;
> +	u8 platformsubinfo;
> +	u8 flash;
> +	u8 privacyled;
> +	u8 degree;
> +	u8 mipilinkdefined;
> +	u32 mclkspeed;
> +	u8 controllogicid;
> +	u8 reserved1[3];
> +	u8 mclkport;
> +	u8 reserved2[13];
> +} __packed__;
> +
> +/* Fields needed by bridge driver */
> +struct sensor_bios_data {

And cio2_sensor_data ?

> +	struct device *dev;
> +	u8 link;
> +	u8 lanes;
> +	u8 degree;
> +	u32 mclkspeed;
> +};
> +
> +#endif
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index f68ef0f6b..827457110 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>  static int cio2_pci_probe(struct pci_dev *pci_dev,
>  			  const struct pci_device_id *id)
>  {
> +	struct fwnode_handle *endpoint;
>  	struct cio2_device *cio2;
>  	int r;
>  
> +	/*
> +	 * On some platforms no connections to sensors are defined in firmware,
> +	 * if the device has no endpoints then we can try to build those as
> +	 * software_nodes parsed from SSDB.
> +	 *
> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
> +	 * but not yet ready for use (either not attached to the i2c bus yet,
> +	 * or not done probing themselves).

Why do we need for the I2C devices to be probed, isn't it enough to have
them created ?

> +	 */
> +
> +	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&pci_dev->dev), NULL);
> +	if (!endpoint) {
> +		r = cio2_bridge_build(pci_dev);
> +		if (r)
> +			return r;
> +	}
> +
>  	cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL);
>  	if (!cio2)
>  		return -ENOMEM;
> @@ -1825,6 +1843,9 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
>  {
>  	struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
>  
> +	if (is_software_node(dev_fwnode(&pci_dev->dev)))
> +		cio2_bridge_burn(pci_dev);
> +
>  	media_device_unregister(&cio2->media_dev);
>  	v4l2_async_notifier_unregister(&cio2->notifier);
>  	v4l2_async_notifier_cleanup(&cio2->notifier);
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> index 549b08f88..80a081d7e 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> @@ -436,4 +436,13 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
>  	return container_of(vq, struct cio2_queue, vbq);
>  }
>  
> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
> +	int cio2_bridge_build(struct pci_dev *cio2);
> +	void cio2_bridge_burn(struct pci_dev *cio2);

No need for an extra indentation level, neither here, not below.

> +#else
> +

NO need for this blank line.

> +	int cio2_bridge_build(struct pci_dev *cio2) { return 0; }
> +	void cio2_bridge_burn(struct pci_dev *cio2) { }
> +#endif
> +
>  #endif

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24  1:24   ` Laurent Pinchart
@ 2020-10-24  8:50     ` Dan Scally
  2020-10-24  9:37       ` Laurent Pinchart
  2020-10-24 15:11     ` Sakari Ailus
  1 sibling, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-24  8:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

On 24/10/2020 02:24, Laurent Pinchart wrote:
> Hi Daniel,
>
> Thank you for the patch.
Thank you for reviewing it - very helpful comments
>
> On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
>> Currently on platforms designed for Windows, connections between CIO2 and
>> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
>> driver to compensate by building software_node connections, parsing the
>> connection properties from the sensor's SSDB buffer.
>>
>> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes in v3:
>> 	- Rather than overwriting the device's primary fwnode, we now
>> 	simply assign a secondary. Some of the preceding patches alter the
>> 	existing driver code and v4l2 framework to allow for that.
>> 	- Rather than reprobe() the sensor after connecting the devices in
>> 	cio2-bridge we create the software_nodes right away. In this case,
>> 	sensor drivers will have to defer probing until they detect that a
>> 	fwnode graph is connecting them to the CIO2 device.
>> 	- Error paths in connect_supported_devices() moved outside the
>> 	loop
>> 	- Replaced pr_*() with dev_*() throughout
>> 	- Moved creation of software_node / property_entry arrays to stack
>> 	- A lot of formatting changes.
>>
>>  MAINTAINERS                                   |   1 +
>>  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
>>  drivers/media/pci/intel/ipu3/Makefile         |   3 +-
>>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
>>  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
>>  7 files changed, 472 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 5d768d5ad..4c9c646c7 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>>  M:	Yong Zhi <yong.zhi@intel.com>
>>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>>  M:	Bingbu Cao <bingbu.cao@intel.com>
>> +M:	Dan Scally <djrscally@gmail.com>
>>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>>  L:	linux-media@vger.kernel.org
>>  S:	Maintained
>> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
>> index 82d7f17e6..d14cbceae 100644
>> --- a/drivers/media/pci/intel/ipu3/Kconfig
>> +++ b/drivers/media/pci/intel/ipu3/Kconfig
>> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>>  	  connected camera.
>>  	  The module will be called ipu3-cio2.
>> +
>> +config CIO2_BRIDGE
>> +	bool "IPU3 CIO2 Sensors Bridge"
>> +	depends on VIDEO_IPU3_CIO2
>> +	help
>> +	  This extension provides an API for the ipu3-cio2 driver to create
>> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
>> +	  can be used to enable support for cameras in detachable / hybrid
>> +	  devices that ship with Windows.
>> +
>> +	  Say Y here if your device is a detachable / hybrid laptop that comes
>> +	  with Windows installed by the OEM, for example:
>> +
>> +	  	- Some Microsoft Surface models
>> +		- The Lenovo Miix line
>> +		- Dell 7285
>> +
>> +	  If in doubt, say N here.
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index b4e3266d9..933777e6e 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -1,4 +1,5 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>>  
>> -ipu3-cio2-y += ipu3-cio2-main.o
>> \ No newline at end of file
>> +ipu3-cio2-y += ipu3-cio2-main.o
>> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
>> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> new file mode 100644
>> index 000000000..bbe072f04
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> @@ -0,0 +1,327 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Author: Dan Scally <djrscally@gmail.com>
>> +#include <linux/acpi.h>
>> +#include <linux/device.h>
>> +#include <linux/fwnode.h>
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pci.h>
>> +#include <linux/property.h>
>> +#include <media/v4l2-subdev.h>
>> +
>> +#include "cio2-bridge.h"
>> +
>> +/*
>> + * Extend this array with ACPI Hardware ID's of devices known to be
>> + * working
>> + */
>> +static const char * const supported_devices[] = {
>> +	"INT33BE",
>> +	"OVTI2680",
>> +};
>> +
>> +static struct software_node cio2_hid_node = { CIO2_HID };
>> +
>> +static struct cio2_bridge bridge;
> While there shouldn't be more than one CIO2 instance, we try to develop
> drivers in a way that avoids global per-device variables. Could all this
> be allocated dynamically, with the pointer returned by
> cio2_bridge_build() and stored in the cio2_device structure ?
Yes, ok, I'll make that change.
>> +
>> +static const char * const port_names[] = {
>> +	"port0", "port1", "port2", "port3"
>> +};
>> +
>> +static const struct property_entry remote_endpoints[] = {
>> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, Sensor Property */
>> +			   &bridge.sensors[0].swnodes[SWNODE_CIO2_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, CIO2 Property */
>> +			   &bridge.sensors[0].swnodes[SWNODE_SENSOR_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[1].swnodes[SWNODE_CIO2_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[1].swnodes[SWNODE_SENSOR_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[2].swnodes[SWNODE_CIO2_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[2].swnodes[SWNODE_SENSOR_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[3].swnodes[SWNODE_CIO2_ENDPOINT]),
>> +	PROPERTY_ENTRY_REF("remote-endpoint",
>> +			   &bridge.sensors[3].swnodes[SWNODE_SENSOR_ENDPOINT]),
>> +};
> For the same reason, I would move this to the sensor structure (with two
> property_entry per sensor). That will simplify the code below, avoiding
> indexing this array with bridge.n_sensors * 2.
I had some trouble with that which is why I ended up doing things this
way; I'll revisit it and see if I can resolve that.
>> +
>> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)
> To avoid potential future namespace classes, I'd advise naming the
> functions with a cio2_bridge_ prefix, even the static ones.
>
> And maybe cio2_bridge_read_acpi_buffer(), as this function reads a
> buffer ?
Ack to both; and to the similar comments re: variable naming below.
>> +{
>> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>> +	struct acpi_handle *handle;
>> +	union acpi_object *obj;
>> +	acpi_status status;
>> +	int ret;
>> +
>> +	handle = ACPI_HANDLE(dev);
>> +
>> +	status = acpi_evaluate_object(handle, id, NULL, &buffer);
>> +	if (ACPI_FAILURE(status))
>> +		return -ENODEV;
>> +
>> +	obj = buffer.pointer;
>> +	if (!obj) {
>> +		dev_err(dev, "Couldn't locate ACPI buffer\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (obj->type != ACPI_TYPE_BUFFER) {
>> +		dev_err(dev, "Couldn't read ACPI buffer\n");
>> +		ret = -ENODEV;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	if (obj->buffer.length > size) {
>> +		dev_err(dev, "Given buffer is too small\n");
>> +		ret = -ENODEV;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
>> +	ret = obj->buffer.length;
>> +
>> +out_free_buff:
>> +	kfree(buffer.pointer);
>> +	return ret;
>> +}
>> +
>> +static int get_acpi_ssdb_sensor_data(struct device *dev,
>> +				     struct sensor_bios_data *sensor)
>> +{
>> +	struct sensor_bios_data_packed sensor_data;
>> +	int ret;
>> +
>> +	ret = read_acpi_block(dev, "SSDB", &sensor_data, sizeof(sensor_data));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	sensor->link = sensor_data.link;
>> +	sensor->lanes = sensor_data.lanes;
>> +	sensor->mclkspeed = sensor_data.mclkspeed;
>> +	sensor->degree = sensor_data.degree;
> How about storing a sensor_bios_data_packed inside sensor_bios_data ?
> That will avoid copying fields individually, with manual addition of
> extra fields as they become useful. Usage of the sensor_bios_data
> structure would turn from sensor->degree to sensor->ssdb.degree, which
> is slightly longer, but I think more maintainable.
Inside the struct sensor you mean (confusingly, the variable named
sensor here is _not_ of type struct sensor, which I acknowledge is plain
silly)? If so, agreed, I'll change it to that. That's also consistent
with what I'm doing with the equivalent struct for the PMIC's CLDB in
the regulator work so that makes sense anyway.
>> +
>> +	return 0;
>> +}
>> +
>> +static int create_fwnode_properties(struct sensor *sensor,
>> +				    struct sensor_bios_data *ssdb)
>> +{
>> +	struct property_entry *cio2_properties = sensor->cio2_properties;
>> +	struct property_entry *dev_properties = sensor->dev_properties;
>> +	struct property_entry *ep_properties = sensor->ep_properties;
>> +	int i;
> i never takes negative values, you can make it an unsigned int. Same for
> other occurrences below.
>
>> +
>> +	/* device fwnode properties */
>> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);
> I would memset() bridge to 0 in one go and avoid individual memsets. And
> if you allocate it with kzalloc() it will be initialized to 0.
Yep ok, I'll initialize the whole thing with kzalloc at the start then
>
>> +
>> +	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
>> +					       ssdb->mclkspeed);
>> +	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
>> +
>> +	/* endpoint fwnode properties */
>> +	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
>> +
>> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
>> +					   GFP_KERNEL);
> Given that there can't be more than 4 data lanes, how about turning
> data_lanes into an array with 4 entries, to avoid the dynamic allocation
> ? You will have to validate ssdb->lanes in connect_supported_devices(),
> to make sure not to overflow the array. This and the next function can
> then be turned into void functions.
OK - is that generally better then (I.E. avoiding dynamic allocation),
or just when the "wasted" memory is so small?
>
>> +
>> +	if (!sensor->data_lanes)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < ssdb->lanes; i++)
>> +		sensor->data_lanes[i] = i + 1;
>> +
>> +	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
>> +	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
>> +							sensor->data_lanes,
>> +							ssdb->lanes);
>> +	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
>> +
>> +	/* cio2 endpoint props */
>> +	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
>> +
>> +	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
>> +							  sensor->data_lanes,
>> +							  ssdb->lanes);
>> +	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
>> +
>> +	return 0;
>> +}
>> +
>> +static int create_connection_swnodes(struct sensor *sensor,
>> +				     struct sensor_bios_data *ssdb)
>> +{
>> +	struct software_node *nodes = sensor->swnodes;
>> +
>> +	memset(nodes, 0, sizeof(struct software_node) * 6);
>> +
>> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
>> +					       sensor->dev_properties);
>> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT("port0",
>> +					      &nodes[SWNODE_SENSOR_HID]);
>> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT("endpoint0",
>> +						      &nodes[SWNODE_SENSOR_PORT],
>> +						      sensor->ep_properties);
>> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(port_names[ssdb->link],
>> +					    &cio2_hid_node);
>> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT("endpoint0",
>> +						    &nodes[SWNODE_CIO2_PORT],
>> +						    sensor->cio2_properties);
>> +
>> +	return 0;
>> +}
>> +
>> +static void cio2_bridge_unregister_sensors(void)
>> +{
>> +	struct sensor *sensor;
>> +	int i;
>> +
>> +	for (i = 0; i < bridge.n_sensors; i++) {
>> +		sensor = &bridge.sensors[i];
>> +
>> +		software_node_unregister_nodes_reverse(sensor->swnodes);
>> +
>> +		kfree(sensor->data_lanes);
>> +
>> +		put_device(sensor->dev);
>> +		acpi_dev_put(sensor->adev);
>> +	}
>> +}
>> +
>> +static int connect_supported_devices(struct pci_dev *cio2)
>> +{
>> +	struct sensor_bios_data ssdb;
>> +	struct fwnode_handle *fwnode;
>> +	struct acpi_device *adev;
>> +	struct sensor *sensor;
>> +	struct device *dev;
>> +	int i, ret;
>> +
>> +	ret = 0;
> You can initialize ret to 0 when declaring the variable.
Is that ok on the same like as i's declaration, or should I split them?
>
>> +	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
>> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> What if there are multiple sensor of the same model ?

Hmm, yeah, that would be a bit of a pickle. I guess the newer
smartphones have multiple sensors on the back, which I presume are the
same model. So that will probably crop up at some point. How about
instead I use bus_for_each_dev() and in the applied function check if
the _HID is in the supported list?

>
>> +		if (!adev)
>> +			continue;
>> +
> Does acpi_dev_get_first_match_dev() skip disabled devices (as reported
> by _STA) ?
Yes.
>> +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
>> +		if (!dev) {
>> +			ret = -EPROBE_DEFER;
>> +			goto err_rollback;
>> +		}
>> +
>> +		sensor = &bridge.sensors[bridge.n_sensors];
>> +		sensor->dev = dev;
>> +		sensor->adev = adev;
>> +
>> +		snprintf(sensor->name, ACPI_ID_LEN, "%s",
>> +			 supported_devices[i]);
> How about strlcpy() ?
Sure
>> +
>> +		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
>> +		if (ret)
>> +			goto err_free_dev;
>> +
>> +		ret = create_fwnode_properties(sensor, &ssdb);
>> +		if (ret)
>> +			goto err_free_dev;
>> +
>> +		ret = create_connection_swnodes(sensor, &ssdb);
>> +		if (ret)
>> +			goto err_free_dev;
>> +
>> +		ret = software_node_register_nodes(sensor->swnodes);
>> +		if (ret)
>> +			goto err_free_dev;
>> +
>> +		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
>> +		if (!fwnode) {
>> +			ret = -ENODEV;
>> +			goto err_free_swnodes;
>> +		}
>> +
>> +		set_secondary_fwnode(dev, fwnode);
> I wonder if we could avoid depending on the I2C device being created by
> getting the fwnode from adev, and setting ->secondary manually. adev
> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
Let me try that; I initially wanted to do
set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
dev being created but it turns out &adev->dev isn't the same pointer. I
shall try it and see.
>
>> +
>> +		dev_info(&cio2->dev, "Found supported device %s\n",
>> +			 supported_devices[i]);
>> +
>> +		bridge.n_sensors++;
>> +		continue;
>> +	}
>> +
>> +	return ret;
>> +
>> +err_free_swnodes:
>> +	software_node_unregister_nodes_reverse(sensor->swnodes);
>> +err_free_dev:
>> +	put_device(dev);
>> +err_rollback:
>> +	acpi_dev_put(adev);
> I think you'll leak sensor->data_lanes here. It won't be a problem if
> you don't allocate it manually, as proposed above. I however wonder if
> error handling couldn't be simplified by increasing bridge.n_sensors
> earlier, and skipping cleanup in cio2_bridge_unregister_sensors() for
> the fields that haven't been initialized (for instance kfree() is a
> no-op on NULL pointers, so that's already handled).
Errrr the only sticky bit there is the desire _not_ to unwind all the
sensors if it managed to successfully connect one of them; if I'm just
calling cio2_bridge_unregister_sensors() on any error then a failure for
one sensor will result in no working cameras, where this way at least
one of them might be available.
>
>> +
>> +	/*
>> +	 * If an iteration of this loop results in -EPROBE_DEFER then
>> +	 * we need to roll back any sensors that were successfully
>> +	 * registered. Any other error and we'll skip that step, as
>> +	 * it seems better to have one successfully connected sensor.
>> +	 */
>> +
>> +	if (ret == -EPROBE_DEFER)
>> +		cio2_bridge_unregister_sensors();
>> +
>> +	return ret;
>> +}
>> +
>> +int cio2_bridge_build(struct pci_dev *cio2)
>> +{
>> +	struct fwnode_handle *fwnode;
>> +	int ret;
>> +
>> +	pci_dev_get(cio2);
>> +
>> +	ret = software_node_register(&cio2_hid_node);
>> +	if (ret < 0) {
>> +		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
>> +		goto err_put_cio2;
>> +	}
>> +
>> +	ret = connect_supported_devices(cio2);
>> +	if (ret == -EPROBE_DEFER)
>> +		goto err_unregister_cio2;
>> +
>> +	if (bridge.n_sensors == 0) {
>> +		ret = -EPROBE_DEFER;
>> +		goto err_unregister_cio2;
>> +	}
>> +
>> +	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
>> +
>> +	fwnode = software_node_fwnode(&cio2_hid_node);
>> +	if (!fwnode) {
>> +		dev_err(&cio2->dev,
>> +			"Error getting fwnode from cio2 software_node\n");
>> +		ret = -ENODEV;
>> +		goto err_unregister_sensors;
>> +	}
>> +
>> +	set_secondary_fwnode(&cio2->dev, fwnode);
>> +
>> +	return 0;
>> +
>> +err_unregister_sensors:
>> +	cio2_bridge_unregister_sensors();
>> +err_unregister_cio2:
>> +	software_node_unregister(&cio2_hid_node);
>> +err_put_cio2:
>> +	pci_dev_put(cio2);
>> +
>> +	return ret;
>> +}
>> +
>> +void cio2_bridge_burn(struct pci_dev *cio2)
> Interesting function name :-) I like the creativity, but I think
> consistency with the rest of the kernel code should unfortunately be
> favoured.

Heh yep - already changed to _init/_clean per Andy's comments. Couldn't
resist the pun!

>> +	struct sensor sensors[MAX_CONNECTED_DEVICES];
>> +};
>> +
>> +/* Data representation as it is in ACPI SSDB buffer */
>> +struct sensor_bios_data_packed {
> Similarly as above, I'd use a cio2_ prefix, and I think you can drop the
> _packed suffix. How about naming it cio2_sensor_ssdb_data (or even just
> cio2_sensor_ssdb) to make it clearer that it contains the SSDB data ?
Already done (well, sensor_ssdb currently) to keep consistent with
struct pmic_cldb that was introduced. I'll add the cio2 prefix.
>
>> +	u8 version;
>> +	u8 sku;
>> +	u8 guid_csi2[16];
>> +	u8 devfunction;
>> +	u8 bus;
>> +	u32 dphylinkenfuses;
>> +	u32 clockdiv;
>> +	u8 link;
>> +	u8 lanes;
>> +	u32 csiparams[10];
>> +	u32 maxlanespeed;
>> +	u8 sensorcalibfileidx;
>> +	u8 sensorcalibfileidxInMBZ[3];
>> +	u8 romtype;
>> +	u8 vcmtype;
>> +	u8 platforminfo;
>> +	u8 platformsubinfo;
>> +	u8 flash;
>> +	u8 privacyled;
>> +	u8 degree;
>> +	u8 mipilinkdefined;
>> +	u32 mclkspeed;
>> +	u8 controllogicid;
>> +	u8 reserved1[3];
>> +	u8 mclkport;
>> +	u8 reserved2[13];
>> +} __packed__;
>> +
>> +/* Fields needed by bridge driver */
>> +struct sensor_bios_data {
> And cio2_sensor_data ?
Ack
>
>> +	struct device *dev;
>> +	u8 link;
>> +	u8 lanes;
>> +	u8 degree;
>> +	u32 mclkspeed;
>> +};
>> +
>> +#endif
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> index f68ef0f6b..827457110 100644
>> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> @@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>>  static int cio2_pci_probe(struct pci_dev *pci_dev,
>>  			  const struct pci_device_id *id)
>>  {
>> +	struct fwnode_handle *endpoint;
>>  	struct cio2_device *cio2;
>>  	int r;
>>  
>> +	/*
>> +	 * On some platforms no connections to sensors are defined in firmware,
>> +	 * if the device has no endpoints then we can try to build those as
>> +	 * software_nodes parsed from SSDB.
>> +	 *
>> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
>> +	 * but not yet ready for use (either not attached to the i2c bus yet,
>> +	 * or not done probing themselves).
> Why do we need for the I2C devices to be probed, isn't it enough to have
> them created ?
Ooops  - a relic of the prior version that I missed out when cleaning up
- I'll fix that
> No need for an extra indentation level, neither here, not below.
> NO need for this blank line.
Both fixed - thanks very much

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24  8:50     ` Dan Scally
@ 2020-10-24  9:37       ` Laurent Pinchart
  2020-10-24 22:28         ` Daniel Scally
  2020-10-26 16:10         ` Andy Shevchenko
  0 siblings, 2 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24  9:37 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

Hi Daniel,

On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> On 24/10/2020 02:24, Laurent Pinchart wrote:
>
> > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> >> Currently on platforms designed for Windows, connections between CIO2 and
> >> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> >> driver to compensate by building software_node connections, parsing the
> >> connection properties from the sensor's SSDB buffer.
> >>
> >> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> >> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> >> ---
> >> Changes in v3:
> >> 	- Rather than overwriting the device's primary fwnode, we now
> >> 	simply assign a secondary. Some of the preceding patches alter the
> >> 	existing driver code and v4l2 framework to allow for that.
> >> 	- Rather than reprobe() the sensor after connecting the devices in
> >> 	cio2-bridge we create the software_nodes right away. In this case,
> >> 	sensor drivers will have to defer probing until they detect that a
> >> 	fwnode graph is connecting them to the CIO2 device.
> >> 	- Error paths in connect_supported_devices() moved outside the
> >> 	loop
> >> 	- Replaced pr_*() with dev_*() throughout
> >> 	- Moved creation of software_node / property_entry arrays to stack
> >> 	- A lot of formatting changes.
> >>
> >>  MAINTAINERS                                   |   1 +
> >>  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
> >>  drivers/media/pci/intel/ipu3/Makefile         |   3 +-
> >>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
> >>  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
> >>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
> >>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
> >>  7 files changed, 472 insertions(+), 1 deletion(-)
> >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
> >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 5d768d5ad..4c9c646c7 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
> >>  M:	Yong Zhi <yong.zhi@intel.com>
> >>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
> >>  M:	Bingbu Cao <bingbu.cao@intel.com>
> >> +M:	Dan Scally <djrscally@gmail.com>
> >>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
> >>  L:	linux-media@vger.kernel.org
> >>  S:	Maintained
> >> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> >> index 82d7f17e6..d14cbceae 100644
> >> --- a/drivers/media/pci/intel/ipu3/Kconfig
> >> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> >> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
> >>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
> >>  	  connected camera.
> >>  	  The module will be called ipu3-cio2.
> >> +
> >> +config CIO2_BRIDGE
> >> +	bool "IPU3 CIO2 Sensors Bridge"
> >> +	depends on VIDEO_IPU3_CIO2
> >> +	help
> >> +	  This extension provides an API for the ipu3-cio2 driver to create
> >> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> >> +	  can be used to enable support for cameras in detachable / hybrid
> >> +	  devices that ship with Windows.
> >> +
> >> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> >> +	  with Windows installed by the OEM, for example:
> >> +
> >> +	  	- Some Microsoft Surface models
> >> +		- The Lenovo Miix line
> >> +		- Dell 7285
> >> +
> >> +	  If in doubt, say N here.
> >> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> >> index b4e3266d9..933777e6e 100644
> >> --- a/drivers/media/pci/intel/ipu3/Makefile
> >> +++ b/drivers/media/pci/intel/ipu3/Makefile
> >> @@ -1,4 +1,5 @@
> >>  # SPDX-License-Identifier: GPL-2.0-only
> >>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> >>  
> >> -ipu3-cio2-y += ipu3-cio2-main.o
> >> \ No newline at end of file
> >> +ipu3-cio2-y += ipu3-cio2-main.o
> >> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> >> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> >> new file mode 100644
> >> index 000000000..bbe072f04
> >> --- /dev/null
> >> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> >> @@ -0,0 +1,327 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +// Author: Dan Scally <djrscally@gmail.com>
> >> +#include <linux/acpi.h>
> >> +#include <linux/device.h>
> >> +#include <linux/fwnode.h>
> >> +#include <linux/i2c.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/module.h>
> >> +#include <linux/pci.h>
> >> +#include <linux/property.h>
> >> +#include <media/v4l2-subdev.h>
> >> +
> >> +#include "cio2-bridge.h"
> >> +
> >> +/*
> >> + * Extend this array with ACPI Hardware ID's of devices known to be
> >> + * working
> >> + */
> >> +static const char * const supported_devices[] = {
> >> +	"INT33BE",
> >> +	"OVTI2680",
> >> +};
> >> +
> >> +static struct software_node cio2_hid_node = { CIO2_HID };
> >> +
> >> +static struct cio2_bridge bridge;
> >
> > While there shouldn't be more than one CIO2 instance, we try to develop
> > drivers in a way that avoids global per-device variables. Could all this
> > be allocated dynamically, with the pointer returned by
> > cio2_bridge_build() and stored in the cio2_device structure ?
>
> Yes, ok, I'll make that change.
>
> >> +
> >> +static const char * const port_names[] = {
> >> +	"port0", "port1", "port2", "port3"
> >> +};
> >> +
> >> +static const struct property_entry remote_endpoints[] = {
> >> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, Sensor Property */
> >> +			   &bridge.sensors[0].swnodes[SWNODE_CIO2_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, CIO2 Property */
> >> +			   &bridge.sensors[0].swnodes[SWNODE_SENSOR_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[1].swnodes[SWNODE_CIO2_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[1].swnodes[SWNODE_SENSOR_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[2].swnodes[SWNODE_CIO2_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[2].swnodes[SWNODE_SENSOR_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[3].swnodes[SWNODE_CIO2_ENDPOINT]),
> >> +	PROPERTY_ENTRY_REF("remote-endpoint",
> >> +			   &bridge.sensors[3].swnodes[SWNODE_SENSOR_ENDPOINT]),
> >> +};
> >
> > For the same reason, I would move this to the sensor structure (with two
> > property_entry per sensor). That will simplify the code below, avoiding
> > indexing this array with bridge.n_sensors * 2.
>
> I had some trouble with that which is why I ended up doing things this
> way; I'll revisit it and see if I can resolve that.
>
> >> +
> >> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)
> >
> > To avoid potential future namespace classes, I'd advise naming the
> > functions with a cio2_bridge_ prefix, even the static ones.
> >
> > And maybe cio2_bridge_read_acpi_buffer(), as this function reads a
> > buffer ?
>
> Ack to both; and to the similar comments re: variable naming below.
>
> >> +{
> >> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> >> +	struct acpi_handle *handle;
> >> +	union acpi_object *obj;
> >> +	acpi_status status;
> >> +	int ret;
> >> +
> >> +	handle = ACPI_HANDLE(dev);
> >> +
> >> +	status = acpi_evaluate_object(handle, id, NULL, &buffer);
> >> +	if (ACPI_FAILURE(status))
> >> +		return -ENODEV;
> >> +
> >> +	obj = buffer.pointer;
> >> +	if (!obj) {
> >> +		dev_err(dev, "Couldn't locate ACPI buffer\n");
> >> +		return -ENODEV;
> >> +	}
> >> +
> >> +	if (obj->type != ACPI_TYPE_BUFFER) {
> >> +		dev_err(dev, "Couldn't read ACPI buffer\n");
> >> +		ret = -ENODEV;
> >> +		goto out_free_buff;
> >> +	}
> >> +
> >> +	if (obj->buffer.length > size) {
> >> +		dev_err(dev, "Given buffer is too small\n");
> >> +		ret = -ENODEV;
> >> +		goto out_free_buff;
> >> +	}
> >> +
> >> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> >> +	ret = obj->buffer.length;
> >> +
> >> +out_free_buff:
> >> +	kfree(buffer.pointer);
> >> +	return ret;
> >> +}
> >> +
> >> +static int get_acpi_ssdb_sensor_data(struct device *dev,
> >> +				     struct sensor_bios_data *sensor)
> >> +{
> >> +	struct sensor_bios_data_packed sensor_data;
> >> +	int ret;
> >> +
> >> +	ret = read_acpi_block(dev, "SSDB", &sensor_data, sizeof(sensor_data));
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	sensor->link = sensor_data.link;
> >> +	sensor->lanes = sensor_data.lanes;
> >> +	sensor->mclkspeed = sensor_data.mclkspeed;
> >> +	sensor->degree = sensor_data.degree;
> >
> > How about storing a sensor_bios_data_packed inside sensor_bios_data ?
> > That will avoid copying fields individually, with manual addition of
> > extra fields as they become useful. Usage of the sensor_bios_data
> > structure would turn from sensor->degree to sensor->ssdb.degree, which
> > is slightly longer, but I think more maintainable.
>
> Inside the struct sensor you mean (confusingly, the variable named
> sensor here is _not_ of type struct sensor, which I acknowledge is plain
> silly)? If so, agreed, I'll change it to that. That's also consistent
> with what I'm doing with the equivalent struct for the PMIC's CLDB in
> the regulator work so that makes sense anyway.

Yes. Looking at it again, the sensor_bios_data structure can likely be
dropped, as it bundles a struct device pointer, which is unused, with
fields copied from sensor_bios_data_packed, which should be stored in
the sensor struct.

> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int create_fwnode_properties(struct sensor *sensor,
> >> +				    struct sensor_bios_data *ssdb)
> >> +{
> >> +	struct property_entry *cio2_properties = sensor->cio2_properties;
> >> +	struct property_entry *dev_properties = sensor->dev_properties;
> >> +	struct property_entry *ep_properties = sensor->ep_properties;
> >> +	int i;
> >
> > i never takes negative values, you can make it an unsigned int. Same for
> > other occurrences below.
> >
> >> +
> >> +	/* device fwnode properties */
> >> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);
> >
> > I would memset() bridge to 0 in one go and avoid individual memsets. And
> > if you allocate it with kzalloc() it will be initialized to 0.
>
> Yep ok, I'll initialize the whole thing with kzalloc at the start then
>
> >> +
> >> +	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
> >> +					       ssdb->mclkspeed);
> >> +	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
> >> +
> >> +	/* endpoint fwnode properties */
> >> +	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
> >> +
> >> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
> >> +					   GFP_KERNEL);
> >
> > Given that there can't be more than 4 data lanes, how about turning
> > data_lanes into an array with 4 entries, to avoid the dynamic allocation
> > ? You will have to validate ssdb->lanes in connect_supported_devices(),
> > to make sure not to overflow the array. This and the next function can
> > then be turned into void functions.
>
> OK - is that generally better then (I.E. avoiding dynamic allocation),
> or just when the "wasted" memory is so small?

Just when the amount of wasted memory is small.

> >> +
> >> +	if (!sensor->data_lanes)
> >> +		return -ENOMEM;
> >> +
> >> +	for (i = 0; i < ssdb->lanes; i++)
> >> +		sensor->data_lanes[i] = i + 1;
> >> +
> >> +	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
> >> +	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> >> +							sensor->data_lanes,
> >> +							ssdb->lanes);
> >> +	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
> >> +
> >> +	/* cio2 endpoint props */
> >> +	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
> >> +
> >> +	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> >> +							  sensor->data_lanes,
> >> +							  ssdb->lanes);
> >> +	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int create_connection_swnodes(struct sensor *sensor,
> >> +				     struct sensor_bios_data *ssdb)
> >> +{
> >> +	struct software_node *nodes = sensor->swnodes;
> >> +
> >> +	memset(nodes, 0, sizeof(struct software_node) * 6);
> >> +
> >> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> >> +					       sensor->dev_properties);
> >> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT("port0",
> >> +					      &nodes[SWNODE_SENSOR_HID]);
> >> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> >> +						      &nodes[SWNODE_SENSOR_PORT],
> >> +						      sensor->ep_properties);
> >> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(port_names[ssdb->link],
> >> +					    &cio2_hid_node);
> >> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> >> +						    &nodes[SWNODE_CIO2_PORT],
> >> +						    sensor->cio2_properties);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void cio2_bridge_unregister_sensors(void)
> >> +{
> >> +	struct sensor *sensor;
> >> +	int i;
> >> +
> >> +	for (i = 0; i < bridge.n_sensors; i++) {
> >> +		sensor = &bridge.sensors[i];
> >> +
> >> +		software_node_unregister_nodes_reverse(sensor->swnodes);
> >> +
> >> +		kfree(sensor->data_lanes);
> >> +
> >> +		put_device(sensor->dev);
> >> +		acpi_dev_put(sensor->adev);
> >> +	}
> >> +}
> >> +
> >> +static int connect_supported_devices(struct pci_dev *cio2)
> >> +{
> >> +	struct sensor_bios_data ssdb;
> >> +	struct fwnode_handle *fwnode;
> >> +	struct acpi_device *adev;
> >> +	struct sensor *sensor;
> >> +	struct device *dev;
> >> +	int i, ret;
> >> +
> >> +	ret = 0;
> >
> > You can initialize ret to 0 when declaring the variable.
>
> Is that ok on the same like as i's declaration, or should I split them?

I usually prefer splitting them, but that's a matter of personal taste I
suppose. This being said, as i should be an unsigned int, they will have
to be split anyway.

> >> +	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
> >> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> >
> > What if there are multiple sensor of the same model ?
> 
> Hmm, yeah, that would be a bit of a pickle. I guess the newer
> smartphones have multiple sensors on the back, which I presume are the
> same model. So that will probably crop up at some point. How about
> instead I use bus_for_each_dev() and in the applied function check if
> the _HID is in the supported list?

Sounds good to me.

> >> +		if (!adev)
> >> +			continue;
> >> +
> >
> > Does acpi_dev_get_first_match_dev() skip disabled devices (as reported
> > by _STA) ?
>
> Yes.
>
> >> +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
> >> +		if (!dev) {
> >> +			ret = -EPROBE_DEFER;
> >> +			goto err_rollback;
> >> +		}
> >> +
> >> +		sensor = &bridge.sensors[bridge.n_sensors];
> >> +		sensor->dev = dev;
> >> +		sensor->adev = adev;
> >> +
> >> +		snprintf(sensor->name, ACPI_ID_LEN, "%s",
> >> +			 supported_devices[i]);
> >
> > How about strlcpy() ?
>
> Sure
>
> >> +
> >> +		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
> >> +		if (ret)
> >> +			goto err_free_dev;
> >> +
> >> +		ret = create_fwnode_properties(sensor, &ssdb);
> >> +		if (ret)
> >> +			goto err_free_dev;
> >> +
> >> +		ret = create_connection_swnodes(sensor, &ssdb);
> >> +		if (ret)
> >> +			goto err_free_dev;
> >> +
> >> +		ret = software_node_register_nodes(sensor->swnodes);
> >> +		if (ret)
> >> +			goto err_free_dev;
> >> +
> >> +		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> >> +		if (!fwnode) {
> >> +			ret = -ENODEV;
> >> +			goto err_free_swnodes;
> >> +		}
> >> +
> >> +		set_secondary_fwnode(dev, fwnode);
> >
> > I wonder if we could avoid depending on the I2C device being created by
> > getting the fwnode from adev, and setting ->secondary manually. adev
> > would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
>
> Let me try that; I initially wanted to do
> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
> dev being created but it turns out &adev->dev isn't the same pointer. I
> shall try it and see.
>
> >> +
> >> +		dev_info(&cio2->dev, "Found supported device %s\n",
> >> +			 supported_devices[i]);
> >> +
> >> +		bridge.n_sensors++;
> >> +		continue;
> >> +	}
> >> +
> >> +	return ret;
> >> +
> >> +err_free_swnodes:
> >> +	software_node_unregister_nodes_reverse(sensor->swnodes);
> >> +err_free_dev:
> >> +	put_device(dev);
> >> +err_rollback:
> >> +	acpi_dev_put(adev);
> >
> > I think you'll leak sensor->data_lanes here. It won't be a problem if
> > you don't allocate it manually, as proposed above. I however wonder if
> > error handling couldn't be simplified by increasing bridge.n_sensors
> > earlier, and skipping cleanup in cio2_bridge_unregister_sensors() for
> > the fields that haven't been initialized (for instance kfree() is a
> > no-op on NULL pointers, so that's already handled).
>
> Errrr the only sticky bit there is the desire _not_ to unwind all the
> sensors if it managed to successfully connect one of them; if I'm just
> calling cio2_bridge_unregister_sensors() on any error then a failure for
> one sensor will result in no working cameras, where this way at least
> one of them might be available.

Good point. I expect this to be reworked anyway if we can stop depending
on the I2C device being created, there should be no need to defer
probing in that case.

> >> +
> >> +	/*
> >> +	 * If an iteration of this loop results in -EPROBE_DEFER then
> >> +	 * we need to roll back any sensors that were successfully
> >> +	 * registered. Any other error and we'll skip that step, as
> >> +	 * it seems better to have one successfully connected sensor.
> >> +	 */
> >> +
> >> +	if (ret == -EPROBE_DEFER)
> >> +		cio2_bridge_unregister_sensors();
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +int cio2_bridge_build(struct pci_dev *cio2)
> >> +{
> >> +	struct fwnode_handle *fwnode;
> >> +	int ret;
> >> +
> >> +	pci_dev_get(cio2);
> >> +
> >> +	ret = software_node_register(&cio2_hid_node);
> >> +	if (ret < 0) {
> >> +		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
> >> +		goto err_put_cio2;
> >> +	}
> >> +
> >> +	ret = connect_supported_devices(cio2);
> >> +	if (ret == -EPROBE_DEFER)
> >> +		goto err_unregister_cio2;
> >> +
> >> +	if (bridge.n_sensors == 0) {
> >> +		ret = -EPROBE_DEFER;
> >> +		goto err_unregister_cio2;
> >> +	}
> >> +
> >> +	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
> >> +
> >> +	fwnode = software_node_fwnode(&cio2_hid_node);
> >> +	if (!fwnode) {
> >> +		dev_err(&cio2->dev,
> >> +			"Error getting fwnode from cio2 software_node\n");
> >> +		ret = -ENODEV;
> >> +		goto err_unregister_sensors;
> >> +	}
> >> +
> >> +	set_secondary_fwnode(&cio2->dev, fwnode);
> >> +
> >> +	return 0;
> >> +
> >> +err_unregister_sensors:
> >> +	cio2_bridge_unregister_sensors();
> >> +err_unregister_cio2:
> >> +	software_node_unregister(&cio2_hid_node);
> >> +err_put_cio2:
> >> +	pci_dev_put(cio2);
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +void cio2_bridge_burn(struct pci_dev *cio2)
> >
> > Interesting function name :-) I like the creativity, but I think
> > consistency with the rest of the kernel code should unfortunately be
> > favoured.
> 
> Heh yep - already changed to _init/_clean per Andy's comments. Couldn't
> resist the pun!
> 
> >> +	struct sensor sensors[MAX_CONNECTED_DEVICES];
> >> +};
> >> +
> >> +/* Data representation as it is in ACPI SSDB buffer */
> >> +struct sensor_bios_data_packed {
> >
> > Similarly as above, I'd use a cio2_ prefix, and I think you can drop the
> > _packed suffix. How about naming it cio2_sensor_ssdb_data (or even just
> > cio2_sensor_ssdb) to make it clearer that it contains the SSDB data ?
>
> Already done (well, sensor_ssdb currently) to keep consistent with
> struct pmic_cldb that was introduced. I'll add the cio2 prefix.
>
> >> +	u8 version;
> >> +	u8 sku;
> >> +	u8 guid_csi2[16];
> >> +	u8 devfunction;
> >> +	u8 bus;
> >> +	u32 dphylinkenfuses;
> >> +	u32 clockdiv;
> >> +	u8 link;
> >> +	u8 lanes;
> >> +	u32 csiparams[10];
> >> +	u32 maxlanespeed;
> >> +	u8 sensorcalibfileidx;
> >> +	u8 sensorcalibfileidxInMBZ[3];
> >> +	u8 romtype;
> >> +	u8 vcmtype;
> >> +	u8 platforminfo;
> >> +	u8 platformsubinfo;
> >> +	u8 flash;
> >> +	u8 privacyled;
> >> +	u8 degree;
> >> +	u8 mipilinkdefined;
> >> +	u32 mclkspeed;
> >> +	u8 controllogicid;
> >> +	u8 reserved1[3];
> >> +	u8 mclkport;
> >> +	u8 reserved2[13];
> >> +} __packed__;
> >> +
> >> +/* Fields needed by bridge driver */
> >> +struct sensor_bios_data {
> >
> > And cio2_sensor_data ?
>
> Ack
>
> >> +	struct device *dev;
> >> +	u8 link;
> >> +	u8 lanes;
> >> +	u8 degree;
> >> +	u32 mclkspeed;
> >> +};
> >> +
> >> +#endif
> >> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> index f68ef0f6b..827457110 100644
> >> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> @@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
> >>  static int cio2_pci_probe(struct pci_dev *pci_dev,
> >>  			  const struct pci_device_id *id)
> >>  {
> >> +	struct fwnode_handle *endpoint;
> >>  	struct cio2_device *cio2;
> >>  	int r;
> >>  
> >> +	/*
> >> +	 * On some platforms no connections to sensors are defined in firmware,
> >> +	 * if the device has no endpoints then we can try to build those as
> >> +	 * software_nodes parsed from SSDB.
> >> +	 *
> >> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
> >> +	 * but not yet ready for use (either not attached to the i2c bus yet,
> >> +	 * or not done probing themselves).
> >
> > Why do we need for the I2C devices to be probed, isn't it enough to have
> > them created ?
>
> Ooops  - a relic of the prior version that I missed out when cleaning up
> - I'll fix that
>
> > No need for an extra indentation level, neither here, not below.
> > NO need for this blank line.
>
> Both fixed - thanks very much

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-24  0:39           ` Laurent Pinchart
@ 2020-10-24 14:29             ` Sakari Ailus
  2020-10-24 16:33               ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Sakari Ailus @ 2020-10-24 14:29 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, Andy Shevchenko, linux-kernel, linux-media,
	linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	sergey.senozhatsky, rostedt, pmladek, mchehab, tian.shu.qiu,
	bingbu.cao, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

On Sat, Oct 24, 2020 at 03:39:55AM +0300, Laurent Pinchart wrote:
> Hi Sakari
> 
> On Wed, Oct 21, 2020 at 01:49:10AM +0300, Sakari Ailus wrote:
> > On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
> > > On 20/10/2020 13:06, Sakari Ailus wrote:
> > > > On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
> > > >> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> > > >>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> > > >>> only; that status being determined through the .device_is_available() op
> > > >>> of the device's fwnode. As software_nodes don't have that operation and
> > > >>> adding it is meaningless, we instead need to check if the device's fwnode
> > > >>> is a software_node and if so pass the appropriate flag to disable that
> > > >>> check
> > > >> Period.
> > > >>
> > > >> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
> > > > The device availability test is actually there for a reason. Some firmware
> > > > implementations put all the potential devices in the tables and only one
> > > > (of some) of them are available.
> > > >
> > > > Could this be implemented so that if the node is a software node, then get
> > > > its parent and then see if that is available?
> > > >
> > > > I guess that could be implemented in software node ops. Any opinions?
> > > Actually when considering the cio2 device, it seems that
> > > set_secondary_fwnode() actually overwrites the _primary_, given
> > > fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
> > > this wouldn't work.
> > 
> > Ouch. I wonder when this happens --- have you checked what's the primary
> > there? I guess it might be if it's a PCI device without the corresponding
> > ACPI device node?
> > 
> > I remember you had an is_available implementation that just returned true
> > for software nodes in an early version of the set? I think it would still
> > be a lesser bad in this case.
> 
> How about the following ?

Looks good to me.

> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 81bd01ed4042..ea44ba846299 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -706,9 +706,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>  /**
>   * fwnode_device_is_available - check if a device is available for use
>   * @fwnode: Pointer to the fwnode of the device.
> + *
> + * For fwnode node types that don't implement the .device_is_available()
> + * operation, such as software nodes, this function returns true.
>   */
>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>  {
> +	if (!fwnode_has_op(fwnode, device_is_available))
> +		return true;
>  	return fwnode_call_bool_op(fwnode, device_is_available);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);
> 

-- 
Sakari Ailus

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24  1:24   ` Laurent Pinchart
  2020-10-24  8:50     ` Dan Scally
@ 2020-10-24 15:11     ` Sakari Ailus
  1 sibling, 0 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-24 15:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao, yong.zhi,
	rafael, gregkh, kitakar, dan.carpenter

Hi Laurent, Daniel,

On Sat, Oct 24, 2020 at 04:24:11AM +0300, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> > Currently on platforms designed for Windows, connections between CIO2 and
> > sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> > driver to compensate by building software_node connections, parsing the
> > connection properties from the sensor's SSDB buffer.
> > 
> > Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> > Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > ---
> > Changes in v3:
> > 	- Rather than overwriting the device's primary fwnode, we now
> > 	simply assign a secondary. Some of the preceding patches alter the
> > 	existing driver code and v4l2 framework to allow for that.
> > 	- Rather than reprobe() the sensor after connecting the devices in
> > 	cio2-bridge we create the software_nodes right away. In this case,
> > 	sensor drivers will have to defer probing until they detect that a
> > 	fwnode graph is connecting them to the CIO2 device.
> > 	- Error paths in connect_supported_devices() moved outside the
> > 	loop
> > 	- Replaced pr_*() with dev_*() throughout
> > 	- Moved creation of software_node / property_entry arrays to stack
> > 	- A lot of formatting changes.
> > 
> >  MAINTAINERS                                   |   1 +
> >  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
> >  drivers/media/pci/intel/ipu3/Makefile         |   3 +-
> >  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
> >  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
> >  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
> >  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
> >  7 files changed, 472 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
> >  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 5d768d5ad..4c9c646c7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
> >  M:	Yong Zhi <yong.zhi@intel.com>
> >  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
> >  M:	Bingbu Cao <bingbu.cao@intel.com>
> > +M:	Dan Scally <djrscally@gmail.com>
> >  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
> >  L:	linux-media@vger.kernel.org
> >  S:	Maintained
> > diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> > index 82d7f17e6..d14cbceae 100644
> > --- a/drivers/media/pci/intel/ipu3/Kconfig
> > +++ b/drivers/media/pci/intel/ipu3/Kconfig
> > @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
> >  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
> >  	  connected camera.
> >  	  The module will be called ipu3-cio2.
> > +
> > +config CIO2_BRIDGE
> > +	bool "IPU3 CIO2 Sensors Bridge"
> > +	depends on VIDEO_IPU3_CIO2
> > +	help
> > +	  This extension provides an API for the ipu3-cio2 driver to create
> > +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> > +	  can be used to enable support for cameras in detachable / hybrid
> > +	  devices that ship with Windows.
> > +
> > +	  Say Y here if your device is a detachable / hybrid laptop that comes
> > +	  with Windows installed by the OEM, for example:
> > +
> > +	  	- Some Microsoft Surface models
> > +		- The Lenovo Miix line
> > +		- Dell 7285
> > +
> > +	  If in doubt, say N here.
> > diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> > index b4e3266d9..933777e6e 100644
> > --- a/drivers/media/pci/intel/ipu3/Makefile
> > +++ b/drivers/media/pci/intel/ipu3/Makefile
> > @@ -1,4 +1,5 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> >  
> > -ipu3-cio2-y += ipu3-cio2-main.o
> > \ No newline at end of file
> > +ipu3-cio2-y += ipu3-cio2-main.o
> > +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> > diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> > new file mode 100644
> > index 000000000..bbe072f04
> > --- /dev/null
> > +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> > @@ -0,0 +1,327 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Author: Dan Scally <djrscally@gmail.com>
> > +#include <linux/acpi.h>
> > +#include <linux/device.h>
> > +#include <linux/fwnode.h>
> > +#include <linux/i2c.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/pci.h>
> > +#include <linux/property.h>
> > +#include <media/v4l2-subdev.h>
> > +
> > +#include "cio2-bridge.h"
> > +
> > +/*
> > + * Extend this array with ACPI Hardware ID's of devices known to be
> > + * working
> > + */
> > +static const char * const supported_devices[] = {
> > +	"INT33BE",
> > +	"OVTI2680",
> > +};
> > +
> > +static struct software_node cio2_hid_node = { CIO2_HID };
> > +
> > +static struct cio2_bridge bridge;
> 
> While there shouldn't be more than one CIO2 instance, we try to develop
> drivers in a way that avoids global per-device variables. Could all this
> be allocated dynamically, with the pointer returned by
> cio2_bridge_build() and stored in the cio2_device structure ?

I don't mind but the Windows ACPI table design assumes there's a single
CIO2. Thus the same assumption can be made here, too. Admittedly, I think
it could be cleaner that way.

...

> > +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
> > +		if (!dev) {
> > +			ret = -EPROBE_DEFER;
> > +			goto err_rollback;
> > +		}
> > +
> > +		sensor = &bridge.sensors[bridge.n_sensors];
> > +		sensor->dev = dev;
> > +		sensor->adev = adev;
> > +
> > +		snprintf(sensor->name, ACPI_ID_LEN, "%s",
> > +			 supported_devices[i]);
> 
> How about strlcpy() ?

Or even strscpy()?

> > +void cio2_bridge_burn(struct pci_dev *cio2)
> 
> Interesting function name :-) I like the creativity, but I think
> consistency with the rest of the kernel code should unfortunately be
> favoured.

I guess we can use any pairs that make sense. Create and destroy? Build and
plunder?

-- 
Regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-10-20  9:41   ` Andy Shevchenko
  2020-10-24  1:24   ` Laurent Pinchart
@ 2020-10-24 15:14   ` Sakari Ailus
  2020-10-24 20:28     ` Dan Scally
  2 siblings, 1 reply; 82+ messages in thread
From: Sakari Ailus @ 2020-10-24 15:14 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Daniel,

Thanks for the update.

On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> Currently on platforms designed for Windows, connections between CIO2 and
> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> driver to compensate by building software_node connections, parsing the
> connection properties from the sensor's SSDB buffer.
> 
> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes in v3:
> 	- Rather than overwriting the device's primary fwnode, we now
> 	simply assign a secondary. Some of the preceding patches alter the
> 	existing driver code and v4l2 framework to allow for that.
> 	- Rather than reprobe() the sensor after connecting the devices in
> 	cio2-bridge we create the software_nodes right away. In this case,
> 	sensor drivers will have to defer probing until they detect that a
> 	fwnode graph is connecting them to the CIO2 device.
> 	- Error paths in connect_supported_devices() moved outside the
> 	loop
> 	- Replaced pr_*() with dev_*() throughout
> 	- Moved creation of software_node / property_entry arrays to stack
> 	- A lot of formatting changes.
> 
>  MAINTAINERS                                   |   1 +
>  drivers/media/pci/intel/ipu3/Kconfig          |  18 +
>  drivers/media/pci/intel/ipu3/Makefile         |   3 +-
>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 327 ++++++++++++++++++
>  drivers/media/pci/intel/ipu3/cio2-bridge.h    |  94 +++++
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  21 ++
>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   9 +
>  7 files changed, 472 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5d768d5ad..4c9c646c7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8848,6 +8848,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>  M:	Yong Zhi <yong.zhi@intel.com>
>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>  M:	Bingbu Cao <bingbu.cao@intel.com>
> +M:	Dan Scally <djrscally@gmail.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 82d7f17e6..d14cbceae 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>  	  connected camera.
>  	  The module will be called ipu3-cio2.
> +
> +config CIO2_BRIDGE
> +	bool "IPU3 CIO2 Sensors Bridge"
> +	depends on VIDEO_IPU3_CIO2
> +	help
> +	  This extension provides an API for the ipu3-cio2 driver to create
> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> +	  can be used to enable support for cameras in detachable / hybrid
> +	  devices that ship with Windows.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM, for example:
> +
> +	  	- Some Microsoft Surface models
> +		- The Lenovo Miix line
> +		- Dell 7285
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index b4e3266d9..933777e6e 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>  
> -ipu3-cio2-y += ipu3-cio2-main.o
> \ No newline at end of file
> +ipu3-cio2-y += ipu3-cio2-main.o
> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> new file mode 100644
> index 000000000..bbe072f04
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> @@ -0,0 +1,327 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Author: Dan Scally <djrscally@gmail.com>

/* Author: ... */

But not the SPDX tag.

> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/fwnode.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/property.h>
> +#include <media/v4l2-subdev.h>
> +
> +#include "cio2-bridge.h"
> +
> +/*
> + * Extend this array with ACPI Hardware ID's of devices known to be
> + * working
> + */
> +static const char * const supported_devices[] = {
> +	"INT33BE",
> +	"OVTI2680",
> +};
> +
> +static struct software_node cio2_hid_node = { CIO2_HID };
> +
> +static struct cio2_bridge bridge;
> +
> +static const char * const port_names[] = {
> +	"port0", "port1", "port2", "port3"
> +};
> +
> +static const struct property_entry remote_endpoints[] = {

How about another dimension, for local and remote? Or make it a struct with
local and remote fields. Perhaps a struct would be better?

This could also be nicer to initialise in a function.

> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, Sensor Property */
> +			   &bridge.sensors[0].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint", /* Sensor 0, CIO2 Property */
> +			   &bridge.sensors[0].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[1].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[1].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[2].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[2].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[3].swnodes[SWNODE_CIO2_ENDPOINT]),
> +	PROPERTY_ENTRY_REF("remote-endpoint",
> +			   &bridge.sensors[3].swnodes[SWNODE_SENSOR_ENDPOINT]),
> +};
> +
> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct acpi_handle *handle;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret;
> +
> +	handle = ACPI_HANDLE(dev);
> +
> +	status = acpi_evaluate_object(handle, id, NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(dev, "Couldn't locate ACPI buffer\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(dev, "Couldn't read ACPI buffer\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > size) {
> +		dev_err(dev, "Given buffer is too small\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> +	ret = obj->buffer.length;
> +
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int get_acpi_ssdb_sensor_data(struct device *dev,
> +				     struct sensor_bios_data *sensor)
> +{
> +	struct sensor_bios_data_packed sensor_data;
> +	int ret;
> +
> +	ret = read_acpi_block(dev, "SSDB", &sensor_data, sizeof(sensor_data));
> +	if (ret < 0)
> +		return ret;
> +
> +	sensor->link = sensor_data.link;
> +	sensor->lanes = sensor_data.lanes;
> +	sensor->mclkspeed = sensor_data.mclkspeed;
> +	sensor->degree = sensor_data.degree;
> +
> +	return 0;
> +}
> +
> +static int create_fwnode_properties(struct sensor *sensor,
> +				    struct sensor_bios_data *ssdb)
> +{
> +	struct property_entry *cio2_properties = sensor->cio2_properties;
> +	struct property_entry *dev_properties = sensor->dev_properties;
> +	struct property_entry *ep_properties = sensor->ep_properties;
> +	int i;
> +
> +	/* device fwnode properties */
> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);

I'd put them all to the struct itself. Then the compiler will be able to
check array indices.

> +
> +	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
> +					       ssdb->mclkspeed);
> +	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
> +
> +	/* endpoint fwnode properties */
> +	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
> +
> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
> +					   GFP_KERNEL);
> +
> +	if (!sensor->data_lanes)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < ssdb->lanes; i++)
> +		sensor->data_lanes[i] = i + 1;
> +
> +	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
> +	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> +							sensor->data_lanes,
> +							ssdb->lanes);
> +	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
> +
> +	/* cio2 endpoint props */
> +	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
> +
> +	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
> +							  sensor->data_lanes,
> +							  ssdb->lanes);
> +	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
> +
> +	return 0;
> +}
> +
> +static int create_connection_swnodes(struct sensor *sensor,
> +				     struct sensor_bios_data *ssdb)
> +{
> +	struct software_node *nodes = sensor->swnodes;
> +
> +	memset(nodes, 0, sizeof(struct software_node) * 6);

Could you make the index an enum, and add an item to the end used to tell
the number of entries. It could be called e.g. NR_OF_SENSOR_SWNODES.

> +
> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> +					       sensor->dev_properties);
> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT("port0",
> +					      &nodes[SWNODE_SENSOR_HID]);
> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> +						      &nodes[SWNODE_SENSOR_PORT],
> +						      sensor->ep_properties);
> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(port_names[ssdb->link],
> +					    &cio2_hid_node);
> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT("endpoint0",
> +						    &nodes[SWNODE_CIO2_PORT],
> +						    sensor->cio2_properties);
> +
> +	return 0;
> +}
> +
> +static void cio2_bridge_unregister_sensors(void)
> +{
> +	struct sensor *sensor;
> +	int i;
> +
> +	for (i = 0; i < bridge.n_sensors; i++) {
> +		sensor = &bridge.sensors[i];
> +
> +		software_node_unregister_nodes_reverse(sensor->swnodes);
> +
> +		kfree(sensor->data_lanes);
> +
> +		put_device(sensor->dev);
> +		acpi_dev_put(sensor->adev);
> +	}
> +}
> +
> +static int connect_supported_devices(struct pci_dev *cio2)
> +{
> +	struct sensor_bios_data ssdb;
> +	struct fwnode_handle *fwnode;
> +	struct acpi_device *adev;
> +	struct sensor *sensor;
> +	struct device *dev;
> +	int i, ret;
> +
> +	ret = 0;

In declaration.

> +	for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);

Please wrap no later than at 80.

> +		if (!adev)
> +			continue;
> +
> +		dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
> +		if (!dev) {
> +			ret = -EPROBE_DEFER;
> +			goto err_rollback;
> +		}
> +
> +		sensor = &bridge.sensors[bridge.n_sensors];
> +		sensor->dev = dev;
> +		sensor->adev = adev;
> +
> +		snprintf(sensor->name, ACPI_ID_LEN, "%s",

sizeof(sensor->name)

> +			 supported_devices[i]);
> +
> +		ret = get_acpi_ssdb_sensor_data(dev, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_fwnode_properties(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = create_connection_swnodes(sensor, &ssdb);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		ret = software_node_register_nodes(sensor->swnodes);
> +		if (ret)
> +			goto err_free_dev;
> +
> +		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> +		if (!fwnode) {
> +			ret = -ENODEV;
> +			goto err_free_swnodes;
> +		}
> +
> +		set_secondary_fwnode(dev, fwnode);
> +
> +		dev_info(&cio2->dev, "Found supported device %s\n",
> +			 supported_devices[i]);
> +
> +		bridge.n_sensors++;
> +		continue;
> +	}
> +
> +	return ret;
> +
> +err_free_swnodes:
> +	software_node_unregister_nodes_reverse(sensor->swnodes);
> +err_free_dev:
> +	put_device(dev);
> +err_rollback:
> +	acpi_dev_put(adev);
> +
> +	/*
> +	 * If an iteration of this loop results in -EPROBE_DEFER then
> +	 * we need to roll back any sensors that were successfully
> +	 * registered. Any other error and we'll skip that step, as
> +	 * it seems better to have one successfully connected sensor.
> +	 */
> +
> +	if (ret == -EPROBE_DEFER)
> +		cio2_bridge_unregister_sensors();
> +
> +	return ret;
> +}
> +
> +int cio2_bridge_build(struct pci_dev *cio2)
> +{
> +	struct fwnode_handle *fwnode;
> +	int ret;
> +
> +	pci_dev_get(cio2);

Could you check that this isn't used by more than one user? The current
implementation assumes that. I'm not sure if there could be more instances
of CIO2 but if there were, that'd be an issue currently.

> +
> +	ret = software_node_register(&cio2_hid_node);
> +	if (ret < 0) {
> +		dev_err(&cio2->dev, "Failed to register the CIO2 HID node\n");
> +		goto err_put_cio2;
> +	}
> +
> +	ret = connect_supported_devices(cio2);
> +	if (ret == -EPROBE_DEFER)
> +		goto err_unregister_cio2;
> +
> +	if (bridge.n_sensors == 0) {
> +		ret = -EPROBE_DEFER;
> +		goto err_unregister_cio2;
> +	}
> +
> +	dev_info(&cio2->dev, "Connected %d cameras\n", bridge.n_sensors);
> +
> +	fwnode = software_node_fwnode(&cio2_hid_node);
> +	if (!fwnode) {
> +		dev_err(&cio2->dev,
> +			"Error getting fwnode from cio2 software_node\n");
> +		ret = -ENODEV;
> +		goto err_unregister_sensors;
> +	}
> +
> +	set_secondary_fwnode(&cio2->dev, fwnode);
> +
> +	return 0;
> +
> +err_unregister_sensors:
> +	cio2_bridge_unregister_sensors();
> +err_unregister_cio2:
> +	software_node_unregister(&cio2_hid_node);
> +err_put_cio2:
> +	pci_dev_put(cio2);
> +
> +	return ret;
> +}
> +
> +void cio2_bridge_burn(struct pci_dev *cio2)
> +{
> +	pci_dev_put(cio2);
> +
> +	cio2_bridge_unregister_sensors();
> +
> +	software_node_unregister(&cio2_hid_node);
> +}
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> new file mode 100644
> index 000000000..077354ca8
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> @@ -0,0 +1,94 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#ifndef __CIO2_BRIDGE_H
> +#define __CIO2_BRIDGE_H
> +
> +#define MAX_CONNECTED_DEVICES			4
> +#define SWNODE_SENSOR_HID			0
> +#define SWNODE_SENSOR_PORT			1
> +#define SWNODE_SENSOR_ENDPOINT			2
> +#define SWNODE_CIO2_PORT			3
> +#define SWNODE_CIO2_ENDPOINT			4
> +#define SWNODE_NULL_TERMINATOR			5
> +
> +#define CIO2_HID				"INT343E"
> +#define CIO2_PCI_ID				0x9d32
> +
> +#define ENDPOINT_SENSOR				0
> +#define ENDPOINT_CIO2				1
> +
> +#define NODE_SENSOR(_HID, _PROPS)		\
> +	((const struct software_node) {		\
> +		.name = _HID,			\
> +		.properties = _PROPS,		\
> +	})
> +
> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> +	((const struct software_node) {		\
> +		_PORT,				\
> +		_SENSOR_NODE,			\
> +	})
> +
> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> +	((const struct software_node) {		\
> +		_EP,				\
> +		_PORT,				\
> +		_PROPS,				\
> +	})
> +
> +struct sensor {

How about calling this e.g. cio2_sensor? sensor is rather generic.

> +	char name[ACPI_ID_LEN];
> +	struct device *dev;
> +	struct acpi_device *adev;
> +	struct software_node swnodes[6];
> +	struct property_entry dev_properties[3];
> +	struct property_entry ep_properties[4];
> +	struct property_entry cio2_properties[3];
> +	u32 *data_lanes;

The maximum is four so you could as well make this static.

> +};
> +
> +struct cio2_bridge {
> +	int n_sensors;

Do you need negative values? %u, too, if not.

> +	struct sensor sensors[MAX_CONNECTED_DEVICES];
> +};
> +
> +/* Data representation as it is in ACPI SSDB buffer */
> +struct sensor_bios_data_packed {
> +	u8 version;
> +	u8 sku;
> +	u8 guid_csi2[16];
> +	u8 devfunction;
> +	u8 bus;
> +	u32 dphylinkenfuses;
> +	u32 clockdiv;
> +	u8 link;
> +	u8 lanes;
> +	u32 csiparams[10];
> +	u32 maxlanespeed;
> +	u8 sensorcalibfileidx;
> +	u8 sensorcalibfileidxInMBZ[3];
> +	u8 romtype;
> +	u8 vcmtype;
> +	u8 platforminfo;
> +	u8 platformsubinfo;
> +	u8 flash;
> +	u8 privacyled;
> +	u8 degree;
> +	u8 mipilinkdefined;
> +	u32 mclkspeed;
> +	u8 controllogicid;
> +	u8 reserved1[3];
> +	u8 mclkport;
> +	u8 reserved2[13];
> +} __packed__;
> +
> +/* Fields needed by bridge driver */
> +struct sensor_bios_data {
> +	struct device *dev;
> +	u8 link;
> +	u8 lanes;
> +	u8 degree;
> +	u32 mclkspeed;
> +};
> +
> +#endif
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index f68ef0f6b..827457110 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>  static int cio2_pci_probe(struct pci_dev *pci_dev,
>  			  const struct pci_device_id *id)
>  {
> +	struct fwnode_handle *endpoint;
>  	struct cio2_device *cio2;
>  	int r;
>  
> +	/*
> +	 * On some platforms no connections to sensors are defined in firmware,
> +	 * if the device has no endpoints then we can try to build those as
> +	 * software_nodes parsed from SSDB.
> +	 *
> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
> +	 * but not yet ready for use (either not attached to the i2c bus yet,
> +	 * or not done probing themselves).
> +	 */
> +
> +	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&pci_dev->dev), NULL);
> +	if (!endpoint) {
> +		r = cio2_bridge_build(pci_dev);
> +		if (r)
> +			return r;
> +	}

} else {
	fwnode_handle_put(endpoint);
}

> +
>  	cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL);
>  	if (!cio2)
>  		return -ENOMEM;
> @@ -1825,6 +1843,9 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
>  {
>  	struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
>  
> +	if (is_software_node(dev_fwnode(&pci_dev->dev)))
> +		cio2_bridge_burn(pci_dev);
> +
>  	media_device_unregister(&cio2->media_dev);
>  	v4l2_async_notifier_unregister(&cio2->notifier);
>  	v4l2_async_notifier_cleanup(&cio2->notifier);
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> index 549b08f88..80a081d7e 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> @@ -436,4 +436,13 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
>  	return container_of(vq, struct cio2_queue, vbq);
>  }
>  
> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
> +	int cio2_bridge_build(struct pci_dev *cio2);
> +	void cio2_bridge_burn(struct pci_dev *cio2);
> +#else
> +
> +	int cio2_bridge_build(struct pci_dev *cio2) { return 0; }
> +	void cio2_bridge_burn(struct pci_dev *cio2) { }
> +#endif
> +
>  #endif

-- 
Regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-24 14:29             ` Sakari Ailus
@ 2020-10-24 16:33               ` Dan Scally
  2020-10-24 16:55                 ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-24 16:33 UTC (permalink / raw)
  To: Sakari Ailus, Laurent Pinchart
  Cc: Andy Shevchenko, linux-kernel, linux-media, linux.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, yong.zhi, rafael, gregkh,
	kitakar, dan.carpenter

On 24/10/2020 15:29, Sakari Ailus wrote:
> On Sat, Oct 24, 2020 at 03:39:55AM +0300, Laurent Pinchart wrote:
>> Hi Sakari
>>
>> On Wed, Oct 21, 2020 at 01:49:10AM +0300, Sakari Ailus wrote:
>>> On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
>>>> On 20/10/2020 13:06, Sakari Ailus wrote:
>>>>> On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
>>>>>> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
>>>>>>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
>>>>>>> only; that status being determined through the .device_is_available() op
>>>>>>> of the device's fwnode. As software_nodes don't have that operation and
>>>>>>> adding it is meaningless, we instead need to check if the device's fwnode
>>>>>>> is a software_node and if so pass the appropriate flag to disable that
>>>>>>> check
>>>>>> Period.
>>>>>>
>>>>>> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
>>>>> The device availability test is actually there for a reason. Some firmware
>>>>> implementations put all the potential devices in the tables and only one
>>>>> (of some) of them are available.
>>>>>
>>>>> Could this be implemented so that if the node is a software node, then get
>>>>> its parent and then see if that is available?
>>>>>
>>>>> I guess that could be implemented in software node ops. Any opinions?
>>>> Actually when considering the cio2 device, it seems that
>>>> set_secondary_fwnode() actually overwrites the _primary_, given
>>>> fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
>>>> this wouldn't work.
>>> Ouch. I wonder when this happens --- have you checked what's the primary
>>> there? I guess it might be if it's a PCI device without the corresponding
>>> ACPI device node?
>>>
>>> I remember you had an is_available implementation that just returned true
>>> for software nodes in an early version of the set? I think it would still
>>> be a lesser bad in this case.
>> How about the following ?
> Looks good to me.
If we're agreed on this (and it's fine by me too), do you want me to
include it in the next set, or are you going to do it separately Laurent?
>> diff --git a/drivers/base/property.c b/drivers/base/property.c
>> index 81bd01ed4042..ea44ba846299 100644
>> --- a/drivers/base/property.c
>> +++ b/drivers/base/property.c
>> @@ -706,9 +706,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>>  /**
>>   * fwnode_device_is_available - check if a device is available for use
>>   * @fwnode: Pointer to the fwnode of the device.
>> + *
>> + * For fwnode node types that don't implement the .device_is_available()
>> + * operation, such as software nodes, this function returns true.
>>   */
>>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>>  {
>> +	if (!fwnode_has_op(fwnode, device_is_available))
>> +		return true;
>>  	return fwnode_call_bool_op(fwnode, device_is_available);
>>  }
>>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);
>>

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

* Re: [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so
  2020-10-24 16:33               ` Dan Scally
@ 2020-10-24 16:55                 ` Laurent Pinchart
  0 siblings, 0 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24 16:55 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, Andy Shevchenko, linux-kernel, linux-media,
	linux.walleij, prabhakar.mahadev-lad.rj, heikki.krogerus,
	dmitry.torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, jacopo+renesas, robh, davem, linux,
	sergey.senozhatsky, rostedt, pmladek, mchehab, tian.shu.qiu,
	bingbu.cao, yong.zhi, rafael, gregkh, kitakar, dan.carpenter

Hi Dan,

On Sat, Oct 24, 2020 at 05:33:32PM +0100, Dan Scally wrote:
> On 24/10/2020 15:29, Sakari Ailus wrote:
> > On Sat, Oct 24, 2020 at 03:39:55AM +0300, Laurent Pinchart wrote:
> >> On Wed, Oct 21, 2020 at 01:49:10AM +0300, Sakari Ailus wrote:
> >>> On Tue, Oct 20, 2020 at 08:56:07PM +0100, Dan Scally wrote:
> >>>> On 20/10/2020 13:06, Sakari Ailus wrote:
> >>>>> On Tue, Oct 20, 2020 at 12:19:58PM +0300, Andy Shevchenko wrote:
> >>>>>> On Mon, Oct 19, 2020 at 11:59:01PM +0100, Daniel Scally wrote:
> >>>>>>> fwnode_graph_get_endpoint_by_id() will optionally parse enabled devices
> >>>>>>> only; that status being determined through the .device_is_available() op
> >>>>>>> of the device's fwnode. As software_nodes don't have that operation and
> >>>>>>> adding it is meaningless, we instead need to check if the device's fwnode
> >>>>>>> is a software_node and if so pass the appropriate flag to disable that
> >>>>>>> check
> >>>>>>
> >>>>>> Period.
> >>>>>>
> >>>>>> I'm wondering if actually this can be hidden in fwnode_graph_get_endpoint_by_id().
> >>>>>
> >>>>> The device availability test is actually there for a reason. Some firmware
> >>>>> implementations put all the potential devices in the tables and only one
> >>>>> (of some) of them are available.
> >>>>>
> >>>>> Could this be implemented so that if the node is a software node, then get
> >>>>> its parent and then see if that is available?
> >>>>>
> >>>>> I guess that could be implemented in software node ops. Any opinions?
> >>>>
> >>>> Actually when considering the cio2 device, it seems that
> >>>> set_secondary_fwnode() actually overwrites the _primary_, given
> >>>> fwnode_is_primary(dev->fwnode) returns false. So in at least some cases,
> >>>> this wouldn't work.
> >>>
> >>> Ouch. I wonder when this happens --- have you checked what's the primary
> >>> there? I guess it might be if it's a PCI device without the corresponding
> >>> ACPI device node?
> >>>
> >>> I remember you had an is_available implementation that just returned true
> >>> for software nodes in an early version of the set? I think it would still
> >>> be a lesser bad in this case.
> >>
> >> How about the following ?
> >
> > Looks good to me.
>
> If we're agreed on this (and it's fine by me too), do you want me to
> include it in the next set, or are you going to do it separately Laurent?

Feel free to include it in the next version, but I can send a patch if
you prefer.

> >> diff --git a/drivers/base/property.c b/drivers/base/property.c
> >> index 81bd01ed4042..ea44ba846299 100644
> >> --- a/drivers/base/property.c
> >> +++ b/drivers/base/property.c
> >> @@ -706,9 +706,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
> >>  /**
> >>   * fwnode_device_is_available - check if a device is available for use
> >>   * @fwnode: Pointer to the fwnode of the device.
> >> + *
> >> + * For fwnode node types that don't implement the .device_is_available()
> >> + * operation, such as software nodes, this function returns true.
> >>   */
> >>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
> >>  {
> >> +	if (!fwnode_has_op(fwnode, device_is_available))
> >> +		return true;
> >>  	return fwnode_call_bool_op(fwnode, device_is_available);
> >>  }
> >>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24 15:14   ` Sakari Ailus
@ 2020-10-24 20:28     ` Dan Scally
  2020-10-25 11:18       ` Sakari Ailus
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-24 20:28 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

On 24/10/2020 16:14, Sakari Ailus wrote:
> Hi Daniel,
>
> Thanks for the update.
Thanks for the comments as always
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Author: Dan Scally <djrscally@gmail.com>
> /* Author: ... */
>
> But not the SPDX tag.
Weird - okedokey
>> +#include <linux/acpi.h>
>> +#include <linux/device.h>
>> +#include <linux/fwnode.h>
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pci.h>
>> +#include <linux/property.h>
>> +#include <media/v4l2-subdev.h>
>> +
>> +#include "cio2-bridge.h"
>> +
>> +/*
>> + * Extend this array with ACPI Hardware ID's of devices known to be
>> + * working
>> + */
>> +static const char * const supported_devices[] = {
>> +	"INT33BE",
>> +	"OVTI2680",
>> +};
>> +
>> +static struct software_node cio2_hid_node = { CIO2_HID };
>> +
>> +static struct cio2_bridge bridge;
>> +
>> +static const char * const port_names[] = {
>> +	"port0", "port1", "port2", "port3"
>> +};
>> +
>> +static const struct property_entry remote_endpoints[] = {
> How about another dimension, for local and remote? Or make it a struct with
> local and remote fields. Perhaps a struct would be better?
>
> This could also be nicer to initialise in a function.
Sure; a struct probably would be cleaner I agree. I shall make that change
>> +static int create_fwnode_properties(struct sensor *sensor,
>> +				    struct sensor_bios_data *ssdb)
>> +{
>> +	struct property_entry *cio2_properties = sensor->cio2_properties;
>> +	struct property_entry *dev_properties = sensor->dev_properties;
>> +	struct property_entry *ep_properties = sensor->ep_properties;
>> +	int i;
>> +
>> +	/* device fwnode properties */
>> +	memset(dev_properties, 0, sizeof(struct property_entry) * 3);
> I'd put them all to the struct itself. Then the compiler will be able to
> check array indices.
Makes sense; I think I was just trying to save line length in the rest
of that function by that.
>> +
>> +	dev_properties[0] = PROPERTY_ENTRY_U32("clock-frequency",
>> +					       ssdb->mclkspeed);
>> +	dev_properties[1] = PROPERTY_ENTRY_U8("rotation", ssdb->degree);
>> +
>> +	/* endpoint fwnode properties */
>> +	memset(ep_properties, 0, sizeof(struct property_entry) * 4);
>> +
>> +	sensor->data_lanes = kmalloc_array(ssdb->lanes, sizeof(u32),
>> +					   GFP_KERNEL);
>> +
>> +	if (!sensor->data_lanes)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < ssdb->lanes; i++)
>> +		sensor->data_lanes[i] = i + 1;
>> +
>> +	ep_properties[0] = PROPERTY_ENTRY_U32("bus-type", 5);
>> +	ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
>> +							sensor->data_lanes,
>> +							ssdb->lanes);
>> +	ep_properties[2] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_SENSOR];
>> +
>> +	/* cio2 endpoint props */
>> +	memset(cio2_properties, 0, sizeof(struct property_entry) * 3);
>> +
>> +	cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
>> +							  sensor->data_lanes,
>> +							  ssdb->lanes);
>> +	cio2_properties[1] = remote_endpoints[(bridge.n_sensors * 2) + ENDPOINT_CIO2];
>> +
>> +	return 0;
>> +}
>> +
>> +static int create_connection_swnodes(struct sensor *sensor,
>> +				     struct sensor_bios_data *ssdb)
>> +{
>> +	struct software_node *nodes = sensor->swnodes;
>> +
>> +	memset(nodes, 0, sizeof(struct software_node) * 6);
> Could you make the index an enum, and add an item to the end used to tell
> the number of entries. It could be called e.g. NR_OF_SENSOR_SWNODES.
Ooh I like that, it's neat; thanks - will do.
>> +int cio2_bridge_build(struct pci_dev *cio2)
>> +{
>> +	struct fwnode_handle *fwnode;
>> +	int ret;
>> +
>> +	pci_dev_get(cio2);
> Could you check that this isn't used by more than one user? The current
> implementation assumes that. I'm not sure if there could be more instances
> of CIO2 but if there were, that'd be an issue currently.

I can check; can't think of anything better than just failing out if it
turns out to be in use already though - any ideas or is that appropriate?

>> +struct sensor {
> How about calling this e.g. cio2_sensor? sensor is rather generic.
Yup, will probably prefix all such generically named vars with cio2_*
and functions with cio2_bridge_*().
>> +	char name[ACPI_ID_LEN];
>> +	struct device *dev;
>> +	struct acpi_device *adev;
>> +	struct software_node swnodes[6];
>> +	struct property_entry dev_properties[3];
>> +	struct property_entry ep_properties[4];
>> +	struct property_entry cio2_properties[3];
>> +	u32 *data_lanes;
> The maximum is four so you could as well make this static.
Ack
>> +};
>> +
>> +struct cio2_bridge {
>> +	int n_sensors;
> Do you need negative values? %u, too, if not.
I do not, I will switch to using unsigned.
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> index f68ef0f6b..827457110 100644
>> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> @@ -1715,9 +1715,27 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>>  static int cio2_pci_probe(struct pci_dev *pci_dev,
>>  			  const struct pci_device_id *id)
>>  {
>> +	struct fwnode_handle *endpoint;
>>  	struct cio2_device *cio2;
>>  	int r;
>>  
>> +	/*
>> +	 * On some platforms no connections to sensors are defined in firmware,
>> +	 * if the device has no endpoints then we can try to build those as
>> +	 * software_nodes parsed from SSDB.
>> +	 *
>> +	 * This may EPROBE_DEFER if supported devices are found defined in ACPI
>> +	 * but not yet ready for use (either not attached to the i2c bus yet,
>> +	 * or not done probing themselves).
>> +	 */
>> +
>> +	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&pci_dev->dev), NULL);
>> +	if (!endpoint) {
>> +		r = cio2_bridge_build(pci_dev);
>> +		if (r)
>> +			return r;
>> +	}
> } else {
> 	fwnode_handle_put(endpoint);
> }
Ah, of course, thank you.

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24  9:37       ` Laurent Pinchart
@ 2020-10-24 22:28         ` Daniel Scally
  2020-10-24 22:36           ` Laurent Pinchart
  2020-10-26 16:10         ` Andy Shevchenko
  1 sibling, 1 reply; 82+ messages in thread
From: Daniel Scally @ 2020-10-24 22:28 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

Hi Laurent

On 24/10/2020 10:37, Laurent Pinchart wrote:
>
>>> I wonder if we could avoid depending on the I2C device being created by
>>> getting the fwnode from adev, and setting ->secondary manually. adev
>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
>> Let me try that; I initially wanted to do
>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
>> dev being created but it turns out &adev->dev isn't the same pointer. I
>> shall try it and see.


Actually, thinking on this further I think maybe we can't avoid that -
it's not actually in this patch series but during assigning GPIO
resources parsed from PMIC's ACPI node to the sensor, I'm using
dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table


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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24 22:28         ` Daniel Scally
@ 2020-10-24 22:36           ` Laurent Pinchart
  2020-10-24 22:50             ` Daniel Scally
  2020-10-26  8:20             ` Dan Scally
  0 siblings, 2 replies; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-24 22:36 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

Hi Dan,

On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
> On 24/10/2020 10:37, Laurent Pinchart wrote:
> >
> >>> I wonder if we could avoid depending on the I2C device being created by
> >>> getting the fwnode from adev, and setting ->secondary manually. adev
> >>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
> >> Let me try that; I initially wanted to do
> >> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
> >> dev being created but it turns out &adev->dev isn't the same pointer. I
> >> shall try it and see.
> 
> Actually, thinking on this further I think maybe we can't avoid that -
> it's not actually in this patch series but during assigning GPIO
> resources parsed from PMIC's ACPI node to the sensor, I'm using
> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table

Any chance we can construct the I2C device name from the ACPI device,
the same way that the ACPI/I2C core does ? It may be a dead end, but if
we could avoid depending on the I2C device, I think it will make
initialization easier. I have a feeling that will be difficult though,
as we'll need the I2C bus number, which won't be readily available.

Maybe this calls for extending the gpiod lookup API, but that would then
likely be something we would build on top. I'm thinking about a way to
specify the GPIO mapping in the software node, and retrieving it from
there, the same way this is done for GPIOs in OF-based systems.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24 22:36           ` Laurent Pinchart
@ 2020-10-24 22:50             ` Daniel Scally
  2020-10-26  8:20             ` Dan Scally
  1 sibling, 0 replies; 82+ messages in thread
From: Daniel Scally @ 2020-10-24 22:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

Hi Laurent

On 24/10/2020 23:36, Laurent Pinchart wrote:
> Hi Dan,
>
> On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
>> On 24/10/2020 10:37, Laurent Pinchart wrote:
>>
>>>>> I wonder if we could avoid depending on the I2C device being created by
>>>>> getting the fwnode from adev, and setting ->secondary manually. adev
>>>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
>>>> Let me try that; I initially wanted to do
>>>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
>>>> dev being created but it turns out &adev->dev isn't the same pointer. I
>>>> shall try it and see.
>> Actually, thinking on this further I think maybe we can't avoid that -
>> it's not actually in this patch series but during assigning GPIO
>> resources parsed from PMIC's ACPI node to the sensor, I'm using
>> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table
> Any chance we can construct the I2C device name from the ACPI device,
> the same way that the ACPI/I2C core does ? It may be a dead end, but if
> we could avoid depending on the I2C device, I think it will make
> initialization easier. I have a feeling that will be difficult though,
> as we'll need the I2C bus number, which won't be readily available.

I'd have to look into how the ACPI/I2C core does it to be confident, but
I think it would be ok. Doesn't look to me like the bus number is
involved; my sensor's device names come through as "i2c-OVTI2680:00";
that's just a prefix tacked on to dev_name(adev->dev). I'm sure there's
something that will stop it being quite so easy, but hopefully not
insurmountable.

> Maybe this calls for extending the gpiod lookup API, but that would then
> likely be something we would build on top. I'm thinking about a way to
> specify the GPIO mapping in the software node, and retrieving it from
> there, the same way this is done for GPIOs in OF-based systems.
Yeah that's an option too; I had had the same thought actually. Probably
an extensive piece of work in its own right though

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24 20:28     ` Dan Scally
@ 2020-10-25 11:18       ` Sakari Ailus
  0 siblings, 0 replies; 82+ messages in thread
From: Sakari Ailus @ 2020-10-25 11:18 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

Hi Daniel,

On Sat, Oct 24, 2020 at 09:28:07PM +0100, Dan Scally wrote:
...
> >> +int cio2_bridge_build(struct pci_dev *cio2)
> >> +{
> >> +	struct fwnode_handle *fwnode;
> >> +	int ret;
> >> +
> >> +	pci_dev_get(cio2);
> > Could you check that this isn't used by more than one user? The current
> > implementation assumes that. I'm not sure if there could be more instances
> > of CIO2 but if there were, that'd be an issue currently.
> 
> I can check; can't think of anything better than just failing out if it
> turns out to be in use already though - any ideas or is that appropriate?

A negative error code would be appropriate, e.g. -EBUSY.

-- 
Regards,

Sakari Ailus

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24 22:36           ` Laurent Pinchart
  2020-10-24 22:50             ` Daniel Scally
@ 2020-10-26  8:20             ` Dan Scally
  2020-10-26 16:05               ` Andy Shevchenko
  1 sibling, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-10-26  8:20 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, andriy.shevchenko, sergey.senozhatsky,
	rostedt, pmladek, mchehab, tian.shu.qiu, bingbu.cao,
	sakari.ailus, yong.zhi, rafael, gregkh, kitakar

On 24/10/2020 23:36, Laurent Pinchart wrote:
> Hi Dan,
>
> On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
>> On 24/10/2020 10:37, Laurent Pinchart wrote:
>>>>> I wonder if we could avoid depending on the I2C device being created by
>>>>> getting the fwnode from adev, and setting ->secondary manually. adev
>>>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
>>>> Let me try that; I initially wanted to do
>>>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
>>>> dev being created but it turns out &adev->dev isn't the same pointer. I
>>>> shall try it and see.
>> Actually, thinking on this further I think maybe we can't avoid that -
>> it's not actually in this patch series but during assigning GPIO
>> resources parsed from PMIC's ACPI node to the sensor, I'm using
>> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table
> Any chance we can construct the I2C device name from the ACPI device,
> the same way that the ACPI/I2C core does ? It may be a dead end, but if
> we could avoid depending on the I2C device, I think it will make
> initialization easier. I have a feeling that will be difficult though,
> as we'll need the I2C bus number, which won't be readily available.
OK yeah; the i2c core does indeed just prefix "i2c-" onto the acpi
device name, so I will make this change too.

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-26  8:20             ` Dan Scally
@ 2020-10-26 16:05               ` Andy Shevchenko
  2020-10-29 20:17                 ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-26 16:05 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar

On Mon, Oct 26, 2020 at 08:20:14AM +0000, Dan Scally wrote:
> On 24/10/2020 23:36, Laurent Pinchart wrote:
> > On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
> >> On 24/10/2020 10:37, Laurent Pinchart wrote:
> >>>>> I wonder if we could avoid depending on the I2C device being created by
> >>>>> getting the fwnode from adev, and setting ->secondary manually. adev
> >>>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
> >>>> Let me try that; I initially wanted to do
> >>>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
> >>>> dev being created but it turns out &adev->dev isn't the same pointer. I
> >>>> shall try it and see.
> >> Actually, thinking on this further I think maybe we can't avoid that -
> >> it's not actually in this patch series but during assigning GPIO
> >> resources parsed from PMIC's ACPI node to the sensor, I'm using
> >> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table
> > Any chance we can construct the I2C device name from the ACPI device,
> > the same way that the ACPI/I2C core does ? It may be a dead end, but if
> > we could avoid depending on the I2C device, I think it will make
> > initialization easier. I have a feeling that will be difficult though,
> > as we'll need the I2C bus number, which won't be readily available.
> OK yeah; the i2c core does indeed just prefix "i2c-" onto the acpi
> device name, so I will make this change too.

This is part of the I²C core and if you go this way, do not home grow the
functionality that doesn't belong here.

Instead, export a helper function that will do it for you and for I²C core with
explanation why it's needed.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-24  9:37       ` Laurent Pinchart
  2020-10-24 22:28         ` Daniel Scally
@ 2020-10-26 16:10         ` Andy Shevchenko
  2020-10-29 20:19           ` Laurent Pinchart
  1 sibling, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-26 16:10 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar

On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:

> > >> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > >
> > > What if there are multiple sensor of the same model ?
> > 
> > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > smartphones have multiple sensors on the back, which I presume are the
> > same model. So that will probably crop up at some point. How about
> > instead I use bus_for_each_dev() and in the applied function check if
> > the _HID is in the supported list?
> 
> Sounds good to me.
> 
> > >> +		if (!adev)
> > >> +			continue;

Please, don't.

If we have so weird ACPI tables it must be w/a differently. The all, even badly
formed, ACPI tables I have seen so far are using _UID to distinguish instance
of the device (see second parameter to the above function).

If we meet the very broken table I would like rather to know about, then
silently think ahead what could be best.

I.o.w. don't change this until we will have a real example of the problematic
firmware.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-26 16:05               ` Andy Shevchenko
@ 2020-10-29 20:17                 ` Laurent Pinchart
  2020-10-29 22:36                   ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-29 20:17 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar

Hi Andy,

On Mon, Oct 26, 2020 at 06:05:49PM +0200, Andy Shevchenko wrote:
> On Mon, Oct 26, 2020 at 08:20:14AM +0000, Dan Scally wrote:
> > On 24/10/2020 23:36, Laurent Pinchart wrote:
> > > On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
> > >> On 24/10/2020 10:37, Laurent Pinchart wrote:
> > >>>>> I wonder if we could avoid depending on the I2C device being created by
> > >>>>> getting the fwnode from adev, and setting ->secondary manually. adev
> > >>>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
> > >>>>
> > >>>> Let me try that; I initially wanted to do
> > >>>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
> > >>>> dev being created but it turns out &adev->dev isn't the same pointer. I
> > >>>> shall try it and see.
> > >>
> > >> Actually, thinking on this further I think maybe we can't avoid that -
> > >> it's not actually in this patch series but during assigning GPIO
> > >> resources parsed from PMIC's ACPI node to the sensor, I'm using
> > >> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table
> > >
> > > Any chance we can construct the I2C device name from the ACPI device,
> > > the same way that the ACPI/I2C core does ? It may be a dead end, but if
> > > we could avoid depending on the I2C device, I think it will make
> > > initialization easier. I have a feeling that will be difficult though,
> > > as we'll need the I2C bus number, which won't be readily available.
> >
> > OK yeah; the i2c core does indeed just prefix "i2c-" onto the acpi
> > device name, so I will make this change too.
> 
> This is part of the I²C core and if you go this way, do not home grow the
> functionality that doesn't belong here.
> 
> Instead, export a helper function that will do it for you and for I²C core with
> explanation why it's needed.

Agreed, I was actually considering suggesting that. Hardcoding the same
naming scheme in two places is asking for trouble, especially if we
don't let the I2C maintainers know. It should be easy to do, not
necessarily the highest priority task, but something that should be
handled to get this merged.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-26 16:10         ` Andy Shevchenko
@ 2020-10-29 20:19           ` Laurent Pinchart
  2020-10-29 20:26             ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-29 20:19 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar

Hi Andy,

On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> > On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> 
> > > >> +		adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > > >
> > > > What if there are multiple sensor of the same model ?
> > > 
> > > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > > smartphones have multiple sensors on the back, which I presume are the
> > > same model. So that will probably crop up at some point. How about
> > > instead I use bus_for_each_dev() and in the applied function check if
> > > the _HID is in the supported list?
> > 
> > Sounds good to me.
> > 
> > > >> +		if (!adev)
> > > >> +			continue;
> 
> Please, don't.
> 
> If we have so weird ACPI tables it must be w/a differently. The all, even badly
> formed, ACPI tables I have seen so far are using _UID to distinguish instance
> of the device (see second parameter to the above function).
> 
> If we meet the very broken table I would like rather to know about, then
> silently think ahead what could be best.
> 
> I.o.w. don't change this until we will have a real example of the problematic
> firmware.

I'm not sure to follow you. Daniel's current code loops over all the
supported HID (as stored in the supported_devices table), and then gets
the first ACPI device for each of them. If multiple ACPI devices exist
with the same HID, we need to handle them all, so enumerating all ACPI
devices and checking whether their HID is one we handle seems to be the
right option to me.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 20:19           ` Laurent Pinchart
@ 2020-10-29 20:26             ` Andy Shevchenko
  2020-10-29 21:29               ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-29 20:26 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Andy Shevchenko, Dan Scally, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> > On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> > > On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > > > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> >
> > > > >> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > > > >
> > > > > What if there are multiple sensor of the same model ?
> > > >
> > > > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > > > smartphones have multiple sensors on the back, which I presume are the
> > > > same model. So that will probably crop up at some point. How about
> > > > instead I use bus_for_each_dev() and in the applied function check if
> > > > the _HID is in the supported list?
> > >
> > > Sounds good to me.
> > >
> > > > >> +              if (!adev)
> > > > >> +                      continue;
> >
> > Please, don't.
> >
> > If we have so weird ACPI tables it must be w/a differently. The all, even badly
> > formed, ACPI tables I have seen so far are using _UID to distinguish instance
> > of the device (see second parameter to the above function).
> >
> > If we meet the very broken table I would like rather to know about, then
> > silently think ahead what could be best.
> >
> > I.o.w. don't change this until we will have a real example of the problematic
> > firmware.
>
> I'm not sure to follow you. Daniel's current code loops over all the
> supported HID (as stored in the supported_devices table), and then gets
> the first ACPI device for each of them. If multiple ACPI devices exist
> with the same HID, we need to handle them all, so enumerating all ACPI
> devices and checking whether their HID is one we handle seems to be the
> right option to me.

Devices with the same HID should be still different by another
parameter in ACPI. The above mentioned call just uses the rough
estimation for relaxed conditions. If you expect more than one device
with the same HID how do you expect to distinguish them? The correct
way is to use _UID. It may be absent, or set to a value. And this
value should be unique (as per U letter in UID abbreviation). That
said, the above is good enough till we find the firmware with the
above true (several devices with the same HID). Until then the code is
fine.


-- 
With Best Regards,
Andy Shevchenko

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 20:26             ` Andy Shevchenko
@ 2020-10-29 21:29               ` Laurent Pinchart
  2020-10-29 22:22                 ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-29 21:29 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andy Shevchenko, Dan Scally, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On Thu, Oct 29, 2020 at 10:26:56PM +0200, Andy Shevchenko wrote:
> On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart wrote:
> > On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> > > On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> > > > On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > > > > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > > > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> > >
> > > > > >> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > > > > >
> > > > > > What if there are multiple sensor of the same model ?
> > > > >
> > > > > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > > > > smartphones have multiple sensors on the back, which I presume are the
> > > > > same model. So that will probably crop up at some point. How about
> > > > > instead I use bus_for_each_dev() and in the applied function check if
> > > > > the _HID is in the supported list?
> > > >
> > > > Sounds good to me.
> > > >
> > > > > >> +              if (!adev)
> > > > > >> +                      continue;
> > >
> > > Please, don't.
> > >
> > > If we have so weird ACPI tables it must be w/a differently. The all, even badly
> > > formed, ACPI tables I have seen so far are using _UID to distinguish instance
> > > of the device (see second parameter to the above function).
> > >
> > > If we meet the very broken table I would like rather to know about, then
> > > silently think ahead what could be best.
> > >
> > > I.o.w. don't change this until we will have a real example of the problematic
> > > firmware.
> >
> > I'm not sure to follow you. Daniel's current code loops over all the
> > supported HID (as stored in the supported_devices table), and then gets
> > the first ACPI device for each of them. If multiple ACPI devices exist
> > with the same HID, we need to handle them all, so enumerating all ACPI
> > devices and checking whether their HID is one we handle seems to be the
> > right option to me.
> 
> Devices with the same HID should be still different by another
> parameter in ACPI. The above mentioned call just uses the rough
> estimation for relaxed conditions. If you expect more than one device
> with the same HID how do you expect to distinguish them? The correct
> way is to use _UID. It may be absent, or set to a value. And this
> value should be unique (as per U letter in UID abbreviation). That
> said, the above is good enough till we find the firmware with the
> above true (several devices with the same HID). Until then the code is
> fine.

I expect those devices with the same _HID to have different _UID values,
yes. On the systems I've seen so far, that assumption is not violated,
and I don't think we need to already plan how we will support systems
where multiple devices would have the same _HID and _UID (within the
same scope). There's no disagreement there.

My point is that supported_devices stores HID values, and doesn't care
about UID. The code loops over supported_devices, and for each entry,
calls acpi_dev_get_first_match_dev() and process the ACPI devices
returned by that call. We thus process at most one ACPI device per HID,
which isn't right.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 21:29               ` Laurent Pinchart
@ 2020-10-29 22:22                 ` Andy Shevchenko
  2020-10-29 22:51                   ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-10-29 22:22 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> On Thu, Oct 29, 2020 at 10:26:56PM +0200, Andy Shevchenko wrote:
> > On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart wrote:
> > > On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> > > > On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> > > > > On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > > > > > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > > > > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> > > >
> > > > > > >> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > > > > > >
> > > > > > > What if there are multiple sensor of the same model ?
> > > > > >
> > > > > > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > > > > > smartphones have multiple sensors on the back, which I presume are the
> > > > > > same model. So that will probably crop up at some point. How about
> > > > > > instead I use bus_for_each_dev() and in the applied function check if
> > > > > > the _HID is in the supported list?
> > > > >
> > > > > Sounds good to me.
> > > > >
> > > > > > >> +              if (!adev)
> > > > > > >> +                      continue;
> > > >
> > > > Please, don't.
> > > >
> > > > If we have so weird ACPI tables it must be w/a differently. The all, even badly
> > > > formed, ACPI tables I have seen so far are using _UID to distinguish instance
> > > > of the device (see second parameter to the above function).
> > > >
> > > > If we meet the very broken table I would like rather to know about, then
> > > > silently think ahead what could be best.
> > > >
> > > > I.o.w. don't change this until we will have a real example of the problematic
> > > > firmware.
> > >
> > > I'm not sure to follow you. Daniel's current code loops over all the
> > > supported HID (as stored in the supported_devices table), and then gets
> > > the first ACPI device for each of them. If multiple ACPI devices exist
> > > with the same HID, we need to handle them all, so enumerating all ACPI
> > > devices and checking whether their HID is one we handle seems to be the
> > > right option to me.
> > 
> > Devices with the same HID should be still different by another
> > parameter in ACPI. The above mentioned call just uses the rough
> > estimation for relaxed conditions. If you expect more than one device
> > with the same HID how do you expect to distinguish them? The correct
> > way is to use _UID. It may be absent, or set to a value. And this
> > value should be unique (as per U letter in UID abbreviation). That
> > said, the above is good enough till we find the firmware with the
> > above true (several devices with the same HID). Until then the code is
> > fine.
> 
> I expect those devices with the same _HID to have different _UID values,
> yes. On the systems I've seen so far, that assumption is not violated,
> and I don't think we need to already plan how we will support systems
> where multiple devices would have the same _HID and _UID (within the
> same scope). There's no disagreement there.
> 
> My point is that supported_devices stores HID values, and doesn't care
> about UID. The code loops over supported_devices, and for each entry,
> calls acpi_dev_get_first_match_dev() and process the ACPI devices
> returned by that call. We thus process at most one ACPI device per HID,
> which isn't right.

In this case we probably need something like

struct acpi_device *
acpi_dev_get_next_match_dev(struct acpi_device *adev,
			    const char *hid, const char *uid, s64 hrv)
{
	struct device *start = adev ? &adev->dev : NULL;
	...
	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
	...
}

in drivers/acpi/utils.c and

static inline struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
{
	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
}

in include/linux/acpi.h.

Then we may add

#define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
	     adev;							\
	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))


-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 20:17                 ` Laurent Pinchart
@ 2020-10-29 22:36                   ` Dan Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-10-29 22:36 UTC (permalink / raw)
  To: Laurent Pinchart, Andy Shevchenko
  Cc: linux-kernel, linux-media, linus.walleij,
	prabhakar.mahadev-lad.rj, heikki.krogerus, dmitry.torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, jacopo+renesas,
	robh, davem, linux, sergey.senozhatsky, rostedt, pmladek,
	mchehab, tian.shu.qiu, bingbu.cao, sakari.ailus, yong.zhi,
	rafael, gregkh, kitakar

Hi both

On 29/10/2020 20:17, Laurent Pinchart wrote:
> Hi Andy,
>
> On Mon, Oct 26, 2020 at 06:05:49PM +0200, Andy Shevchenko wrote:
>> On Mon, Oct 26, 2020 at 08:20:14AM +0000, Dan Scally wrote:
>>> On 24/10/2020 23:36, Laurent Pinchart wrote:
>>>> On Sat, Oct 24, 2020 at 11:28:06PM +0100, Daniel Scally wrote:
>>>>> On 24/10/2020 10:37, Laurent Pinchart wrote:
>>>>>>>> I wonder if we could avoid depending on the I2C device being created by
>>>>>>>> getting the fwnode from adev, and setting ->secondary manually. adev
>>>>>>>> would need to be passed to get_acpi_ssdb_sensor_data() instead of dev.
>>>>>>> Let me try that; I initially wanted to do
>>>>>>> set_secondary_fwnode(&adev->dev, fwnode) to avoid depending on the I2C
>>>>>>> dev being created but it turns out &adev->dev isn't the same pointer. I
>>>>>>> shall try it and see.
>>>>> Actually, thinking on this further I think maybe we can't avoid that -
>>>>> it's not actually in this patch series but during assigning GPIO
>>>>> resources parsed from PMIC's ACPI node to the sensor, I'm using
>>>>> dev_name() on the i2c dev to pass to .dev_id member of gpiod_lookup_table
>>>> Any chance we can construct the I2C device name from the ACPI device,
>>>> the same way that the ACPI/I2C core does ? It may be a dead end, but if
>>>> we could avoid depending on the I2C device, I think it will make
>>>> initialization easier. I have a feeling that will be difficult though,
>>>> as we'll need the I2C bus number, which won't be readily available.
>>> OK yeah; the i2c core does indeed just prefix "i2c-" onto the acpi
>>> device name, so I will make this change too.
>> This is part of the I²C core and if you go this way, do not home grow the
>> functionality that doesn't belong here.
>>
>> Instead, export a helper function that will do it for you and for I²C core with
>> explanation why it's needed.
> Agreed, I was actually considering suggesting that. Hardcoding the same
> naming scheme in two places is asking for trouble, especially if we
> don't let the I2C maintainers know. It should be easy to do, not
> necessarily the highest priority task, but something that should be
> handled to get this merged.
Understood - I'll have a look at the best way to do this once I'm
through the current to do list

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 22:22                 ` Andy Shevchenko
@ 2020-10-29 22:51                   ` Laurent Pinchart
  2020-11-13 10:02                     ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-10-29 22:51 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

Hi Andy,

On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> > On Thu, Oct 29, 2020 at 10:26:56PM +0200, Andy Shevchenko wrote:
> > > On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart wrote:
> > > > On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> > > > > On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> > > > > > On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> > > > > > > On 24/10/2020 02:24, Laurent Pinchart wrote:
> > > > > > > > On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> > > > >
> > > > > > > >> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> > > > > > > >
> > > > > > > > What if there are multiple sensor of the same model ?
> > > > > > >
> > > > > > > Hmm, yeah, that would be a bit of a pickle. I guess the newer
> > > > > > > smartphones have multiple sensors on the back, which I presume are the
> > > > > > > same model. So that will probably crop up at some point. How about
> > > > > > > instead I use bus_for_each_dev() and in the applied function check if
> > > > > > > the _HID is in the supported list?
> > > > > >
> > > > > > Sounds good to me.
> > > > > >
> > > > > > > >> +              if (!adev)
> > > > > > > >> +                      continue;
> > > > >
> > > > > Please, don't.
> > > > >
> > > > > If we have so weird ACPI tables it must be w/a differently. The all, even badly
> > > > > formed, ACPI tables I have seen so far are using _UID to distinguish instance
> > > > > of the device (see second parameter to the above function).
> > > > >
> > > > > If we meet the very broken table I would like rather to know about, then
> > > > > silently think ahead what could be best.
> > > > >
> > > > > I.o.w. don't change this until we will have a real example of the problematic
> > > > > firmware.
> > > >
> > > > I'm not sure to follow you. Daniel's current code loops over all the
> > > > supported HID (as stored in the supported_devices table), and then gets
> > > > the first ACPI device for each of them. If multiple ACPI devices exist
> > > > with the same HID, we need to handle them all, so enumerating all ACPI
> > > > devices and checking whether their HID is one we handle seems to be the
> > > > right option to me.
> > > 
> > > Devices with the same HID should be still different by another
> > > parameter in ACPI. The above mentioned call just uses the rough
> > > estimation for relaxed conditions. If you expect more than one device
> > > with the same HID how do you expect to distinguish them? The correct
> > > way is to use _UID. It may be absent, or set to a value. And this
> > > value should be unique (as per U letter in UID abbreviation). That
> > > said, the above is good enough till we find the firmware with the
> > > above true (several devices with the same HID). Until then the code is
> > > fine.
> > 
> > I expect those devices with the same _HID to have different _UID values,
> > yes. On the systems I've seen so far, that assumption is not violated,
> > and I don't think we need to already plan how we will support systems
> > where multiple devices would have the same _HID and _UID (within the
> > same scope). There's no disagreement there.
> > 
> > My point is that supported_devices stores HID values, and doesn't care
> > about UID. The code loops over supported_devices, and for each entry,
> > calls acpi_dev_get_first_match_dev() and process the ACPI devices
> > returned by that call. We thus process at most one ACPI device per HID,
> > which isn't right.
> 
> In this case we probably need something like
> 
> struct acpi_device *
> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> 			    const char *hid, const char *uid, s64 hrv)
> {
> 	struct device *start = adev ? &adev->dev : NULL;
> 	...
> 	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> 	...
> }
> 
> in drivers/acpi/utils.c and
> 
> static inline struct acpi_device *
> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> {
> 	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> }
> 
> in include/linux/acpi.h.
> 
> Then we may add
> 
> #define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
> 	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
> 	     adev;							\
> 	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))

What the cio2-bridge code needs is indeed

	for each hid in supported hids:
		for each acpi device that is compatible with hid:
			...

which could also be expressed as

	for each acpi device:
		if acpi device hid is in supported hids:
			...

I don't mind either option, I'll happily follow the preference of the
ACPI maintainers.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-10-29 22:51                   ` Laurent Pinchart
@ 2020-11-13 10:02                     ` Dan Scally
  2020-11-13 16:22                       ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-11-13 10:02 UTC (permalink / raw)
  To: Laurent Pinchart, Andy Shevchenko
  Cc: Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

On 29/10/2020 22:51, Laurent Pinchart wrote:
> Hi Andy,
>
> On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
>> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
>>> On Thu, Oct 29, 2020 at 10:26:56PM +0200, Andy Shevchenko wrote:
>>>> On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart wrote:
>>>>> On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
>>>>>> On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
>>>>>>> On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
>>>>>>>> On 24/10/2020 02:24, Laurent Pinchart wrote:
>>>>>>>>> On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
>>>>>>>>>> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
>>>>>>>>> What if there are multiple sensor of the same model ?
>>>>>>>> Hmm, yeah, that would be a bit of a pickle. I guess the newer
>>>>>>>> smartphones have multiple sensors on the back, which I presume are the
>>>>>>>> same model. So that will probably crop up at some point. How about
>>>>>>>> instead I use bus_for_each_dev() and in the applied function check if
>>>>>>>> the _HID is in the supported list?
>>>>>>> Sounds good to me.
>>>>>>>
>>>>>>>>>> +              if (!adev)
>>>>>>>>>> +                      continue;
>>>>>> Please, don't.
>>>>>>
>>>>>> If we have so weird ACPI tables it must be w/a differently. The all, even badly
>>>>>> formed, ACPI tables I have seen so far are using _UID to distinguish instance
>>>>>> of the device (see second parameter to the above function).
>>>>>>
>>>>>> If we meet the very broken table I would like rather to know about, then
>>>>>> silently think ahead what could be best.
>>>>>>
>>>>>> I.o.w. don't change this until we will have a real example of the problematic
>>>>>> firmware.
>>>>> I'm not sure to follow you. Daniel's current code loops over all the
>>>>> supported HID (as stored in the supported_devices table), and then gets
>>>>> the first ACPI device for each of them. If multiple ACPI devices exist
>>>>> with the same HID, we need to handle them all, so enumerating all ACPI
>>>>> devices and checking whether their HID is one we handle seems to be the
>>>>> right option to me.
>>>> Devices with the same HID should be still different by another
>>>> parameter in ACPI. The above mentioned call just uses the rough
>>>> estimation for relaxed conditions. If you expect more than one device
>>>> with the same HID how do you expect to distinguish them? The correct
>>>> way is to use _UID. It may be absent, or set to a value. And this
>>>> value should be unique (as per U letter in UID abbreviation). That
>>>> said, the above is good enough till we find the firmware with the
>>>> above true (several devices with the same HID). Until then the code is
>>>> fine.
>>> I expect those devices with the same _HID to have different _UID values,
>>> yes. On the systems I've seen so far, that assumption is not violated,
>>> and I don't think we need to already plan how we will support systems
>>> where multiple devices would have the same _HID and _UID (within the
>>> same scope). There's no disagreement there.
>>>
>>> My point is that supported_devices stores HID values, and doesn't care
>>> about UID. The code loops over supported_devices, and for each entry,
>>> calls acpi_dev_get_first_match_dev() and process the ACPI devices
>>> returned by that call. We thus process at most one ACPI device per HID,
>>> which isn't right.
>> In this case we probably need something like
>>
>> struct acpi_device *
>> acpi_dev_get_next_match_dev(struct acpi_device *adev,
>> 			    const char *hid, const char *uid, s64 hrv)
>> {
>> 	struct device *start = adev ? &adev->dev : NULL;
>> 	...
>> 	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
>> 	...
>> }
>>
>> in drivers/acpi/utils.c and
>>
>> static inline struct acpi_device *
>> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
>> {
>> 	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
>> }
>>
>> in include/linux/acpi.h.
>>
>> Then we may add
>>
>> #define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
>> 	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
>> 	     adev;							\
>> 	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> What the cio2-bridge code needs is indeed
>
> 	for each hid in supported hids:
> 		for each acpi device that is compatible with hid:
> 			...
>
> which could also be expressed as
>
> 	for each acpi device:
> 		if acpi device hid is in supported hids:
> 			...
>
> I don't mind either option, I'll happily follow the preference of the
> ACPI maintainers.
>
Does this need raising elsewhere then? The original idea of just
bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
but it does mean that I need to export acpi_bus_type (currently that
symbol's not available)...that seems much simpler to me but I'm not sure
whether that's something to avoid, and if so whether Andy's approach is
better.


Thoughts?


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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-13 10:02                     ` Dan Scally
@ 2020-11-13 16:22                       ` Laurent Pinchart
  2020-11-13 19:45                         ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-11-13 16:22 UTC (permalink / raw)
  To: Dan Scally
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

Hi Dan,

On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> On 29/10/2020 22:51, Laurent Pinchart wrote:
> > On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> >> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> >>> On Thu, Oct 29, 2020 at 10:26:56PM +0200, Andy Shevchenko wrote:
> >>>> On Thu, Oct 29, 2020 at 10:21 PM Laurent Pinchart wrote:
> >>>>> On Mon, Oct 26, 2020 at 06:10:50PM +0200, Andy Shevchenko wrote:
> >>>>>> On Sat, Oct 24, 2020 at 12:37:02PM +0300, Laurent Pinchart wrote:
> >>>>>>> On Sat, Oct 24, 2020 at 09:50:07AM +0100, Dan Scally wrote:
> >>>>>>>> On 24/10/2020 02:24, Laurent Pinchart wrote:
> >>>>>>>>> On Mon, Oct 19, 2020 at 11:59:03PM +0100, Daniel Scally wrote:
> >>>>>>>>>> +              adev = acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
> >>>>>>>>> What if there are multiple sensor of the same model ?
> >>>>>>>> Hmm, yeah, that would be a bit of a pickle. I guess the newer
> >>>>>>>> smartphones have multiple sensors on the back, which I presume are the
> >>>>>>>> same model. So that will probably crop up at some point. How about
> >>>>>>>> instead I use bus_for_each_dev() and in the applied function check if
> >>>>>>>> the _HID is in the supported list?
> >>>>>>> Sounds good to me.
> >>>>>>>
> >>>>>>>>>> +              if (!adev)
> >>>>>>>>>> +                      continue;
> >>>>>> Please, don't.
> >>>>>>
> >>>>>> If we have so weird ACPI tables it must be w/a differently. The all, even badly
> >>>>>> formed, ACPI tables I have seen so far are using _UID to distinguish instance
> >>>>>> of the device (see second parameter to the above function).
> >>>>>>
> >>>>>> If we meet the very broken table I would like rather to know about, then
> >>>>>> silently think ahead what could be best.
> >>>>>>
> >>>>>> I.o.w. don't change this until we will have a real example of the problematic
> >>>>>> firmware.
> >>>>> I'm not sure to follow you. Daniel's current code loops over all the
> >>>>> supported HID (as stored in the supported_devices table), and then gets
> >>>>> the first ACPI device for each of them. If multiple ACPI devices exist
> >>>>> with the same HID, we need to handle them all, so enumerating all ACPI
> >>>>> devices and checking whether their HID is one we handle seems to be the
> >>>>> right option to me.
> >>>> Devices with the same HID should be still different by another
> >>>> parameter in ACPI. The above mentioned call just uses the rough
> >>>> estimation for relaxed conditions. If you expect more than one device
> >>>> with the same HID how do you expect to distinguish them? The correct
> >>>> way is to use _UID. It may be absent, or set to a value. And this
> >>>> value should be unique (as per U letter in UID abbreviation). That
> >>>> said, the above is good enough till we find the firmware with the
> >>>> above true (several devices with the same HID). Until then the code is
> >>>> fine.
> >>> I expect those devices with the same _HID to have different _UID values,
> >>> yes. On the systems I've seen so far, that assumption is not violated,
> >>> and I don't think we need to already plan how we will support systems
> >>> where multiple devices would have the same _HID and _UID (within the
> >>> same scope). There's no disagreement there.
> >>>
> >>> My point is that supported_devices stores HID values, and doesn't care
> >>> about UID. The code loops over supported_devices, and for each entry,
> >>> calls acpi_dev_get_first_match_dev() and process the ACPI devices
> >>> returned by that call. We thus process at most one ACPI device per HID,
> >>> which isn't right.
> >>
> >> In this case we probably need something like
> >>
> >> struct acpi_device *
> >> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> >> 			    const char *hid, const char *uid, s64 hrv)
> >> {
> >> 	struct device *start = adev ? &adev->dev : NULL;
> >> 	...
> >> 	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> >> 	...
> >> }
> >>
> >> in drivers/acpi/utils.c and
> >>
> >> static inline struct acpi_device *
> >> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> >> {
> >> 	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> >> }
> >>
> >> in include/linux/acpi.h.
> >>
> >> Then we may add
> >>
> >> #define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
> >> 	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
> >> 	     adev;							\
> >> 	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> >
> > What the cio2-bridge code needs is indeed
> >
> > 	for each hid in supported hids:
> > 		for each acpi device that is compatible with hid:
> > 			...
> >
> > which could also be expressed as
> >
> > 	for each acpi device:
> > 		if acpi device hid is in supported hids:
> > 			...
> >
> > I don't mind either option, I'll happily follow the preference of the
> > ACPI maintainers.
>
> Does this need raising elsewhere then? The original idea of just
> bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> but it does mean that I need to export acpi_bus_type (currently that
> symbol's not available)...that seems much simpler to me but I'm not sure
> whether that's something to avoid, and if so whether Andy's approach is
> better.
> 
> Thoughts?

I like simple options :-) A patch to export acpi_bus_type, with enough
context in the commit message (and in the cover latter of the series),
should be enough to provide all the information the ACPI maintainers
need to decide which option is best. With a bit of luck that patch will
be considered the best option and no extra work will be needed.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-13 16:22                       ` Laurent Pinchart
@ 2020-11-13 19:45                         ` Andy Shevchenko
  2020-11-15  8:45                           ` Daniel Scally
  2020-11-16  8:53                           ` Laurent Pinchart
  0 siblings, 2 replies; 82+ messages in thread
From: Andy Shevchenko @ 2020-11-13 19:45 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> > On 29/10/2020 22:51, Laurent Pinchart wrote:
> > > On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> > >> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:

...

> > >> In this case we probably need something like
> > >>
> > >> struct acpi_device *
> > >> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> > >>                        const char *hid, const char *uid, s64 hrv)
> > >> {
> > >>    struct device *start = adev ? &adev->dev : NULL;
> > >>    ...
> > >>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> > >>    ...
> > >> }
> > >>
> > >> in drivers/acpi/utils.c and
> > >>
> > >> static inline struct acpi_device *
> > >> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> > >> {
> > >>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> > >> }
> > >>
> > >> in include/linux/acpi.h.
> > >>
> > >> Then we may add
> > >>
> > >> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
> > >>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> > >>         adev;                                                      \
> > >>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> > >
> > > What the cio2-bridge code needs is indeed
> > >
> > >     for each hid in supported hids:
> > >             for each acpi device that is compatible with hid:
> > >                     ...
> > >
> > > which could also be expressed as
> > >
> > >     for each acpi device:
> > >             if acpi device hid is in supported hids:
> > >                     ...
> > >
> > > I don't mind either option, I'll happily follow the preference of the
> > > ACPI maintainers.
> >
> > Does this need raising elsewhere then? The original idea of just
> > bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> > but it does mean that I need to export acpi_bus_type (currently that
> > symbol's not available)...that seems much simpler to me but I'm not sure
> > whether that's something to avoid, and if so whether Andy's approach is
> > better.
> >
> > Thoughts?
>
> I like simple options :-) A patch to export acpi_bus_type, with enough
> context in the commit message (and in the cover latter of the series),
> should be enough to provide all the information the ACPI maintainers
> need to decide which option is best. With a bit of luck that patch will
> be considered the best option and no extra work will be needed.

The problem with ACPI bus is that it is not as simple as other buses,
i.e. it may have purely ACPI devices along with *companion* devices,
which are usually represented by platform bus. On top of that for
several ACPI devices there can be one physical node and it will be not
so clear what you are exactly looking for by traversing acpi_bus_type.
I believe it's hidden on purpose.


-- 
With Best Regards,
Andy Shevchenko

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-13 19:45                         ` Andy Shevchenko
@ 2020-11-15  8:45                           ` Daniel Scally
  2020-11-16  8:53                           ` Laurent Pinchart
  1 sibling, 0 replies; 82+ messages in thread
From: Daniel Scally @ 2020-11-15  8:45 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

On 13/11/2020 19:45, Andy Shevchenko wrote:
> On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
>> On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
>>> On 29/10/2020 22:51, Laurent Pinchart wrote:
>>>> On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
>>>>> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> ...
>
>>>>> In this case we probably need something like
>>>>>
>>>>> struct acpi_device *
>>>>> acpi_dev_get_next_match_dev(struct acpi_device *adev,
>>>>>                        const char *hid, const char *uid, s64 hrv)
>>>>> {
>>>>>    struct device *start = adev ? &adev->dev : NULL;
>>>>>    ...
>>>>>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
>>>>>    ...
>>>>> }
>>>>>
>>>>> in drivers/acpi/utils.c and
>>>>>
>>>>> static inline struct acpi_device *
>>>>> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
>>>>> {
>>>>>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
>>>>> }
>>>>>
>>>>> in include/linux/acpi.h.
>>>>>
>>>>> Then we may add
>>>>>
>>>>> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
>>>>>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
>>>>>         adev;                                                      \
>>>>>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
>>>> What the cio2-bridge code needs is indeed
>>>>
>>>>     for each hid in supported hids:
>>>>             for each acpi device that is compatible with hid:
>>>>                     ...
>>>>
>>>> which could also be expressed as
>>>>
>>>>     for each acpi device:
>>>>             if acpi device hid is in supported hids:
>>>>                     ...
>>>>
>>>> I don't mind either option, I'll happily follow the preference of the
>>>> ACPI maintainers.
>>> Does this need raising elsewhere then? The original idea of just
>>> bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
>>> but it does mean that I need to export acpi_bus_type (currently that
>>> symbol's not available)...that seems much simpler to me but I'm not sure
>>> whether that's something to avoid, and if so whether Andy's approach is
>>> better.
>>>
>>> Thoughts?
>> I like simple options :-) A patch to export acpi_bus_type, with enough
>> context in the commit message (and in the cover latter of the series),
>> should be enough to provide all the information the ACPI maintainers
>> need to decide which option is best. With a bit of luck that patch will
>> be considered the best option and no extra work will be needed.
> The problem with ACPI bus is that it is not as simple as other buses,
> i.e. it may have purely ACPI devices along with *companion* devices,
> which are usually represented by platform bus. On top of that for
> several ACPI devices there can be one physical node and it will be not
> so clear what you are exactly looking for by traversing acpi_bus_type.
> I believe it's hidden on purpose.
Alright - I followed your suggestion to implement the iterator instead
then and left acpi_bus_type hidden, thanks.

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-13 19:45                         ` Andy Shevchenko
  2020-11-15  8:45                           ` Daniel Scally
@ 2020-11-16  8:53                           ` Laurent Pinchart
  2020-11-16 13:57                             ` Andy Shevchenko
  1 sibling, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-11-16  8:53 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

Hi Andy,

On Fri, Nov 13, 2020 at 09:45:00PM +0200, Andy Shevchenko wrote:
> On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart wrote:
> > On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> > > On 29/10/2020 22:51, Laurent Pinchart wrote:
> > > > On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> > > >> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> 
> ...
> 
> > > >> In this case we probably need something like
> > > >>
> > > >> struct acpi_device *
> > > >> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> > > >>                        const char *hid, const char *uid, s64 hrv)
> > > >> {
> > > >>    struct device *start = adev ? &adev->dev : NULL;
> > > >>    ...
> > > >>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> > > >>    ...
> > > >> }
> > > >>
> > > >> in drivers/acpi/utils.c and
> > > >>
> > > >> static inline struct acpi_device *
> > > >> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> > > >> {
> > > >>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> > > >> }
> > > >>
> > > >> in include/linux/acpi.h.
> > > >>
> > > >> Then we may add
> > > >>
> > > >> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
> > > >>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> > > >>         adev;                                                      \
> > > >>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> > > >
> > > > What the cio2-bridge code needs is indeed
> > > >
> > > >     for each hid in supported hids:
> > > >             for each acpi device that is compatible with hid:
> > > >                     ...
> > > >
> > > > which could also be expressed as
> > > >
> > > >     for each acpi device:
> > > >             if acpi device hid is in supported hids:
> > > >                     ...
> > > >
> > > > I don't mind either option, I'll happily follow the preference of the
> > > > ACPI maintainers.
> > >
> > > Does this need raising elsewhere then? The original idea of just
> > > bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> > > but it does mean that I need to export acpi_bus_type (currently that
> > > symbol's not available)...that seems much simpler to me but I'm not sure
> > > whether that's something to avoid, and if so whether Andy's approach is
> > > better.
> > >
> > > Thoughts?
> >
> > I like simple options :-) A patch to export acpi_bus_type, with enough
> > context in the commit message (and in the cover latter of the series),
> > should be enough to provide all the information the ACPI maintainers
> > need to decide which option is best. With a bit of luck that patch will
> > be considered the best option and no extra work will be needed.
> 
> The problem with ACPI bus is that it is not as simple as other buses,
> i.e. it may have purely ACPI devices along with *companion* devices,
> which are usually represented by platform bus. On top of that for
> several ACPI devices there can be one physical node and it will be not
> so clear what you are exactly looking for by traversing acpi_bus_type.
> I believe it's hidden on purpose.

Maybe there's something I don't get, as I'm not very familiar with the
ACPI implementation in the kernel, but the code in the cio2-bridge,
unless I'm mistaken, is really interested in ACPI devices on the ACPI
bus, not companions or other devices related to the ACPI devices. The
iterators you have proposed above use bus_find_device() on
acpi_bus_type, so I don't really see how they make a difference from a
cio2-bridge point of view. Is your point that acpi_bus_type shouldn't be
exported because it could then be misused by *other* drivers ? Couldn't
those drivers then equally misuse the iterators ?

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-16  8:53                           ` Laurent Pinchart
@ 2020-11-16 13:57                             ` Andy Shevchenko
  2020-11-16 14:10                               ` Laurent Pinchart
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-11-16 13:57 UTC (permalink / raw)
  To: Laurent Pinchart, Andy Shevchenko
  Cc: Dan Scally, Linux Kernel Mailing List, Linux Media Mailing List,
	Linus Walleij, prabhakar.mahadev-lad.rj, Krogerus, Heikki,
	Dmitry Torokhov, laurent.pinchart+renesas,
	kieran.bingham+renesas, Jacopo Mondi, Rob Herring,
	David S. Miller, Rasmus Villemoes, Sergey Senozhatsky,
	Steven Rostedt, Petr Mladek, Mauro Carvalho Chehab, Tian Shu Qiu,
	Bingbu Cao, Sakari Ailus, Yong Zhi, Rafael J. Wysocki,
	Greg Kroah-Hartman, Tsuchiya Yuto

On Mon, Nov 16, 2020 at 10:53 AM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Fri, Nov 13, 2020 at 09:45:00PM +0200, Andy Shevchenko wrote:
> > On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart wrote:
> > > On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> > > > On 29/10/2020 22:51, Laurent Pinchart wrote:
> > > > > On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> > > > >> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> >
> > ...
> >
> > > > >> In this case we probably need something like
> > > > >>
> > > > >> struct acpi_device *
> > > > >> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> > > > >>                        const char *hid, const char *uid, s64 hrv)
> > > > >> {
> > > > >>    struct device *start = adev ? &adev->dev : NULL;
> > > > >>    ...
> > > > >>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> > > > >>    ...
> > > > >> }
> > > > >>
> > > > >> in drivers/acpi/utils.c and
> > > > >>
> > > > >> static inline struct acpi_device *
> > > > >> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> > > > >> {
> > > > >>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> > > > >> }
> > > > >>
> > > > >> in include/linux/acpi.h.
> > > > >>
> > > > >> Then we may add
> > > > >>
> > > > >> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
> > > > >>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> > > > >>         adev;                                                      \
> > > > >>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> > > > >
> > > > > What the cio2-bridge code needs is indeed
> > > > >
> > > > >     for each hid in supported hids:
> > > > >             for each acpi device that is compatible with hid:
> > > > >                     ...
> > > > >
> > > > > which could also be expressed as
> > > > >
> > > > >     for each acpi device:
> > > > >             if acpi device hid is in supported hids:
> > > > >                     ...
> > > > >
> > > > > I don't mind either option, I'll happily follow the preference of the
> > > > > ACPI maintainers.
> > > >
> > > > Does this need raising elsewhere then? The original idea of just
> > > > bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> > > > but it does mean that I need to export acpi_bus_type (currently that
> > > > symbol's not available)...that seems much simpler to me but I'm not sure
> > > > whether that's something to avoid, and if so whether Andy's approach is
> > > > better.
> > > >
> > > > Thoughts?
> > >
> > > I like simple options :-) A patch to export acpi_bus_type, with enough
> > > context in the commit message (and in the cover latter of the series),
> > > should be enough to provide all the information the ACPI maintainers
> > > need to decide which option is best. With a bit of luck that patch will
> > > be considered the best option and no extra work will be needed.
> >
> > The problem with ACPI bus is that it is not as simple as other buses,
> > i.e. it may have purely ACPI devices along with *companion* devices,
> > which are usually represented by platform bus. On top of that for
> > several ACPI devices there can be one physical node and it will be not
> > so clear what you are exactly looking for by traversing acpi_bus_type.
> > I believe it's hidden on purpose.
>
> Maybe there's something I don't get, as I'm not very familiar with the
> ACPI implementation in the kernel, but the code in the cio2-bridge,
> unless I'm mistaken, is really interested in ACPI devices on the ACPI
> bus, not companions or other devices related to the ACPI devices.

AFAICS cio2-bridge wants to find ACPI companion devices which are
enumerated as platform ones (or I²C or SPI).

> The
> iterators you have proposed above use bus_find_device() on
> acpi_bus_type, so I don't really see how they make a difference from a
> cio2-bridge point of view.

This seems to be true. The iterators have no means to distinguish
between companion devices and pure ACPI, for example.
For this one needs to call something like 'get first physical node'
followed by 'let's check that it has a companion and that the one we
have already got from ACPI bus iterator'.

> Is your point that acpi_bus_type shouldn't be
> exported because it could then be misused by *other* drivers ? Couldn't
> those drivers then equally misuse the iterators ?

My point is that the ACPI bus type here is not homogenous.
And thus I think it was the reason behind hiding it. I might be
mistaken and you may ask ACPI maintainers for the clarification.

In summary I think we are trying to solve a problem that has not yet
existed (devices with several same sensors). Do we have a DSDT of such
to look into?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-16 13:57                             ` Andy Shevchenko
@ 2020-11-16 14:10                               ` Laurent Pinchart
  2020-11-16 14:15                                 ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Laurent Pinchart @ 2020-11-16 14:10 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andy Shevchenko, Dan Scally, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

Hi Andy,

On Mon, Nov 16, 2020 at 03:57:17PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 16, 2020 at 10:53 AM Laurent Pinchart wrote:
> > On Fri, Nov 13, 2020 at 09:45:00PM +0200, Andy Shevchenko wrote:
> > > On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart wrote:
> > > > On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> > > > > On 29/10/2020 22:51, Laurent Pinchart wrote:
> > > > > > On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> > > > > >> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> > >
> > > ...
> > >
> > > > > >> In this case we probably need something like
> > > > > >>
> > > > > >> struct acpi_device *
> > > > > >> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> > > > > >>                        const char *hid, const char *uid, s64 hrv)
> > > > > >> {
> > > > > >>    struct device *start = adev ? &adev->dev : NULL;
> > > > > >>    ...
> > > > > >>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> > > > > >>    ...
> > > > > >> }
> > > > > >>
> > > > > >> in drivers/acpi/utils.c and
> > > > > >>
> > > > > >> static inline struct acpi_device *
> > > > > >> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> > > > > >> {
> > > > > >>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> > > > > >> }
> > > > > >>
> > > > > >> in include/linux/acpi.h.
> > > > > >>
> > > > > >> Then we may add
> > > > > >>
> > > > > >> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
> > > > > >>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> > > > > >>         adev;                                                      \
> > > > > >>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> > > > > >
> > > > > > What the cio2-bridge code needs is indeed
> > > > > >
> > > > > >     for each hid in supported hids:
> > > > > >             for each acpi device that is compatible with hid:
> > > > > >                     ...
> > > > > >
> > > > > > which could also be expressed as
> > > > > >
> > > > > >     for each acpi device:
> > > > > >             if acpi device hid is in supported hids:
> > > > > >                     ...
> > > > > >
> > > > > > I don't mind either option, I'll happily follow the preference of the
> > > > > > ACPI maintainers.
> > > > >
> > > > > Does this need raising elsewhere then? The original idea of just
> > > > > bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> > > > > but it does mean that I need to export acpi_bus_type (currently that
> > > > > symbol's not available)...that seems much simpler to me but I'm not sure
> > > > > whether that's something to avoid, and if so whether Andy's approach is
> > > > > better.
> > > > >
> > > > > Thoughts?
> > > >
> > > > I like simple options :-) A patch to export acpi_bus_type, with enough
> > > > context in the commit message (and in the cover latter of the series),
> > > > should be enough to provide all the information the ACPI maintainers
> > > > need to decide which option is best. With a bit of luck that patch will
> > > > be considered the best option and no extra work will be needed.
> > >
> > > The problem with ACPI bus is that it is not as simple as other buses,
> > > i.e. it may have purely ACPI devices along with *companion* devices,
> > > which are usually represented by platform bus. On top of that for
> > > several ACPI devices there can be one physical node and it will be not
> > > so clear what you are exactly looking for by traversing acpi_bus_type.
> > > I believe it's hidden on purpose.
> >
> > Maybe there's something I don't get, as I'm not very familiar with the
> > ACPI implementation in the kernel, but the code in the cio2-bridge,
> > unless I'm mistaken, is really interested in ACPI devices on the ACPI
> > bus, not companions or other devices related to the ACPI devices.
> 
> AFAICS cio2-bridge wants to find ACPI companion devices which are
> enumerated as platform ones (or I²C or SPI).

I thought we were looking for ACPI devices, not companion devices, in
order to extract information from the DSDT and store it in a software
node. I could very well be wrong though.

> > The
> > iterators you have proposed above use bus_find_device() on
> > acpi_bus_type, so I don't really see how they make a difference from a
> > cio2-bridge point of view.
> 
> This seems to be true. The iterators have no means to distinguish
> between companion devices and pure ACPI, for example.
> For this one needs to call something like 'get first physical node'
> followed by 'let's check that it has a companion and that the one we
> have already got from ACPI bus iterator'.
> 
> > Is your point that acpi_bus_type shouldn't be
> > exported because it could then be misused by *other* drivers ? Couldn't
> > those drivers then equally misuse the iterators ?
> 
> My point is that the ACPI bus type here is not homogenous.
> And thus I think it was the reason behind hiding it. I might be
> mistaken and you may ask ACPI maintainers for the clarification.
> 
> In summary I think we are trying to solve a problem that has not yet
> existed (devices with several same sensors). Do we have a DSDT of such
> to look into?

Not to my knowledge.

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-16 14:10                               ` Laurent Pinchart
@ 2020-11-16 14:15                                 ` Dan Scally
  2020-11-16 16:16                                   ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-11-16 14:15 UTC (permalink / raw)
  To: Laurent Pinchart, Andy Shevchenko
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto


On 16/11/2020 14:10, Laurent Pinchart wrote:
> Hi Andy,
>
> On Mon, Nov 16, 2020 at 03:57:17PM +0200, Andy Shevchenko wrote:
>> On Mon, Nov 16, 2020 at 10:53 AM Laurent Pinchart wrote:
>>> On Fri, Nov 13, 2020 at 09:45:00PM +0200, Andy Shevchenko wrote:
>>>> On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart wrote:
>>>>> On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
>>>>>> On 29/10/2020 22:51, Laurent Pinchart wrote:
>>>>>>> On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
>>>>>>>> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
>>>> ...
>>>>
>>>>>>>> In this case we probably need something like
>>>>>>>>
>>>>>>>> struct acpi_device *
>>>>>>>> acpi_dev_get_next_match_dev(struct acpi_device *adev,
>>>>>>>>                        const char *hid, const char *uid, s64 hrv)
>>>>>>>> {
>>>>>>>>    struct device *start = adev ? &adev->dev : NULL;
>>>>>>>>    ...
>>>>>>>>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
>>>>>>>>    ...
>>>>>>>> }
>>>>>>>>
>>>>>>>> in drivers/acpi/utils.c and
>>>>>>>>
>>>>>>>> static inline struct acpi_device *
>>>>>>>> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
>>>>>>>> {
>>>>>>>>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
>>>>>>>> }
>>>>>>>>
>>>>>>>> in include/linux/acpi.h.
>>>>>>>>
>>>>>>>> Then we may add
>>>>>>>>
>>>>>>>> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
>>>>>>>>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
>>>>>>>>         adev;                                                      \
>>>>>>>>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
>>>>>>> What the cio2-bridge code needs is indeed
>>>>>>>
>>>>>>>     for each hid in supported hids:
>>>>>>>             for each acpi device that is compatible with hid:
>>>>>>>                     ...
>>>>>>>
>>>>>>> which could also be expressed as
>>>>>>>
>>>>>>>     for each acpi device:
>>>>>>>             if acpi device hid is in supported hids:
>>>>>>>                     ...
>>>>>>>
>>>>>>> I don't mind either option, I'll happily follow the preference of the
>>>>>>> ACPI maintainers.
>>>>>> Does this need raising elsewhere then? The original idea of just
>>>>>> bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
>>>>>> but it does mean that I need to export acpi_bus_type (currently that
>>>>>> symbol's not available)...that seems much simpler to me but I'm not sure
>>>>>> whether that's something to avoid, and if so whether Andy's approach is
>>>>>> better.
>>>>>>
>>>>>> Thoughts?
>>>>> I like simple options :-) A patch to export acpi_bus_type, with enough
>>>>> context in the commit message (and in the cover latter of the series),
>>>>> should be enough to provide all the information the ACPI maintainers
>>>>> need to decide which option is best. With a bit of luck that patch will
>>>>> be considered the best option and no extra work will be needed.
>>>> The problem with ACPI bus is that it is not as simple as other buses,
>>>> i.e. it may have purely ACPI devices along with *companion* devices,
>>>> which are usually represented by platform bus. On top of that for
>>>> several ACPI devices there can be one physical node and it will be not
>>>> so clear what you are exactly looking for by traversing acpi_bus_type.
>>>> I believe it's hidden on purpose.
>>> Maybe there's something I don't get, as I'm not very familiar with the
>>> ACPI implementation in the kernel, but the code in the cio2-bridge,
>>> unless I'm mistaken, is really interested in ACPI devices on the ACPI
>>> bus, not companions or other devices related to the ACPI devices.
>> AFAICS cio2-bridge wants to find ACPI companion devices which are
>> enumerated as platform ones (or I²C or SPI).
> I thought we were looking for ACPI devices, not companion devices, in
> order to extract information from the DSDT and store it in a software
> node. I could very well be wrong though.
This is correct - the code to fetch the various resources we're looking
at all uses acpi_device. Whether using Andy's iterator suggestions or
previous bus_for_each_dev(&acpi_bus_type...) I'm just getting the
acpi_device via to_acpi_dev() and using that.
>>> The
>>> iterators you have proposed above use bus_find_device() on
>>> acpi_bus_type, so I don't really see how they make a difference from a
>>> cio2-bridge point of view.
>> This seems to be true. The iterators have no means to distinguish
>> between companion devices and pure ACPI, for example.
>> For this one needs to call something like 'get first physical node'
>> followed by 'let's check that it has a companion and that the one we
>> have already got from ACPI bus iterator'.
>>
>>> Is your point that acpi_bus_type shouldn't be
>>> exported because it could then be misused by *other* drivers ? Couldn't
>>> those drivers then equally misuse the iterators ?
>> My point is that the ACPI bus type here is not homogenous.
>> And thus I think it was the reason behind hiding it. I might be
>> mistaken and you may ask ACPI maintainers for the clarification.
>>
>> In summary I think we are trying to solve a problem that has not yet
>> existed (devices with several same sensors). Do we have a DSDT of such
>> to look into?
> Not to my knowledge.
>

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-16 14:15                                 ` Dan Scally
@ 2020-11-16 16:16                                   ` Andy Shevchenko
  2020-11-17 12:01                                     ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-11-16 16:16 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On Mon, Nov 16, 2020 at 02:15:01PM +0000, Dan Scally wrote:
> On 16/11/2020 14:10, Laurent Pinchart wrote:
> > On Mon, Nov 16, 2020 at 03:57:17PM +0200, Andy Shevchenko wrote:
> >> On Mon, Nov 16, 2020 at 10:53 AM Laurent Pinchart wrote:
> >>> On Fri, Nov 13, 2020 at 09:45:00PM +0200, Andy Shevchenko wrote:
> >>>> On Fri, Nov 13, 2020 at 6:22 PM Laurent Pinchart wrote:
> >>>>> On Fri, Nov 13, 2020 at 10:02:30AM +0000, Dan Scally wrote:
> >>>>>> On 29/10/2020 22:51, Laurent Pinchart wrote:
> >>>>>>> On Fri, Oct 30, 2020 at 12:22:15AM +0200, Andy Shevchenko wrote:
> >>>>>>>> On Thu, Oct 29, 2020 at 11:29:30PM +0200, Laurent Pinchart wrote:
> >>>> ...
> >>>>
> >>>>>>>> In this case we probably need something like
> >>>>>>>>
> >>>>>>>> struct acpi_device *
> >>>>>>>> acpi_dev_get_next_match_dev(struct acpi_device *adev,
> >>>>>>>>                        const char *hid, const char *uid, s64 hrv)
> >>>>>>>> {
> >>>>>>>>    struct device *start = adev ? &adev->dev : NULL;
> >>>>>>>>    ...
> >>>>>>>>    dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> >>>>>>>>    ...
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> in drivers/acpi/utils.c and
> >>>>>>>>
> >>>>>>>> static inline struct acpi_device *
> >>>>>>>> acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> >>>>>>>> {
> >>>>>>>>    return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> in include/linux/acpi.h.
> >>>>>>>>
> >>>>>>>> Then we may add
> >>>>>>>>
> >>>>>>>> #define for_each_acpi_dev_match(adev, hid, uid, hrv)                       \
> >>>>>>>>    for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> >>>>>>>>         adev;                                                      \
> >>>>>>>>         adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> >>>>>>> What the cio2-bridge code needs is indeed
> >>>>>>>
> >>>>>>>     for each hid in supported hids:
> >>>>>>>             for each acpi device that is compatible with hid:
> >>>>>>>                     ...
> >>>>>>>
> >>>>>>> which could also be expressed as
> >>>>>>>
> >>>>>>>     for each acpi device:
> >>>>>>>             if acpi device hid is in supported hids:
> >>>>>>>                     ...
> >>>>>>>
> >>>>>>> I don't mind either option, I'll happily follow the preference of the
> >>>>>>> ACPI maintainers.
> >>>>>> Does this need raising elsewhere then? The original idea of just
> >>>>>> bus_for_each_dev(&acpi_bus_type...) I have now tested and it works fine,
> >>>>>> but it does mean that I need to export acpi_bus_type (currently that
> >>>>>> symbol's not available)...that seems much simpler to me but I'm not sure
> >>>>>> whether that's something to avoid, and if so whether Andy's approach is
> >>>>>> better.
> >>>>>>
> >>>>>> Thoughts?
> >>>>> I like simple options :-) A patch to export acpi_bus_type, with enough
> >>>>> context in the commit message (and in the cover latter of the series),
> >>>>> should be enough to provide all the information the ACPI maintainers
> >>>>> need to decide which option is best. With a bit of luck that patch will
> >>>>> be considered the best option and no extra work will be needed.
> >>>> The problem with ACPI bus is that it is not as simple as other buses,
> >>>> i.e. it may have purely ACPI devices along with *companion* devices,
> >>>> which are usually represented by platform bus. On top of that for
> >>>> several ACPI devices there can be one physical node and it will be not
> >>>> so clear what you are exactly looking for by traversing acpi_bus_type.
> >>>> I believe it's hidden on purpose.
> >>> Maybe there's something I don't get, as I'm not very familiar with the
> >>> ACPI implementation in the kernel, but the code in the cio2-bridge,
> >>> unless I'm mistaken, is really interested in ACPI devices on the ACPI
> >>> bus, not companions or other devices related to the ACPI devices.
> >> AFAICS cio2-bridge wants to find ACPI companion devices which are
> >> enumerated as platform ones (or I²C or SPI).
> > I thought we were looking for ACPI devices, not companion devices, in
> > order to extract information from the DSDT and store it in a software
> > node. I could very well be wrong though.
> This is correct - the code to fetch the various resources we're looking
> at all uses acpi_device. Whether using Andy's iterator suggestions or
> previous bus_for_each_dev(&acpi_bus_type...) I'm just getting the
> acpi_device via to_acpi_dev() and using that.

If you try to get an I²C ore SPI device out of pure ACPI device (with given
APCI _HID) you will fail. So, it's not correct. You are retrieving companion
devices, while they are still in the struct acpi_device.

And don't ask me, why it's so. I wasn't designed that and didn't affect any
decision made there.

> >>> The
> >>> iterators you have proposed above use bus_find_device() on
> >>> acpi_bus_type, so I don't really see how they make a difference from a
> >>> cio2-bridge point of view.
> >> This seems to be true. The iterators have no means to distinguish
> >> between companion devices and pure ACPI, for example.
> >> For this one needs to call something like 'get first physical node'
> >> followed by 'let's check that it has a companion and that the one we
> >> have already got from ACPI bus iterator'.
> >>
> >>> Is your point that acpi_bus_type shouldn't be
> >>> exported because it could then be misused by *other* drivers ? Couldn't
> >>> those drivers then equally misuse the iterators ?
> >> My point is that the ACPI bus type here is not homogenous.
> >> And thus I think it was the reason behind hiding it. I might be
> >> mistaken and you may ask ACPI maintainers for the clarification.
> >>
> >> In summary I think we are trying to solve a problem that has not yet
> >> existed (devices with several same sensors). Do we have a DSDT of such
> >> to look into?
> > Not to my knowledge.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-16 16:16                                   ` Andy Shevchenko
@ 2020-11-17 12:01                                     ` Dan Scally
  2020-11-17 16:42                                       ` Andy Shevchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Dan Scally @ 2020-11-17 12:01 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Laurent Pinchart, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On 16/11/2020 16:16, Andy Shevchenko wrote:
> On Mon, Nov 16, 2020 at 02:15:01PM +0000, Dan Scally wrote:
>> On 16/11/2020 14:10, Laurent Pinchart wrote:
>>> I thought we were looking for ACPI devices, not companion devices, in
>>> order to extract information from the DSDT and store it in a software
>>> node. I could very well be wrong though.
>> This is correct - the code to fetch the various resources we're looking
>> at all uses acpi_device. Whether using Andy's iterator suggestions or
>> previous bus_for_each_dev(&acpi_bus_type...) I'm just getting the
>> acpi_device via to_acpi_dev() and using that.
> If you try to get an I²C ore SPI device out of pure ACPI device (with given
> APCI _HID) you will fail. So, it's not correct. You are retrieving companion
> devices, while they are still in the struct acpi_device.
>
> And don't ask me, why it's so. I wasn't designed that and didn't affect any
> decision made there.

Well, in terms of the actual device we're getting, I don't think we're
fundamentally doing anything different between the methods...unless I'm
really mistaken.


Originally implementation was like:


const char *supported_devices[] = {

        "OVTI2680",

};


static int cio2_bridge_connect_supported_devices(void)

{

        struct acpi_device *adev;

        int i;

        for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {

                adev =
acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);

...

}


and acpi_dev_get_first_match_dev() likewise just returns adev via
to_acpi_device(dev).


So, maybe we don't need to do the iterating over all devices with
matching _HID at all, in which case it can be dropped, but if we're
doing it then I can't see that it's different to the original
implementation in terms of the struct acpi_device we're working with or
the route taken to get it.


Either way; ACPI maintainers asked to be CC'd on the next patchset
anyway, so they'll see what we're doing and be able to weigh in.




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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-17 12:01                                     ` Dan Scally
@ 2020-11-17 16:42                                       ` Andy Shevchenko
  2020-11-17 22:59                                         ` Dan Scally
  0 siblings, 1 reply; 82+ messages in thread
From: Andy Shevchenko @ 2020-11-17 16:42 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On Tue, Nov 17, 2020 at 2:02 PM Dan Scally <djrscally@gmail.com> wrote:
>
> On 16/11/2020 16:16, Andy Shevchenko wrote:
> > On Mon, Nov 16, 2020 at 02:15:01PM +0000, Dan Scally wrote:
> >> On 16/11/2020 14:10, Laurent Pinchart wrote:
> >>> I thought we were looking for ACPI devices, not companion devices, in
> >>> order to extract information from the DSDT and store it in a software
> >>> node. I could very well be wrong though.
> >> This is correct - the code to fetch the various resources we're looking
> >> at all uses acpi_device. Whether using Andy's iterator suggestions or
> >> previous bus_for_each_dev(&acpi_bus_type...) I'm just getting the
> >> acpi_device via to_acpi_dev() and using that.
> > If you try to get an I²C ore SPI device out of pure ACPI device (with given
> > APCI _HID) you will fail. So, it's not correct. You are retrieving companion
> > devices, while they are still in the struct acpi_device.
> >
> > And don't ask me, why it's so. I wasn't designed that and didn't affect any
> > decision made there.
>
> Well, in terms of the actual device we're getting, I don't think we're
> fundamentally doing anything different between the methods...unless I'm
> really mistaken.
>
>
> Originally implementation was like:
>
>
> const char *supported_devices[] = {
>
>         "OVTI2680",
>
> };
>
>
> static int cio2_bridge_connect_supported_devices(void)
>
> {
>
>         struct acpi_device *adev;
>
>         int i;
>
>         for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
>
>                 adev =
> acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
>
> ...
>
> }
>
>
> and acpi_dev_get_first_match_dev() likewise just returns adev via
> to_acpi_device(dev).
>
>
> So, maybe we don't need to do the iterating over all devices with
> matching _HID at all, in which case it can be dropped, but if we're
> doing it then I can't see that it's different to the original
> implementation in terms of the struct acpi_device we're working with or
> the route taken to get it.
>
>
> Either way; ACPI maintainers asked to be CC'd on the next patchset
> anyway, so they'll see what we're doing and be able to weigh in.

Implementation wise the two approaches are quite similar for now, indeed.
I would rather go with an iterator approach for a simple reason, EFI
code already has something which may utilize iterators rather than
using their home grown solution.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-17 16:42                                       ` Andy Shevchenko
@ 2020-11-17 22:59                                         ` Dan Scally
  0 siblings, 0 replies; 82+ messages in thread
From: Dan Scally @ 2020-11-17 22:59 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Laurent Pinchart, Linux Kernel Mailing List,
	Linux Media Mailing List, Linus Walleij,
	prabhakar.mahadev-lad.rj, Krogerus, Heikki, Dmitry Torokhov,
	laurent.pinchart+renesas, kieran.bingham+renesas, Jacopo Mondi,
	Rob Herring, David S. Miller, Rasmus Villemoes,
	Sergey Senozhatsky, Steven Rostedt, Petr Mladek,
	Mauro Carvalho Chehab, Tian Shu Qiu, Bingbu Cao, Sakari Ailus,
	Yong Zhi, Rafael J. Wysocki, Greg Kroah-Hartman, Tsuchiya Yuto

On 17/11/2020 16:42, Andy Shevchenko wrote:
> On Tue, Nov 17, 2020 at 2:02 PM Dan Scally <djrscally@gmail.com> wrote:
>> On 16/11/2020 16:16, Andy Shevchenko wrote:
>>> On Mon, Nov 16, 2020 at 02:15:01PM +0000, Dan Scally wrote:
>>>> On 16/11/2020 14:10, Laurent Pinchart wrote:
>>>>> I thought we were looking for ACPI devices, not companion devices, in
>>>>> order to extract information from the DSDT and store it in a software
>>>>> node. I could very well be wrong though.
>>>> This is correct - the code to fetch the various resources we're looking
>>>> at all uses acpi_device. Whether using Andy's iterator suggestions or
>>>> previous bus_for_each_dev(&acpi_bus_type...) I'm just getting the
>>>> acpi_device via to_acpi_dev() and using that.
>>> If you try to get an I²C ore SPI device out of pure ACPI device (with given
>>> APCI _HID) you will fail. So, it's not correct. You are retrieving companion
>>> devices, while they are still in the struct acpi_device.
>>>
>>> And don't ask me, why it's so. I wasn't designed that and didn't affect any
>>> decision made there.
>> Well, in terms of the actual device we're getting, I don't think we're
>> fundamentally doing anything different between the methods...unless I'm
>> really mistaken.
>>
>>
>> Originally implementation was like:
>>
>>
>> const char *supported_devices[] = {
>>
>>         "OVTI2680",
>>
>> };
>>
>>
>> static int cio2_bridge_connect_supported_devices(void)
>>
>> {
>>
>>         struct acpi_device *adev;
>>
>>         int i;
>>
>>         for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
>>
>>                 adev =
>> acpi_dev_get_first_match_dev(supported_devices[i], NULL, -1);
>>
>> ...
>>
>> }
>>
>>
>> and acpi_dev_get_first_match_dev() likewise just returns adev via
>> to_acpi_device(dev).
>>
>>
>> So, maybe we don't need to do the iterating over all devices with
>> matching _HID at all, in which case it can be dropped, but if we're
>> doing it then I can't see that it's different to the original
>> implementation in terms of the struct acpi_device we're working with or
>> the route taken to get it.
>>
>>
>> Either way; ACPI maintainers asked to be CC'd on the next patchset
>> anyway, so they'll see what we're doing and be able to weigh in.
> Implementation wise the two approaches are quite similar for now, indeed.
> I would rather go with an iterator approach for a simple reason, EFI
> code already has something which may utilize iterators rather than
> using their home grown solution.
Alright - let's stick with that approach and leave the handling multiple
sensors of same model in then. That's the current state of the code
anyway, and it means it can be used elsewhere too.

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

end of thread, other threads:[~2020-11-17 22:59 UTC | newest]

Thread overview: 82+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-19 22:58 [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
2020-10-19 22:58 ` [RFC PATCH v3 1/9] software_node: Add helper function to unregister arrays of software_nodes ordered parent to child Daniel Scally
2020-10-20  9:22   ` Andy Shevchenko
2020-10-20 10:05   ` Sakari Ailus
2020-10-20 11:01     ` Andy Shevchenko
2020-10-20 11:02       ` Andy Shevchenko
2020-10-20 11:04       ` Heikki Krogerus
2020-10-20 22:52     ` Dan Scally
2020-10-21  9:40       ` Andy Shevchenko
2020-10-21  9:54         ` Dan Scally
2020-10-19 22:58 ` [RFC PATCH v3 2/9] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
2020-10-20  7:23   ` Petr Mladek
2020-10-20  9:20   ` Andy Shevchenko
2020-10-19 22:58 ` [RFC PATCH v3 3/9] software_node: Fix failure to hold refcount in software_node_get_next_child Daniel Scally
2020-10-20 12:44   ` Rafael J. Wysocki
2020-10-20 13:31   ` Sakari Ailus
2020-10-20 23:25     ` Dan Scally
2020-10-21  9:33       ` Andy Shevchenko
2020-10-21  9:37         ` Sakari Ailus
2020-10-21  9:56         ` Dan Scally
2020-10-19 22:58 ` [RFC PATCH v3 4/9] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
2020-10-20  9:17   ` Andy Shevchenko
2020-10-20 12:35   ` Sakari Ailus
2020-10-20 13:32     ` Sakari Ailus
2020-10-19 22:58 ` [RFC PATCH v3 5/9] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
2020-10-20  9:16   ` Andy Shevchenko
2020-10-24  0:28   ` Laurent Pinchart
2020-10-19 22:59 ` [RFC PATCH v3 6/9] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple sources files retaining ipu3-cio2 name Daniel Scally
2020-10-20  9:15   ` Andy Shevchenko
2020-10-20 20:41     ` Dan Scally
2020-10-24  0:34   ` Laurent Pinchart
2020-10-19 22:59 ` [RFC PATCH v3 7/9] ipu3-cio2: Check if pci_dev->dev's fwnode is a software_node in cio2_parse_firmware() and set FWNODE_GRAPH_DEVICE_DISABLED if so Daniel Scally
2020-10-20  9:19   ` Andy Shevchenko
2020-10-20 12:06     ` Sakari Ailus
2020-10-20 19:56       ` Dan Scally
2020-10-20 22:49         ` Sakari Ailus
2020-10-20 22:55           ` Dan Scally
2020-10-24  0:39           ` Laurent Pinchart
2020-10-24 14:29             ` Sakari Ailus
2020-10-24 16:33               ` Dan Scally
2020-10-24 16:55                 ` Laurent Pinchart
2020-10-19 22:59 ` [RFC PATCH v3 8/9] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
2020-10-19 22:59 ` [RFC PATCH v3 9/9] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
2020-10-20  9:41   ` Andy Shevchenko
2020-10-21 22:05     ` Daniel Scally
2020-10-22 13:40       ` Andy Shevchenko
2020-10-23 10:06         ` Dan Scally
2020-10-24  1:24   ` Laurent Pinchart
2020-10-24  8:50     ` Dan Scally
2020-10-24  9:37       ` Laurent Pinchart
2020-10-24 22:28         ` Daniel Scally
2020-10-24 22:36           ` Laurent Pinchart
2020-10-24 22:50             ` Daniel Scally
2020-10-26  8:20             ` Dan Scally
2020-10-26 16:05               ` Andy Shevchenko
2020-10-29 20:17                 ` Laurent Pinchart
2020-10-29 22:36                   ` Dan Scally
2020-10-26 16:10         ` Andy Shevchenko
2020-10-29 20:19           ` Laurent Pinchart
2020-10-29 20:26             ` Andy Shevchenko
2020-10-29 21:29               ` Laurent Pinchart
2020-10-29 22:22                 ` Andy Shevchenko
2020-10-29 22:51                   ` Laurent Pinchart
2020-11-13 10:02                     ` Dan Scally
2020-11-13 16:22                       ` Laurent Pinchart
2020-11-13 19:45                         ` Andy Shevchenko
2020-11-15  8:45                           ` Daniel Scally
2020-11-16  8:53                           ` Laurent Pinchart
2020-11-16 13:57                             ` Andy Shevchenko
2020-11-16 14:10                               ` Laurent Pinchart
2020-11-16 14:15                                 ` Dan Scally
2020-11-16 16:16                                   ` Andy Shevchenko
2020-11-17 12:01                                     ` Dan Scally
2020-11-17 16:42                                       ` Andy Shevchenko
2020-11-17 22:59                                         ` Dan Scally
2020-10-24 15:11     ` Sakari Ailus
2020-10-24 15:14   ` Sakari Ailus
2020-10-24 20:28     ` Dan Scally
2020-10-25 11:18       ` Sakari Ailus
2020-10-20  9:24 ` [RFC PATCH v3 0/9] Add functionality to ipu3-cio2 driver " Andy Shevchenko
2020-10-20 13:38 ` Rafael J. Wysocki
2020-10-21 20:59   ` Daniel Scally

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