/* * 获取当前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; }
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; }