[RFC PATCH 06/15] usbcore: make usb_port a proper parent of a usb_device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We jump through a few hoops to support maintaining a usb_port as a sibling of a
usb_device. Namely ->power_is_on and ->did_runtime_put are artifacts of
pm_ignore_children and the organization of the device tree.  Re-organize the
hierarchy to enable using the runtime_status as the indicator of whether a
port should be active.  To preserve the userspace abi a link from the hub to
the child device is provided.

Before:
# readlink -f /sys/devices/pci0000:00/0000:00:14.0/usb2/2-1
              /sys/devices/pci0000:00/0000:00:14.0/usb2/2-1
              +-------+
              |  hub  |
              +---^---+
                  |
            +-----+----+
            |          |
        +---+---+  +---+---+
        | intf  |  |device |
        +---^---+  +-------+
            |
        +---+---+
        | port  |
        +-------+

After:
# readlink -f /sys/devices/pci0000:00/0000:00:14.0/usb2/2-1
              /sys/devices/pci0000:00/0000:00:14.0/usb2/2-0:1.0/port1/2-1

              +-------+
              |  hub  |
              +---^---+
                  |
              +---+---+
              | intf  |
              +---^---+
                  |
              +---+---+
              | port  |
              +---^---+
                  |
              +---+---+
              |device |
              +-------+

Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 drivers/usb/core/hub.c |   16 +++++-----------
 drivers/usb/core/usb.c |   14 ++++++++++++--
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 06cec635e703..b78eb4cdf5ed 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2066,9 +2066,9 @@ void usb_disconnect(struct usb_device **pdev)
 	if (udev->parent) {
 		struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
 		struct usb_port	*port_dev = hub->ports[udev->portnum - 1];
+		struct usb_device *hdev = udev->parent;
 
-		sysfs_remove_link(&udev->dev.kobj, "port");
-		sysfs_remove_link(&port_dev->dev.kobj, "device");
+		sysfs_remove_link(&hdev->dev.kobj, dev_name(&udev->dev));
 
 		if (!port_dev->did_runtime_put)
 			pm_runtime_put(&port_dev->dev);
@@ -2377,19 +2377,13 @@ int usb_new_device(struct usb_device *udev)
 	if (udev->parent) {
 		struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
 		struct usb_port	*port_dev = hub->ports[udev->portnum - 1];
+		struct usb_device *hdev = udev->parent;
 
-		err = sysfs_create_link(&udev->dev.kobj,
-				&port_dev->dev.kobj, "port");
+		err = sysfs_create_link(&hdev->dev.kobj, &udev->dev.kobj,
+					dev_name(&udev->dev));
 		if (err)
 			goto fail;
 
-		err = sysfs_create_link(&port_dev->dev.kobj,
-				&udev->dev.kobj, "device");
-		if (err) {
-			sysfs_remove_link(&udev->dev.kobj, "port");
-			goto fail;
-		}
-
 		pm_runtime_get_sync(&port_dev->dev);
 	}
 
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4d1144990d4c..c55711420222 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -42,7 +42,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 
-#include "usb.h"
+#include "hub.h"
 
 
 const char *usbcore_name = "usbcore";
@@ -458,6 +458,13 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
 		dev_set_name(&dev->dev, "usb%d", bus->busnum);
 		root_hub = 1;
 	} else {
+		struct usb_hub *hub = usb_hub_to_struct_hub(parent);
+
+		if (!hub) {
+			kfree(dev);
+			return NULL;
+		}
+
 		/* match any labeling on the hubs; it's one-based */
 		if (parent->devpath[0] == '0') {
 			snprintf(dev->devpath, sizeof dev->devpath,
@@ -476,7 +483,10 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
 					(15 << ((parent->level - 1)*4));
 		}
 
-		dev->dev.parent = &parent->dev;
+		/* usb hierarchy is hub->device device-model hierarchy is
+		 * hub->intf->port->device
+		 */
+		dev->dev.parent = &hub->ports[port1 - 1]->dev;
 		dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
 
 		/* hub driver sets up TT records */

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux