]> git.itanic.dy.fi Git - linux-stable/commitdiff
usb: typec: class: Don't use port parent for getting mux handles
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>
Thu, 20 Sep 2018 11:23:44 +0000 (14:23 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Apr 2019 04:26:30 +0000 (06:26 +0200)
commit 23481121c81d984193edf1532f5e123637e50903 upstream.

It is not possible to use the parent of the port device when
requesting mux handles as the parent may be a multiport USB
Type-C or PD controller. The muxes must be assigned to the
ports, not the controllers.

This will also move the requesting of the muxes after the
port device is initialized.

Acked-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/class.c

index e61dffb27a0c64bab899c36f674f922278d92f6e..00141e05bc72429ba1b4f0b54eeb9f661b20207a 100644 (file)
@@ -1500,7 +1500,7 @@ typec_port_register_altmode(struct typec_port *port,
 
        sprintf(id, "id%04xm%02x", desc->svid, desc->mode);
 
-       mux = typec_mux_get(port->dev.parent, id);
+       mux = typec_mux_get(&port->dev, id);
        if (IS_ERR(mux))
                return ERR_CAST(mux);
 
@@ -1540,18 +1540,6 @@ struct typec_port *typec_register_port(struct device *parent,
                return ERR_PTR(id);
        }
 
-       port->sw = typec_switch_get(cap->fwnode ? &port->dev : parent);
-       if (IS_ERR(port->sw)) {
-               ret = PTR_ERR(port->sw);
-               goto err_switch;
-       }
-
-       port->mux = typec_mux_get(parent, "typec-mux");
-       if (IS_ERR(port->mux)) {
-               ret = PTR_ERR(port->mux);
-               goto err_mux;
-       }
-
        switch (cap->type) {
        case TYPEC_PORT_SRC:
                port->pwr_role = TYPEC_SOURCE;
@@ -1592,13 +1580,26 @@ struct typec_port *typec_register_port(struct device *parent,
        port->port_type = cap->type;
        port->prefer_role = cap->prefer_role;
 
+       device_initialize(&port->dev);
        port->dev.class = typec_class;
        port->dev.parent = parent;
        port->dev.fwnode = cap->fwnode;
        port->dev.type = &typec_port_dev_type;
        dev_set_name(&port->dev, "port%d", id);
 
-       ret = device_register(&port->dev);
+       port->sw = typec_switch_get(&port->dev);
+       if (IS_ERR(port->sw)) {
+               put_device(&port->dev);
+               return ERR_CAST(port->sw);
+       }
+
+       port->mux = typec_mux_get(&port->dev, "typec-mux");
+       if (IS_ERR(port->mux)) {
+               put_device(&port->dev);
+               return ERR_CAST(port->mux);
+       }
+
+       ret = device_add(&port->dev);
        if (ret) {
                dev_err(parent, "failed to register port (%d)\n", ret);
                put_device(&port->dev);
@@ -1606,15 +1607,6 @@ struct typec_port *typec_register_port(struct device *parent,
        }
 
        return port;
-
-err_mux:
-       typec_switch_put(port->sw);
-
-err_switch:
-       ida_simple_remove(&typec_index_ida, port->id);
-       kfree(port);
-
-       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(typec_register_port);