Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:14:53 +0000 (08:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:14:53 +0000 (08:14 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
  spi / PM: Support dev_pm_ops
  PM: Prototype the pm_generic_ operations
  PM / Runtime: Generic resume shouldn't set RPM_ACTIVE unconditionally
  PM: Use dev_name() in core device suspend and resume routines
  PM: Permit registration of parentless devices during system suspend
  PM: Replace the device power.status field with a bit field
  PM: Remove redundant checks from core device resume routines
  PM: Use a different list of devices for each stage of device suspend
  PM: Avoid compiler warning in pm_noirq_op()
  PM: Use pm_wakeup_pending() in __device_suspend()
  PM / Wakeup: Replace pm_check_wakeup_events() with pm_wakeup_pending()
  PM: Prevent dpm_prepare() from returning errors unnecessarily
  PM: Fix references to basic-pm-debugging.txt in drivers-testing.txt
  PM / Runtime: Add synchronous runtime interface for interrupt handlers (v3)
  PM / Hibernate: When failed, in_suspend should be reset
  PM / Hibernate: hibernation_ops->leave should be checked too
  Freezer: Fix a race during freezing of TASK_STOPPED tasks
  PM: Use proper ccflag flag in kernel/power/Makefile
  PM / Runtime: Fix comments to match runtime callback code

1  2 
drivers/usb/core/driver.c
kernel/power/suspend.c

@@@ -27,6 -27,7 +27,6 @@@
  #include <linux/usb.h>
  #include <linux/usb/quirks.h>
  #include <linux/usb/hcd.h>
 -#include <linux/pm_runtime.h>
  
  #include "usb.h"
  
@@@ -375,7 -376,7 +375,7 @@@ static int usb_unbind_interface(struct 
                 * Just re-enable it without affecting the endpoint toggles.
                 */
                usb_enable_interface(udev, intf, false);
-       } else if (!error && intf->dev.power.status == DPM_ON) {
+       } else if (!error && !intf->dev.power.in_suspend) {
                r = usb_set_interface(udev, intf->altsetting[0].
                                desc.bInterfaceNumber, 0);
                if (r < 0)
@@@ -960,7 -961,7 +960,7 @@@ void usb_rebind_intf(struct usb_interfa
        }
  
        /* Try to rebind the interface */
-       if (intf->dev.power.status == DPM_ON) {
+       if (!intf->dev.power.in_suspend) {
                intf->needs_binding = 0;
                rc = device_attach(&intf->dev);
                if (rc < 0)
@@@ -1107,8 -1108,7 +1107,7 @@@ static int usb_resume_interface(struct 
        if (intf->condition == USB_INTERFACE_UNBOUND) {
  
                /* Carry out a deferred switch to altsetting 0 */
-               if (intf->needs_altsetting0 &&
-                               intf->dev.power.status == DPM_ON) {
+               if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) {
                        usb_set_interface(udev, intf->altsetting[0].
                                        desc.bInterfaceNumber, 0);
                        intf->needs_altsetting0 = 0;
@@@ -1261,7 -1261,6 +1260,7 @@@ static int usb_resume_both(struct usb_d
                                        udev->reset_resume);
                }
        }
 +      usb_mark_last_busy(udev);
  
   done:
        dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
@@@ -1329,6 -1328,7 +1328,6 @@@ int usb_resume(struct device *dev, pm_m
                        pm_runtime_disable(dev);
                        pm_runtime_set_active(dev);
                        pm_runtime_enable(dev);
 -                      udev->last_busy = jiffies;
                        do_unbind_rebind(udev, DO_REBIND);
                }
        }
@@@ -1396,8 -1396,33 +1395,8 @@@ void usb_autosuspend_device(struct usb_
  {
        int     status;
  
 -      udev->last_busy = jiffies;
 -      status = pm_runtime_put_sync(&udev->dev);
 -      dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
 -                      __func__, atomic_read(&udev->dev.power.usage_count),
 -                      status);
 -}
 -
 -/**
 - * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
 - * @udev: the usb_device to autosuspend
 - *
 - * This routine should be called when a core subsystem thinks @udev may
 - * be ready to autosuspend.
 - *
 - * @udev's usage counter left unchanged.  If it is 0 and all the interfaces
 - * are inactive then an autosuspend will be attempted.  The attempt may
 - * fail or be delayed.
 - *
 - * The caller must hold @udev's device lock.
 - *
 - * This routine can run only in process context.
 - */
 -void usb_try_autosuspend_device(struct usb_device *udev)
 -{
 -      int     status;
 -
 -      status = pm_runtime_idle(&udev->dev);
 +      usb_mark_last_busy(udev);
 +      status = pm_runtime_put_sync_autosuspend(&udev->dev);
        dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
                        __func__, atomic_read(&udev->dev.power.usage_count),
                        status);
@@@ -1456,7 -1481,7 +1455,7 @@@ void usb_autopm_put_interface(struct us
        struct usb_device       *udev = interface_to_usbdev(intf);
        int                     status;
  
 -      udev->last_busy = jiffies;
 +      usb_mark_last_busy(udev);
        atomic_dec(&intf->pm_usage_cnt);
        status = pm_runtime_put_sync(&intf->dev);
        dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
@@@ -1483,11 -1508,32 +1482,11 @@@ EXPORT_SYMBOL_GPL(usb_autopm_put_interf
  void usb_autopm_put_interface_async(struct usb_interface *intf)
  {
        struct usb_device       *udev = interface_to_usbdev(intf);
 -      unsigned long           last_busy;
 -      int                     status = 0;
 +      int                     status;
  
 -      last_busy = udev->last_busy;
 -      udev->last_busy = jiffies;
 +      usb_mark_last_busy(udev);
        atomic_dec(&intf->pm_usage_cnt);
 -      pm_runtime_put_noidle(&intf->dev);
 -
 -      if (udev->dev.power.runtime_auto) {
 -              /* Optimization: Don't schedule a delayed autosuspend if
 -               * the timer is already running and the expiration time
 -               * wouldn't change.
 -               *
 -               * We have to use the interface's timer.  Attempts to
 -               * schedule a suspend for the device would fail because
 -               * the interface is still active.
 -               */
 -              if (intf->dev.power.timer_expires == 0 ||
 -                              round_jiffies_up(last_busy) !=
 -                              round_jiffies_up(jiffies)) {
 -                      status = pm_schedule_suspend(&intf->dev,
 -                                      jiffies_to_msecs(
 -                                      round_jiffies_up_relative(
 -                                              udev->autosuspend_delay)));
 -              }
 -      }
 +      status = pm_runtime_put(&intf->dev);
        dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
                        __func__, atomic_read(&intf->dev.power.usage_count),
                        status);
@@@ -1507,7 -1553,7 +1506,7 @@@ void usb_autopm_put_interface_no_suspen
  {
        struct usb_device       *udev = interface_to_usbdev(intf);
  
 -      udev->last_busy = jiffies;
 +      usb_mark_last_busy(udev);
        atomic_dec(&intf->pm_usage_cnt);
        pm_runtime_put_noidle(&intf->dev);
  }
@@@ -1565,9 -1611,18 +1564,9 @@@ EXPORT_SYMBOL_GPL(usb_autopm_get_interf
   */
  int usb_autopm_get_interface_async(struct usb_interface *intf)
  {
 -      int             status = 0;
 -      enum rpm_status s;
 -
 -      /* Don't request a resume unless the interface is already suspending
 -       * or suspended.  Doing so would force a running suspend timer to be
 -       * cancelled.
 -       */
 -      pm_runtime_get_noresume(&intf->dev);
 -      s = ACCESS_ONCE(intf->dev.power.runtime_status);
 -      if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
 -              status = pm_request_resume(&intf->dev);
 +      int     status;
  
 +      status = pm_runtime_get(&intf->dev);
        if (status < 0 && status != -EINPROGRESS)
                pm_runtime_put_noidle(&intf->dev);
        else
@@@ -1594,7 -1649,7 +1593,7 @@@ void usb_autopm_get_interface_no_resume
  {
        struct usb_device       *udev = interface_to_usbdev(intf);
  
 -      udev->last_busy = jiffies;
 +      usb_mark_last_busy(udev);
        atomic_inc(&intf->pm_usage_cnt);
        pm_runtime_get_noresume(&intf->dev);
  }
@@@ -1605,6 -1660,7 +1604,6 @@@ static int autosuspend_check(struct usb
  {
        int                     w, i;
        struct usb_interface    *intf;
 -      unsigned long           suspend_time, j;
  
        /* Fail if autosuspend is disabled, or any interfaces are in use, or
         * any interface drivers require remote wakeup but it isn't available.
                return -EOPNOTSUPP;
        }
        udev->do_remote_wakeup = w;
 -
 -      /* If everything is okay but the device hasn't been idle for long
 -       * enough, queue a delayed autosuspend request.
 -       */
 -      j = ACCESS_ONCE(jiffies);
 -      suspend_time = udev->last_busy + udev->autosuspend_delay;
 -      if (time_before(j, suspend_time)) {
 -              pm_schedule_suspend(&udev->dev, jiffies_to_msecs(
 -                              round_jiffies_up_relative(suspend_time - j)));
 -              return -EAGAIN;
 -      }
        return 0;
  }
  
  static int usb_runtime_suspend(struct device *dev)
  {
 -      int     status = 0;
 +      struct usb_device       *udev = to_usb_device(dev);
 +      int                     status;
  
        /* A USB device can be suspended if it passes the various autosuspend
         * checks.  Runtime suspend for a USB device means suspending all the
         * interfaces and then the device itself.
         */
 -      if (is_usb_device(dev)) {
 -              struct usb_device       *udev = to_usb_device(dev);
 -
 -              if (autosuspend_check(udev) != 0)
 -                      return -EAGAIN;
 -
 -              status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
 -
 -              /* If an interface fails the suspend, adjust the last_busy
 -               * time so that we don't get another suspend attempt right
 -               * away.
 -               */
 -              if (status) {
 -                      udev->last_busy = jiffies +
 -                                      (udev->autosuspend_delay == 0 ?
 -                                              HZ/2 : 0);
 -              }
 -
 -              /* Prevent the parent from suspending immediately after */
 -              else if (udev->parent)
 -                      udev->parent->last_busy = jiffies;
 -      }
 +      if (autosuspend_check(udev) != 0)
 +              return -EAGAIN;
  
 -      /* Runtime suspend for a USB interface doesn't mean anything. */
 +      status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
        return status;
  }
  
  static int usb_runtime_resume(struct device *dev)
  {
 +      struct usb_device       *udev = to_usb_device(dev);
 +      int                     status;
 +
        /* Runtime resume for a USB device means resuming both the device
         * and all its interfaces.
         */
 -      if (is_usb_device(dev)) {
 -              struct usb_device       *udev = to_usb_device(dev);
 -              int                     status;
 -
 -              status = usb_resume_both(udev, PMSG_AUTO_RESUME);
 -              udev->last_busy = jiffies;
 -              return status;
 -      }
 -
 -      /* Runtime resume for a USB interface doesn't mean anything. */
 -      return 0;
 +      status = usb_resume_both(udev, PMSG_AUTO_RESUME);
 +      return status;
  }
  
  static int usb_runtime_idle(struct device *dev)
  {
 +      struct usb_device       *udev = to_usb_device(dev);
 +
        /* An idle USB device can be suspended if it passes the various
 -       * autosuspend checks.  An idle interface can be suspended at
 -       * any time.
 +       * autosuspend checks.
         */
 -      if (is_usb_device(dev)) {
 -              struct usb_device       *udev = to_usb_device(dev);
 -
 -              if (autosuspend_check(udev) != 0)
 -                      return 0;
 -      }
 -
 -      pm_runtime_suspend(dev);
 +      if (autosuspend_check(udev) == 0)
 +              pm_runtime_autosuspend(dev);
        return 0;
  }
  
diff --combined kernel/power/suspend.c
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/mm.h>
  #include <linux/slab.h>
  #include <linux/suspend.h>
 +#include <trace/events/power.h>
  
  #include "power.h"
  
@@@ -164,7 -163,7 +164,7 @@@ static int suspend_enter(suspend_state_
  
        error = sysdev_suspend(PMSG_SUSPEND);
        if (!error) {
-               if (!suspend_test(TEST_CORE) && pm_check_wakeup_events()) {
+               if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
                        error = suspend_ops->enter(state);
                        events_check_enabled = false;
                }
@@@ -202,7 -201,6 +202,7 @@@ int suspend_devices_and_enter(suspend_s
        if (!suspend_ops)
                return -ENOSYS;
  
 +      trace_machine_suspend(state);
        if (suspend_ops->begin) {
                error = suspend_ops->begin(state);
                if (error)
   Close:
        if (suspend_ops->end)
                suspend_ops->end();
 +      trace_machine_suspend(PWR_EVENT_EXIT);
        return error;
  
   Recover_platform: