/*
 * 获取当前profile
 */
int pwrctrl_dfs_get_profile(void)
{
	g_cur_profile = (s32)CPUFREQ_CUR_PROFILE;
	if ((g_cur_profile < BALONG_FREQ_MIN) || (g_cur_profile > BALONG_FREQ_MAX))
	{
		g_cur_profile = BALONG_FREQ_MAX;
		cpufreq_info("m3 cpufreq return right cur_profile value? %d\n", g_cur_profile);
	}
	return g_cur_profile;
}
static void register_icc_for_cpufreq(void)
{
	s32 ret;
	u32 channel_id_set = ICC_CHN_MCORE_CCORE << 16 | MCU_CCORE_CPUFREQ;
	ret = bsp_icc_event_register(channel_id_set, (read_cb_func)balong_cpufreq_cb_getprofile, (void *)NULL, (write_cb_func)NULL, (void *)NULL);
	if (ret != BSP_OK)
	{
		cpufreq_err("icc register failed %d\n", ret);
	}
	cpufreq_info("register icc %d\n", ret);
}
static s32 balong_cpufreq_cb_getprofile(u32 channel_id , u32 len, void* context)
{
	s32 ret = 0;
	struct cpufreq_msg cm = {0};
	ret = bsp_icc_read(channel_id, (u8*)&cm, len);

	if(len != (u32)ret)
	{
		cpufreq_err("balong_cpufreq_cb_getload error \r\n");
		return -1;
	}
	g_stDfsCpuControl.enCurProfile = cm.profile;
	cpufreq_info("get icc from Mcore msg_type->>%d, source->>%d, profile->>%d\n", cm.msg_type, cm.source, cm.profile);
	return 0;
}
s32 balong_cpufreq_cb_getprofile(u32 channel_id , u32 len, void* context)
{

	s32 ret = 0;
	struct cpufreq_msg cm = {0};
	ret = bsp_icc_read(channel_id, (u8*)&cm, len);

	if((s32)len != ret)
	{
		cpufreq_err("balong_cpufreq_cb_getload error \r\n");
		return BSP_ERROR;
	}

	cpufreq_info("get icc from Mcore msg_type->>%d, source->>%d, profile->>%d\n", cm.msg_type, cm.source, cm.profile);

	return BSP_OK;
}
/*
 * Here we notify other drivers of the proposed change and the final change.
 *
 *
 *根据relation做相应动作
 */
static s32 balong_cpufreq_target(struct cpufreq_policy *policy,
				     u32 target_freq,
				     u32 relation)
{
	u32 result = 2;
	u32 new_index = 0;
	int cur_profile = 0;
	struct cpufreq_msg task_msg = {0,0,0,0};
	
	
	cpufreq_frequency_table_target(policy, balong_clockrate_table,
					   target_freq, relation, &new_index);
					   
	cpufreq_debug("target_freq %d new_index%d\n", target_freq, new_index);

	cur_profile = pwrctrl_dfs_get_profile();
	
	if ((CPUFREQ_RELATION_H == relation) && (BALONG_FREQ_MAX != cur_profile))
	{
		result = DFS_PROFILE_UP_TARGET;
	}
	else if ((CPUFREQ_RELATION_L == relation) && (BALONG_FREQ_MIN != cur_profile))
	{
		result = DFS_PROFILE_DOWN_TARGET;
	}
	else
	{
		policy->cur = balong_clockrate_table[cur_profile].frequency;
		g_cur_freq = policy->cur;
		cpufreq_info("set target relation %d, cur pro %d\n", relation, policy->cur);
		return BSP_ERROR;
	}
	
	cpufreq_frequency_target_profile(balong_clockrate_table[new_index].frequency, relation, &new_index);

	task_msg.msg_type = CPUFREQ_ADJUST_FREQ;
	task_msg.source = CPUFREQ_ACORE;
	task_msg.content = result;
	task_msg.profile = new_index;
	balong_cpufreq_icc_send(&task_msg);
	
	policy->cur = balong_clockrate_table[cur_profile].frequency;
	g_cur_freq = policy->cur;
	return BSP_OK;
}
示例#6
0
void print_i7z_single ()
{
    struct cpu_heirarchy_info chi;
    struct cpu_socket_info socket_0={.max_cpu=0, .socket_num=0, .processor_num={-1,-1,-1,-1,-1,-1,-1,-1}};
    struct cpu_socket_info socket_1={.max_cpu=0, .socket_num=1, .processor_num={-1,-1,-1,-1,-1,-1,-1,-1}};

    construct_CPU_Heirarchy_info(&chi);
    construct_sibling_list(&chi);
//      print_CPU_Heirarchy(chi);
    construct_socket_information(&chi, &socket_0, &socket_1, socket_0_num, socket_1_num);
//    print_socket_information(&socket_0);
//    print_socket_information(&socket_1);

    int printw_offset = (0) * 14;

    //Make an array size max 8 (to accomdate Nehalem-EXEX -lol) to store the core-num that are candidates for a given socket
    //removing it from here as it is already allocated in the function
    //int *core_list, core_list_size_phy, core_list_size_log;

    //iterator
    int i;

    //turbo_mode enabled/disabled flag
    char TURBO_MODE;

    double cpu_freq_cpuinfo;

    cpu_freq_cpuinfo = cpufreq_info ();
    //estimate the freq using the estimate_MHz() code that is almost mhz accurate
    cpu_freq_cpuinfo = estimate_MHz ();

    //Print a slew of information on the ncurses window
    //I already print that in the loop so..
    mvprintw (0, 0, "WAIT .... ");


    //estimate the freq using the estimate_MHz() code that is almost mhz accurate
    cpu_freq_cpuinfo = estimate_MHz ();
    mvprintw (3, 0, "True Frequency (without accounting Turbo) %0.0f MHz\n",
              cpu_freq_cpuinfo);


    //MSR number and hi:low bit of that MSR
    //This msr contains a lot of stuff, per socket wise
    //one can pass any core number and then get in multiplier etc
    int PLATFORM_INFO_MSR = 206;    //CE 15:8
    int PLATFORM_INFO_MSR_low = 8;
    int PLATFORM_INFO_MSR_high = 15;

    unsigned long long int old_val_CORE[2][numCPUs_max], new_val_CORE[2][numCPUs_max];
    unsigned long long int old_val_REF[2][numCPUs_max], new_val_REF[2][numCPUs_max];
    unsigned long long int old_val_C3[2][numCPUs_max], new_val_C3[2][numCPUs_max];
    unsigned long long int old_val_C6[2][numCPUs_max], new_val_C6[2][numCPUs_max];
    unsigned long long int old_val_C7[2][numCPUs_max], new_val_C7[2][numCPUs_max];

    unsigned long long int old_TSC[2][numCPUs_max], new_TSC[2][numCPUs_max];
    long double C0_time[2][numCPUs_max], C1_time[2][numCPUs_max],
    C3_time[2][numCPUs_max], C6_time[2][numCPUs_max], C7_time[2][numCPUs_max];
    double _FREQ[2][numCPUs_max], _MULT[2][numCPUs_max];
    struct timeval tvstart[2][numCPUs_max], tvstop[2][numCPUs_max];

    struct timespec one_second_sleep;
    one_second_sleep.tv_sec = 0;
    one_second_sleep.tv_nsec = 499999999;   // 500msec



    //Get turbo mode status by reading msr within turbo_status
    TURBO_MODE = turbo_status ();

    //Flags and other things about HT.
    int HT_ON;
    char HT_ON_str[30];

    int kk_1 = 11;

    //below variables is used to monitor if any cores went offline etc.
    int online_cpus[MAX_PROCESSORS]; //Max 2 x Nehalem-EX with total 32 threads

    double estimated_mhz=0;
    int socket_num;

    //below variables stores how many cpus were observed till date for the socket
    int max_cpus_observed=0;

    for (;;) {
        construct_CPU_Heirarchy_info(&chi);
        construct_sibling_list(&chi);
        construct_socket_information(&chi, &socket_0, &socket_1, socket_0_num, socket_1_num);


        //HT enabled if num logical > num physical cores
        if (chi.HT==1) {
            strncpy (HT_ON_str, "Hyper Threading ON\0", 30);
            HT_ON = 1;
        } else {
            strncpy (HT_ON_str, "Hyper Threading OFF\0", 30);
            HT_ON = 0;
        }

        refresh ();

        SET_ONLINE_ARRAY_PLUS1(online_cpus)

        //In the function calls below socket_num is set to the socket to print for
        //printw_offset is the offset gap between the printing of the two sockets
        //kk_1 and kk_2 are the variables that have to be set, i have to use them internally
        //so in future if there are more sockets to be printed, add more kk_*
        socket_num=0;
        printw_offset=0;

        //printf("socket0 max cpu %d\n",socket_0.max_cpu);
        //printf("socket1 max cpu %d\n",socket_0.max_cpu);


        //below code in (else case) is to handle when for 2 sockets system, cpu1 is populated and cpu0 is empty.
        //single socket code but in an intelligent manner and not assuming that cpu0 is always populated before cpu1
        if(socket_0.max_cpu>1){
            socket_num=0;
            print_i7z_socket_single(socket_0, printw_offset, PLATFORM_INFO_MSR,  PLATFORM_INFO_MSR_high, PLATFORM_INFO_MSR_low,
                                online_cpus, cpu_freq_cpuinfo, one_second_sleep, TURBO_MODE, HT_ON_str, &kk_1, old_val_CORE[socket_num],
                                old_val_REF[socket_num], old_val_C3[socket_num], old_val_C6[socket_num],old_val_C7[socket_num],
                                old_TSC[socket_num], estimated_mhz, new_val_CORE[socket_num], new_val_REF[socket_num], new_val_C3[socket_num],
                                new_val_C6[socket_num],new_val_C7[socket_num], new_TSC[socket_num], _FREQ[socket_num], _MULT[socket_num], C0_time[socket_num], C1_time[socket_num],
                                C3_time[socket_num], C6_time[socket_num],C7_time[socket_num], tvstart[socket_num], tvstop[socket_num], &max_cpus_observed);
    }else{
        socket_num=1;
        print_i7z_socket_single(socket_1, printw_offset, PLATFORM_INFO_MSR,  PLATFORM_INFO_MSR_high, PLATFORM_INFO_MSR_low,
                        online_cpus, cpu_freq_cpuinfo, one_second_sleep, TURBO_MODE, HT_ON_str, &kk_1, old_val_CORE[socket_num],
                                old_val_REF[socket_num], old_val_C3[socket_num], old_val_C6[socket_num],old_val_C7[socket_num],
                                old_TSC[socket_num], estimated_mhz, new_val_CORE[socket_num], new_val_REF[socket_num], new_val_C3[socket_num],
                                new_val_C6[socket_num],new_val_C7[socket_num], new_TSC[socket_num], _FREQ[socket_num], _MULT[socket_num], C0_time[socket_num], C1_time[socket_num],
                                C3_time[socket_num], C6_time[socket_num],C7_time[socket_num], tvstart[socket_num], tvstop[socket_num], &max_cpus_observed);
    }
    }

}
/*find a freq in all table*/
static int cpufreq_frequency_table_target(struct cpufreq_frequency_table *table,
				   unsigned int target_freq,
				   unsigned int relation,
				   unsigned int *index)
{/*lint !e578 */
	struct cpufreq_frequency_table optimal = {
		.index = ~0,
		.frequency = 0,
	};
	struct cpufreq_frequency_table suboptimal = {
		.index = ~0,
		.frequency = 0,
	};
	unsigned int i;
	/*lint --e{744} */
	switch (relation) {
	case DFS_PROFILE_UP:
		suboptimal.frequency = ~0;
		break;
	case DFS_PROFILE_DOWN:
		optimal.frequency = ~0;
		break;
	}

	for (i = 0; (table[i].frequency != (u32)CPUFREQ_TABLE_END); i++) {
		unsigned int freq = table[i].frequency;
		if (freq == (u32)CPUFREQ_ENTRY_INVALID)
			continue;
		if ((freq < balong_query_profile_table[BALONG_FREQ_MIN].cpu_frequency) || (freq > balong_query_profile_table[BALONG_FREQ_MAX].cpu_frequency))
			continue;
		switch (relation) {
		case DFS_PROFILE_UP:
			if (freq <= target_freq) {
				if (freq >= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq <= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		case DFS_PROFILE_DOWN:
			if (freq >= target_freq) {
				if (freq <= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq >= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		}
	}
	if (optimal.index > i) {
		if (suboptimal.index > i)
			return BSP_ERROR;
		*index = suboptimal.index;
	} else
		*index = optimal.index;

	return BSP_OK;
}
/*****************************************************************************
Function:   PWRCTRL_DfsMgrExcuteVoteResultCpu
Description:Handle the Profile Vote Result
Input:      enResult:   The Vote Value
Output:     None
Return:     None
Others:
*****************************************************************************/
static int  cpufreq_excute_result_cpu(u32 relation, u32 target_freq)
{
	u32 result = 2;
	u32 new_index = 0;
	int cur_profile = 0;
	struct cpufreq_msg task_msg = {0,0,0,0};

	cpufreq_frequency_table_target(balong_clockrate_table,
					   target_freq, relation, &new_index);

	cpufreq_debug("target_freq %d new_index%d\n", target_freq, new_index);

	cur_profile = pwrctrl_dfs_get_profile();
	if ((DFS_PROFILE_UP == relation) && (BALONG_FREQ_MAX != cur_profile))
	{
		result = DFS_PROFILE_UP_TARGET;
	}
	else if ((DFS_PROFILE_DOWN == relation) && (BALONG_FREQ_MIN != cur_profile))
	{
		result = DFS_PROFILE_DOWN_TARGET;
	}
	else
	{
		cpufreq_err("set target relation %d, cur pro %d\n", relation, cur_profile);
		return BSP_ERROR;
	}

	cpufreq_frequency_target_profile(balong_clockrate_table[new_index].frequency, relation, &new_index);

	task_msg.msg_type = CPUFREQ_ADJUST_FREQ;
	task_msg.source = CPUFREQ_CCORE;
	task_msg.content = result;
	task_msg.profile = new_index;
	balong_cpufreq_icc_send(&task_msg);
	g_stDfsCpuControl.enCurProfile = (u32)cur_profile;
	return BSP_OK;

}

unsigned int cpufreq_calccpu_cpuload(void)
{
	u32 end_time = 0;
	u32 idle_time = 0;
	u32 wall_time = 0;
	u32 cpu_load = 0;
	unsigned long irqlock = 0;
	local_irq_save(irqlock);
	end_time = bsp_get_slice_value();
	wall_time = get_timer_slice_delta(g_cpufreq_start_time, end_time);
	idle_time = g_ulDfsCcpuIdleTime_long;
	g_cpufreq_start_time = end_time;
	g_ulDfsCcpuIdleTime_long = 0;
	g_flowctrl_in_interr_times = 0;
	cpu_load = (wall_time == 0) ? (0) : (((wall_time - idle_time) * 100) / wall_time);
	local_irq_restore(irqlock);
	if (cpu_load > 100)
	{
		cpu_load = g_ulCCpuload;
		cpufreq_info("cpuload: %d, wall:%d, idle:%d\n", cpu_load, wall_time, idle_time);
	}
	return cpu_load;
}