mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-14 14:34:28 +08:00
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: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20210407065555.88110-5-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b433c4c789
commit
ee64fc599b
@ -1601,7 +1601,6 @@ static void typec_release(struct device *dev)
|
||||
ida_destroy(&port->mode_ids);
|
||||
typec_switch_put(port->sw);
|
||||
typec_mux_put(port->mux);
|
||||
free_pld(port->pld);
|
||||
kfree(port->cap);
|
||||
kfree(port);
|
||||
}
|
||||
@ -2027,7 +2026,9 @@ struct typec_port *typec_register_port(struct device *parent,
|
||||
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;
|
||||
}
|
||||
@ -2041,8 +2042,10 @@ EXPORT_SYMBOL_GPL(typec_register_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);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(typec_unregister_port);
|
||||
|
||||
|
@ -79,7 +79,7 @@ extern const struct device_type typec_port_dev_type;
|
||||
extern struct class typec_mux_class;
|
||||
extern struct class typec_class;
|
||||
|
||||
void *get_pld(struct device *dev);
|
||||
void free_pld(void *pld);
|
||||
int typec_link_ports(struct typec_port *connector);
|
||||
void typec_unlink_ports(struct typec_port *connector);
|
||||
|
||||
#endif /* __USB_TYPEC_CLASS__ */
|
||||
|
@ -34,7 +34,7 @@ static int acpi_pld_match(const struct acpi_pld_info *pld1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *get_pld(struct device *dev)
|
||||
static void *get_pld(struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
struct acpi_pld_info *pld;
|
||||
@ -53,7 +53,7 @@ void *get_pld(struct device *dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_pld(void *pld)
|
||||
static void free_pld(void *pld)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
ACPI_FREE(pld);
|
||||
@ -217,3 +217,61 @@ void typec_unlink_port(struct device *port)
|
||||
class_for_each_device(&typec_class, NULL, port, port_match_and_unlink);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user