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

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


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b433c4c7
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -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,9 +2042,11 @@ 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);

static int __init typec_init(void)
+2 −2
Original line number Diff line number Diff line
@@ -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__ */
+60 −2
Original line number Diff line number Diff line
@@ -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);
}