static void update_runnables_state(void) { unsigned int nr_cpus = num_online_cpus(); unsigned int max_cpus = tegra_cpq_max_cpus(); unsigned int min_cpus = tegra_cpq_min_cpus(); unsigned int avg_nr_run = avg_nr_running(); unsigned int nr_run; if (runnables_state == DISABLED) return; for (nr_run = 1; nr_run < ARRAY_SIZE(nr_run_thresholds); nr_run++) { unsigned int nr_threshold = nr_run_thresholds[nr_run - 1]; if (nr_run_last <= nr_run) nr_threshold += NR_FSHIFT / nr_run_hysteresis; if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT_EXP))) break; } nr_run_last = nr_run; if (nr_run > 1 && (nr_cpus > max_cpus || nr_run < nr_cpus) && nr_cpus > min_cpus) { runnables_state = DOWN; } else if (nr_cpus < min_cpus || nr_run > nr_cpus) { runnables_state = UP; } else { runnables_state = IDLE; } }
static void max_cpus_change(void) { if (cpq_state == TEGRA_CPQ_DISABLED) return; if (tegra_cpq_max_cpus() < num_online_cpus()) schedule_work(&minmax_work); }
static int update_core_config(unsigned int cpunumber, bool up) { int ret = -EINVAL; unsigned int nr_cpus = num_online_cpus(); int max_cpus = tegra_cpq_max_cpus(); int min_cpus = tegra_cpq_min_cpus(); #if CPUQUIET_DEBUG_VERBOSE pr_info(CPUQUIET_TAG "%s\n", __func__); #endif if (cpq_state == TEGRA_CPQ_DISABLED || cpunumber >= nr_cpu_ids) return ret; /* sync with tegra_cpuquiet_work_func else if we are currently switching to LP and an up comes we can end up with more then 1 core up and governor stopped and !lp mode */ if (!mutex_trylock (&hotplug_lock)){ #if CPUQUIET_DEBUG_VERBOSE pr_info(CPUQUIET_TAG "%s failed to get hotplug_lock\n", __func__); #endif return -EBUSY; } if (up) { if(is_lp_cluster()) { ret = -EBUSY; } else { if (nr_cpus < max_cpus){ show_status("UP", 0, cpunumber); ret = cpu_up(cpunumber); } } } else { if (is_lp_cluster()) { ret = -EBUSY; } else { if (nr_cpus > 1 && nr_cpus > min_cpus){ show_status("DOWN", 0, cpunumber); ret = cpu_down(cpunumber); } } } mutex_unlock(&hotplug_lock); return ret; }
static void min_max_constraints_workfunc(struct work_struct *work) { int count = -1; bool up = false; unsigned int cpu; int nr_cpus = num_online_cpus(); int max_cpus = tegra_cpq_max_cpus(); int min_cpus = tegra_cpq_min_cpus(); if (cpq_state == TEGRA_CPQ_DISABLED) return; if (is_lp_cluster()) return; if (nr_cpus < min_cpus) { up = true; count = min_cpus - nr_cpus; } else if (nr_cpus > max_cpus && max_cpus >= min_cpus) { count = nr_cpus - max_cpus; } for (;count > 0; count--) { if (up) { cpu = best_core_to_turn_up(); if (cpu < nr_cpu_ids){ show_status("UP", 0, cpu); cpu_up(cpu); } else break; } else { cpu = cpumask_next(0, cpu_online_mask); if (cpu < nr_cpu_ids){ show_status("DOWN", 0, cpu); cpu_down(cpu); } else break; } } }
static void update_rq_stats_state(void) { static bool first_call = true; unsigned int rq_depth; unsigned int nr_cpu_online; unsigned int max_cpus = tegra_cpq_max_cpus(); unsigned int min_cpus = tegra_cpq_min_cpus(); static cputime64_t total_time = 0; static cputime64_t last_time; cputime64_t current_time; cputime64_t this_time = 0; int index; if (rq_stats_state == DISABLED) return; current_time = ktime_to_ms(ktime_get()); if (current_time <= start_delay){ rq_stats_state = IDLE; return; } if (first_call) { first_call = false; } else { this_time = current_time - last_time; } total_time += this_time; rq_depth = get_rq_info(); nr_cpu_online = num_online_cpus(); rq_stats_state = IDLE; if (nr_cpu_online) { index = (nr_cpu_online - 1) * 2; if ((nr_cpu_online < CONFIG_NR_CPUS) && (rq_depth >= NwNs_Threshold[index])) { if (total_time >= TwTs_Threshold[index]) { if (nr_cpu_online < max_cpus){ #if DEBUG pr_info(RQ_STATS_TAG "UP rq_depth=%d total_time=%lld NwNs_Threshold[index]=%d TwTs_Threshold[index]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", rq_depth, total_time, NwNs_Threshold[index], TwTs_Threshold[index], nr_cpu_online, min_cpus, max_cpus); #endif rq_stats_state = UP; } } } else if (rq_depth <= NwNs_Threshold[index+1]) { if (total_time >= TwTs_Threshold[index+1] ) { if ((nr_cpu_online > 1) && (nr_cpu_online > min_cpus)){ #if DEBUG pr_info(RQ_STATS_TAG "DOWN rq_depth=%d total_time=%lld NwNs_Threshold[index+1]=%d TwTs_Threshold[index+1]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", rq_depth, total_time, NwNs_Threshold[index+1], TwTs_Threshold[index+1], nr_cpu_online, min_cpus, max_cpus); #endif rq_stats_state = DOWN; } } } else { rq_stats_state = IDLE; total_time = 0; } } else { total_time = 0; } if (rq_stats_state != IDLE) { total_time = 0; } last_time = ktime_to_ms(ktime_get()); }