1 # Copyright (c) 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import glob 6 import logging 7 import os 8 9 from autotest_lib.client.bin import test, utils 10 from autotest_lib.client.common_lib import error 11 12 class kernel_Delay(test.test): 13 """ 14 Test to ensure that udelay() delays at least as long as requested 15 (as compared to ktime()). 16 17 Test a variety of delays at mininmum and maximum cpu frequencies. 18 19 """ 20 version = 1 21 22 # Module not present prior to 3.8. From 4.4 on, module renamed. 23 MIN_KERNEL_VER = '3.8' 24 OLD_MODULE_NAME = 'udelay_test' 25 NEW_KERNEL_VER = '4.4' 26 NEW_MODULE_NAME = 'test_udelay' 27 28 UDELAY_PATH = '/sys/kernel/debug/udelay_test' 29 QUIET_GOVERNOR_PATH = '/sys/devices/system/cpu/cpuquiet/current_governor' 30 GOVERNOR_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' 31 SETSPEED_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_setspeed' 32 CUR_FREQ_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq' 33 CPUFREQ_AVAIL_GOVERNORS_PATH = ( 34 '/sys/devices/system/cpu/cpu0/cpufreq/' 35 'scaling_available_governors') 36 CPUFREQ_AVAIL_FREQS_PATH = ( 37 '/sys/devices/system/cpu/cpu0/cpufreq/' 38 'scaling_available_frequencies') 39 40 # Test a variety of delays 41 # 1..200, 200..500 (by 10), 500..2000 (by 100) 42 DELAYS = range(1, 200) + range(200, 500, 10) + range(500, 2001, 100) 43 ITERATIONS = 100 44 45 _governor_paths = [] 46 _setspeed_paths = [] 47 _cur_freq_paths = [] 48 49 def _set_file(self, contents, filename): 50 """ 51 Write a string to a file. 52 53 @param contents: the contents to write to the file 54 @param filename: the filename to use 55 56 """ 57 logging.debug('setting %s to %s', filename, contents) 58 with open(filename, 'w') as f: 59 f.write(contents) 60 61 62 def _get_file(self, filename): 63 """ 64 Read a string from a file. 65 66 @returns: the contents of the file (string) 67 68 """ 69 with open(filename, 'r') as f: 70 return f.read() 71 72 73 def _get_freqs(self): 74 """ 75 Get the current CPU frequencies. 76 77 @returns: the CPU frequencies of each CPU (list of int) 78 79 """ 80 return [int(self._get_file(p)) for p in self._cur_freq_paths] 81 82 83 def _get_freqs_string(self): 84 """ 85 Get the current CPU frequencies. 86 87 @returns: the CPU frequencies of each CPU (string) 88 89 """ 90 return ' '.join(str(x) for x in self._get_freqs()) 91 92 93 def _get_governors(self): 94 """ 95 Get the current CPU governors. 96 97 @returns: the CPU governors of each CPU (list of string) 98 99 """ 100 return [self._get_file(p).rstrip() for p in self._governor_paths] 101 102 103 def _get_quiet_governor(self): 104 """ 105 Get the current CPU quiet governor. 106 107 @returns: the CPU quiet governor or None if it does not exist (string) 108 109 """ 110 if os.path.isfile(self.QUIET_GOVERNOR_PATH): 111 return self._get_file(self.QUIET_GOVERNOR_PATH).rstrip() 112 else: 113 return None 114 115 116 def _reset_freq(self, initial_governors, initial_quiet_governor): 117 """ 118 Unlimit the CPU frequency. 119 120 @param initial_governors: list of initial governors to reset state to 121 @param initial_quiet_governor: initial quiet governor to reset state to 122 123 """ 124 for p, g in zip(self._governor_paths, initial_governors): 125 self._set_file(g, p) 126 if initial_quiet_governor and os.path.isfile(self.QUIET_GOVERNOR_PATH): 127 self._set_file(initial_quiet_governor, self.QUIET_GOVERNOR_PATH) 128 129 130 def _set_freq(self, freq): 131 """ 132 Set the CPU frequency. 133 134 @param freq: desired CPU frequency 135 136 """ 137 # Prevent CPUs from going up and down during the test if the option 138 # is available. 139 if os.path.isfile(self.QUIET_GOVERNOR_PATH): 140 logging.info('changing to userspace cpuquiet governor'); 141 self._set_file('userspace', self.QUIET_GOVERNOR_PATH) 142 143 for p in self._governor_paths: 144 self._set_file('userspace', p) 145 for p in self._setspeed_paths: 146 self._set_file(str(freq), p) 147 logging.info( 148 'cpu frequencies set to %s with userspace governor', 149 self._get_freqs_string()) 150 self._check_freq(freq) 151 152 153 def _check_freq(self, freq): 154 """ 155 Check the CPU frequencies are set as requested. 156 157 @param freq: desired CPU frequency 158 159 """ 160 for p in self._governor_paths: 161 governor = self._get_file(p).rstrip() 162 if governor != 'userspace': 163 raise error.TestFail('governor changed from userspace to %s' % ( 164 governor)) 165 for p in self._setspeed_paths: 166 speed = int(self._get_file(p)) 167 if speed != freq: 168 raise error.TestFail('setspeed changed from %s to %s' % ( 169 freq, speed)) 170 freqs = self._get_freqs() 171 for f in freqs: 172 if f != freq: 173 raise error.TestFail('frequency set to %s instead of %s' % ( 174 f, freq)) 175 176 177 def _test_udelay(self, usecs): 178 """ 179 Test udelay() for a given amount of time. 180 181 @param usecs: number of usecs to delay for each iteration 182 183 """ 184 self._set_file('%d %d' % (usecs, self.ITERATIONS), self.UDELAY_PATH) 185 with open(self.UDELAY_PATH, 'r') as f: 186 for line in f: 187 line = line.rstrip() 188 logging.info('result: %s', line) 189 if 'FAIL' in line: 190 raise error.TestFail('udelay failed: %s' % line) 191 192 def _test_all_delays(self): 193 """ 194 Test udelay() over all configured delays. 195 196 """ 197 for usecs in self.DELAYS: 198 self._test_udelay(usecs) 199 200 def _test_userspace(self): 201 """ 202 Test udelay() using userspace governor. 203 204 """ 205 logging.info('testing with userspace governor') 206 with open(self.CPUFREQ_AVAIL_FREQS_PATH, 'r') as f: 207 available_freqs = [int(x) for x in f.readline().split()] 208 209 max_freq = max(available_freqs) 210 min_freq = min(available_freqs) 211 logging.info('cpu frequency max %d min %d', max_freq, min_freq) 212 213 freqs = [ min_freq, max_freq ] 214 for freq in freqs: 215 self._set_freq(freq) 216 self._test_all_delays() 217 self._check_freq(freq) 218 219 def run_once(self): 220 kernel_ver = os.uname()[2] 221 if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0: 222 logging.info( 223 'skipping test: old kernel %s (min %s) missing module %s', 224 kernel_ver, self.MIN_KERNEL_VER, self.OLD_MODULE_NAME) 225 return 226 227 if utils.compare_versions(kernel_ver, self.NEW_KERNEL_VER) < 0: 228 module_name = self.OLD_MODULE_NAME 229 else: 230 module_name = self.NEW_MODULE_NAME 231 232 utils.load_module(module_name) 233 234 self._governor_paths = glob.glob(self.GOVERNOR_GLOB) 235 self._setspeed_paths = glob.glob(self.SETSPEED_GLOB) 236 self._cur_freq_paths = glob.glob(self.CUR_FREQ_GLOB) 237 initial_governors = self._get_governors() 238 initial_quiet_governor = self._get_quiet_governor() 239 240 with open(self.CPUFREQ_AVAIL_GOVERNORS_PATH, 'r') as f: 241 available_governors = set(f.readline().split()) 242 logging.info('governors: %s', ' '.join(available_governors)) 243 244 try: 245 if 'userspace' in available_governors: 246 self._test_userspace() 247 else: 248 logging.warning('testing with existing governor') 249 self._test_all_delays() 250 finally: 251 self._reset_freq(initial_governors, initial_quiet_governor) 252 utils.unload_module(module_name) 253