Hi Greg, Looks like no one has objected to these patches in a couple days. Do you want to queue these up, or should I send you a pull request? Sarah Sharp On Sun, Jul 08, 2012 at 10:23:00PM +0800, Lan Tianyu wrote: > Change since v7: update Documentation/ABI and fix dev_err() show pattern > > Change since v4: remove struct usb_port->udev member since it is not used. > > This patch is to make usb port a real device under usb hub interface. > Move port_owner to struct usb_port. > > Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> > Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> > --- > Documentation/ABI/testing/sysfs-bus-usb | 7 +++ > drivers/usb/core/hub.c | 91 +++++++++++++++++++++++++------ > 2 files changed, 82 insertions(+), 16 deletions(-) > > diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb > index 6df4e6f..d5bb5be 100644 > --- a/Documentation/ABI/testing/sysfs-bus-usb > +++ b/Documentation/ABI/testing/sysfs-bus-usb > @@ -208,3 +208,10 @@ Description: > such as ACPI. This file will read either "removable" or > "fixed" if the information is available, and "unknown" > otherwise. > + > +What: /sys/bus/usb/devices/.../(hub interface)/portX > +Date: July 2012 > +Contact: Lan Tianyu <tianyu.lan@xxxxxxxxx> > +Description: > + The /sys/bus/usb/devices/.../(hub interface)/portX > + is usb port device's sysfs directory. > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index 4cc8dc9..a59e509 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -37,6 +37,11 @@ > #endif > #endif > > +struct usb_port { > + struct device dev; > + struct dev_state *port_owner; > +}; > + > struct usb_hub { > struct device *intfdev; /* the "interface" device */ > struct usb_device *hdev; > @@ -81,7 +86,11 @@ struct usb_hub { > u8 indicator[USB_MAXCHILDREN]; > struct delayed_work leds; > struct delayed_work init_work; > - struct dev_state **port_owners; > + struct usb_port **ports; > +}; > + > +struct device_type usb_port_device_type = { > + .name = "usb_port", > }; > > static inline int hub_is_superspeed(struct usb_device *hdev) > @@ -154,6 +163,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); > #define HUB_DEBOUNCE_STEP 25 > #define HUB_DEBOUNCE_STABLE 100 > > +#define to_usb_port(_dev) \ > + container_of(_dev, struct usb_port, dev) > > static int usb_reset_and_verify_device(struct usb_device *udev); > > @@ -1220,6 +1231,48 @@ static int hub_post_reset(struct usb_interface *intf) > return 0; > } > > +static void usb_port_device_release(struct device *dev) > +{ > + struct usb_port *port_dev = to_usb_port(dev); > + > + kfree(port_dev); > +} > + > +static void usb_hub_remove_port_device(struct usb_hub *hub, > + int port1) > +{ > + device_unregister(&hub->ports[port1 - 1]->dev); > +} > + > +static int usb_hub_create_port_device(struct usb_hub *hub, > + int port1) > +{ > + struct usb_port *port_dev = NULL; > + int retval; > + > + port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); > + if (!port_dev) { > + retval = -ENOMEM; > + goto exit; > + } > + > + hub->ports[port1 - 1] = port_dev; > + port_dev->dev.parent = hub->intfdev; > + port_dev->dev.type = &usb_port_device_type; > + port_dev->dev.release = usb_port_device_release; > + dev_set_name(&port_dev->dev, "port%d", port1); > + > + retval = device_register(&port_dev->dev); > + if (retval) > + goto error_register; > + return 0; > + > +error_register: > + put_device(&port_dev->dev); > +exit: > + return retval; > +} > + > static int hub_configure(struct usb_hub *hub, > struct usb_endpoint_descriptor *endpoint) > { > @@ -1229,7 +1282,7 @@ static int hub_configure(struct usb_hub *hub, > u16 hubstatus, hubchange; > u16 wHubCharacteristics; > unsigned int pipe; > - int maxp, ret; > + int maxp, ret, i; > char *message = "out of memory"; > > hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); > @@ -1271,9 +1324,9 @@ static int hub_configure(struct usb_hub *hub, > > hdev->children = kzalloc(hdev->maxchild * > sizeof(struct usb_device *), GFP_KERNEL); > - hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), > - GFP_KERNEL); > - if (!hdev->children || !hub->port_owners) { > + hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), > + GFP_KERNEL); > + if (!hdev->children || !hub->ports) { > ret = -ENOMEM; > goto fail; > } > @@ -1482,6 +1535,11 @@ static int hub_configure(struct usb_hub *hub, > if (hub->has_indicators && blinkenlights) > hub->indicator [0] = INDICATOR_CYCLE; > > + for (i = 0; i < hdev->maxchild; i++) > + if (usb_hub_create_port_device(hub, i + 1) < 0) > + dev_err(hub->intfdev, > + "couldn't create port%d device.\n", i + 1); > + > hub_activate(hub, HUB_INIT); > return 0; > > @@ -1506,6 +1564,10 @@ static void hub_disconnect(struct usb_interface *intf) > { > struct usb_hub *hub = usb_get_intfdata(intf); > struct usb_device *hdev = interface_to_usbdev(intf); > + int i; > + > + for (i = 0; i < hdev->maxchild; i++) > + usb_hub_remove_port_device(hub, i + 1); > > /* Take the hub off the event list and don't let it be added again */ > spin_lock_irq(&hub_event_lock); > @@ -1528,7 +1590,7 @@ static void hub_disconnect(struct usb_interface *intf) > > usb_free_urb(hub->urb); > kfree(hdev->children); > - kfree(hub->port_owners); > + kfree(hub->ports); > kfree(hub->descriptor); > kfree(hub->status); > kfree(hub->buffer); > @@ -1660,7 +1722,7 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, > /* This assumes that devices not managed by the hub driver > * will always have maxchild equal to 0. > */ > - *ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]); > + *ppowner = &(hdev_to_hub(hdev)->ports[port1 - 1]->port_owner); > return 0; > } > > @@ -1697,16 +1759,14 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, > > void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) > { > + struct usb_hub *hub = hdev_to_hub(hdev); > int n; > - struct dev_state **powner; > > - n = find_port_owner(hdev, 1, &powner); > - if (n == 0) { > - for (; n < hdev->maxchild; (++n, ++powner)) { > - if (*powner == owner) > - *powner = NULL; > - } > + for (n = 0; n < hdev->maxchild; n++) { > + if (hub->ports[n]->port_owner == owner) > + hub->ports[n]->port_owner = NULL; > } > + > } > > /* The caller must hold udev's lock */ > @@ -1717,10 +1777,9 @@ bool usb_device_is_owned(struct usb_device *udev) > if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) > return false; > hub = hdev_to_hub(udev->parent); > - return !!hub->port_owners[udev->portnum - 1]; > + return !!hub->ports[udev->portnum - 1]->port_owner; > } > > - > static void recursively_mark_NOTATTACHED(struct usb_device *udev) > { > int i; > -- > 1.7.6.rc2.8.g28eb > -- 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