Hi Yoshihiro,
On Wed, Apr 18, 2018 at 05:09:58PM +0900, Yoshihiro Shimoda wrote:
> This patch adds device connection parsing in of_platform_populate().
>
> TODO:
> - How to free the devcon memories?
> - How to remove the devcon instances?
>
> Signed-off-by: Yoshihiro Shimoda <[email protected]>
> ---
> drivers/of/platform.c | 66
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/of.h | 1 +
> 2 files changed, 67 insertions(+)
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index c00d81d..41c018d 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -17,6 +17,7 @@
> #include <linux/slab.h>
> #include <linux/of_address.h>
> #include <linux/of_device.h>
> +#include <linux/of_graph.h>
> #include <linux/of_iommu.h>
> #include <linux/of_irq.h>
> #include <linux/of_platform.h>
> @@ -326,6 +327,63 @@ static const struct of_dev_auxdata *of_dev_lookup(const
> struct of_dev_auxdata *l
> return NULL;
> }
>
> +static int of_parse_device_connection(struct device_node *np)
> +{
> + struct device_node *child_ep, *parent, *remote_parent;
> + struct platform_device *pdev, *remote_pdev;
> + struct device_connection *devcon = NULL;
> + const char *id;
> +
> + if (of_node_check_flag(np, OF_DEVICE_CONNECTED)) {
> + pr_debug("%s() - skipping %pOF, already device connected\n",
> + __func__, np);
> + return 0;
> + }
> +
> + of_node_set_flag(np, OF_DEVICE_CONNECTED);
> +
> + for_each_endpoint_of_node(np, child_ep) {
> + if (of_property_read_string(child_ep, "device-connection-id",
> + &id) < 0)
> + continue;
> +
> + remote_parent = of_graph_get_remote_port_parent(child_ep);
> + if (!remote_parent)
> + return 0;
> +
> + parent = of_graph_get_port_parent(child_ep);
> + if (!parent)
> + return 0;
> +
> + pdev = of_find_device_by_node(parent);
> + if (!pdev)
> + return 0;
> +
> + /*
> + * WARN_ON in really_probe() may happen if devm_kzalloc is
> + * used. TODO: How to free this?
> + */
> + devcon = kzalloc(sizeof(*devcon), GFP_KERNEL);
> + if (!devcon)
> + return -ENOMEM;
> +
> + devcon->id = id;
> + remote_pdev = of_find_device_by_node(remote_parent);
> + if (!remote_pdev) {
> + kfree(devcon);
> + return 0;
> + }
> +
> + devcon->endpoint[0] = dev_name(&pdev->dev);
> + devcon->endpoint[1] = dev_name(&remote_pdev->dev);
> +
> + /* TODO: How to remove the connection? */
> + device_connection_add(devcon);
This is wrong. You are converting a connection that is described in
graph into a "build-in" one. If the connection is already described in
graph there is no need to, actually, we _should not_, add it to the
list of "build-in" connection descriptions.
What should be done is that we parse the graph the moment
device_connection_find*() is called. And that should be done in
drivers/base/devcon.c .
> + }
> +
> + return 0;
> +}
> +
> /**
> * of_platform_bus_create() - Create a device for a node and its children.
> * @bus: device node of the bus to instantiate
> @@ -477,6 +535,14 @@ int of_platform_populate(struct device_node *root,
> }
> of_node_set_flag(root, OF_POPULATED_BUS);
>
> + for_each_child_of_node(root, child) {
> + rc = of_parse_device_connection(child);
> + if (rc) {
> + of_node_put(child);
> + break;
> + }
> + }
> +
> of_node_put(root);
> return rc;
> }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 4d25e4f..30aa103 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -143,6 +143,7 @@ static inline void of_node_put(struct device_node *node)
> { }
> #define OF_DETACHED 2 /* node has been detached from the device tree */
> #define OF_POPULATED 3 /* device already created for the node */
> #define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children
> of this node */
> +#define OF_DEVICE_CONNECTED 5 /* checked devcon on of_platform_populate */
>
> #define OF_BAD_ADDR ((u64)-1)
Thanks,
--
heikki
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html