diff options
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r-- | drivers/usb/core/usb.c | 165 |
1 files changed, 105 insertions, 60 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 4c57f3f649ed..0eefff7bcb3c 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -107,10 +107,19 @@ static int usb_probe_interface(struct device *dev) | |||
107 | id = usb_match_id (intf, driver->id_table); | 107 | id = usb_match_id (intf, driver->id_table); |
108 | if (id) { | 108 | if (id) { |
109 | dev_dbg (dev, "%s - got id\n", __FUNCTION__); | 109 | dev_dbg (dev, "%s - got id\n", __FUNCTION__); |
110 | |||
111 | /* Interface "power state" doesn't correspond to any hardware | ||
112 | * state whatsoever. We use it to record when it's bound to | ||
113 | * a driver that may start I/0: it's not frozen/quiesced. | ||
114 | */ | ||
115 | mark_active(intf); | ||
110 | intf->condition = USB_INTERFACE_BINDING; | 116 | intf->condition = USB_INTERFACE_BINDING; |
111 | error = driver->probe (intf, id); | 117 | error = driver->probe (intf, id); |
112 | intf->condition = error ? USB_INTERFACE_UNBOUND : | 118 | if (error) { |
113 | USB_INTERFACE_BOUND; | 119 | mark_quiesced(intf); |
120 | intf->condition = USB_INTERFACE_UNBOUND; | ||
121 | } else | ||
122 | intf->condition = USB_INTERFACE_BOUND; | ||
114 | } | 123 | } |
115 | 124 | ||
116 | return error; | 125 | return error; |
@@ -136,6 +145,7 @@ static int usb_unbind_interface(struct device *dev) | |||
136 | 0); | 145 | 0); |
137 | usb_set_intfdata(intf, NULL); | 146 | usb_set_intfdata(intf, NULL); |
138 | intf->condition = USB_INTERFACE_UNBOUND; | 147 | intf->condition = USB_INTERFACE_UNBOUND; |
148 | mark_quiesced(intf); | ||
139 | 149 | ||
140 | return 0; | 150 | return 0; |
141 | } | 151 | } |
@@ -299,6 +309,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, | |||
299 | dev->driver = &driver->driver; | 309 | dev->driver = &driver->driver; |
300 | usb_set_intfdata(iface, priv); | 310 | usb_set_intfdata(iface, priv); |
301 | iface->condition = USB_INTERFACE_BOUND; | 311 | iface->condition = USB_INTERFACE_BOUND; |
312 | mark_active(iface); | ||
302 | 313 | ||
303 | /* if interface was already added, bind now; else let | 314 | /* if interface was already added, bind now; else let |
304 | * the future device_add() bind it, bypassing probe() | 315 | * the future device_add() bind it, bypassing probe() |
@@ -345,6 +356,7 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
345 | dev->driver = NULL; | 356 | dev->driver = NULL; |
346 | usb_set_intfdata(iface, NULL); | 357 | usb_set_intfdata(iface, NULL); |
347 | iface->condition = USB_INTERFACE_UNBOUND; | 358 | iface->condition = USB_INTERFACE_UNBOUND; |
359 | mark_quiesced(iface); | ||
348 | } | 360 | } |
349 | 361 | ||
350 | /** | 362 | /** |
@@ -557,6 +569,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, | |||
557 | { | 569 | { |
558 | struct usb_interface *intf; | 570 | struct usb_interface *intf; |
559 | struct usb_device *usb_dev; | 571 | struct usb_device *usb_dev; |
572 | struct usb_host_interface *alt; | ||
560 | int i = 0; | 573 | int i = 0; |
561 | int length = 0; | 574 | int length = 0; |
562 | 575 | ||
@@ -573,7 +586,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, | |||
573 | 586 | ||
574 | intf = to_usb_interface(dev); | 587 | intf = to_usb_interface(dev); |
575 | usb_dev = interface_to_usbdev (intf); | 588 | usb_dev = interface_to_usbdev (intf); |
576 | 589 | alt = intf->cur_altsetting; | |
590 | |||
577 | if (usb_dev->devnum < 0) { | 591 | if (usb_dev->devnum < 0) { |
578 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | 592 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); |
579 | return -ENODEV; | 593 | return -ENODEV; |
@@ -615,46 +629,27 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, | |||
615 | usb_dev->descriptor.bDeviceProtocol)) | 629 | usb_dev->descriptor.bDeviceProtocol)) |
616 | return -ENOMEM; | 630 | return -ENOMEM; |
617 | 631 | ||
618 | if (usb_dev->descriptor.bDeviceClass == 0) { | 632 | if (add_hotplug_env_var(envp, num_envp, &i, |
619 | struct usb_host_interface *alt = intf->cur_altsetting; | 633 | buffer, buffer_size, &length, |
634 | "INTERFACE=%d/%d/%d", | ||
635 | alt->desc.bInterfaceClass, | ||
636 | alt->desc.bInterfaceSubClass, | ||
637 | alt->desc.bInterfaceProtocol)) | ||
638 | return -ENOMEM; | ||
620 | 639 | ||
621 | /* 2.4 only exposed interface zero. in 2.5, hotplug | 640 | if (add_hotplug_env_var(envp, num_envp, &i, |
622 | * agents are called for all interfaces, and can use | 641 | buffer, buffer_size, &length, |
623 | * $DEVPATH/bInterfaceNumber if necessary. | 642 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", |
624 | */ | 643 | le16_to_cpu(usb_dev->descriptor.idVendor), |
625 | if (add_hotplug_env_var(envp, num_envp, &i, | 644 | le16_to_cpu(usb_dev->descriptor.idProduct), |
626 | buffer, buffer_size, &length, | 645 | le16_to_cpu(usb_dev->descriptor.bcdDevice), |
627 | "INTERFACE=%d/%d/%d", | 646 | usb_dev->descriptor.bDeviceClass, |
628 | alt->desc.bInterfaceClass, | 647 | usb_dev->descriptor.bDeviceSubClass, |
629 | alt->desc.bInterfaceSubClass, | 648 | usb_dev->descriptor.bDeviceProtocol, |
630 | alt->desc.bInterfaceProtocol)) | 649 | alt->desc.bInterfaceClass, |
631 | return -ENOMEM; | 650 | alt->desc.bInterfaceSubClass, |
632 | 651 | alt->desc.bInterfaceProtocol)) | |
633 | if (add_hotplug_env_var(envp, num_envp, &i, | 652 | return -ENOMEM; |
634 | buffer, buffer_size, &length, | ||
635 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | ||
636 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
637 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
638 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
639 | usb_dev->descriptor.bDeviceClass, | ||
640 | usb_dev->descriptor.bDeviceSubClass, | ||
641 | usb_dev->descriptor.bDeviceProtocol, | ||
642 | alt->desc.bInterfaceClass, | ||
643 | alt->desc.bInterfaceSubClass, | ||
644 | alt->desc.bInterfaceProtocol)) | ||
645 | return -ENOMEM; | ||
646 | } else { | ||
647 | if (add_hotplug_env_var(envp, num_envp, &i, | ||
648 | buffer, buffer_size, &length, | ||
649 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*", | ||
650 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
651 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
652 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
653 | usb_dev->descriptor.bDeviceClass, | ||
654 | usb_dev->descriptor.bDeviceSubClass, | ||
655 | usb_dev->descriptor.bDeviceProtocol)) | ||
656 | return -ENOMEM; | ||
657 | } | ||
658 | 653 | ||
659 | envp[i] = NULL; | 654 | envp[i] = NULL; |
660 | 655 | ||
@@ -709,12 +704,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
709 | { | 704 | { |
710 | struct usb_device *dev; | 705 | struct usb_device *dev; |
711 | 706 | ||
712 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 707 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
713 | if (!dev) | 708 | if (!dev) |
714 | return NULL; | 709 | return NULL; |
715 | 710 | ||
716 | memset(dev, 0, sizeof(*dev)); | ||
717 | |||
718 | bus = usb_bus_get(bus); | 711 | bus = usb_bus_get(bus); |
719 | if (!bus) { | 712 | if (!bus) { |
720 | kfree(dev); | 713 | kfree(dev); |
@@ -1402,13 +1395,30 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, | |||
1402 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 1395 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
1403 | } | 1396 | } |
1404 | 1397 | ||
1398 | static int verify_suspended(struct device *dev, void *unused) | ||
1399 | { | ||
1400 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | ||
1401 | } | ||
1402 | |||
1405 | static int usb_generic_suspend(struct device *dev, pm_message_t message) | 1403 | static int usb_generic_suspend(struct device *dev, pm_message_t message) |
1406 | { | 1404 | { |
1407 | struct usb_interface *intf; | 1405 | struct usb_interface *intf; |
1408 | struct usb_driver *driver; | 1406 | struct usb_driver *driver; |
1407 | int status; | ||
1409 | 1408 | ||
1410 | if (dev->driver == &usb_generic_driver) | 1409 | /* USB devices enter SUSPEND state through their hubs, but can be |
1411 | return usb_suspend_device (to_usb_device(dev), message); | 1410 | * marked for FREEZE as soon as their children are already idled. |
1411 | * But those semantics are useless, so we equate the two (sigh). | ||
1412 | */ | ||
1413 | if (dev->driver == &usb_generic_driver) { | ||
1414 | if (dev->power.power_state.event == message.event) | ||
1415 | return 0; | ||
1416 | /* we need to rule out bogus requests through sysfs */ | ||
1417 | status = device_for_each_child(dev, NULL, verify_suspended); | ||
1418 | if (status) | ||
1419 | return status; | ||
1420 | return usb_suspend_device (to_usb_device(dev)); | ||
1421 | } | ||
1412 | 1422 | ||
1413 | if ((dev->driver == NULL) || | 1423 | if ((dev->driver == NULL) || |
1414 | (dev->driver_data == &usb_generic_driver_data)) | 1424 | (dev->driver_data == &usb_generic_driver_data)) |
@@ -1417,23 +1427,44 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) | |||
1417 | intf = to_usb_interface(dev); | 1427 | intf = to_usb_interface(dev); |
1418 | driver = to_usb_driver(dev->driver); | 1428 | driver = to_usb_driver(dev->driver); |
1419 | 1429 | ||
1420 | /* there's only one USB suspend state */ | 1430 | /* with no hardware, USB interfaces only use FREEZE and ON states */ |
1421 | if (intf->dev.power.power_state.event) | 1431 | if (!is_active(intf)) |
1422 | return 0; | 1432 | return 0; |
1423 | 1433 | ||
1424 | if (driver->suspend) | 1434 | if (driver->suspend && driver->resume) { |
1425 | return driver->suspend(intf, message); | 1435 | status = driver->suspend(intf, message); |
1426 | return 0; | 1436 | if (status) |
1437 | dev_err(dev, "%s error %d\n", "suspend", status); | ||
1438 | else | ||
1439 | mark_quiesced(intf); | ||
1440 | } else { | ||
1441 | // FIXME else if there's no suspend method, disconnect... | ||
1442 | dev_warn(dev, "no %s?\n", "suspend"); | ||
1443 | status = 0; | ||
1444 | } | ||
1445 | return status; | ||
1427 | } | 1446 | } |
1428 | 1447 | ||
1429 | static int usb_generic_resume(struct device *dev) | 1448 | static int usb_generic_resume(struct device *dev) |
1430 | { | 1449 | { |
1431 | struct usb_interface *intf; | 1450 | struct usb_interface *intf; |
1432 | struct usb_driver *driver; | 1451 | struct usb_driver *driver; |
1452 | struct usb_device *udev; | ||
1453 | int status; | ||
1433 | 1454 | ||
1434 | /* devices resume through their hub */ | 1455 | if (dev->power.power_state.event == PM_EVENT_ON) |
1435 | if (dev->driver == &usb_generic_driver) | 1456 | return 0; |
1457 | |||
1458 | /* mark things as "on" immediately, no matter what errors crop up */ | ||
1459 | dev->power.power_state.event = PM_EVENT_ON; | ||
1460 | |||
1461 | /* devices resume through their hubs */ | ||
1462 | if (dev->driver == &usb_generic_driver) { | ||
1463 | udev = to_usb_device(dev); | ||
1464 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1465 | return 0; | ||
1436 | return usb_resume_device (to_usb_device(dev)); | 1466 | return usb_resume_device (to_usb_device(dev)); |
1467 | } | ||
1437 | 1468 | ||
1438 | if ((dev->driver == NULL) || | 1469 | if ((dev->driver == NULL) || |
1439 | (dev->driver_data == &usb_generic_driver_data)) | 1470 | (dev->driver_data == &usb_generic_driver_data)) |
@@ -1442,8 +1473,22 @@ static int usb_generic_resume(struct device *dev) | |||
1442 | intf = to_usb_interface(dev); | 1473 | intf = to_usb_interface(dev); |
1443 | driver = to_usb_driver(dev->driver); | 1474 | driver = to_usb_driver(dev->driver); |
1444 | 1475 | ||
1445 | if (driver->resume) | 1476 | udev = interface_to_usbdev(intf); |
1446 | return driver->resume(intf); | 1477 | if (udev->state == USB_STATE_NOTATTACHED) |
1478 | return 0; | ||
1479 | |||
1480 | /* if driver was suspended, it has a resume method; | ||
1481 | * however, sysfs can wrongly mark things as suspended | ||
1482 | * (on the "no suspend method" FIXME path above) | ||
1483 | */ | ||
1484 | if (driver->resume) { | ||
1485 | status = driver->resume(intf); | ||
1486 | if (status) { | ||
1487 | dev_err(dev, "%s error %d\n", "resume", status); | ||
1488 | mark_quiesced(intf); | ||
1489 | } | ||
1490 | } else | ||
1491 | dev_warn(dev, "no %s?\n", "resume"); | ||
1447 | return 0; | 1492 | return 0; |
1448 | } | 1493 | } |
1449 | 1494 | ||