Revert "usb: move struct usb_device->children to struct usb_hub_port->child"
This reverts commit bebc56d58d
.
The call here is fragile and not well thought out, so revert it, it's
not fully baked yet and I don't want this to go into 3.5.
Cc: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e44694e858
commit
fa286188ce
|
@ -157,7 +157,8 @@ static void usbip_dump_usb_device(struct usb_device *udev)
|
||||||
dev_dbg(dev, "have_langid %d, string_langid %d\n",
|
dev_dbg(dev, "have_langid %d, string_langid %d\n",
|
||||||
udev->have_langid, udev->string_langid);
|
udev->have_langid, udev->string_langid);
|
||||||
|
|
||||||
dev_dbg(dev, "maxchild %d\n", udev->maxchild);
|
dev_dbg(dev, "maxchild %d, children %p\n",
|
||||||
|
udev->maxchild, udev->children);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbip_dump_request_type(__u8 rt)
|
static void usbip_dump_request_type(__u8 rt)
|
||||||
|
|
|
@ -590,8 +590,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
|
||||||
|
|
||||||
/* Now look at all of this device's children. */
|
/* Now look at all of this device's children. */
|
||||||
for (chix = 0; chix < usbdev->maxchild; chix++) {
|
for (chix = 0; chix < usbdev->maxchild; chix++) {
|
||||||
struct usb_device *childdev =
|
struct usb_device *childdev = usbdev->children[chix];
|
||||||
usb_get_hub_child_device(usbdev, chix + 1);
|
|
||||||
|
|
||||||
if (childdev) {
|
if (childdev) {
|
||||||
usb_lock_device(childdev);
|
usb_lock_device(childdev);
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
|
|
||||||
struct usb_hub_port {
|
struct usb_hub_port {
|
||||||
void *port_owner;
|
void *port_owner;
|
||||||
struct usb_device *child;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usb_hub {
|
struct usb_hub {
|
||||||
|
@ -94,7 +93,7 @@ static inline int hub_is_superspeed(struct usb_device *hdev)
|
||||||
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
|
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Protect struct usb_device->state and struct usb_hub_port->child members
|
/* Protect struct usb_device->state and ->children members
|
||||||
* Note: Both are also protected by ->dev.sem, except that ->state can
|
* Note: Both are also protected by ->dev.sem, except that ->state can
|
||||||
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
|
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
|
||||||
static DEFINE_SPINLOCK(device_state_lock);
|
static DEFINE_SPINLOCK(device_state_lock);
|
||||||
|
@ -177,7 +176,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus)
|
||||||
/* Note that hdev or one of its children must be locked! */
|
/* Note that hdev or one of its children must be locked! */
|
||||||
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
|
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
|
||||||
{
|
{
|
||||||
if (!hdev || !hdev->actconfig || !hdev->maxchild)
|
if (!hdev || !hdev->actconfig)
|
||||||
return NULL;
|
return NULL;
|
||||||
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
||||||
}
|
}
|
||||||
|
@ -650,8 +649,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
|
||||||
struct usb_device *hdev = hub->hdev;
|
struct usb_device *hdev = hub->hdev;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (hub->port_data[port1-1].child && set_state)
|
if (hdev->children[port1-1] && set_state)
|
||||||
usb_set_device_state(hub->port_data[port1-1].child,
|
usb_set_device_state(hdev->children[port1-1],
|
||||||
USB_STATE_NOTATTACHED);
|
USB_STATE_NOTATTACHED);
|
||||||
if (!hub->error && !hub_is_superspeed(hub->hdev))
|
if (!hub->error && !hub_is_superspeed(hub->hdev))
|
||||||
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
|
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
|
||||||
|
@ -807,7 +806,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||||
* which ports need attention.
|
* which ports need attention.
|
||||||
*/
|
*/
|
||||||
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
||||||
struct usb_device *udev = hub->port_data[port1-1].child;
|
struct usb_device *udev = hdev->children[port1-1];
|
||||||
u16 portstatus, portchange;
|
u16 portstatus, portchange;
|
||||||
|
|
||||||
portstatus = portchange = 0;
|
portstatus = portchange = 0;
|
||||||
|
@ -972,8 +971,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
|
||||||
if (type != HUB_SUSPEND) {
|
if (type != HUB_SUSPEND) {
|
||||||
/* Disconnect all the children */
|
/* Disconnect all the children */
|
||||||
for (i = 0; i < hdev->maxchild; ++i) {
|
for (i = 0; i < hdev->maxchild; ++i) {
|
||||||
if (hub->port_data[i].child)
|
if (hdev->children[i])
|
||||||
usb_disconnect(&hub->port_data[i].child);
|
usb_disconnect(&hdev->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,9 +1051,11 @@ static int hub_configure(struct usb_hub *hub,
|
||||||
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
|
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
|
||||||
(hdev->maxchild == 1) ? "" : "s");
|
(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),
|
hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!hub->port_data) {
|
if (!hub->port_data || !hdev->children) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -1286,6 +1287,7 @@ static unsigned highspeed_hubs;
|
||||||
static void hub_disconnect(struct usb_interface *intf)
|
static void hub_disconnect(struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
struct usb_hub *hub = usb_get_intfdata(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 */
|
/* Take the hub off the event list and don't let it be added again */
|
||||||
spin_lock_irq(&hub_event_lock);
|
spin_lock_irq(&hub_event_lock);
|
||||||
|
@ -1307,6 +1309,7 @@ static void hub_disconnect(struct usb_interface *intf)
|
||||||
highspeed_hubs--;
|
highspeed_hubs--;
|
||||||
|
|
||||||
usb_free_urb(hub->urb);
|
usb_free_urb(hub->urb);
|
||||||
|
kfree(hdev->children);
|
||||||
kfree(hub->port_data);
|
kfree(hub->port_data);
|
||||||
kfree(hub->descriptor);
|
kfree(hub->descriptor);
|
||||||
kfree(hub->status);
|
kfree(hub->status);
|
||||||
|
@ -1394,7 +1397,6 @@ static int
|
||||||
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
||||||
{
|
{
|
||||||
struct usb_device *hdev = interface_to_usbdev (intf);
|
struct usb_device *hdev = interface_to_usbdev (intf);
|
||||||
struct usb_hub *hub = usb_get_intfdata(intf);
|
|
||||||
|
|
||||||
/* assert ifno == 0 (part of hub spec) */
|
/* assert ifno == 0 (part of hub spec) */
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
@ -1408,11 +1410,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
||||||
else {
|
else {
|
||||||
info->nports = hdev->maxchild;
|
info->nports = hdev->maxchild;
|
||||||
for (i = 0; i < info->nports; i++) {
|
for (i = 0; i < info->nports; i++) {
|
||||||
if (hub->port_data[i].child == NULL)
|
if (hdev->children[i] == NULL)
|
||||||
info->port[i] = 0;
|
info->port[i] = 0;
|
||||||
else
|
else
|
||||||
info->port[i] =
|
info->port[i] =
|
||||||
hub->port_data[i].child->devnum;
|
hdev->children[i]->devnum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&device_state_lock);
|
spin_unlock_irq(&device_state_lock);
|
||||||
|
@ -1499,13 +1501,11 @@ bool usb_device_is_owned(struct usb_device *udev)
|
||||||
|
|
||||||
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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < udev->maxchild; ++i) {
|
for (i = 0; i < udev->maxchild; ++i) {
|
||||||
if (hub->port_data[i].child)
|
if (udev->children[i])
|
||||||
recursively_mark_NOTATTACHED(
|
recursively_mark_NOTATTACHED(udev->children[i]);
|
||||||
hub->port_data[i].child);
|
|
||||||
}
|
}
|
||||||
if (udev->state == USB_STATE_SUSPENDED)
|
if (udev->state == USB_STATE_SUSPENDED)
|
||||||
udev->active_duration -= jiffies;
|
udev->active_duration -= jiffies;
|
||||||
|
@ -1669,7 +1669,6 @@ static void hub_free_dev(struct usb_device *udev)
|
||||||
void usb_disconnect(struct usb_device **pdev)
|
void usb_disconnect(struct usb_device **pdev)
|
||||||
{
|
{
|
||||||
struct usb_device *udev = *pdev;
|
struct usb_device *udev = *pdev;
|
||||||
struct usb_hub *hub = hdev_to_hub(udev);
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* mark the device as inactive, so any further urb submissions for
|
/* mark the device as inactive, so any further urb submissions for
|
||||||
|
@ -1684,8 +1683,8 @@ void usb_disconnect(struct usb_device **pdev)
|
||||||
|
|
||||||
/* Free up all the children before we remove this device */
|
/* Free up all the children before we remove this device */
|
||||||
for (i = 0; i < udev->maxchild; i++) {
|
for (i = 0; i < udev->maxchild; i++) {
|
||||||
if (hub->port_data[i].child)
|
if (udev->children[i])
|
||||||
usb_disconnect(&hub->port_data[i].child);
|
usb_disconnect(&udev->children[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deallocate hcd/hardware state ... nuking all pending urbs and
|
/* deallocate hcd/hardware state ... nuking all pending urbs and
|
||||||
|
@ -2766,7 +2765,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
|
||||||
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
|
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
|
|
||||||
udev = hub->port_data[port1-1].child;
|
udev = hdev->children [port1-1];
|
||||||
if (udev && udev->can_submit) {
|
if (udev && udev->can_submit) {
|
||||||
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
|
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
|
||||||
if (PMSG_IS_AUTO(msg))
|
if (PMSG_IS_AUTO(msg))
|
||||||
|
@ -3267,7 +3266,7 @@ hub_power_remaining (struct usb_hub *hub)
|
||||||
|
|
||||||
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
|
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
|
||||||
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
||||||
struct usb_device *udev = hub->port_data[port1 - 1].child;
|
struct usb_device *udev = hdev->children[port1 - 1];
|
||||||
int delta;
|
int delta;
|
||||||
|
|
||||||
if (!udev)
|
if (!udev)
|
||||||
|
@ -3331,7 +3330,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Try to resuscitate an existing device */
|
/* Try to resuscitate an existing device */
|
||||||
udev = hub->port_data[port1-1].child;
|
udev = hdev->children[port1-1];
|
||||||
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
|
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
|
||||||
udev->state != USB_STATE_NOTATTACHED) {
|
udev->state != USB_STATE_NOTATTACHED) {
|
||||||
usb_lock_device(udev);
|
usb_lock_device(udev);
|
||||||
|
@ -3360,7 +3359,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||||
|
|
||||||
/* Disconnect any existing devices under this port */
|
/* Disconnect any existing devices under this port */
|
||||||
if (udev)
|
if (udev)
|
||||||
usb_disconnect(&hub->port_data[port1-1].child);
|
usb_disconnect(&hdev->children[port1-1]);
|
||||||
clear_bit(port1, hub->change_bits);
|
clear_bit(port1, hub->change_bits);
|
||||||
|
|
||||||
/* We can forget about a "removed" device when there's a physical
|
/* We can forget about a "removed" device when there's a physical
|
||||||
|
@ -3475,7 +3474,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||||
&& highspeed_hubs != 0)
|
&& highspeed_hubs != 0)
|
||||||
check_highspeed (hub, udev, port1);
|
check_highspeed (hub, udev, port1);
|
||||||
|
|
||||||
/* Store the hub port's child pointer. At this point
|
/* Store the parent's children[] pointer. At this point
|
||||||
* udev becomes globally accessible, although presumably
|
* udev becomes globally accessible, although presumably
|
||||||
* no one will look at it until hdev is unlocked.
|
* no one will look at it until hdev is unlocked.
|
||||||
*/
|
*/
|
||||||
|
@ -3489,7 +3488,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||||
if (hdev->state == USB_STATE_NOTATTACHED)
|
if (hdev->state == USB_STATE_NOTATTACHED)
|
||||||
status = -ENOTCONN;
|
status = -ENOTCONN;
|
||||||
else
|
else
|
||||||
hub->port_data[port1-1].child = udev;
|
hdev->children[port1-1] = udev;
|
||||||
spin_unlock_irq(&device_state_lock);
|
spin_unlock_irq(&device_state_lock);
|
||||||
|
|
||||||
/* Run it through the hoops (find a driver, etc) */
|
/* Run it through the hoops (find a driver, etc) */
|
||||||
|
@ -3497,7 +3496,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||||
status = usb_new_device(udev);
|
status = usb_new_device(udev);
|
||||||
if (status) {
|
if (status) {
|
||||||
spin_lock_irq(&device_state_lock);
|
spin_lock_irq(&device_state_lock);
|
||||||
hub->port_data[port1-1].child = NULL;
|
hdev->children[port1-1] = NULL;
|
||||||
spin_unlock_irq(&device_state_lock);
|
spin_unlock_irq(&device_state_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3543,7 +3542,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
hdev = hub->hdev;
|
hdev = hub->hdev;
|
||||||
udev = hub->port_data[port - 1].child;
|
udev = hdev->children[port-1];
|
||||||
if (!hub_is_superspeed(hdev)) {
|
if (!hub_is_superspeed(hdev)) {
|
||||||
if (!(portchange & USB_PORT_STAT_C_SUSPEND))
|
if (!(portchange & USB_PORT_STAT_C_SUSPEND))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3697,7 +3696,7 @@ static void hub_events(void)
|
||||||
*/
|
*/
|
||||||
if (!(portstatus & USB_PORT_STAT_ENABLE)
|
if (!(portstatus & USB_PORT_STAT_ENABLE)
|
||||||
&& !connect_change
|
&& !connect_change
|
||||||
&& hub->port_data[i-1].child) {
|
&& hdev->children[i-1]) {
|
||||||
dev_err (hub_dev,
|
dev_err (hub_dev,
|
||||||
"port %i "
|
"port %i "
|
||||||
"disabled by hub (EMI?), "
|
"disabled by hub (EMI?), "
|
||||||
|
@ -4235,15 +4234,3 @@ void usb_queue_reset_device(struct usb_interface *iface)
|
||||||
schedule_work(&iface->reset_ws);
|
schedule_work(&iface->reset_ws);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
|
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);
|
|
||||||
|
|
||||||
|
|
|
@ -2040,8 +2040,7 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
|
||||||
map[udev->devnum/32] |= (1 << (udev->devnum % 32));
|
map[udev->devnum/32] |= (1 << (udev->devnum % 32));
|
||||||
|
|
||||||
for (chix = 0; chix < udev->maxchild; chix++) {
|
for (chix = 0; chix < udev->maxchild; chix++) {
|
||||||
struct usb_device *childdev =
|
struct usb_device *childdev = udev->children[chix];
|
||||||
usb_get_hub_child_device(udev, chix + 1);
|
|
||||||
|
|
||||||
if (childdev)
|
if (childdev)
|
||||||
collect_usb_address_map(childdev, map);
|
collect_usb_address_map(childdev, map);
|
||||||
|
|
|
@ -424,6 +424,7 @@ enum usb_device_removable {
|
||||||
* access from userspace
|
* access from userspace
|
||||||
* @usbfs_dentry: usbfs dentry entry for the device
|
* @usbfs_dentry: usbfs dentry entry for the device
|
||||||
* @maxchild: number of ports if hub
|
* @maxchild: number of ports if hub
|
||||||
|
* @children: child devices - USB devices that are attached to this hub
|
||||||
* @quirks: quirks of the whole device
|
* @quirks: quirks of the whole device
|
||||||
* @urbnum: number of URBs submitted for the whole device
|
* @urbnum: number of URBs submitted for the whole device
|
||||||
* @active_duration: total time device is not suspended
|
* @active_duration: total time device is not suspended
|
||||||
|
@ -490,6 +491,7 @@ struct usb_device {
|
||||||
struct list_head filelist;
|
struct list_head filelist;
|
||||||
|
|
||||||
int maxchild;
|
int maxchild;
|
||||||
|
struct usb_device **children;
|
||||||
|
|
||||||
u32 quirks;
|
u32 quirks;
|
||||||
atomic_t urbnum;
|
atomic_t urbnum;
|
||||||
|
@ -515,8 +517,6 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)
|
||||||
|
|
||||||
extern struct usb_device *usb_get_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 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 */
|
/* USB device locking */
|
||||||
#define usb_lock_device(udev) device_lock(&(udev)->dev)
|
#define usb_lock_device(udev) device_lock(&(udev)->dev)
|
||||||
|
|
Loading…
Reference in New Issue