diff options
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/Kconfig | 7 | ||||
-rw-r--r-- | drivers/cpuidle/Kconfig.arm | 1 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 2 | ||||
-rw-r--r-- | drivers/cpuidle/driver.c | 11 | ||||
-rw-r--r-- | drivers/cpuidle/governors/ladder.c | 4 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 44 | ||||
-rw-r--r-- | drivers/cpuidle/sysfs.c | 2 |
7 files changed, 30 insertions, 41 deletions
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 1b96fb91d32c..32748c36c477 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -15,12 +15,7 @@ config CPU_IDLE if CPU_IDLE config CPU_IDLE_MULTIPLE_DRIVERS - bool "Support multiple cpuidle drivers" - default n - help - Allows the cpuidle framework to use different drivers for each CPU. - This is useful if you have a system with different CPU latencies and - states. If unsure say N. + bool config CPU_IDLE_GOV_LADDER bool "Ladder governor (for periodic timer tick)" diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index b6d69e899f5d..a186dec8e5df 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -10,6 +10,7 @@ config ARM_ARMADA_370_XP_CPUIDLE config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" depends on ARCH_VEXPRESS_TC2_PM + depends on MCPM select ARM_CPU_SUSPEND select CPU_IDLE_MULTIPLE_DRIVERS help diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index cb7019977c50..ee9df5e3f5eb 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -119,11 +119,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, ktime_t time_start, time_end; s64 diff; + trace_cpu_idle_rcuidle(index, dev->cpu); time_start = ktime_get(); entered_state = target_state->enter(dev, drv, index); time_end = ktime_get(); + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); if (!cpuidle_state_is_coupled(dev, drv, entered_state)) local_irq_enable(); diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 9634f20e3926..e431d11abf8d 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -182,10 +182,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) static int poll_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - ktime_t t1, t2; - s64 diff; - - t1 = ktime_get(); local_irq_enable(); if (!current_set_polling_and_test()) { while (!need_resched()) @@ -193,13 +189,6 @@ static int poll_idle(struct cpuidle_device *dev, } current_clr_polling(); - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - return index; } diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 9f08e8cce1af..044ee0df5871 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -144,7 +144,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; - for (i = 0; i < drv->state_count; i++) { + for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { state = &drv->states[i]; lstate = &ldev->states[i]; @@ -156,7 +156,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, if (i < drv->state_count - 1) lstate->threshold.promotion_time = state->exit_latency; - if (i > 0) + if (i > CPUIDLE_DRIVER_STATE_START) lstate->threshold.demotion_time = state->exit_latency; } diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c4f80c15a48d..27702742b319 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -31,11 +31,11 @@ * The default values do not overflow. */ #define BUCKETS 12 -#define INTERVALS 8 +#define INTERVAL_SHIFT 3 +#define INTERVALS (1UL << INTERVAL_SHIFT) #define RESOLUTION 1024 #define DECAY 8 #define MAX_INTERESTING 50000 -#define STDDEV_THRESH 400 /* @@ -134,15 +134,12 @@ struct menu_device { #define LOAD_INT(x) ((x) >> FSHIFT) #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) -static int get_loadavg(void) +static inline int get_loadavg(unsigned long load) { - unsigned long this = this_cpu_load(); - - - return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10; + return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10; } -static inline int which_bucket(unsigned int duration) +static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters) { int bucket = 0; @@ -152,7 +149,7 @@ static inline int which_bucket(unsigned int duration) * This allows us to calculate * E(duration)|iowait */ - if (nr_iowait_cpu(smp_processor_id())) + if (nr_iowaiters) bucket = BUCKETS/2; if (duration < 10) @@ -175,16 +172,16 @@ static inline int which_bucket(unsigned int duration) * to be, the higher this multiplier, and thus the higher * the barrier to go to an expensive C state. */ -static inline int performance_multiplier(void) +static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load) { int mult = 1; /* for higher loadavg, we are more reluctant */ - mult += 2 * get_loadavg(); + mult += 2 * get_loadavg(load); /* for IO wait tasks (per cpu!) we add 5x each */ - mult += 10 * nr_iowait_cpu(smp_processor_id()); + mult += 10 * nr_iowaiters; return mult; } @@ -228,7 +225,10 @@ again: max = value; } } - do_div(avg, divisor); + if (divisor == INTERVALS) + avg >>= INTERVAL_SHIFT; + else + do_div(avg, divisor); /* Then try to determine standard deviation */ stddev = 0; @@ -239,7 +239,11 @@ again: stddev += diff * diff; } } - do_div(stddev, divisor); + if (divisor == INTERVALS) + stddev >>= INTERVAL_SHIFT; + else + do_div(stddev, divisor); + /* * The typical interval is obtained when standard deviation is small * or standard deviation is small compared to the average interval. @@ -289,7 +293,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); int i; unsigned int interactivity_req; - struct timespec t; + unsigned long nr_iowaiters, cpu_load; if (data->needs_update) { menu_update(drv, dev); @@ -303,12 +307,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) return 0; /* determine the expected residency time, round up */ - t = ktime_to_timespec(tick_nohz_get_sleep_length()); - data->next_timer_us = - t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC; - + data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length()); - data->bucket = which_bucket(data->next_timer_us); + get_iowait_load(&nr_iowaiters, &cpu_load); + data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); /* * Force the result of multiplication to be 64 bits even if both @@ -326,7 +328,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * duration / latency ratio. Adjust the latency limit if * necessary. */ - interactivity_req = data->predicted_us / performance_multiplier(); + interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); if (latency_req > interactivity_req) latency_req = interactivity_req; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index efe2f175168f..97c5903b4606 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -445,7 +445,7 @@ static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) #define define_one_driver_ro(_name, show) \ static struct cpuidle_driver_attr attr_driver_##_name = \ - __ATTR(_name, 0644, show, NULL) + __ATTR(_name, 0444, show, NULL) struct cpuidle_driver_kobj { struct cpuidle_driver *drv; |