1 # Copyright 2017 Google Inc. 2 # 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 from _hardware import HardwareException, Expectation 7 from _hardware_android import HardwareAndroid 8 from collections import namedtuple 9 import itertools 10 11 CPU_CLOCK_RATE = 1670400 12 GPU_CLOCK_RATE = 510000000 13 14 DEVFREQ_DIRNAME = '/sys/class/devfreq' 15 DEVFREQ_THROTTLE = 0.74 16 DEVFREQ_BLACKLIST = ('b00000.qcom,kgsl-3d0', 'soc:qcom,kgsl-busmon', 17 'soc:qcom,m4m') 18 DevfreqKnobs = namedtuple('knobs', 19 ('available_governors', 'available_frequencies', 20 'governor', 'min_freq', 'max_freq', 'cur_freq')) 21 22 class HardwarePixel(HardwareAndroid): 23 def __init__(self, adb): 24 HardwareAndroid.__init__(self, adb) 25 self._discover_devfreqs() 26 27 def __enter__(self): 28 HardwareAndroid.__enter__(self) 29 if not self._adb.is_root(): 30 return self 31 32 self._adb.shell('\n'.join([ 33 # enable and lock the two fast cores. 34 ''' 35 for N in 3 2; do 36 echo 1 > /sys/devices/system/cpu/cpu$N/online 37 echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor 38 echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq 39 echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq 40 echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed 41 done''' % tuple(CPU_CLOCK_RATE for _ in range(3)), 42 43 # turn off the two slow cores 44 ''' 45 for N in 1 0; do 46 echo 0 > /sys/devices/system/cpu/cpu$N/online 47 done''', 48 49 # gpu perf commands from 50 # https://developer.qualcomm.com/qfile/28823/lm80-p0436-11_adb_commands.pdf 51 ''' 52 echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split 53 echo 1 > /sys/class/kgsl/kgsl-3d0/force_bus_on 54 echo 1 > /sys/class/kgsl/kgsl-3d0/force_rail_on 55 echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on 56 echo 1000000 > /sys/class/kgsl/kgsl-3d0/idle_timer 57 echo userspace > /sys/class/kgsl/kgsl-3d0/devfreq/governor 58 echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel 59 echo 2 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel 60 echo 2 > /sys/class/kgsl/kgsl-3d0/thermal_pwrlevel 61 echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq 62 echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq 63 echo %i > /sys/class/kgsl/kgsl-3d0/max_gpuclk 64 echo %i > /sys/class/kgsl/kgsl-3d0/gpuclk''' % 65 tuple(GPU_CLOCK_RATE for _ in range(4))] + \ 66 67 self._devfreq_lock_cmds)) 68 69 return self 70 71 def sanity_check(self): 72 HardwareAndroid.sanity_check(self) 73 74 if not self._adb.is_root(): 75 return 76 77 result = self._adb.check(' '.join( 78 ['cat', 79 '/sys/class/power_supply/battery/capacity', 80 '/sys/devices/system/cpu/online'] + \ 81 ['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i 82 for i in range(2, 4)] + \ 83 ['/sys/class/kgsl/kgsl-3d0/thermal_pwrlevel', 84 '/sys/kernel/debug/clk/gpu_gx_gfx3d_clk/measure', 85 '/sys/kernel/debug/clk/bimc_clk/measure', 86 '/sys/class/thermal/thermal_zone22/temp', 87 '/sys/class/thermal/thermal_zone23/temp'] + \ 88 self._devfreq_sanity_knobs)) 89 90 expectations = \ 91 [Expectation(int, min_value=30, name='battery', sleeptime=30*60), 92 Expectation(str, exact_value='2-3', name='online cpus')] + \ 93 [Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i) 94 for i in range(2, 4)] + \ 95 [Expectation(int, exact_value=2, name='gpu thermal power level'), 96 Expectation(long, min_value=(GPU_CLOCK_RATE - 5000), 97 max_value=(GPU_CLOCK_RATE + 5000), 98 name='measured gpu clock'), 99 Expectation(long, min_value=902390000, max_value=902409999, 100 name='measured ddr clock', sleeptime=10), 101 Expectation(int, max_value=41000, name='pm8994_tz temperature'), 102 Expectation(int, max_value=40, name='msm_therm temperature')] + \ 103 self._devfreq_sanity_expectations 104 105 Expectation.check_all(expectations, result.splitlines()) 106 107 def _discover_devfreqs(self): 108 self._devfreq_lock_cmds = list() 109 self._devfreq_sanity_knobs = list() 110 self._devfreq_sanity_expectations = list() 111 112 results = iter(self._adb.check('''\ 113 KNOBS='%s' 114 for DEVICE in %s/*; do 115 if cd $DEVICE && ls $KNOBS >/dev/null; then 116 basename $DEVICE 117 cat $KNOBS 118 fi 119 done 2>/dev/null''' % 120 (' '.join(DevfreqKnobs._fields), DEVFREQ_DIRNAME)).splitlines()) 121 122 while True: 123 batch = tuple(itertools.islice(results, 1 + len(DevfreqKnobs._fields))) 124 if not batch: 125 break 126 127 devfreq = batch[0] 128 if devfreq in DEVFREQ_BLACKLIST: 129 continue 130 131 path = '%s/%s' % (DEVFREQ_DIRNAME, devfreq) 132 133 knobs = DevfreqKnobs(*batch[1:]) 134 if not 'performance' in knobs.available_governors.split(): 135 print('WARNING: devfreq %s does not have performance governor' % path) 136 continue 137 138 self._devfreq_lock_cmds.append('echo performance > %s/governor' % path) 139 140 frequencies = map(int, knobs.available_frequencies.split()) 141 if frequencies: 142 # choose the lowest frequency that is >= DEVFREQ_THROTTLE * max. 143 frequencies.sort() 144 target = DEVFREQ_THROTTLE * frequencies[-1] 145 idx = len(frequencies) - 1 146 while idx > 0 and frequencies[idx - 1] >= target: 147 idx -= 1 148 bench_frequency = frequencies[idx] 149 self._devfreq_lock_cmds.append('echo %i > %s/min_freq' % 150 (bench_frequency, path)) 151 self._devfreq_lock_cmds.append('echo %i > %s/max_freq' % 152 (bench_frequency, path)) 153 self._devfreq_sanity_knobs.append('%s/cur_freq' % path) 154 self._devfreq_sanity_expectations.append( 155 Expectation(int, exact_value=bench_frequency, 156 name='%s/cur_freq' % path)) 157