1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
# Copyright 2017 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from _hardware import HardwareException, Expectation
from _hardware_android import HardwareAndroid
from collections import namedtuple
import itertools
CPU_CLOCK_RATE = 1670400
GPU_CLOCK_RATE = 510000000
DEVFREQ_DIRNAME = '/sys/class/devfreq'
DEVFREQ_THROTTLE = 0.74
DEVFREQ_BLACKLIST = ('b00000.qcom,kgsl-3d0', 'soc:qcom,kgsl-busmon',
'soc:qcom,m4m')
DevfreqKnobs = namedtuple('knobs',
('available_governors', 'available_frequencies',
'governor', 'min_freq', 'max_freq', 'cur_freq'))
class HardwarePixel(HardwareAndroid):
def __init__(self, adb):
HardwareAndroid.__init__(self, adb)
self._discover_devfreqs()
def __enter__(self):
HardwareAndroid.__enter__(self)
self._lock_clocks()
return self
def __exit__(self, exception_type, exception_value, exception_traceback):
# pixel struggles waking up; just pull a hard reboot.
self._adb.reboot()
def _lock_clocks(self):
if not self._adb.is_root():
return
self._adb.shell('\n'.join(['''\
stop thermal-engine
stop thermald
stop perfd
stop mpdecision''',
# enable and lock the two fast cores.
'''
for N in 3 2; do
echo 1 > /sys/devices/system/cpu/cpu$N/online
echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
# turn off the two slow cores
'''
for N in 1 0; do
echo 0 > /sys/devices/system/cpu/cpu$N/online
done''',
# gpu perf commands from
# https://developer.qualcomm.com/qfile/28823/lm80-p0436-11_adb_commands.pdf
'''
echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
echo 1 > /sys/class/kgsl/kgsl-3d0/force_bus_on
echo 1 > /sys/class/kgsl/kgsl-3d0/force_rail_on
echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
echo 1000000 > /sys/class/kgsl/kgsl-3d0/idle_timer
echo userspace > /sys/class/kgsl/kgsl-3d0/devfreq/governor
echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo 2 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
echo 2 > /sys/class/kgsl/kgsl-3d0/thermal_pwrlevel
echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
echo %i > /sys/class/kgsl/kgsl-3d0/max_gpuclk
echo %i > /sys/class/kgsl/kgsl-3d0/gpuclk''' %
tuple(GPU_CLOCK_RATE for _ in range(4))] + \
self._devfreq_lock_cmds))
def _unlock_clocks(self):
if not self._adb.is_root():
return
self._adb.shell('\n'.join(
self._devfreq_unlock_cmds + [
# restore gpu settings to default.
'''
echo 133000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
echo 600000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
echo 0 > /sys/class/kgsl/kgsl-3d0/gpuclk
echo msm-adreno-tz > /sys/class/kgsl/kgsl-3d0/devfreq/governor
echo 6 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo 1 > /sys/class/kgsl/kgsl-3d0/thermal_pwrlevel
echo 0 > /sys/class/kgsl/kgsl-3d0/idle_timer
echo 0 > /sys/class/kgsl/kgsl-3d0/force_clk_on
echo 0 > /sys/class/kgsl/kgsl-3d0/force_rail_on
echo 0 > /sys/class/kgsl/kgsl-3d0/force_bus_on
echo 1 > /sys/class/kgsl/kgsl-3d0/bus_split''',
# turn the disabled cores back on.
'''
for N in 0 1; do
echo 1 > /sys/devices/system/cpu/cpu$N/online
done''',
# unlock the 2 enabled big cores.
'''
for N in 2 3; do
echo 307200 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
echo 2150400 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
echo sched > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
done''',
'''
start mpdecision
start perfd
start thermald
start thermal-engine''']))
def sanity_check(self):
HardwareAndroid.sanity_check(self)
if not self._adb.is_root():
return
result = self._adb.check(' '.join(
['cat',
'/sys/class/power_supply/battery/capacity',
'/sys/devices/system/cpu/online'] + \
['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i
for i in range(2, 4)] + \
['/sys/class/kgsl/kgsl-3d0/thermal_pwrlevel',
'/sys/kernel/debug/clk/gpu_gx_gfx3d_clk/measure',
'/sys/kernel/debug/clk/bimc_clk/measure',
'/sys/class/thermal/thermal_zone22/temp',
'/sys/class/thermal/thermal_zone23/temp'] + \
self._devfreq_sanity_knobs))
expectations = \
[Expectation(int, min_value=30, name='battery', sleeptime=30*60),
Expectation(str, exact_value='2-3', name='online cpus')] + \
[Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i)
for i in range(2, 4)] + \
[Expectation(int, exact_value=2, name='gpu thermal power level'),
Expectation(long, min_value=(GPU_CLOCK_RATE - 5000),
max_value=(GPU_CLOCK_RATE + 5000),
name='measured gpu clock'),
Expectation(long, min_value=902390000, max_value=902409999,
name='measured ddr clock', sleeptime=10),
Expectation(int, max_value=41000, name='pm8994_tz temperature'),
Expectation(int, max_value=40, name='msm_therm temperature')] + \
self._devfreq_sanity_expectations
Expectation.check_all(expectations, result.splitlines())
def _discover_devfreqs(self):
self._devfreq_lock_cmds = list()
self._devfreq_unlock_cmds = list()
self._devfreq_sanity_knobs = list()
self._devfreq_sanity_expectations = list()
results = iter(self._adb.check('''\
KNOBS='%s'
for DEVICE in %s/*; do
if cd $DEVICE && ls $KNOBS >/dev/null; then
basename $DEVICE
cat $KNOBS
fi
done 2>/dev/null''' %
(' '.join(DevfreqKnobs._fields), DEVFREQ_DIRNAME)).splitlines())
while True:
batch = tuple(itertools.islice(results, 1 + len(DevfreqKnobs._fields)))
if not batch:
break
devfreq = batch[0]
if devfreq in DEVFREQ_BLACKLIST:
continue
path = '%s/%s' % (DEVFREQ_DIRNAME, devfreq)
knobs = DevfreqKnobs(*batch[1:])
if not 'performance' in knobs.available_governors.split():
print('WARNING: devfreq %s does not have performance governor' % path)
continue
self._devfreq_lock_cmds.append('echo performance > %s/governor' % path)
self._devfreq_unlock_cmds.append('echo %s > %s/governor' %
(knobs.governor, path))
frequencies = map(int, knobs.available_frequencies.split())
if frequencies:
# choose the lowest frequency that is >= DEVFREQ_THROTTLE * max.
frequencies.sort()
target = DEVFREQ_THROTTLE * frequencies[-1]
idx = len(frequencies) - 1
while idx > 0 and frequencies[idx - 1] >= target:
idx -= 1
bench_frequency = frequencies[idx]
self._devfreq_lock_cmds.append('echo %i > %s/min_freq' %
(bench_frequency, path))
self._devfreq_lock_cmds.append('echo %i > %s/max_freq' %
(bench_frequency, path))
self._devfreq_unlock_cmds.append('echo %s > %s/min_freq' %
(knobs.min_freq, path))
self._devfreq_unlock_cmds.append('echo %s > %s/max_freq' %
(knobs.max_freq, path))
self._devfreq_sanity_knobs.append('%s/cur_freq' % path)
self._devfreq_sanity_expectations.append(
Expectation(int, exact_value=bench_frequency,
name='%s/cur_freq' % path))
|