small-package/luci-app-amlogic/root/usr/sbin/fixcpufreq.pl

166 lines
4.0 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use File::Basename;
my $uci_config_name;
if(-f "/etc/config/amlogic") {
$uci_config_name="amlogic";
} elsif(-f "/etc/config/cpufreq") {
$uci_config_name="cpufreq";
} else {
print "Can not found amlogic or cpufreq config file!\n";
exit(0);
}
my @policy_ids;
my @policy_homes = </sys/devices/system/cpu/cpufreq/policy?>;
if(@policy_homes) {
foreach my $policy_home (@policy_homes) {
push @policy_ids, substr($policy_home, -1);
}
} else {
print "Can not found any policy!\n";
exit 0;
}
our $need_commit = 0;
for(my $i=0; $i <= $#policy_ids; $i++) {
&fix_invalid_value($uci_config_name, $policy_ids[$i], $policy_homes[$i]);
}
if($need_commit > 0) {
&uci_commit($uci_config_name);
}
exit 0;
################################# function ####################################
sub fix_invalid_value {
my($uci_config, $policy_id, $policy_home) = @_;
my %gove_hash = &get_gove_hash($policy_home);
my @freqs = &get_freq_list($policy_home);
my %freq_hash = &get_freq_hash(@freqs);
my $min_freq = &get_min_freq(@freqs);
my $max_freq = &get_max_freq(@freqs);
my $uci_section = "settings";
my $uci_option;
if($uci_config eq "cpufreq" ) {
$uci_option = "governor";
} else {
$uci_option = "governor" . $policy_id;
}
# 如果未设置 governor, 或该 goveernor 不存在, 则修败默认值为 schedutil
my $config_gove = &uci_get_by_type($uci_config, $uci_section, $uci_option, "NA");
if( ($config_gove eq "NA") ||
($gove_hash{$config_gove} != 1)) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, "schedutil");
$need_commit++;
}
# 如果出现不存在的 minfreq, 则修改为实际的 min_freq
if($uci_config eq "cpufreq" ) {
# "minifreq" is a spelling error that has always existed in the upstream source code
$uci_option = "minifreq";
} else {
$uci_option = "minfreq" . $policy_id;
}
my $config_min_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
if($freq_hash{$config_min_freq} != 1) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, $min_freq);
$need_commit++;
}
# 如果出现不存在的 maxfreq
# 或 maxfreq < minfreq, 则修改为实际的 max_freq
if($uci_config eq "cpufreq" ) {
$uci_option = "maxfreq";
} else {
$uci_option = "maxfreq" . $policy_id;
}
my $config_max_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
if( ( $freq_hash{$config_max_freq} != 1) ||
( $config_max_freq < $config_min_freq)) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, $max_freq);
$need_commit++;
}
}
sub get_freq_list {
my $policy_home = shift;
my @ret_ary;
open my $fh, "<", "${policy_home}/scaling_available_frequencies" or die;
$_ = <$fh>;
chomp;
@ret_ary = split /\s+/;
close($fh);
return @ret_ary;
}
sub get_freq_hash {
my @freq_ary = @_;
my %ret_hash;
foreach my $freq (@freq_ary) {
if($freq =~ m/\d+/) {
$ret_hash{$freq} = 1;
}
}
return %ret_hash;
}
sub get_min_freq {
my @freq_ary = @_;
return (sort {$a<=>$b} @freq_ary)[0];
}
sub get_max_freq {
my @freq_ary = @_;
return (sort {$a<=>$b} @freq_ary)[-1];
}
sub get_gove_hash {
my $policy_home = shift;
my %ret_hash;
open my $fh, "<", "${policy_home}/scaling_available_governors" or die;
$_ = <$fh>;
chomp;
my @gov_ary = split /\s+/;
foreach my $gov (@gov_ary) {
#print "gov: $gov\n";
if($gov =~ m/\w+/) {
$ret_hash{$gov} = 1;
}
}
close($fh);
return %ret_hash;
}
sub uci_get_by_type {
my($config,$section,$option,$default) = @_;
my $ret;
$ret=`uci get ${config}.\@${section}\[0\].${option} 2>/dev/null`;
# 消除回车换行
$ret =~ s/[\n\r]//g;
if($ret eq '') {
return $default;
} else {
return $ret;
}
}
sub uci_set_by_type {
my($config,$section,$option,$value) = @_;
my $ret;
system("uci set ${config}.\@${section}\[0\].${option}=${value}");
return;
}
sub uci_commit {
my $config = shift;
system("uci commit ${config}");
return;
}