]> Pileus Git - ~andy/linux/commitdiff
Merge branches 'pm-cpuidle' and 'pm-cpufreq'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 6 Dec 2013 01:17:59 +0000 (02:17 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 6 Dec 2013 01:17:59 +0000 (02:17 +0100)
* pm-cpuidle:
  cpuidle: Check for dev before deregistering it.
  intel_idle: Fixed C6 state on Avoton/Rangeley processors

* pm-cpufreq:
  cpufreq: fix garbage kobjects on errors during suspend/resume
  cpufreq: suspend governors on system suspend/hibernate

1  2  3 
drivers/base/power/main.c
include/linux/cpufreq.h

index 1b41fca3d65a54545c6c124e0df696998c29a1af,1b41fca3d65a54545c6c124e0df696998c29a1af,10c3510d72a9426ad91dd4f76ec94db01239fa52..e3219dfd736c64fbf13976ce3fa7f66b89e6484e
   #include <linux/async.h>
   #include <linux/suspend.h>
   #include <trace/events/power.h>
++ #include <linux/cpufreq.h>
   #include <linux/cpuidle.h>
  +#include <linux/timer.h>
  +
   #include "../base.h"
   #include "power.h"
   
@@@@ -392,71 -392,71 -391,6 +393,71 @@@@ static int dpm_run_callback(pm_callback
        return error;
   }
   
  +#ifdef CONFIG_DPM_WATCHDOG
  +struct dpm_watchdog {
  +     struct device           *dev;
  +     struct task_struct      *tsk;
  +     struct timer_list       timer;
  +};
  +
  +#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
  +     struct dpm_watchdog wd
  +
  +/**
  + * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
  + * @data: Watchdog object address.
  + *
  + * Called when a driver has timed out suspending or resuming.
  + * There's not much we can do here to recover so panic() to
  + * capture a crash-dump in pstore.
  + */
  +static void dpm_watchdog_handler(unsigned long data)
  +{
  +     struct dpm_watchdog *wd = (void *)data;
  +
  +     dev_emerg(wd->dev, "**** DPM device timeout ****\n");
  +     show_stack(wd->tsk, NULL);
  +     panic("%s %s: unrecoverable failure\n",
  +             dev_driver_string(wd->dev), dev_name(wd->dev));
  +}
  +
  +/**
  + * dpm_watchdog_set - Enable pm watchdog for given device.
  + * @wd: Watchdog. Must be allocated on the stack.
  + * @dev: Device to handle.
  + */
  +static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
  +{
  +     struct timer_list *timer = &wd->timer;
  +
  +     wd->dev = dev;
  +     wd->tsk = current;
  +
  +     init_timer_on_stack(timer);
  +     /* use same timeout value for both suspend and resume */
  +     timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
  +     timer->function = dpm_watchdog_handler;
  +     timer->data = (unsigned long)wd;
  +     add_timer(timer);
  +}
  +
  +/**
  + * dpm_watchdog_clear - Disable suspend/resume watchdog.
  + * @wd: Watchdog to disable.
  + */
  +static void dpm_watchdog_clear(struct dpm_watchdog *wd)
  +{
  +     struct timer_list *timer = &wd->timer;
  +
  +     del_timer_sync(timer);
  +     destroy_timer_on_stack(timer);
  +}
  +#else
  +#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
  +#define dpm_watchdog_set(x, y)
  +#define dpm_watchdog_clear(x)
  +#endif
  +
   /*------------------------- Resume routines -------------------------*/
   
   /**
@@@@ -540,6 -540,6 -474,7 +541,7 @@@@ static void dpm_resume_noirq(pm_message
        dpm_show_time(starttime, state, "noirq");
        resume_device_irqs();
        cpuidle_resume();
++      cpufreq_resume();
   }
   
   /**
@@@@ -643,7 -643,7 -578,6 +645,7 @@@@ static int device_resume(struct device 
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
  +     DECLARE_DPM_WATCHDOG_ON_STACK(wd);
   
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
                goto Complete;
   
        dpm_wait(dev->parent, async);
  +     dpm_watchdog_set(&wd, dev);
        device_lock(dev);
   
        /*
   
    Unlock:
        device_unlock(dev);
  +     dpm_watchdog_clear(&wd);
   
    Complete:
        complete_all(&dev->power.completion);
@@@@ -757,7 -757,7 -689,7 +759,7 @@@@ void dpm_resume(pm_message_t state
        async_error = 0;
   
        list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
  -             INIT_COMPLETION(dev->power.completion);
  +             reinit_completion(&dev->power.completion);
                if (is_async(dev)) {
                        get_device(dev);
                        async_schedule(async_resume, dev);
@@@@ -955,6 -955,6 -887,7 +957,7 @@@@ static int dpm_suspend_noirq(pm_message
        ktime_t starttime = ktime_get();
        int error = 0;
   
++      cpufreq_suspend();
        cpuidle_pause();
        suspend_device_irqs();
        mutex_lock(&dpm_list_mtx);
@@@@ -1130,7 -1130,7 -1063,6 +1133,7 @@@@ static int __device_suspend(struct devi
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
  +     DECLARE_DPM_WATCHDOG_ON_STACK(wd);
   
        dpm_wait_for_children(dev, async);
   
        if (dev->power.syscore)
                goto Complete;
   
  +     dpm_watchdog_set(&wd, dev);
        device_lock(dev);
   
        if (dev->pm_domain) {
        }
   
        device_unlock(dev);
  +     dpm_watchdog_clear(&wd);
   
    Complete:
        complete_all(&dev->power.completion);
@@@@ -1237,7 -1237,7 -1167,7 +1240,7 @@@@ static void async_suspend(void *data, a
   
   static int device_suspend(struct device *dev)
   {
  -     INIT_COMPLETION(dev->power.completion);
  +     reinit_completion(&dev->power.completion);
   
        if (pm_async_enabled && dev->power.async_suspend) {
                get_device(dev);
@@@@ -1350,9 -1350,9 -1280,6 +1353,9 @@@@ static int device_prepare(struct devic
   
        device_unlock(dev);
   
  +     if (error)
  +             pm_runtime_put(dev);
  +
        return error;
   }
   
diff --combined include/linux/cpufreq.h
index dc196bbcf227288bce4d4d3e2db60dae5cde3dec,dc196bbcf227288bce4d4d3e2db60dae5cde3dec,91716658e9a19d8f3e09310c614498a540eb5f0c..ee5fe9d77ae8ef400031978a3990430b7aa57f4a
@@@@ -107,16 -107,16 -107,8 +107,16 @@@@ struct cpufreq_policy 
   #define CPUFREQ_SHARED_TYPE_ALL       (2) /* All dependent CPUs should set freq */
   #define CPUFREQ_SHARED_TYPE_ANY       (3) /* Freq can be set from any dependent CPU*/
   
  +#ifdef CONFIG_CPU_FREQ
   struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
   void cpufreq_cpu_put(struct cpufreq_policy *policy);
  +#else
  +static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
  +{
  +     return NULL;
  +}
  +static inline void cpufreq_cpu_put(struct cpufreq_policy *policy) { }
  +#endif
   
   static inline bool policy_is_shared(struct cpufreq_policy *policy)
   {
@@@@ -280,6 -280,6 -272,14 +280,14 @@@@ cpufreq_verify_within_cpu_limits(struc
                        policy->cpuinfo.max_freq);
   }
   
++ #ifdef CONFIG_CPU_FREQ
++ void cpufreq_suspend(void);
++ void cpufreq_resume(void);
++ #else
++ static inline void cpufreq_suspend(void) {}
++ static inline void cpufreq_resume(void) {}
++ #endif
++ 
   /*********************************************************************
    *                     CPUFREQ NOTIFIER INTERFACE                    *
    *********************************************************************/