From 1666faedb567d03cde1d656ae24c6cc253e67373 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 19 Aug 2019 13:07:22 +0300 Subject: software node: Add software_node_find_by_name() Function that searches software nodes by node name. Signed-off-by: Heikki Krogerus Reviewed-by: Hans de Goede Tested-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/base/swnode.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/property.h | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index e7b3aa3bd55a..ee2a405cca9a 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -620,6 +620,43 @@ static const struct fwnode_operations software_node_ops = { /* -------------------------------------------------------------------------- */ +/** + * software_node_find_by_name - Find software node by name + * @parent: Parent of the software node + * @name: Name of the software node + * + * The function will find a node that is child of @parent and that is named + * @name. If no node is found, the function returns NULL. + * + * NOTE: you will need to drop the reference with fwnode_handle_put() after use. + */ +const struct software_node * +software_node_find_by_name(const struct software_node *parent, const char *name) +{ + struct swnode *swnode; + struct kobject *k; + + if (!name) + return NULL; + + spin_lock(&swnode_kset->list_lock); + + list_for_each_entry(k, &swnode_kset->list, entry) { + swnode = kobj_to_swnode(k); + if (parent == swnode->node->parent && swnode->node->name && + !strcmp(name, swnode->node->name)) { + kobject_get(&swnode->kobj); + break; + } + swnode = NULL; + } + + spin_unlock(&swnode_kset->list_lock); + + return swnode ? swnode->node : NULL; +} +EXPORT_SYMBOL_GPL(software_node_find_by_name); + static int software_node_register_properties(struct software_node *node, const struct property_entry *properties) diff --git a/include/linux/property.h b/include/linux/property.h index 5a910ad79591..9b3d4ca3a73a 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -421,6 +421,10 @@ bool is_software_node(const struct fwnode_handle *fwnode); const struct software_node *to_software_node(struct fwnode_handle *fwnode); struct fwnode_handle *software_node_fwnode(const struct software_node *node); +const struct software_node * +software_node_find_by_name(const struct software_node *parent, + const char *name); + int software_node_register_nodes(const struct software_node *nodes); void software_node_unregister_nodes(const struct software_node *nodes); -- cgit v1.2.3 From d2a90ebb65536a6deeb9daf5aa8e0700e8cbb43a Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 19 Aug 2019 13:07:23 +0300 Subject: usb: roles: intel_xhci: Supplying software node for the role mux The primary purpose for this node will be to allow linking the users of the switch to it. The users will be for example USB Type-C connectors. By supplying a reference to this node in the software nodes representing the USB Type-C controllers or connectors, the drivers for those devices can access the switch. Signed-off-by: Heikki Krogerus Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/usb/roles/intel-xhci-usb-role-switch.c | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c index 277de96181f9..7325a84dd1c8 100644 --- a/drivers/usb/roles/intel-xhci-usb-role-switch.c +++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c @@ -39,6 +39,10 @@ struct intel_xhci_usb_data { void __iomem *base; }; +static const struct software_node intel_xhci_usb_node = { + "intel-xhci-usb-sw", +}; + static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) { struct intel_xhci_usb_data *data = dev_get_drvdata(dev); @@ -122,17 +126,13 @@ static enum usb_role intel_xhci_usb_get_role(struct device *dev) return role; } -static const struct usb_role_switch_desc sw_desc = { - .set = intel_xhci_usb_set_role, - .get = intel_xhci_usb_get_role, - .allow_userspace_control = true, -}; - static int intel_xhci_usb_probe(struct platform_device *pdev) { + struct usb_role_switch_desc sw_desc = { }; struct device *dev = &pdev->dev; struct intel_xhci_usb_data *data; struct resource *res; + int ret; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -147,9 +147,20 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); + ret = software_node_register(&intel_xhci_usb_node); + if (ret) + return ret; + + sw_desc.set = intel_xhci_usb_set_role, + sw_desc.get = intel_xhci_usb_get_role, + sw_desc.allow_userspace_control = true, + sw_desc.fwnode = software_node_fwnode(&intel_xhci_usb_node); + data->role_sw = usb_role_switch_register(dev, &sw_desc); - if (IS_ERR(data->role_sw)) + if (IS_ERR(data->role_sw)) { + fwnode_handle_put(sw_desc.fwnode); return PTR_ERR(data->role_sw); + } pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -164,6 +175,8 @@ static int intel_xhci_usb_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); usb_role_switch_unregister(data->role_sw); + fwnode_handle_put(software_node_fwnode(&intel_xhci_usb_node)); + return 0; } -- cgit v1.2.3 From 78cd4bf53635d3aeb73435bc89eb6eb39450f315 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 19 Aug 2019 13:07:24 +0300 Subject: platform/x86: intel_cht_int33fe: Use new API to gain access to the role switch The driver for the Intel USB role mux now always supplies software node for the role switch, so no longer checking that, and never creating separate node for the role switch. From now on using software_node_find_by_name() function to get the handle to the USB role switch. Signed-off-by: Heikki Krogerus Acked-by: Andy Shevchenko Reviewed-by: Hans de Goede Tested-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/intel_cht_int33fe.c | 57 ++++++-------------------------- 1 file changed, 10 insertions(+), 47 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 4fbdff48a4b5..1d5d877b9582 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -34,7 +34,6 @@ enum { INT33FE_NODE_MAX17047, INT33FE_NODE_PI3USB30532, INT33FE_NODE_DISPLAYPORT, - INT33FE_NODE_ROLE_SWITCH, INT33FE_NODE_USB_CONNECTOR, INT33FE_NODE_MAX, }; @@ -45,7 +44,6 @@ struct cht_int33fe_data { struct i2c_client *pi3usb30532; struct fwnode_handle *dp; - struct fwnode_handle *mux; }; static const struct software_node nodes[]; @@ -139,46 +137,10 @@ static const struct software_node nodes[] = { { "max17047", NULL, max17047_props }, { "pi3usb30532" }, { "displayport" }, - { "usb-role-switch" }, { "connector", &nodes[0], usb_connector_props, usb_connector_refs }, { } }; -static int cht_int33fe_setup_mux(struct cht_int33fe_data *data) -{ - struct fwnode_handle *fwnode; - struct device *dev; - struct device *p; - - fwnode = software_node_fwnode(&nodes[INT33FE_NODE_ROLE_SWITCH]); - if (!fwnode) - return -ENODEV; - - /* First finding the platform device */ - p = bus_find_device_by_name(&platform_bus_type, NULL, - "intel_xhci_usb_sw"); - if (!p) - return -EPROBE_DEFER; - - /* Then the mux child device */ - dev = device_find_child_by_name(p, "intel_xhci_usb_sw-role-switch"); - put_device(p); - if (!dev) - return -EPROBE_DEFER; - - /* If there already is a node for the mux, using that one. */ - if (dev->fwnode) - fwnode_remove_software_node(fwnode); - else - dev->fwnode = fwnode; - - data->mux = fwnode_handle_get(dev->fwnode); - put_device(dev); - mux_ref.node = to_software_node(data->mux); - - return 0; -} - static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) { struct fwnode_handle *fwnode; @@ -211,10 +173,9 @@ static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data) { software_node_unregister_nodes(nodes); - if (data->mux) { - fwnode_handle_put(data->mux); + if (mux_ref.node) { + fwnode_handle_put(software_node_fwnode(mux_ref.node)); mux_ref.node = NULL; - data->mux = NULL; } if (data->dp) { @@ -235,14 +196,16 @@ static int cht_int33fe_add_nodes(struct cht_int33fe_data *data) /* The devices that are not created in this driver need extra steps. */ /* - * There is no ACPI device node for the USB role mux, so we need to find - * the mux device and assign our node directly to it. That means we - * depend on the mux driver. This function will return -PROBE_DEFER - * until the mux device is registered. + * There is no ACPI device node for the USB role mux, so we need to wait + * until the mux driver has created software node for the mux device. + * It means we depend on the mux driver. This function will return + * -EPROBE_DEFER until the mux device is registered. */ - ret = cht_int33fe_setup_mux(data); - if (ret) + mux_ref.node = software_node_find_by_name(NULL, "intel-xhci-usb-sw"); + if (!mux_ref.node) { + ret = -EPROBE_DEFER; goto err_remove_nodes; + } /* * The DP connector does have ACPI device node. In this case we can just -- cgit v1.2.3 From 149f3b87840e7d292ad059f5fc23f1fa2fc98b9e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Aug 2019 23:32:27 +0300 Subject: device property: Remove duplicate test for NULL There is no need to check twice for a NULL in fwnode_call_bool_op(). Signed-off-by: Andy Shevchenko Reviewed-by: Sakari Ailus Signed-off-by: Rafael J. Wysocki --- include/linux/fwnode.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index a11c8c56c78b..ababd6bc82f3 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -110,10 +110,11 @@ struct fwnode_operations { (fwnode ? (fwnode_has_op(fwnode, op) ? \ (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ -EINVAL) -#define fwnode_call_bool_op(fwnode, op, ...) \ - (fwnode ? (fwnode_has_op(fwnode, op) ? \ - (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) : \ - false) + +#define fwnode_call_bool_op(fwnode, op, ...) \ + (fwnode_has_op(fwnode, op) ? \ + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) + #define fwnode_call_ptr_op(fwnode, op, ...) \ (fwnode_has_op(fwnode, op) ? \ (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL) -- cgit v1.2.3 From 3a2650a878b814735430b1b7a25fd190dfacf22e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 30 Aug 2019 17:09:23 +0200 Subject: ACPI / property: Fix acpi_graph_get_remote_endpoint() name in kerneldoc The function is called acpi_graph_get_remote_endpoint(), not acpi_graph_get_remote_enpoint(). Fixes: 79389a83bc3888a9 ("ACPI / property: Add support for remote endpoints") Signed-off-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- drivers/acpi/property.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index ea3d700da3ca..2cb35d30cb14 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -1210,7 +1210,7 @@ static struct fwnode_handle *acpi_graph_get_child_prop_value( /** - * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint + * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint * @fwnode: Endpoint firmware node pointing to a remote device * @endpoint: Firmware node of remote endpoint is filled here if not %NULL * -- cgit v1.2.3 From 616368735e4aa6e3d25cd3474b746014ee490a7b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 30 Aug 2019 10:51:55 +0300 Subject: software node: Initialize the return value in software_node_to_swnode() The software node is searched from a list that may be empty when the function is called. This makes sure that the function returns NULL even if the list is empty. Fixes: 80488a6b1d3c ("software node: Add support for static node descriptors") Reported-by: kbuild test robot Reported-by: Dan Carpenter Signed-off-by: Heikki Krogerus Reviewed-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- 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 ee2a405cca9a..1838d72e618a 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(is_software_node); static struct swnode * software_node_to_swnode(const struct software_node *node) { - struct swnode *swnode; + struct swnode *swnode = NULL; struct kobject *k; if (!node) -- cgit v1.2.3 From 016049a816774edc9c3cd81afa7724d7ab001585 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 30 Aug 2019 10:51:56 +0300 Subject: software node: Initialize the return value in software_node_find_by_name() The software node is searched from a list that may be empty when the function is called. This makes sure that the function returns NULL if the list is empty. Fixes: 1666faedb567 ("software node: Add software_node_find_by_name()") Reported-by: kbuild test robot Reported-by: Dan Carpenter Signed-off-by: Heikki Krogerus Reviewed-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- 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 1838d72e618a..a1f3f0994f9f 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -633,7 +633,7 @@ static const struct fwnode_operations software_node_ops = { const struct software_node * software_node_find_by_name(const struct software_node *parent, const char *name) { - struct swnode *swnode; + struct swnode *swnode = NULL; struct kobject *k; if (!name) -- cgit v1.2.3