aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2005-09-13 22:57:27 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:38 -0400
commit390a8c345e6415cbf811232feedac70b56c9fc8d (patch)
tree5a27e9421575c080d31884c4eedeed710d7134f1 /drivers/usb/core
parentc9f89fa40cf274130b56475175a35af961d4b165 (diff)
[PATCH] remove usb_suspend_device() parameter
This patch removes the extra usb_suspend_device() parameter. The original reason to pass that parameter was so that this routine could suspend any active children. A previous patch removed that functionality ... leaving no reason to pass the parameter. A close analogy is pci_set_power_state, which doesn't need a pm_message_t either. On the internal code path that comes through the driver model, the parameter is now used to distinguish cases where USB devices need to "freeze" but not suspend. It also checks for an error case that's accessible through sysfs: attempting to suspend a device before its interfaces (or for hubs, ports). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/core/hub.c | 34 +++++++++++++++++++++------------- drivers/usb/core/usb.c | 23 +++++++++++++++++++++-- drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/ohci-pci.c | 2 +- include/linux/usb.h | 2 +- 6 files changed, 46 insertions(+), 19 deletions(-)
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hub.c34
-rw-r--r--drivers/usb/core/usb.c23
2 files changed, 42 insertions, 15 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d3337d9c31dc..33127b828d60 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1323,11 +1323,9 @@ int usb_new_device(struct usb_device *udev)
1323 * (Includes HNP test device.) 1323 * (Includes HNP test device.)
1324 */ 1324 */
1325 if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { 1325 if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
1326 static int __usb_suspend_device (struct usb_device *, 1326 static int __usb_suspend_device(struct usb_device *,
1327 int port1, pm_message_t state); 1327 int port1);
1328 err = __usb_suspend_device(udev, 1328 err = __usb_suspend_device(udev, udev->bus->otg_port);
1329 udev->bus->otg_port,
1330 PMSG_SUSPEND);
1331 if (err < 0) 1329 if (err < 0)
1332 dev_dbg(&udev->dev, "HNP fail, %d\n", err); 1330 dev_dbg(&udev->dev, "HNP fail, %d\n", err);
1333 } 1331 }
@@ -1517,7 +1515,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
1517 /* FIXME let caller ask to power down the port: 1515 /* FIXME let caller ask to power down the port:
1518 * - some devices won't enumerate without a VBUS power cycle 1516 * - some devices won't enumerate without a VBUS power cycle
1519 * - SRP saves power that way 1517 * - SRP saves power that way
1520 * - usb_suspend_device(dev, PMSG_SUSPEND) 1518 * - ... new call, TBD ...
1521 * That's easy if this hub can switch power per-port, and 1519 * That's easy if this hub can switch power per-port, and
1522 * khubd reactivates the port later (timer, SRP, etc). 1520 * khubd reactivates the port later (timer, SRP, etc).
1523 * Powerdown must be optional, because of reset/DFU. 1521 * Powerdown must be optional, because of reset/DFU.
@@ -1599,9 +1597,12 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
1599 * Other than re-initializing the hub (plug/unplug, except for root hubs), 1597 * Other than re-initializing the hub (plug/unplug, except for root hubs),
1600 * Linux (2.6) currently has NO mechanisms to initiate that: no khubd 1598 * Linux (2.6) currently has NO mechanisms to initiate that: no khubd
1601 * timer, no SRP, no requests through sysfs. 1599 * timer, no SRP, no requests through sysfs.
1600 *
1601 * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
1602 * the root hub for their bus goes into global suspend ... so we don't
1603 * (falsely) update the device power state to say it suspended.
1602 */ 1604 */
1603static int __usb_suspend_device (struct usb_device *udev, int port1, 1605static int __usb_suspend_device (struct usb_device *udev, int port1)
1604 pm_message_t state)
1605{ 1606{
1606 int status; 1607 int status;
1607 1608
@@ -1648,14 +1649,13 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
1648 udev); 1649 udev);
1649 1650
1650 if (status == 0) 1651 if (status == 0)
1651 udev->dev.power.power_state = state; 1652 udev->dev.power.power_state = PMSG_SUSPEND;
1652 return status; 1653 return status;
1653} 1654}
1654 1655
1655/** 1656/**
1656 * usb_suspend_device - suspend a usb device 1657 * usb_suspend_device - suspend a usb device
1657 * @udev: device that's no longer in active use 1658 * @udev: device that's no longer in active use
1658 * @state: PMSG_SUSPEND to suspend
1659 * Context: must be able to sleep; device not locked 1659 * Context: must be able to sleep; device not locked
1660 * 1660 *
1661 * Suspends a USB device that isn't in active use, conserving power. 1661 * Suspends a USB device that isn't in active use, conserving power.
@@ -1664,13 +1664,16 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
1664 * suspend by the host, using usb_resume_device(). It's also routine 1664 * suspend by the host, using usb_resume_device(). It's also routine
1665 * to disconnect devices while they are suspended. 1665 * to disconnect devices while they are suspended.
1666 * 1666 *
1667 * This only affects the USB hardware for a device; its interfaces
1668 * (and, for hubs, child devices) must already have been suspended.
1669 *
1667 * Suspending OTG devices may trigger HNP, if that's been enabled 1670 * Suspending OTG devices may trigger HNP, if that's been enabled
1668 * between a pair of dual-role devices. That will change roles, such 1671 * between a pair of dual-role devices. That will change roles, such
1669 * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral. 1672 * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
1670 * 1673 *
1671 * Returns 0 on success, else negative errno. 1674 * Returns 0 on success, else negative errno.
1672 */ 1675 */
1673int usb_suspend_device(struct usb_device *udev, pm_message_t state) 1676int usb_suspend_device(struct usb_device *udev)
1674{ 1677{
1675 int port1, status; 1678 int port1, status;
1676 1679
@@ -1678,12 +1681,15 @@ int usb_suspend_device(struct usb_device *udev, pm_message_t state)
1678 if (port1 < 0) 1681 if (port1 < 0)
1679 return port1; 1682 return port1;
1680 1683
1681 status = __usb_suspend_device(udev, port1, state); 1684 status = __usb_suspend_device(udev, port1);
1682 usb_unlock_device(udev); 1685 usb_unlock_device(udev);
1683 return status; 1686 return status;
1684} 1687}
1685 1688
1686/* 1689/*
1690 * If the USB "suspend" state is in use (rather than "global suspend"),
1691 * many devices will be individually taken out of suspend state using
1692 * special" resume" signaling. These routines kick in shortly after
1687 * hardware resume signaling is finished, either because of selective 1693 * hardware resume signaling is finished, either because of selective
1688 * resume (by host) or remote wakeup (by device) ... now see what changed 1694 * resume (by host) or remote wakeup (by device) ... now see what changed
1689 * in the tree that's rooted at this device. 1695 * in the tree that's rooted at this device.
@@ -1986,13 +1992,15 @@ void usb_resume_root_hub(struct usb_device *hdev)
1986 1992
1987#else /* !CONFIG_USB_SUSPEND */ 1993#else /* !CONFIG_USB_SUSPEND */
1988 1994
1989int usb_suspend_device(struct usb_device *udev, pm_message_t state) 1995int usb_suspend_device(struct usb_device *udev)
1990{ 1996{
1997 /* state does NOT lie by saying it's USB_STATE_SUSPENDED! */
1991 return 0; 1998 return 0;
1992} 1999}
1993 2000
1994int usb_resume_device(struct usb_device *udev) 2001int usb_resume_device(struct usb_device *udev)
1995{ 2002{
2003 udev->dev.power_state.event = PM_EVENT_ON;
1996 return 0; 2004 return 0;
1997} 2005}
1998 2006
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 6ecfdce4f848..e89dbd43e952 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1414,14 +1414,33 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
1414 usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); 1414 usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
1415} 1415}
1416 1416
1417static int verify_suspended(struct device *dev, void *unused)
1418{
1419 return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
1420}
1421
1417static int usb_generic_suspend(struct device *dev, pm_message_t message) 1422static int usb_generic_suspend(struct device *dev, pm_message_t message)
1418{ 1423{
1419 struct usb_interface *intf; 1424 struct usb_interface *intf;
1420 struct usb_driver *driver; 1425 struct usb_driver *driver;
1421 int status; 1426 int status;
1422 1427
1423 if (dev->driver == &usb_generic_driver) 1428 /* USB devices enter SUSPEND state through their hubs, but can be
1424 return usb_suspend_device (to_usb_device(dev), message); 1429 * marked for FREEZE as soon as their children are already idled.
1430 */
1431 if (dev->driver == &usb_generic_driver) {
1432 if (dev->power.power_state.event == message.event)
1433 return 0;
1434 /* we need to rule out bogus requests through sysfs */
1435 status = device_for_each_child(dev, NULL, verify_suspended);
1436 if (status)
1437 return status;
1438 if (message.event == PM_EVENT_FREEZE) {
1439 dev->power.power_state = message;
1440 return 0;
1441 }
1442 return usb_suspend_device (to_usb_device(dev));
1443 }
1425 1444
1426 if ((dev->driver == NULL) || 1445 if ((dev->driver == NULL) ||
1427 (dev->driver_data == &usb_generic_driver_data)) 1446 (dev->driver_data == &usb_generic_driver_data))