aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hub.c33
-rw-r--r--drivers/usb/core/message.c1
-rw-r--r--drivers/usb/core/usb.c65
-rw-r--r--drivers/usb/core/usb.h18
-rw-r--r--drivers/usb/input/hid-core.c2
-rw-r--r--drivers/usb/misc/usbtest.c10
-rw-r--r--drivers/usb/net/pegasus.c2
-rw-r--r--drivers/usb/net/usbnet.c2
8 files changed, 85 insertions, 48 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c3e2024c4347..61341d2f3c0e 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1624,7 +1624,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
1624 struct usb_driver *driver; 1624 struct usb_driver *driver;
1625 1625
1626 intf = udev->actconfig->interface[i]; 1626 intf = udev->actconfig->interface[i];
1627 if (state.event <= intf->dev.power.power_state.event) 1627 if (!is_active(intf))
1628 continue; 1628 continue;
1629 if (!intf->dev.driver) 1629 if (!intf->dev.driver)
1630 continue; 1630 continue;
@@ -1632,11 +1632,12 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
1632 1632
1633 if (driver->suspend) { 1633 if (driver->suspend) {
1634 status = driver->suspend(intf, state); 1634 status = driver->suspend(intf, state);
1635 if (intf->dev.power.power_state.event != state.event 1635 if (status == 0)
1636 || status) 1636 mark_quiesced(intf);
1637 else
1637 dev_err(&intf->dev, 1638 dev_err(&intf->dev,
1638 "suspend %d fail, code %d\n", 1639 "suspend error %d\n",
1639 state.event, status); 1640 status);
1640 } 1641 }
1641 1642
1642 /* only drivers with suspend() can ever resume(); 1643 /* only drivers with suspend() can ever resume();
@@ -1787,7 +1788,7 @@ static int finish_port_resume(struct usb_device *udev)
1787 struct usb_driver *driver; 1788 struct usb_driver *driver;
1788 1789
1789 intf = udev->actconfig->interface[i]; 1790 intf = udev->actconfig->interface[i];
1790 if (intf->dev.power.power_state.event == PM_EVENT_ON) 1791 if (is_active(intf))
1791 continue; 1792 continue;
1792 if (!intf->dev.driver) { 1793 if (!intf->dev.driver) {
1793 /* FIXME maybe force to alt 0 */ 1794 /* FIXME maybe force to alt 0 */
@@ -1800,12 +1801,14 @@ static int finish_port_resume(struct usb_device *udev)
1800 continue; 1801 continue;
1801 1802
1802 /* can we do better than just logging errors? */ 1803 /* can we do better than just logging errors? */
1804 mark_active(intf);
1803 status = driver->resume(intf); 1805 status = driver->resume(intf);
1804 if (intf->dev.power.power_state.event != PM_EVENT_ON 1806 if (status < 0) {
1805 || status) 1807 mark_quiesced(intf);
1806 dev_dbg(&intf->dev, 1808 dev_dbg(&intf->dev,
1807 "resume fail, state %d code %d\n", 1809 "resume error %d\n",
1808 intf->dev.power.power_state.event, status); 1810 status);
1811 }
1809 } 1812 }
1810 status = 0; 1813 status = 0;
1811 1814
@@ -1952,7 +1955,7 @@ static int remote_wakeup(struct usb_device *udev)
1952 return status; 1955 return status;
1953} 1956}
1954 1957
1955static int hub_suspend(struct usb_interface *intf, pm_message_t state) 1958static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
1956{ 1959{
1957 struct usb_hub *hub = usb_get_intfdata (intf); 1960 struct usb_hub *hub = usb_get_intfdata (intf);
1958 struct usb_device *hdev = hub->hdev; 1961 struct usb_device *hdev = hub->hdev;
@@ -1970,14 +1973,13 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t state)
1970 if (!udev) 1973 if (!udev)
1971 continue; 1974 continue;
1972 down(&udev->serialize); 1975 down(&udev->serialize);
1973 status = __usb_suspend_device(udev, port1, state); 1976 status = __usb_suspend_device(udev, port1, msg);
1974 up(&udev->serialize); 1977 up(&udev->serialize);
1975 if (status < 0) 1978 if (status < 0)
1976 dev_dbg(&intf->dev, "suspend port %d --> %d\n", 1979 dev_dbg(&intf->dev, "suspend port %d --> %d\n",
1977 port1, status); 1980 port1, status);
1978 } 1981 }
1979 1982
1980 intf->dev.power.power_state = state;
1981 return 0; 1983 return 0;
1982} 1984}
1983 1985
@@ -1988,9 +1990,6 @@ static int hub_resume(struct usb_interface *intf)
1988 unsigned port1; 1990 unsigned port1;
1989 int status; 1991 int status;
1990 1992
1991 if (intf->dev.power.power_state.event == PM_EVENT_ON)
1992 return 0;
1993
1994 for (port1 = 1; port1 <= hdev->maxchild; port1++) { 1993 for (port1 = 1; port1 <= hdev->maxchild; port1++) {
1995 struct usb_device *udev; 1994 struct usb_device *udev;
1996 u16 portstat, portchange; 1995 u16 portstat, portchange;
@@ -2024,8 +2023,6 @@ static int hub_resume(struct usb_interface *intf)
2024 } 2023 }
2025 up(&udev->serialize); 2024 up(&udev->serialize);
2026 } 2025 }
2027 intf->dev.power.power_state = PMSG_ON;
2028
2029 hub->resume_root_hub = 0; 2026 hub->resume_root_hub = 0;
2030 hub_activate(hub); 2027 hub_activate(hub);
2031 return 0; 2028 return 0;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f9a81e84dbdf..ebf59ea99263 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1393,6 +1393,7 @@ free_interfaces:
1393 intf->dev.dma_mask = dev->dev.dma_mask; 1393 intf->dev.dma_mask = dev->dev.dma_mask;
1394 intf->dev.release = release_interface; 1394 intf->dev.release = release_interface;
1395 device_initialize (&intf->dev); 1395 device_initialize (&intf->dev);
1396 mark_quiesced(intf);
1396 sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", 1397 sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
1397 dev->bus->busnum, dev->devpath, 1398 dev->bus->busnum, dev->devpath,
1398 configuration, 1399 configuration,
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4c57f3f649ed..6ecfdce4f848 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/**
@@ -1404,8 +1416,9 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
1404 1416
1405static int usb_generic_suspend(struct device *dev, pm_message_t message) 1417static int usb_generic_suspend(struct device *dev, pm_message_t message)
1406{ 1418{
1407 struct usb_interface *intf; 1419 struct usb_interface *intf;
1408 struct usb_driver *driver; 1420 struct usb_driver *driver;
1421 int status;
1409 1422
1410 if (dev->driver == &usb_generic_driver) 1423 if (dev->driver == &usb_generic_driver)
1411 return usb_suspend_device (to_usb_device(dev), message); 1424 return usb_suspend_device (to_usb_device(dev), message);
@@ -1417,21 +1430,34 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
1417 intf = to_usb_interface(dev); 1430 intf = to_usb_interface(dev);
1418 driver = to_usb_driver(dev->driver); 1431 driver = to_usb_driver(dev->driver);
1419 1432
1420 /* there's only one USB suspend state */ 1433 /* with no hardware, USB interfaces only use FREEZE and ON states */
1421 if (intf->dev.power.power_state.event) 1434 if (!is_active(intf))
1422 return 0; 1435 return 0;
1423 1436
1424 if (driver->suspend) 1437 if (driver->suspend && driver->resume) {
1425 return driver->suspend(intf, message); 1438 status = driver->suspend(intf, message);
1426 return 0; 1439 if (status)
1440 dev_err(dev, "%s error %d\n", "suspend", status);
1441 else
1442 mark_quiesced(intf);
1443 } else {
1444 // FIXME else if there's no suspend method, disconnect...
1445 dev_warn(dev, "no %s?\n", "suspend");
1446 status = 0;
1447 }
1448 return status;
1427} 1449}
1428 1450
1429static int usb_generic_resume(struct device *dev) 1451static int usb_generic_resume(struct device *dev)
1430{ 1452{
1431 struct usb_interface *intf; 1453 struct usb_interface *intf;
1432 struct usb_driver *driver; 1454 struct usb_driver *driver;
1455 int status;
1456
1457 if (dev->power.power_state.event == PM_EVENT_ON)
1458 return 0;
1433 1459
1434 /* devices resume through their hub */ 1460 /* devices resume through their hubs */
1435 if (dev->driver == &usb_generic_driver) 1461 if (dev->driver == &usb_generic_driver)
1436 return usb_resume_device (to_usb_device(dev)); 1462 return usb_resume_device (to_usb_device(dev));
1437 1463
@@ -1442,8 +1468,19 @@ static int usb_generic_resume(struct device *dev)
1442 intf = to_usb_interface(dev); 1468 intf = to_usb_interface(dev);
1443 driver = to_usb_driver(dev->driver); 1469 driver = to_usb_driver(dev->driver);
1444 1470
1445 if (driver->resume) 1471 /* if driver was suspended, it has a resume method;
1446 return driver->resume(intf); 1472 * however, sysfs can wrongly mark things as suspended
1473 * (on the "no suspend method" FIXME path above)
1474 */
1475 mark_active(intf);
1476 if (driver->resume) {
1477 status = driver->resume(intf);
1478 if (status) {
1479 dev_err(dev, "%s error %d\n", "resume", status);
1480 mark_quiesced(intf);
1481 }
1482 } else
1483 dev_warn(dev, "no %s?\n", "resume");
1447 return 0; 1484 return 0;
1448} 1485}
1449 1486
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index e6504f3370ad..3741a990403e 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -28,6 +28,24 @@ extern void usb_major_cleanup(void);
28extern int usb_host_init(void); 28extern int usb_host_init(void);
29extern void usb_host_cleanup(void); 29extern void usb_host_cleanup(void);
30 30
31/* Interfaces and their "power state" are owned by usbcore */
32
33static inline void mark_active(struct usb_interface *f)
34{
35 f->dev.power.power_state.event = PM_EVENT_ON;
36}
37
38static inline void mark_quiesced(struct usb_interface *f)
39{
40 f->dev.power.power_state.event = PM_EVENT_FREEZE;
41}
42
43static inline int is_active(struct usb_interface *f)
44{
45 return f->dev.power.power_state.event == PM_EVENT_ON;
46}
47
48
31/* for labeling diagnostics */ 49/* for labeling diagnostics */
32extern const char *usbcore_name; 50extern const char *usbcore_name;
33 51
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 411a0645a7a3..f7fcce731f54 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1887,7 +1887,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1887 struct hid_device *hid = usb_get_intfdata (intf); 1887 struct hid_device *hid = usb_get_intfdata (intf);
1888 1888
1889 usb_kill_urb(hid->urbin); 1889 usb_kill_urb(hid->urbin);
1890 intf->dev.power.power_state = PMSG_SUSPEND;
1891 dev_dbg(&intf->dev, "suspend\n"); 1890 dev_dbg(&intf->dev, "suspend\n");
1892 return 0; 1891 return 0;
1893} 1892}
@@ -1897,7 +1896,6 @@ static int hid_resume(struct usb_interface *intf)
1897 struct hid_device *hid = usb_get_intfdata (intf); 1896 struct hid_device *hid = usb_get_intfdata (intf);
1898 int status; 1897 int status;
1899 1898
1900 intf->dev.power.power_state = PMSG_ON;
1901 if (hid->open) 1899 if (hid->open)
1902 status = usb_submit_urb(hid->urbin, GFP_NOIO); 1900 status = usb_submit_urb(hid->urbin, GFP_NOIO);
1903 else 1901 else
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 54799eb0bc60..d055196533af 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1948,21 +1948,11 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
1948 1948
1949static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) 1949static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
1950{ 1950{
1951 struct usbtest_dev *dev = usb_get_intfdata (intf);
1952
1953 down (&dev->sem);
1954 intf->dev.power.power_state = PMSG_SUSPEND;
1955 up (&dev->sem);
1956 return 0; 1951 return 0;
1957} 1952}
1958 1953
1959static int usbtest_resume (struct usb_interface *intf) 1954static int usbtest_resume (struct usb_interface *intf)
1960{ 1955{
1961 struct usbtest_dev *dev = usb_get_intfdata (intf);
1962
1963 down (&dev->sem);
1964 intf->dev.power.power_state = PMSG_ON;
1965 up (&dev->sem);
1966 return 0; 1956 return 0;
1967} 1957}
1968 1958
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 6a4ffe6c3977..537eb181d985 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -1384,7 +1384,6 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
1384 usb_kill_urb(pegasus->rx_urb); 1384 usb_kill_urb(pegasus->rx_urb);
1385 usb_kill_urb(pegasus->intr_urb); 1385 usb_kill_urb(pegasus->intr_urb);
1386 } 1386 }
1387 intf->dev.power.power_state = PMSG_SUSPEND;
1388 return 0; 1387 return 0;
1389} 1388}
1390 1389
@@ -1392,7 +1391,6 @@ static int pegasus_resume (struct usb_interface *intf)
1392{ 1391{
1393 struct pegasus *pegasus = usb_get_intfdata(intf); 1392 struct pegasus *pegasus = usb_get_intfdata(intf);
1394 1393
1395 intf->dev.power.power_state = PMSG_ON;
1396 netif_device_attach (pegasus->net); 1394 netif_device_attach (pegasus->net);
1397 if (netif_running(pegasus->net)) { 1395 if (netif_running(pegasus->net)) {
1398 pegasus->rx_urb->status = 0; 1396 pegasus->rx_urb->status = 0;
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index fce81d738933..74f05c9c84d5 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -1185,7 +1185,6 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
1185 netif_device_detach (dev->net); 1185 netif_device_detach (dev->net);
1186 (void) unlink_urbs (dev, &dev->rxq); 1186 (void) unlink_urbs (dev, &dev->rxq);
1187 (void) unlink_urbs (dev, &dev->txq); 1187 (void) unlink_urbs (dev, &dev->txq);
1188 intf->dev.power.power_state = PMSG_SUSPEND;
1189 return 0; 1188 return 0;
1190} 1189}
1191EXPORT_SYMBOL_GPL(usbnet_suspend); 1190EXPORT_SYMBOL_GPL(usbnet_suspend);
@@ -1194,7 +1193,6 @@ int usbnet_resume (struct usb_interface *intf)
1194{ 1193{
1195 struct usbnet *dev = usb_get_intfdata(intf); 1194 struct usbnet *dev = usb_get_intfdata(intf);
1196 1195
1197 intf->dev.power.power_state = PMSG_ON;
1198 netif_device_attach (dev->net); 1196 netif_device_attach (dev->net);
1199 tasklet_schedule (&dev->bh); 1197 tasklet_schedule (&dev->bh);
1200 return 0; 1198 return 0;