diff options
| author | Andrew Morton <akpm@osdl.org> | 2006-03-23 04:38:34 -0500 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-04-14 14:41:25 -0400 | 
| commit | 026694920579590c73b5c56705d543568ed5ad41 (patch) | |
| tree | 1c3ad318fe65c5812dd33008af8e77389ee31c46 | |
| parent | 372254018eb1b65ee69210d11686bfc65c8d84db (diff) | |
[PATCH] pm: print name of failed suspend function
Print more diagnostic info to help identify the source of power management
suspend failures.
Example:
usb_hcd_pci_suspend(): pci_set_power_state+0x0/0x1af() returns -22
pci_device_suspend(): usb_hcd_pci_suspend+0x0/0x11b() returns -22
suspend_device(): pci_device_suspend+0x0/0x34() returns -22
Work-in-progress.  It needs lots more suspend_report_result() calls sprinkled
everywhere.
Cc: Patrick Mochel <mochel@digitalimplant.org>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@suspend2.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/base/power/suspend.c | 12 | ||||
| -rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 6 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 7 | ||||
| -rw-r--r-- | include/linux/pm.h | 8 | 
5 files changed, 31 insertions, 8 deletions
| diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index bdb60663f2ef..662209d3f42d 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/vt_kern.h> | 11 | #include <linux/vt_kern.h> | 
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> | 
| 13 | #include <linux/kallsyms.h> | ||
| 14 | #include <linux/pm.h> | ||
| 13 | #include "../base.h" | 15 | #include "../base.h" | 
| 14 | #include "power.h" | 16 | #include "power.h" | 
| 15 | 17 | ||
| @@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state) | |||
| 58 | if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { | 60 | if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { | 
| 59 | dev_dbg(dev, "suspending\n"); | 61 | dev_dbg(dev, "suspending\n"); | 
| 60 | error = dev->bus->suspend(dev, state); | 62 | error = dev->bus->suspend(dev, state); | 
| 63 | suspend_report_result(dev->bus->suspend, error); | ||
| 61 | } | 64 | } | 
| 62 | up(&dev->sem); | 65 | up(&dev->sem); | 
| 63 | return error; | 66 | return error; | 
| @@ -169,3 +172,12 @@ int device_power_down(pm_message_t state) | |||
| 169 | 172 | ||
| 170 | EXPORT_SYMBOL_GPL(device_power_down); | 173 | EXPORT_SYMBOL_GPL(device_power_down); | 
| 171 | 174 | ||
| 175 | void __suspend_report_result(const char *function, void *fn, int ret) | ||
| 176 | { | ||
| 177 | if (ret) { | ||
| 178 | printk(KERN_ERR "%s(): ", function); | ||
| 179 | print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); | ||
| 180 | printk("%d\n", ret); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | EXPORT_SYMBOL_GPL(__suspend_report_result); | ||
| diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f22f69ac6445..1456759936c5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) | |||
| 271 | struct pci_driver * drv = pci_dev->driver; | 271 | struct pci_driver * drv = pci_dev->driver; | 
| 272 | int i = 0; | 272 | int i = 0; | 
| 273 | 273 | ||
| 274 | if (drv && drv->suspend) | 274 | if (drv && drv->suspend) { | 
| 275 | i = drv->suspend(pci_dev, state); | 275 | i = drv->suspend(pci_dev, state); | 
| 276 | else | 276 | suspend_report_result(drv->suspend, i); | 
| 277 | } else { | ||
| 277 | pci_save_state(pci_dev); | 278 | pci_save_state(pci_dev); | 
| 279 | } | ||
| 278 | return i; | 280 | return i; | 
| 279 | } | 281 | } | 
| 280 | 282 | ||
| diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bea1ad1ad5ba..042fa5265cf6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 307 | * Can enter D0 from any state, but if we can only go deeper | 307 | * Can enter D0 from any state, but if we can only go deeper | 
| 308 | * to sleep if we're already in a low power state | 308 | * to sleep if we're already in a low power state | 
| 309 | */ | 309 | */ | 
| 310 | if (state != PCI_D0 && dev->current_state > state) | 310 | if (state != PCI_D0 && dev->current_state > state) { | 
| 311 | printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n", | ||
| 312 | __FUNCTION__, pci_name(dev), state, dev->current_state); | ||
| 311 | return -EINVAL; | 313 | return -EINVAL; | 
| 312 | else if (dev->current_state == state) | 314 | } else if (dev->current_state == state) | 
| 313 | return 0; /* we're already there */ | 315 | return 0; /* we're already there */ | 
| 314 | 316 | ||
| 315 | /* find PCI PM capability in list */ | 317 | /* find PCI PM capability in list */ | 
| diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 0d2193b69235..66b78404ab34 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
| @@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
| 213 | 213 | ||
| 214 | if (hcd->driver->suspend) { | 214 | if (hcd->driver->suspend) { | 
| 215 | retval = hcd->driver->suspend(hcd, message); | 215 | retval = hcd->driver->suspend(hcd, message); | 
| 216 | if (retval) { | 216 | suspend_report_result(hcd->driver->suspend, retval); | 
| 217 | dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n", | 217 | if (retval) | 
| 218 | retval); | ||
| 219 | goto done; | 218 | goto done; | 
| 220 | } | ||
| 221 | } | 219 | } | 
| 222 | synchronize_irq(dev->irq); | 220 | synchronize_irq(dev->irq); | 
| 223 | 221 | ||
| @@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
| 263 | * some device state (e.g. as part of clock reinit). | 261 | * some device state (e.g. as part of clock reinit). | 
| 264 | */ | 262 | */ | 
| 265 | retval = pci_set_power_state (dev, PCI_D3hot); | 263 | retval = pci_set_power_state (dev, PCI_D3hot); | 
| 264 | suspend_report_result(pci_set_power_state, retval); | ||
| 266 | if (retval == 0) { | 265 | if (retval == 0) { | 
| 267 | int wake = device_can_wakeup(&hcd->self.root_hub->dev); | 266 | int wake = device_can_wakeup(&hcd->self.root_hub->dev); | 
| 268 | 267 | ||
| diff --git a/include/linux/pm.h b/include/linux/pm.h index 6df2585c0169..66be58902b17 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state); | |||
| 199 | 199 | ||
| 200 | extern int dpm_runtime_suspend(struct device *, pm_message_t); | 200 | extern int dpm_runtime_suspend(struct device *, pm_message_t); | 
| 201 | extern void dpm_runtime_resume(struct device *); | 201 | extern void dpm_runtime_resume(struct device *); | 
| 202 | extern void __suspend_report_result(const char *function, void *fn, int ret); | ||
| 203 | |||
| 204 | #define suspend_report_result(fn, ret) \ | ||
| 205 | do { \ | ||
| 206 | __suspend_report_result(__FUNCTION__, fn, ret); \ | ||
| 207 | } while (0) | ||
| 202 | 208 | ||
| 203 | #else /* !CONFIG_PM */ | 209 | #else /* !CONFIG_PM */ | 
| 204 | 210 | ||
| @@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev) | |||
| 219 | { | 225 | { | 
| 220 | } | 226 | } | 
| 221 | 227 | ||
| 228 | #define suspend_report_result(fn, ret) do { } while (0) | ||
| 229 | |||
| 222 | #endif | 230 | #endif | 
| 223 | 231 | ||
| 224 | /* changes to device_may_wakeup take effect on the next pm state change. | 232 | /* changes to device_may_wakeup take effect on the next pm state change. | 
