Merge branch 'pm-cpuidle'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 26 Nov 2019 09:26:26 +0000 (10:26 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 26 Nov 2019 09:26:26 +0000 (10:26 +0100)
* pm-cpuidle:
  cpuidle: Pass exit latency limit to cpuidle_use_deepest_state()
  cpuidle: Allow idle injection to apply exit latency limit
  cpuidle: Introduce cpuidle_driver_state_disabled() for driver quirks
  cpuidle: teo: Avoid code duplication in conditionals
  cpuidle: teo: Avoid using "early hits" incorrectly
  cpuidle: teo: Exclude cpuidle overhead from computations
  cpuidle: Use nanoseconds as the unit of time
  cpuidle: Consolidate disabled state checks
  ACPI: processor_idle: Skip dummy wait if kernel is in guest
  cpuidle: Do not unset the driver if it is there already
  cpuidle: teo: Fix "early hits" handling for disabled idle states
  cpuidle: teo: Consider hits and misses metrics of disabled states
  cpuidle: teo: Rename local variable in teo_select()
  cpuidle: teo: Ignore disabled idle states that are too deep

1  2 
include/linux/cpu.h
kernel/sched/idle.c

diff --combined include/linux/cpu.h
@@@ -59,11 -59,6 +59,11 @@@ extern ssize_t cpu_show_l1tf(struct dev
                             struct device_attribute *attr, char *buf);
  extern ssize_t cpu_show_mds(struct device *dev,
                            struct device_attribute *attr, char *buf);
 +extern ssize_t cpu_show_tsx_async_abort(struct device *dev,
 +                                      struct device_attribute *attr,
 +                                      char *buf);
 +extern ssize_t cpu_show_itlb_multihit(struct device *dev,
 +                                    struct device_attribute *attr, char *buf);
  
  extern __printf(4, 5)
  struct device *cpu_device_create(struct device *parent, void *drvdata,
@@@ -184,7 -179,12 +184,12 @@@ void arch_cpu_idle_dead(void)
  int cpu_report_state(int cpu);
  int cpu_check_up_prepare(int cpu);
  void cpu_set_state_online(int cpu);
- void play_idle(unsigned long duration_us);
+ void play_idle_precise(u64 duration_ns, u64 latency_ns);
+ static inline void play_idle(unsigned long duration_us)
+ {
+       play_idle_precise(duration_us * NSEC_PER_USEC, U64_MAX);
+ }
  
  #ifdef CONFIG_HOTPLUG_CPU
  bool cpu_wait_death(unsigned int cpu, int seconds);
@@@ -218,7 -218,28 +223,7 @@@ static inline int cpuhp_smt_enable(void
  static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; }
  #endif
  
 -/*
 - * These are used for a global "mitigations=" cmdline option for toggling
 - * optional CPU mitigations.
 - */
 -enum cpu_mitigations {
 -      CPU_MITIGATIONS_OFF,
 -      CPU_MITIGATIONS_AUTO,
 -      CPU_MITIGATIONS_AUTO_NOSMT,
 -};
 -
 -extern enum cpu_mitigations cpu_mitigations;
 -
 -/* mitigations=off */
 -static inline bool cpu_mitigations_off(void)
 -{
 -      return cpu_mitigations == CPU_MITIGATIONS_OFF;
 -}
 -
 -/* mitigations=auto,nosmt */
 -static inline bool cpu_mitigations_auto_nosmt(void)
 -{
 -      return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
 -}
 +extern bool cpu_mitigations_off(void);
 +extern bool cpu_mitigations_auto_nosmt(void);
  
  #endif /* _LINUX_CPU_H_ */
diff --combined kernel/sched/idle.c
@@@ -104,7 -104,7 +104,7 @@@ static int call_cpuidle(struct cpuidle_
         * update no idle residency and return.
         */
        if (current_clr_polling_and_test()) {
-               dev->last_residency = 0;
+               dev->last_residency_ns = 0;
                local_irq_enable();
                return -EBUSY;
        }
@@@ -165,7 -165,9 +165,9 @@@ static void cpuidle_idle_call(void
         * until a proper wakeup interrupt happens.
         */
  
-       if (idle_should_enter_s2idle() || dev->use_deepest_state) {
+       if (idle_should_enter_s2idle() || dev->forced_idle_latency_limit_ns) {
+               u64 max_latency_ns;
                if (idle_should_enter_s2idle()) {
                        rcu_idle_enter();
  
                        }
  
                        rcu_idle_exit();
+                       max_latency_ns = U64_MAX;
+               } else {
+                       max_latency_ns = dev->forced_idle_latency_limit_ns;
                }
  
                tick_nohz_idle_stop_tick();
                rcu_idle_enter();
  
-               next_state = cpuidle_find_deepest_state(drv, dev);
+               next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns);
                call_cpuidle(drv, dev, next_state);
        } else {
                bool stop_tick = true;
@@@ -311,7 -317,7 +317,7 @@@ static enum hrtimer_restart idle_inject
        return HRTIMER_NORESTART;
  }
  
- void play_idle(unsigned long duration_us)
+ void play_idle_precise(u64 duration_ns, u64 latency_ns)
  {
        struct idle_timer it;
  
        WARN_ON_ONCE(current->nr_cpus_allowed != 1);
        WARN_ON_ONCE(!(current->flags & PF_KTHREAD));
        WARN_ON_ONCE(!(current->flags & PF_NO_SETAFFINITY));
-       WARN_ON_ONCE(!duration_us);
+       WARN_ON_ONCE(!duration_ns);
  
        rcu_sleep_check();
        preempt_disable();
        current->flags |= PF_IDLE;
-       cpuidle_use_deepest_state(true);
+       cpuidle_use_deepest_state(latency_ns);
  
        it.done = 0;
        hrtimer_init_on_stack(&it.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        it.timer.function = idle_inject_timer_fn;
-       hrtimer_start(&it.timer, ns_to_ktime(duration_us * NSEC_PER_USEC),
+       hrtimer_start(&it.timer, ns_to_ktime(duration_ns),
                      HRTIMER_MODE_REL_PINNED);
  
        while (!READ_ONCE(it.done))
                do_idle();
  
-       cpuidle_use_deepest_state(false);
+       cpuidle_use_deepest_state(0);
        current->flags &= ~PF_IDLE;
  
        preempt_fold_need_resched();
        preempt_enable();
  }
- EXPORT_SYMBOL_GPL(play_idle);
+ EXPORT_SYMBOL_GPL(play_idle_precise);
  
  void cpu_startup_entry(enum cpuhp_state state)
  {
@@@ -365,12 -371,6 +371,12 @@@ select_task_rq_idle(struct task_struct 
  {
        return task_cpu(p); /* IDLE tasks as never migrated */
  }
 +
 +static int
 +balance_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
 +{
 +      return WARN_ON_ONCE(1);
 +}
  #endif
  
  /*
@@@ -381,7 -381,7 +387,7 @@@ static void check_preempt_curr_idle(str
        resched_curr(rq);
  }
  
 -static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
 +static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
  {
  }
  
@@@ -466,7 -466,6 +472,7 @@@ const struct sched_class idle_sched_cla
        .set_next_task          = set_next_task_idle,
  
  #ifdef CONFIG_SMP
 +      .balance                = balance_idle,
        .select_task_rq         = select_task_rq_idle,
        .set_cpus_allowed       = set_cpus_allowed_common,
  #endif