Move child's pointer to the struct usb_hub_port since the child device
is directly associated with the port. Provide usb_get_hub_child_device()
to get child's pointer.
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
dev_dbg(dev, "have_langid %d, string_langid %d\n",
udev->have_langid, udev->string_langid);
dev_dbg(dev, "have_langid %d, string_langid %d\n",
udev->have_langid, udev->string_langid);
- dev_dbg(dev, "maxchild %d, children %p\n",
- udev->maxchild, udev->children);
+ dev_dbg(dev, "maxchild %d\n", udev->maxchild);
}
static void usbip_dump_request_type(__u8 rt)
}
static void usbip_dump_request_type(__u8 rt)
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
- struct usb_device *childdev = usbdev->children[chix];
+ struct usb_device *childdev =
+ usb_get_hub_child_device(usbdev, chix + 1);
if (childdev) {
usb_lock_device(childdev);
if (childdev) {
usb_lock_device(childdev);
struct usb_hub_port {
void *port_owner;
struct usb_hub_port {
void *port_owner;
+ struct usb_device *child;
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
}
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
}
-/* Protect struct usb_device->state and ->children members
+/* Protect struct usb_device->state and struct usb_hub_port->child members
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
static DEFINE_SPINLOCK(device_state_lock);
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
static DEFINE_SPINLOCK(device_state_lock);
/* Note that hdev or one of its children must be locked! */
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
{
/* Note that hdev or one of its children must be locked! */
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
{
- if (!hdev || !hdev->actconfig)
+ if (!hdev || !hdev->actconfig || !hdev->maxchild)
return NULL;
return usb_get_intfdata(hdev->actconfig->interface[0]);
}
return NULL;
return usb_get_intfdata(hdev->actconfig->interface[0]);
}
struct usb_device *hdev = hub->hdev;
int ret = 0;
struct usb_device *hdev = hub->hdev;
int ret = 0;
- if (hdev->children[port1-1] && set_state)
- usb_set_device_state(hdev->children[port1-1],
+ if (hub->port_data[port1-1].child && set_state)
+ usb_set_device_state(hub->port_data[port1-1].child,
USB_STATE_NOTATTACHED);
if (!hub->error && !hub_is_superspeed(hub->hdev))
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
USB_STATE_NOTATTACHED);
if (!hub->error && !hub_is_superspeed(hub->hdev))
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
* which ports need attention.
*/
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
* which ports need attention.
*/
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- struct usb_device *udev = hdev->children[port1-1];
+ struct usb_device *udev = hub->port_data[port1-1].child;
u16 portstatus, portchange;
portstatus = portchange = 0;
u16 portstatus, portchange;
portstatus = portchange = 0;
if (type != HUB_SUSPEND) {
/* Disconnect all the children */
for (i = 0; i < hdev->maxchild; ++i) {
if (type != HUB_SUSPEND) {
/* Disconnect all the children */
for (i = 0; i < hdev->maxchild; ++i) {
- if (hdev->children[i])
- usb_disconnect(&hdev->children[i]);
+ if (hub->port_data[i].child)
+ usb_disconnect(&hub->port_data[i].child);
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
(hdev->maxchild == 1) ? "" : "s");
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
(hdev->maxchild == 1) ? "" : "s");
- hdev->children = kzalloc(hdev->maxchild *
- sizeof(struct usb_device *), GFP_KERNEL);
hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port),
GFP_KERNEL);
hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port),
GFP_KERNEL);
- if (!hub->port_data || !hdev->children) {
ret = -ENOMEM;
goto fail;
}
ret = -ENOMEM;
goto fail;
}
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
- struct usb_device *hdev = interface_to_usbdev(intf);
/* Take the hub off the event list and don't let it be added again */
spin_lock_irq(&hub_event_lock);
/* Take the hub off the event list and don't let it be added again */
spin_lock_irq(&hub_event_lock);
highspeed_hubs--;
usb_free_urb(hub->urb);
highspeed_hubs--;
usb_free_urb(hub->urb);
kfree(hub->port_data);
kfree(hub->descriptor);
kfree(hub->status);
kfree(hub->port_data);
kfree(hub->descriptor);
kfree(hub->status);
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
struct usb_device *hdev = interface_to_usbdev (intf);
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
struct usb_device *hdev = interface_to_usbdev (intf);
+ struct usb_hub *hub = usb_get_intfdata(intf);
/* assert ifno == 0 (part of hub spec) */
switch (code) {
/* assert ifno == 0 (part of hub spec) */
switch (code) {
else {
info->nports = hdev->maxchild;
for (i = 0; i < info->nports; i++) {
else {
info->nports = hdev->maxchild;
for (i = 0; i < info->nports; i++) {
- if (hdev->children[i] == NULL)
+ if (hub->port_data[i].child == NULL)
info->port[i] = 0;
else
info->port[i] =
info->port[i] = 0;
else
info->port[i] =
- hdev->children[i]->devnum;
+ hub->port_data[i].child->devnum;
}
}
spin_unlock_irq(&device_state_lock);
}
}
spin_unlock_irq(&device_state_lock);
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
+ struct usb_hub *hub = hdev_to_hub(udev);
int i;
for (i = 0; i < udev->maxchild; ++i) {
int i;
for (i = 0; i < udev->maxchild; ++i) {
- if (udev->children[i])
- recursively_mark_NOTATTACHED(udev->children[i]);
+ if (hub->port_data[i].child)
+ recursively_mark_NOTATTACHED(
+ hub->port_data[i].child);
}
if (udev->state == USB_STATE_SUSPENDED)
udev->active_duration -= jiffies;
}
if (udev->state == USB_STATE_SUSPENDED)
udev->active_duration -= jiffies;
void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *udev = *pdev;
void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *udev = *pdev;
+ struct usb_hub *hub = hdev_to_hub(udev);
int i;
/* mark the device as inactive, so any further urb submissions for
int i;
/* mark the device as inactive, so any further urb submissions for
/* Free up all the children before we remove this device */
for (i = 0; i < udev->maxchild; i++) {
/* Free up all the children before we remove this device */
for (i = 0; i < udev->maxchild; i++) {
- if (udev->children[i])
- usb_disconnect(&udev->children[i]);
+ if (hub->port_data[i].child)
+ usb_disconnect(&hub->port_data[i].child);
}
/* deallocate hcd/hardware state ... nuking all pending urbs and
}
/* deallocate hcd/hardware state ... nuking all pending urbs and
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
- udev = hdev->children [port1-1];
+ udev = hub->port_data[port1-1].child;
if (udev && udev->can_submit) {
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
if (PMSG_IS_AUTO(msg))
if (udev && udev->can_submit) {
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
if (PMSG_IS_AUTO(msg))
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- struct usb_device *udev = hdev->children[port1 - 1];
+ struct usb_device *udev = hub->port_data[port1 - 1].child;
#endif
/* Try to resuscitate an existing device */
#endif
/* Try to resuscitate an existing device */
- udev = hdev->children[port1-1];
+ udev = hub->port_data[port1-1].child;
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) {
usb_lock_device(udev);
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) {
usb_lock_device(udev);
/* Disconnect any existing devices under this port */
if (udev)
/* Disconnect any existing devices under this port */
if (udev)
- usb_disconnect(&hdev->children[port1-1]);
+ usb_disconnect(&hub->port_data[port1-1].child);
clear_bit(port1, hub->change_bits);
/* We can forget about a "removed" device when there's a physical
clear_bit(port1, hub->change_bits);
/* We can forget about a "removed" device when there's a physical
&& highspeed_hubs != 0)
check_highspeed (hub, udev, port1);
&& highspeed_hubs != 0)
check_highspeed (hub, udev, port1);
- /* Store the parent's children[] pointer. At this point
+ /* Store the hub port's child pointer. At this point
* udev becomes globally accessible, although presumably
* no one will look at it until hdev is unlocked.
*/
* udev becomes globally accessible, although presumably
* no one will look at it until hdev is unlocked.
*/
if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN;
else
if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN;
else
- hdev->children[port1-1] = udev;
+ hub->port_data[port1-1].child = udev;
spin_unlock_irq(&device_state_lock);
/* Run it through the hoops (find a driver, etc) */
spin_unlock_irq(&device_state_lock);
/* Run it through the hoops (find a driver, etc) */
status = usb_new_device(udev);
if (status) {
spin_lock_irq(&device_state_lock);
status = usb_new_device(udev);
if (status) {
spin_lock_irq(&device_state_lock);
- hdev->children[port1-1] = NULL;
+ hub->port_data[port1-1].child = NULL;
spin_unlock_irq(&device_state_lock);
}
}
spin_unlock_irq(&device_state_lock);
}
}
int ret;
hdev = hub->hdev;
int ret;
hdev = hub->hdev;
- udev = hdev->children[port-1];
+ udev = hub->port_data[port - 1].child;
if (!hub_is_superspeed(hdev)) {
if (!(portchange & USB_PORT_STAT_C_SUSPEND))
return 0;
if (!hub_is_superspeed(hdev)) {
if (!(portchange & USB_PORT_STAT_C_SUSPEND))
return 0;
*/
if (!(portstatus & USB_PORT_STAT_ENABLE)
&& !connect_change
*/
if (!(portstatus & USB_PORT_STAT_ENABLE)
&& !connect_change
- && hdev->children[i-1]) {
+ && hub->port_data[i-1].child) {
dev_err (hub_dev,
"port %i "
"disabled by hub (EMI?), "
dev_err (hub_dev,
"port %i "
"disabled by hub (EMI?), "
schedule_work(&iface->reset_ws);
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
schedule_work(&iface->reset_ws);
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
+
+struct usb_device *usb_get_hub_child_device(struct usb_device *hdev,
+ int port1)
+{
+ struct usb_hub *hub = hdev_to_hub(hdev);
+
+ if (!hub || port1 > hdev->maxchild || port1 < 1)
+ return NULL;
+ return hub->port_data[port1 - 1].child;
+}
+EXPORT_SYMBOL_GPL(usb_get_hub_child_device);
+
map[udev->devnum/32] |= (1 << (udev->devnum % 32));
for (chix = 0; chix < udev->maxchild; chix++) {
map[udev->devnum/32] |= (1 << (udev->devnum % 32));
for (chix = 0; chix < udev->maxchild; chix++) {
- struct usb_device *childdev = udev->children[chix];
+ struct usb_device *childdev =
+ usb_get_hub_child_device(udev, chix + 1);
if (childdev)
collect_usb_address_map(childdev, map);
if (childdev)
collect_usb_address_map(childdev, map);
* access from userspace
* @usbfs_dentry: usbfs dentry entry for the device
* @maxchild: number of ports if hub
* access from userspace
* @usbfs_dentry: usbfs dentry entry for the device
* @maxchild: number of ports if hub
- * @children: child devices - USB devices that are attached to this hub
* @quirks: quirks of the whole device
* @urbnum: number of URBs submitted for the whole device
* @active_duration: total time device is not suspended
* @quirks: quirks of the whole device
* @urbnum: number of URBs submitted for the whole device
* @active_duration: total time device is not suspended
struct list_head filelist;
int maxchild;
struct list_head filelist;
int maxchild;
- struct usb_device **children;
u32 quirks;
atomic_t urbnum;
u32 quirks;
atomic_t urbnum;
extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
+extern struct usb_device *usb_get_hub_child_device(struct usb_device *hdev,
+ int port1);
/* USB device locking */
#define usb_lock_device(udev) device_lock(&(udev)->dev)
/* USB device locking */
#define usb_lock_device(udev) device_lock(&(udev)->dev)