regards,
Stephen.
On Tue, 29 Jan 2002, Greg KH wrote:
> Hi,
>
> Well after determining that the last version of this patch doesn't show
> the USB tree properly, here's another patch against 2.5.3-pre6 that
> fixes this issue.
>
> With this patch (the driver core changes were from Pat Mochel, thanks
> Pat for putting up with my endless questions) my machine now shows the
> following tree:
>
> [greg@soap x]$ tree
> .
> `-- root
> |-- pci0
> | |-- 00:00.0
> | | |-- power
> | | `-- status
> | |-- 00:01.0
> | | |-- 02:00.0
> | | | |-- power
> | | | `-- status
> | | |-- power
> | | `-- status
> | |-- 00:1e.0
> | | |-- 01:08.0
> | | | |-- power
> | | | `-- status
> | | |-- 01:0d.0
> | | | |-- power
> | | | |-- status
> | | | `-- usb_bus
> | | | |-- power
> | | | `-- status
> | | |-- 01:0d.1
> | | | |-- power
> | | | |-- status
> | | | `-- usb_bus
> | | | |-- 003
> | | | | |-- power
> | | | | `-- status
> | | | |-- power
> | | | `-- status
> | | |-- 01:0d.2
> | | | |-- power
> | | | |-- status
> | | | `-- usb_bus
> | | | |-- power
> | | | `-- status
> | | |-- power
> | | `-- status
> | |-- 00:1f.0
> | | |-- power
> | | `-- status
> | |-- 00:1f.1
> | | |-- power
> | | `-- status
> | |-- 00:1f.2
> | | |-- power
> | | |-- status
> | | `-- usb_bus
> | | |-- 002
> | | | |-- 003
> | | | | |-- power
> | | | | `-- status
> | | | |-- power
> | | | `-- status
> | | |-- power
> | | `-- status
> | |-- 00:1f.3
> | | |-- power
> | | `-- status
> | |-- 00:1f.5
> | | |-- power
> | | `-- status
> | |-- power
> | `-- status
> |-- power
> `-- status
>
>
> I have 2 USB controllers in this system, 1 UHCI controller on the
> motherboard that shows up under PCI device 00:1f.2. There are two
> devices plugged into this bus, a hub, and a trackball plugged into the
> hub. This topology is now shown properly.
>
> The other controller is a USB 2.0 controller that shows up in 3 places
> on the pci bus: 01:0d.0, 01:0d.1, and 01:0d.2. The 01:0d.1 device is
> controlled by the ohci-hcd driver, and a USB hub is plugged into it.
> The ehci-hcd driver controls the other 2 pci devices on the card.
>
> Yes, I need to have better names for the devices than just "usb_bus",
> any suggestions? These devices nodes are really the USB root hubs in
> the USB controller, so they could just have the USB number as the name
> like the other USB devices (001), but that's pretty boring :)
>
> greg k-h
>
>
>
> diff -Nru a/drivers/base/core.c b/drivers/base/core.c
> --- a/drivers/base/core.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/base/core.c Tue Jan 29 16:02:26 2002
> @@ -17,10 +17,7 @@
> # define DBG(x...)
> #endif
>
> -static struct iobus device_root = {
> - bus_id: "root",
> - name: "Logical System Root",
> -};
> +static struct device * device_root;
>
> int (*platform_notify)(struct device * dev) = NULL;
> int (*platform_notify_remove)(struct device * dev) = NULL;
> @@ -28,9 +25,6 @@
> extern int device_make_dir(struct device * dev);
> extern void device_remove_dir(struct device * dev);
>
> -extern int iobus_make_dir(struct iobus * iobus);
> -extern void iobus_remove_dir(struct iobus * iobus);
> -
> static spinlock_t device_lock;
>
> /**
> @@ -47,19 +41,25 @@
>
> if (!dev || !strlen(dev->bus_id))
> return -EINVAL;
> - BUG_ON(!dev->parent);
>
> spin_lock(&device_lock);
> INIT_LIST_HEAD(&dev->node);
> + INIT_LIST_HEAD(&dev->children);
> spin_lock_init(&dev->lock);
> atomic_set(&dev->refcount,2);
>
> - get_iobus(dev->parent);
> - list_add_tail(&dev->node,&dev->parent->devices);
> + if (dev != device_root) {
> + struct device * parent;
> + if (!dev->parent)
> + dev->parent = device_root;
> + parent = dev->parent;
> + get_device(parent);
> + list_add_tail(&dev->node,&parent->children);
> + }
> spin_unlock(&device_lock);
>
> - DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
> - dev->bus_id, dev->name, parent->bus_id);
> + DBG("DEV: registering device: ID = '%s', name = %s\n",
> + dev->bus_id, dev->name);
>
> if ((error = device_make_dir(dev)))
> goto register_done;
> @@ -70,8 +70,8 @@
>
> register_done:
> put_device(dev);
> - if (error)
> - put_iobus(dev->parent);
> + if (error && dev->parent)
> + put_device(dev->parent);
> return error;
> }
>
> @@ -100,9 +100,6 @@
> /* remove the driverfs directory */
> device_remove_dir(dev);
>
> - if (dev->subordinate)
> - iobus_remove_dir(dev->subordinate);
> -
> /* Notify the platform of the removal, in case they
> * need to do anything...
> */
> @@ -116,70 +113,18 @@
> if (dev->driver && dev->driver->remove)
> dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
>
> - put_iobus(dev->parent);
> -}
> -
> -int iobus_register(struct iobus *bus)
> -{
> - int error;
> -
> - if (!bus || !strlen(bus->bus_id))
> - return -EINVAL;
> -
> - spin_lock(&device_lock);
> - atomic_set(&bus->refcount,2);
> - spin_lock_init(&bus->lock);
> - INIT_LIST_HEAD(&bus->node);
> - INIT_LIST_HEAD(&bus->devices);
> - INIT_LIST_HEAD(&bus->children);
> -
> - if (bus != &device_root) {
> - if (!bus->parent)
> - bus->parent = &device_root;
> - get_iobus(bus->parent);
> - list_add_tail(&bus->node,&bus->parent->children);
> - }
> - spin_unlock(&device_lock);
> -
> - DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
> - bus->bus_id,bus->name,bus->parent);
> -
> - error = iobus_make_dir(bus);
> -
> - put_iobus(bus);
> - if (error && bus->parent)
> - put_iobus(bus->parent);
> - return error;
> -}
> -
> -/**
> - * iobus_unregister - remove bus and children from device tree
> - * @bus: pointer to bus structure
> - *
> - * Remove device from parent's list of children and decrement
> - * reference count on controlling device. That should take care of
> - * the rest of the cleanup.
> - */
> -void put_iobus(struct iobus * iobus)
> -{
> - if (!atomic_dec_and_lock(&iobus->refcount,&device_lock))
> - return;
> - list_del_init(&iobus->node);
> - spin_unlock(&device_lock);
> -
> - if (!list_empty(&iobus->devices) ||
> - !list_empty(&iobus->children))
> - BUG();
> -
> - put_iobus(iobus->parent);
> - /* unregister itself */
> - put_device(iobus->self);
> + put_device(dev->parent);
> }
>
> static int __init device_init_root(void)
> {
> - /* initialize parent bus lists */
> - return iobus_register(&device_root);
> + device_root = kmalloc(sizeof(*device_root),GFP_KERNEL);
> + if (!device_root)
> + return -ENOMEM;
> + memset(device_root,0,sizeof(*device_root));
> + strcpy(device_root->bus_id,"root");
> + strcpy(device_root->name,"System Root");
> + return device_register(device_root);
> }
>
> int __init device_driver_init(void)
> @@ -208,5 +153,5 @@
> }
>
> EXPORT_SYMBOL(device_register);
> -EXPORT_SYMBOL(iobus_register);
> +EXPORT_SYMBOL(put_device);
> EXPORT_SYMBOL(device_driver_init);
> diff -Nru a/drivers/base/fs.c b/drivers/base/fs.c
> --- a/drivers/base/fs.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/base/fs.c Tue Jan 29 16:02:26 2002
> @@ -102,28 +102,6 @@
> }
> }
> return 0;
> -}
> -
> -void iobus_remove_dir(struct iobus * iobus)
> -{
> - if (iobus)
> - driverfs_remove_dir(&iobus->dir);
> -}
> -
> -int iobus_make_dir(struct iobus * iobus)
> -{
> - struct driver_dir_entry * parent = NULL;
> - int error;
> -
> - INIT_LIST_HEAD(&iobus->dir.files);
> - iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
> - iobus->dir.name = iobus->bus_id;
> -
> - if (iobus->parent)
> - parent = &iobus->parent->dir;
> -
> - error = driverfs_create_dir(&iobus->dir,parent);
> - return error;
> }
>
> EXPORT_SYMBOL(device_create_file);
> diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
> --- a/drivers/pci/pci.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/pci/pci.c Tue Jan 29 16:02:26 2002
> @@ -1086,13 +1086,7 @@
> child->parent = parent;
> child->ops = parent->ops;
> child->sysdata = parent->sysdata;
> -
> - /* init generic fields */
> - child->iobus.self = &dev->dev;
> - child->iobus.parent = &parent->iobus;
> - dev->dev.subordinate = &child->iobus;
> -
> - strcpy(child->iobus.name,dev->dev.name);
> + child->dev = &dev->dev;
>
> /*
> * Set up the primary, secondary and subordinate
> @@ -1361,16 +1355,11 @@
> DBG("Scanning bus %02x\n", bus->number);
> max = bus->secondary;
>
> - /* we should know for sure what the bus number is, so set the bus ID
> - * for the bus and make sure it's registered in the device tree */
> - sprintf(bus->iobus.bus_id,"pci%d",bus->number);
> - iobus_register(&bus->iobus);
> -
> /* Create a device template */
> memset(&dev0, 0, sizeof(dev0));
> dev0.bus = bus;
> dev0.sysdata = bus->sysdata;
> - dev0.dev.parent = &bus->iobus;
> + dev0.dev.parent = bus->dev;
> dev0.dev.driver = &pci_device_driver;
>
> /* Go find them, Rover! */
> @@ -1430,9 +1419,11 @@
> return NULL;
> list_add_tail(&b->node, &pci_root_buses);
>
> - sprintf(b->iobus.bus_id,"pci%d",bus);
> - strcpy(b->iobus.name,"Host/PCI Bridge");
> - iobus_register(&b->iobus);
> + b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
> + memset(b->dev,0,sizeof(*(b->dev)));
> + sprintf(b->dev->bus_id,"pci%d",bus);
> + strcpy(b->dev->name,"Host/PCI Bridge");
> + device_register(b->dev);
>
> b->number = b->secondary = bus;
> b->resource[0] = &ioport_resource;
> diff -Nru a/drivers/usb/hcd/ehci-hcd.c b/drivers/usb/hcd/ehci-hcd.c
> --- a/drivers/usb/hcd/ehci-hcd.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/usb/hcd/ehci-hcd.c Tue Jan 29 16:02:26 2002
> @@ -290,6 +290,12 @@
> goto done2;
> }
>
> + /* hook up the root hub to the pci controller in the device tree */
> + udev->dev.parent = &ehci->hcd.pdev->dev;
> + strcpy (udev->dev.name, "usb_name");
> + strcpy (udev->dev.bus_id, "usb_bus");
> + device_register (&udev->dev);
> +
> return 0;
> }
>
> diff -Nru a/drivers/usb/hcd/ohci-hcd.c b/drivers/usb/hcd/ohci-hcd.c
> --- a/drivers/usb/hcd/ohci-hcd.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/usb/hcd/ohci-hcd.c Tue Jan 29 16:02:26 2002
> @@ -475,7 +475,13 @@
> // FIXME cleanup
> return -ENODEV;
> }
> -
> +
> + /* hook up the root hub to the pci controller in the device tree */
> + udev->dev.parent = &ohci->hcd.pdev->dev;
> + strcpy (udev->dev.name, "usb_name");
> + strcpy (udev->dev.bus_id, "usb_bus");
> + device_register (&udev->dev);
> +
> return 0;
> }
>
> diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
> --- a/drivers/usb/hub.c Tue Jan 29 16:02:27 2002
> +++ b/drivers/usb/hub.c Tue Jan 29 16:02:27 2002
> @@ -722,8 +722,16 @@
> dev->bus->busnum, dev->devpath, dev->devnum);
>
> /* Run it through the hoops (find a driver, etc) */
> - if (!usb_new_device(dev))
> + if (!usb_new_device(dev)) {
> + /* put the device in the global device tree */
> + dev->dev.parent = &dev->parent->dev;
> + sprintf (&dev->dev.name[0], "USB device %04x:%04x",
> + dev->descriptor.idVendor,
> + dev->descriptor.idProduct);
> + sprintf (&dev->dev.bus_id[0], "%03d", dev->devnum);
> + device_register (&dev->dev);
> goto done;
> + }
>
> /* Free the configuration if there was an error */
> usb_free_dev(dev);
> diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
> --- a/drivers/usb/uhci.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/usb/uhci.c Tue Jan 29 16:02:26 2002
> @@ -2848,6 +2848,12 @@
> goto err_start_root_hub;
> }
>
> + /* hook the root hub up to the pci controller in the device tree */
> + uhci->rh.dev->dev.parent = &dev->dev;
> + strcpy (uhci->rh.dev->dev.name, "usb_name");
> + strcpy (uhci->rh.dev->dev.bus_id, "usb_bus");
> + device_register (&uhci->rh.dev->dev);
> +
> return 0;
>
> /*
> diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
> --- a/drivers/usb/usb-ohci.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/usb/usb-ohci.c Tue Jan 29 16:02:26 2002
> @@ -2508,6 +2508,13 @@
> #ifdef DEBUG
> ohci_dump (ohci, 1);
> #endif
> +
> + /* hook the root hub up to the pci controller in the device tree */
> + ohci->bus->root_hub->dev.parent = &dev->dev;
> + strcpy (ohci->bus->root_hub->dev.name, "usb_name");
> + strcpy (ohci->bus->root_hub->dev.bus_id, "usb_bus");
> + device_register (&ohci->bus->root_hub->dev);
> +
> return 0;
> }
>
> diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
> --- a/drivers/usb/usb-uhci.c Tue Jan 29 16:02:26 2002
> +++ b/drivers/usb/usb-uhci.c Tue Jan 29 16:02:26 2002
> @@ -3028,6 +3028,12 @@
> pci_set_drvdata(dev, s);
> devs=s;
>
> + /* hook the root hub up to the pci controller in the device tree */
> + s->bus->root_hub->dev.parent = &dev->dev;
> + strcpy (s->bus->root_hub->dev.name, "usb_name");
> + strcpy (s->bus->root_hub->dev.bus_id, "usb_bus");
> + device_register (&s->bus->root_hub->dev);
> +
> return 0;
> }
>
> diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
> --- a/drivers/usb/usb.c Tue Jan 29 16:02:27 2002
> +++ b/drivers/usb/usb.c Tue Jan 29 16:02:27 2002
> @@ -1925,6 +1951,7 @@
> if (dev->devnum > 0) {
> clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
> usbfs_remove_device(dev);
> + put_device(&dev->dev);
> }
>
> /* Free up the device itself */
> diff -Nru a/include/linux/device.h b/include/linux/device.h
> --- a/include/linux/device.h Tue Jan 29 16:02:26 2002
> +++ b/include/linux/device.h Tue Jan 29 16:02:26 2002
> @@ -66,10 +66,8 @@
>
> struct device {
> struct list_head node; /* node in sibling list */
> - struct iobus *parent; /* parent bus */
> -
> - struct iobus *subordinate; /* only valid if this device is a
> - bridge device */
> + struct list_head children;
> + struct device *parent;
>
> char name[DEVICE_NAME_SIZE]; /* descriptive ascii string */
> char bus_id[BUS_ID_SIZE]; /* position on parent bus */
> diff -Nru a/include/linux/pci.h b/include/linux/pci.h
> --- a/include/linux/pci.h Tue Jan 29 16:02:26 2002
> +++ b/include/linux/pci.h Tue Jan 29 16:02:26 2002
> @@ -432,8 +432,7 @@
> unsigned char productver; /* product version */
> unsigned char checksum; /* if zero - checksum passed */
> unsigned char pad1;
> -
> - struct iobus iobus; /* Generic device interface */
> + struct device * dev;
> };
>
> #define pci_bus_b(n) list_entry(n, struct pci_bus, node)
> diff -Nru a/include/linux/usb.h b/include/linux/usb.h
> --- a/include/linux/usb.h Tue Jan 29 16:02:26 2002
> +++ b/include/linux/usb.h Tue Jan 29 16:02:26 2002
> @@ -1,6 +1,8 @@
> #ifndef __LINUX_USB_H
> #define __LINUX_USB_H
>
> +#include <linux/device.h>
> +
> /* USB constants */
>
> /*
> @@ -1037,6 +1042,8 @@
>
> struct usb_device *parent;
> struct usb_bus *bus; /* Bus we're part of */
> +
> + struct device dev; /* Generic device interface */
>
> struct usb_device_descriptor descriptor;/* Descriptor */
> struct usb_config_descriptor *config; /* All of the configs */
>
> _______________________________________________
> linux-usb-devel@lists.sourceforge.net
> To unsubscribe, use the last form field at:
> https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
>
-- /------------------------------------+-------------------------\ |Stephen J. Gowdy | SLAC, MailStop 17, | |http://www.slac.stanford.edu/~gowdy/ | 2575 Sand Hill Road, | | | Menlo Park CA 94025, USA | |EMail: gowdy@slac.stanford.edu | Tel: +1 650 926 3144 | \------------------------------------+-------------------------/- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/