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;
	}
}
Exemple #2
0
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);
}
Exemple #3
0
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;
}
Exemple #4
0
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());
}