Commit ee64fc59 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman

usb: typec: Link all ports during connector registration

The connectors may be registered after the ports, so the
"connector" links need to be created for the ports also when
ever a new connector gets registered.
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20210407065555.88110-5-heikki.krogerus@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b433c4c7
...@@ -1601,7 +1601,6 @@ static void typec_release(struct device *dev) ...@@ -1601,7 +1601,6 @@ static void typec_release(struct device *dev)
ida_destroy(&port->mode_ids); ida_destroy(&port->mode_ids);
typec_switch_put(port->sw); typec_switch_put(port->sw);
typec_mux_put(port->mux); typec_mux_put(port->mux);
free_pld(port->pld);
kfree(port->cap); kfree(port->cap);
kfree(port); kfree(port);
} }
...@@ -2027,7 +2026,9 @@ struct typec_port *typec_register_port(struct device *parent, ...@@ -2027,7 +2026,9 @@ struct typec_port *typec_register_port(struct device *parent,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
port->pld = get_pld(&port->dev); ret = typec_link_ports(port);
if (ret)
dev_warn(&port->dev, "failed to create symlinks (%d)\n", ret);
return port; return port;
} }
...@@ -2041,8 +2042,10 @@ EXPORT_SYMBOL_GPL(typec_register_port); ...@@ -2041,8 +2042,10 @@ EXPORT_SYMBOL_GPL(typec_register_port);
*/ */
void typec_unregister_port(struct typec_port *port) void typec_unregister_port(struct typec_port *port)
{ {
if (!IS_ERR_OR_NULL(port)) if (!IS_ERR_OR_NULL(port)) {
typec_unlink_ports(port);
device_unregister(&port->dev); device_unregister(&port->dev);
}
} }
EXPORT_SYMBOL_GPL(typec_unregister_port); EXPORT_SYMBOL_GPL(typec_unregister_port);
......
...@@ -79,7 +79,7 @@ extern const struct device_type typec_port_dev_type; ...@@ -79,7 +79,7 @@ extern const struct device_type typec_port_dev_type;
extern struct class typec_mux_class; extern struct class typec_mux_class;
extern struct class typec_class; extern struct class typec_class;
void *get_pld(struct device *dev); int typec_link_ports(struct typec_port *connector);
void free_pld(void *pld); void typec_unlink_ports(struct typec_port *connector);
#endif /* __USB_TYPEC_CLASS__ */ #endif /* __USB_TYPEC_CLASS__ */
...@@ -34,7 +34,7 @@ static int acpi_pld_match(const struct acpi_pld_info *pld1, ...@@ -34,7 +34,7 @@ static int acpi_pld_match(const struct acpi_pld_info *pld1,
return 0; return 0;
} }
void *get_pld(struct device *dev) static void *get_pld(struct device *dev)
{ {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
struct acpi_pld_info *pld; struct acpi_pld_info *pld;
...@@ -53,7 +53,7 @@ void *get_pld(struct device *dev) ...@@ -53,7 +53,7 @@ void *get_pld(struct device *dev)
#endif #endif
} }
void free_pld(void *pld) static void free_pld(void *pld)
{ {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
ACPI_FREE(pld); ACPI_FREE(pld);
...@@ -217,3 +217,61 @@ void typec_unlink_port(struct device *port) ...@@ -217,3 +217,61 @@ void typec_unlink_port(struct device *port)
class_for_each_device(&typec_class, NULL, port, port_match_and_unlink); class_for_each_device(&typec_class, NULL, port, port_match_and_unlink);
} }
EXPORT_SYMBOL_GPL(typec_unlink_port); EXPORT_SYMBOL_GPL(typec_unlink_port);
static int each_port(struct device *port, void *connector)
{
struct port_node *node;
int ret;
node = create_port_node(port);
if (IS_ERR(node))
return PTR_ERR(node);
if (!connector_match(connector, node)) {
remove_port_node(node);
return 0;
}
ret = link_port(to_typec_port(connector), node);
if (ret) {
remove_port_node(node->pld);
return ret;
}
get_device(connector);
return 0;
}
int typec_link_ports(struct typec_port *con)
{
int ret = 0;
con->pld = get_pld(&con->dev);
if (!con->pld)
return 0;
ret = usb_for_each_port(&con->dev, each_port);
if (ret)
typec_unlink_ports(con);
return ret;
}
void typec_unlink_ports(struct typec_port *con)
{
struct port_node *node;
struct port_node *tmp;
mutex_lock(&con->port_list_lock);
list_for_each_entry_safe(node, tmp, &con->port_list, list) {
__unlink_port(con, node);
remove_port_node(node);
put_device(&con->dev);
}
mutex_unlock(&con->port_list_lock);
free_pld(con->pld);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment