Exemplo n.º 1
0
static void min_cpus_change(void)
{
	bool g_cluster = false;
    cputime64_t on_time = 0;
	
	if (cpq_state == TEGRA_CPQ_DISABLED)
		return;

	mutex_lock(tegra3_cpu_lock);

	if ((tegra_cpq_min_cpus() >= 2) && is_lp_cluster()) {
		if (switch_clk_to_gmode()){
			pr_err(CPUQUIET_TAG "min_cpus_change - switch_clk_to_gmode failed\n");
			mutex_unlock(tegra3_cpu_lock);
			return;
		}
		
		on_time = ktime_to_ms(ktime_get()) - lp_on_time;
		show_status("LP -> off - min_cpus_change", on_time, -1);

		g_cluster = true;
	}

	tegra_cpu_set_speed_cap(NULL);
	mutex_unlock(tegra3_cpu_lock);

	schedule_work(&minmax_work);

	if (g_cluster && !manual_hotplug)
		cpuquiet_device_free();
}
Exemplo n.º 2
0
static void enable_callback(struct cpuquiet_attribute *attr)
{
	int disabled = -1;

	mutex_lock(tegra3_cpu_lock);

	if (!enable && cpq_state != TEGRA_CPQ_DISABLED) {
		disabled = 1;
		cpq_state = TEGRA_CPQ_DISABLED;
	} else if (enable && cpq_state == TEGRA_CPQ_DISABLED) {
		disabled = 0;
		cpq_state = TEGRA_CPQ_IDLE;
		tegra_cpu_set_speed_cap(NULL);
	}

	mutex_unlock(tegra3_cpu_lock);

	if (disabled == -1)
		return;

	pr_info(CPUQUIET_TAG "enable=%d\n", enable);				
	
	if (disabled == 1) {
		cancel_delayed_work_sync(&cpuquiet_work);
		pr_info(CPUQUIET_TAG "enable_callback: clusterswitch disabled\n");
		cpuquiet_device_busy();
	} else if (!disabled) {
		pr_info(CPUQUIET_TAG "enable_callback: clusterswitch enabled\n");
		cpuquiet_device_free();
	}
}
Exemplo n.º 3
0
int tegra_cpuquiet_force_gmode(void)
{
    cputime64_t on_time = 0;

	if (no_lp)
		return -EBUSY;
		
	if (!is_g_cluster_present())
		return -EBUSY;

	if (cpq_state == TEGRA_CPQ_DISABLED)
		return -EBUSY;

	if (is_lp_cluster()) {
		mutex_lock(tegra3_cpu_lock);

		if (switch_clk_to_gmode()) {
			pr_err(CPUQUIET_TAG "tegra_cpuquiet_force_gmode - switch_clk_to_gmode failed\n");
    		mutex_unlock(tegra3_cpu_lock);
    		return -EBUSY;
		}
		
		on_time = ktime_to_ms(ktime_get()) - lp_on_time;
		show_status("LP -> off - force", on_time, -1);

    	mutex_unlock(tegra3_cpu_lock);

		if (!manual_hotplug)
			cpuquiet_device_free();
	}
	
	return 0;
}
Exemplo n.º 4
0
static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
{
	bool g_cluster = false;

	if (cpq_state == TEGRA_CPQ_DISABLED)
		return NOTIFY_OK;

	mutex_lock(tegra3_cpu_lock);

	if ((n >= 1) && is_lp_cluster()) {
		/* make sure cpu rate is within g-mode
		 * range before switching */
		unsigned long speed = max((unsigned long)tegra_getspeed(0),
					clk_get_min_rate(cpu_g_clk) / 1000);
		tegra_update_cpu_speed(speed);

		clk_set_parent(cpu_clk, cpu_g_clk);
		g_cluster = true;
	}

	tegra_cpu_set_speed_cap(NULL);
	mutex_unlock(tegra3_cpu_lock);

	schedule_work(&minmax_work);

	if (g_cluster)
		cpuquiet_device_free();

	return NOTIFY_OK;
}
Exemplo n.º 5
0
static void tegra_cpuquiet_work_func(struct work_struct *work)
{
	int device_busy = -1;

	mutex_lock(tegra3_cpu_lock);

	switch(cpq_state) {
		case TEGRA_CPQ_DISABLED:
		case TEGRA_CPQ_IDLE:
			break;
		case TEGRA_CPQ_SWITCH_TO_G:
			if (is_lp_cluster()) {
				if(!clk_set_parent(cpu_clk, cpu_g_clk)) {
					/*catch-up with governor target speed */
					tegra_cpu_set_speed_cap(NULL);
					/* process pending core requests*/
					device_busy = 0;
				}
			}
			break;
		case TEGRA_CPQ_SWITCH_TO_LP:
			if (!is_lp_cluster() && !no_lp &&
				!pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)
				&& num_online_cpus() == 1) {
				if (!clk_set_parent(cpu_clk, cpu_lp_clk)) {
					/*catch-up with governor target speed*/
					tegra_cpu_set_speed_cap(NULL);
					device_busy = 1;
				}
			}
			break;
		default:
			pr_err("%s: invalid tegra hotplug state %d\n",
		       __func__, cpq_state);
	}

	mutex_unlock(tegra3_cpu_lock);

	if (device_busy == 1) {
		cpuquiet_device_busy();
	} else if (!device_busy) {
		apply_core_config();
		cpuquiet_device_free();
	}
}
Exemplo n.º 6
0
static void set_manual_hotplug(unsigned int mode)
{
	if (manual_hotplug == mode)
		return;
     
	manual_hotplug = mode;	

	pr_info(CPUQUIET_TAG "manual_hotplug=%d\n", manual_hotplug);
		
	// stop governor
	if (manual_hotplug) {
		cancel_delayed_work_sync(&cpuquiet_work);
		cpuquiet_device_busy();
		schedule_work(&cpu_core_state_work);
	} else {
		cpuquiet_device_free();
	}	    
}
Exemplo n.º 7
0
static void enable_callback(struct cpuquiet_attribute *attr)
{
	mutex_lock(tegra3_cpu_lock);

	if (!enable && cpq_state != TEGRA_CPQ_DISABLED) {
		cpq_state = TEGRA_CPQ_DISABLED;
		mutex_unlock(tegra3_cpu_lock);
		cancel_delayed_work_sync(&cpuquiet_work);
		pr_info("Tegra cpuquiet clusterswitch disabled\n");
		cpuquiet_device_busy();
		mutex_lock(tegra3_cpu_lock);
	} else if (enable && cpq_state == TEGRA_CPQ_DISABLED) {
		cpq_state = TEGRA_CPQ_IDLE;
		pr_info("Tegra cpuquiet clusterswitch enabled\n");
		tegra_cpu_set_speed_cap(NULL);
		cpuquiet_device_free();
	}

	mutex_unlock(tegra3_cpu_lock);
}
Exemplo n.º 8
0
void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
{
	if (!is_g_cluster_present())
		return;

	if (cpq_state == TEGRA_CPQ_DISABLED)
		return;

	if (suspend) {
		cpq_state = TEGRA_CPQ_IDLE;

		/* Switch to G-mode if suspend rate is high enough */
		if (is_lp_cluster() && (cpu_freq >= idle_bottom_freq)) {
			clk_set_parent(cpu_clk, cpu_g_clk);
			cpuquiet_device_free();
		}
		return;
	}

	if (is_lp_cluster() && pm_qos_request(PM_QOS_MIN_ONLINE_CPUS) >= 2) {
		if (cpq_state != TEGRA_CPQ_SWITCH_TO_G) {
			/* Force switch */
			cpq_state = TEGRA_CPQ_SWITCH_TO_G;
			queue_delayed_work(
				cpuquiet_wq, &cpuquiet_work, up_delay);
		}
		return;
	}

	if (is_lp_cluster() && (cpu_freq >= idle_top_freq || no_lp)) {
		cpq_state = TEGRA_CPQ_SWITCH_TO_G;
		queue_delayed_work(cpuquiet_wq, &cpuquiet_work, up_delay);
	} else if (!is_lp_cluster() && !no_lp &&
		   cpu_freq <= idle_bottom_freq) {
		cpq_state = TEGRA_CPQ_SWITCH_TO_LP;
		queue_delayed_work(cpuquiet_wq, &cpuquiet_work, down_delay);
	} else {
		cpq_state = TEGRA_CPQ_IDLE;
	}
}
Exemplo n.º 9
0
void tegra_cpuquiet_device_free(void)
{
	if (!manual_hotplug)
		cpuquiet_device_free();
}
Exemplo n.º 10
0
static void tegra_cpuquiet_work_func(struct work_struct *work)
{
	int device_busy = -1;
	cputime64_t on_time = 0;

#if CPUQUIET_DEBUG_VERBOSE
	pr_info(CPUQUIET_TAG "%s\n", __func__);
#endif

	if (!mutex_trylock (&hotplug_lock)){
#if CPUQUIET_DEBUG_VERBOSE
		pr_info(CPUQUIET_TAG "%s failed to get hotplug_lock\n", __func__);
#endif
		return;
	}

	mutex_lock(tegra3_cpu_lock);
	
	switch(cpq_state) {
		case TEGRA_CPQ_DISABLED:
		case TEGRA_CPQ_IDLE:
			break;
		case TEGRA_CPQ_SWITCH_TO_G:
			if (is_lp_cluster()) {
				if (!switch_clk_to_gmode()) {
					on_time = ktime_to_ms(ktime_get()) - lp_on_time;
					show_status("LP -> off", on_time, -1);
					/*catch-up with governor target speed */
					tegra_cpu_set_speed_cap(NULL);
					device_busy = 0;
				} else
					pr_err(CPUQUIET_TAG "tegra_cpuquiet_work_func - switch_clk_to_gmode failed\n");				
			}
#if CPUQUIET_DEBUG_VERBOSE
			else
				pr_info(CPUQUIET_TAG "skipping queued TEGRA_CPQ_SWITCH_TO_G - cond failed\n");
#endif
			break;
		case TEGRA_CPQ_SWITCH_TO_LP:
			if (lp_possible()) {
				if (!switch_clk_to_lpmode()) {
					show_status("LP -> on", 0, -1);
					/*catch-up with governor target speed*/
					tegra_cpu_set_speed_cap(NULL);
					device_busy = 1;
					lp_on_time = ktime_to_ms(ktime_get());
				}
#if CPUQUIET_DEBUG_VERBOSE
				else
					pr_info(CPUQUIET_TAG "skipping queued TEGRA_CPQ_SWITCH_TO_LP - switch_clk_to_lpmode failed\n");
#endif
			}
#if CPUQUIET_DEBUG_VERBOSE
			else
				pr_info(CPUQUIET_TAG "skipping queued TEGRA_CPQ_SWITCH_TO_LP - cond failed\n");
#endif			
			break;
		default:
			pr_err(CPUQUIET_TAG "%s: invalid tegra hotplug state %d\n",
		       __func__, cpq_state);
	}
	
	mutex_unlock(tegra3_cpu_lock);

	mutex_unlock(&hotplug_lock);
	
	if (!manual_hotplug){
		if (device_busy == 1) {
			cpuquiet_device_busy();
		} else if (!device_busy) {
			cpuquiet_device_free();
		}
	}
}