For example: usb2/2-1/2-1:1.0/port1/peer => ../../../../usb3/3-1/3-1:1.0/port1 usb2/2-1/2-1:1.0/port2/peer => ../../../../usb3/3-1/3-1:1.0/port2 usb2/2-1/2-1:1.0/port3/peer => ../../../../usb3/3-1/3-1:1.0/port3 usb2/2-1/2-1:1.0/port4/peer => ../../../../usb3/3-1/3-1:1.0/port4 usb2/2-0:1.0/port1/peer => ../../../usb3/3-0:1.0/port1 usb2/2-0:1.0/port2/peer => ../../../usb3/3-0:1.0/port2 usb2/2-0:1.0/port3/peer => ../../../usb3/3-0:1.0/port3 usb2/2-0:1.0/port4/peer => ../../../usb3/3-0:1.0/port4 usb3/3-1/3-1:1.0/port1/peer => ../../../../usb2/2-1/2-1:1.0/port1 usb3/3-1/3-1:1.0/port2/peer => ../../../../usb2/2-1/2-1:1.0/port2 usb3/3-1/3-1:1.0/port3/peer => ../../../../usb2/2-1/2-1:1.0/port3 usb3/3-1/3-1:1.0/port4/peer => ../../../../usb2/2-1/2-1:1.0/port4 usb3/3-0:1.0/port1/peer => ../../../usb2/2-0:1.0/port1 usb3/3-0:1.0/port2/peer => ../../../usb2/2-0:1.0/port2 usb3/3-0:1.0/port3/peer => ../../../usb2/2-0:1.0/port3 usb3/3-0:1.0/port4/peer => ../../../usb2/2-0:1.0/port4 Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> --- drivers/usb/core/port.c | 40 +++++++++++++++++++++++++++++++--------- 1 files changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 8fae3cd03305..d3aacf093aa1 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -21,7 +21,7 @@ #include "hub.h" -DEFINE_SPINLOCK(peer_lock); +DEFINE_MUTEX(peer_lock); static const struct attribute_group *port_dev_group[]; static ssize_t connect_type_show(struct device *dev, @@ -201,16 +201,20 @@ static void reset_peer(struct usb_port *port_dev, struct usb_port *peer) if (!peer) return; - spin_lock(&peer_lock); - if (port_dev->peer) + mutex_lock(&peer_lock); + if (port_dev->peer) { put_device(&port_dev->peer->dev); - if (peer->peer) + sysfs_remove_link(&port_dev->dev.kobj, "peer"); + } + if (peer->peer) { put_device(&peer->peer->dev); + sysfs_remove_link(&peer->dev.kobj, "peer"); + } port_dev->peer = peer; peer->peer = port_dev; get_device(&peer->dev); get_device(&port_dev->dev); - spin_unlock(&peer_lock); + mutex_unlock(&peer_lock); } /* assumes that location data is only set for external connectors and that @@ -311,19 +315,33 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) dev_dbg(&hub->hdev->dev, "port%d peer = %s\n", port1, peer ? dev_name(peer->dev.parent->parent) : "[none]"); if (peer) { - spin_lock(&peer_lock); + mutex_lock(&peer_lock); get_device(&peer->dev); port_dev->peer = peer; WARN_ON(peer->peer); get_device(&port_dev->dev); peer->peer = port_dev; - spin_unlock(&peer_lock); + mutex_unlock(&peer_lock); } retval = device_add(&port_dev->dev); if (retval) goto error_register; + mutex_lock(&peer_lock); + peer = port_dev->peer; + do if (peer) { + retval = sysfs_create_link(&port_dev->dev.kobj, + &peer->dev.kobj, "peer"); + if (retval) + break; + retval = sysfs_create_link(&peer->dev.kobj, + &port_dev->dev.kobj, "peer"); + } while (0); + mutex_unlock(&peer_lock); + if (retval) + goto error_links; + pm_runtime_set_active(&port_dev->dev); /* It would be dangerous if user space couldn't @@ -339,6 +357,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) error_register: put_device(&port_dev->dev); +error_links: + device_unregister(&port_dev->dev); exit: return retval; } @@ -348,14 +368,16 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1) struct usb_port *port_dev = hub->ports[port1 - 1]; struct usb_port *peer = port_dev->peer; - spin_lock(&peer_lock); + mutex_lock(&peer_lock); if (peer) { peer->peer = NULL; port_dev->peer = NULL; put_device(&port_dev->dev); put_device(&peer->dev); + sysfs_remove_link(&port_dev->dev.kobj, "peer"); + sysfs_remove_link(&peer->dev.kobj, "peer"); } - spin_unlock(&peer_lock); + mutex_unlock(&peer_lock); device_unregister(&port_dev->dev); } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html