• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import glob
6import logging
7import os
8
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11
12class 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    MIN_KERNEL_VER = '3.8'
23    MODULE_NAME = 'udelay_test'
24    UDELAY_PATH = '/sys/kernel/debug/udelay_test'
25    QUIET_GOVERNOR_PATH = '/sys/devices/system/cpu/cpuquiet/current_governor'
26    GOVERNOR_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor'
27    SETSPEED_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_setspeed'
28    CUR_FREQ_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq'
29    CPUFREQ_AVAIL_PATH = (
30            '/sys/devices/system/cpu/cpu0/cpufreq/'
31            'scaling_available_frequencies')
32
33    # Test a variety of delays
34    # 1..200, 200..500 (by 10), 500..2000 (by 100)
35    DELAYS = range(1, 200) + range(200, 500, 10) + range(500, 2001, 100)
36    ITERATIONS = 100
37
38    _governor_paths = []
39    _setspeed_paths = []
40    _cur_freq_paths = []
41
42    def _set_file(self, contents, filename):
43        """
44        Write a string to a file.
45
46        @param contents: the contents to write to the file
47        @param filename: the filename to use
48
49        """
50        logging.debug('setting %s to %s', filename, contents)
51        with open(filename, 'w') as f:
52            f.write(contents)
53
54
55    def _get_file(self, filename):
56        """
57        Read a string from a file.
58
59        @returns: the contents of the file (string)
60
61        """
62        with open(filename, 'r') as f:
63            return f.read()
64
65
66    def _get_freqs(self):
67        """
68        Get the current CPU frequencies.
69
70        @returns: the CPU frequencies of each CPU (list of int)
71
72        """
73        return [int(self._get_file(p)) for p in self._cur_freq_paths]
74
75
76    def _get_freqs_string(self):
77        """
78        Get the current CPU frequencies.
79
80        @returns: the CPU frequencies of each CPU (string)
81
82        """
83        return ' '.join(str(x) for x in self._get_freqs())
84
85
86    def _get_governors(self):
87        """
88        Get the current CPU governors.
89
90        @returns: the CPU governors of each CPU (list of string)
91
92        """
93        return [self._get_file(p).rstrip() for p in self._governor_paths]
94
95
96    def _get_quiet_governor(self):
97        """
98        Get the current CPU quiet governor.
99
100        @returns: the CPU quiet governor or None if it does not exist (string)
101
102        """
103        if os.path.isfile(self.QUIET_GOVERNOR_PATH):
104            return self._get_file(self.QUIET_GOVERNOR_PATH).rstrip()
105        else:
106            return None
107
108
109    def _reset_freq(self, initial_governors, initial_quiet_governor):
110        """
111        Unlimit the CPU frequency.
112
113        @param initial_governors: list of initial governors to reset state to
114        @param initial_quiet_governor: initial quiet governor to reset state to
115
116        """
117        for p, g in zip(self._governor_paths, initial_governors):
118            self._set_file(g, p)
119        if initial_quiet_governor and os.path.isfile(self.QUIET_GOVERNOR_PATH):
120            self._set_file(initial_quiet_governor, self.QUIET_GOVERNOR_PATH)
121
122
123    def _set_freq(self, freq):
124        """
125        Set the CPU frequency.
126
127        @param freq: desired CPU frequency
128
129        """
130        # Prevent CPUs from going up and down during the test if the option
131        # is available.
132        if os.path.isfile(self.QUIET_GOVERNOR_PATH):
133            logging.info('changing to userspace cpuquiet governor');
134            self._set_file('userspace', self.QUIET_GOVERNOR_PATH)
135
136        for p in self._governor_paths:
137            self._set_file('userspace', p)
138        for p in self._setspeed_paths:
139            self._set_file(str(freq), p)
140        logging.info(
141                'cpu frequencies set to %s with userspace governor',
142                self._get_freqs_string())
143        self._check_freq(freq)
144
145
146    def _check_freq(self, freq):
147        """
148        Check the CPU frequencies are set as requested.
149
150        @param freq: desired CPU frequency
151
152        """
153        for p in self._governor_paths:
154            governor = self._get_file(p).rstrip()
155            if governor != 'userspace':
156                raise error.TestFail('governor changed from userspace to %s' % (
157                        governor))
158        for p in self._setspeed_paths:
159            speed = int(self._get_file(p))
160            if speed != freq:
161                raise error.TestFail('setspeed changed from %s to %s' % (
162                        freq, speed))
163        freqs = self._get_freqs()
164        for f in freqs:
165            if f != freq:
166                raise error.TestFail('frequency set to %s instead of %s' % (
167                        f, freq))
168
169
170    def _test_udelay(self, usecs):
171        """
172        Test udelay() for a given amount of time.
173
174        @param usecs: number of usecs to delay for each iteration
175
176        """
177        self._set_file('%d %d' % (usecs, self.ITERATIONS), self.UDELAY_PATH)
178        with open(self.UDELAY_PATH, 'r') as f:
179            for line in f:
180                line = line.rstrip()
181                logging.info('result: %s', line)
182                if 'FAIL' in line:
183                    raise error.TestFail('udelay failed: %s' % line)
184
185
186    def run_once(self):
187        kernel_ver = os.uname()[2]
188        if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0:
189            logging.info(
190                    'skipping test: old kernel %s (min %s) missing module %s',
191                    kernel_ver, self.MIN_KERNEL_VER, self.MODULE_NAME)
192            return
193
194        utils.load_module(self.MODULE_NAME)
195
196        self._governor_paths = glob.glob(self.GOVERNOR_GLOB)
197        self._setspeed_paths = glob.glob(self.SETSPEED_GLOB)
198        self._cur_freq_paths = glob.glob(self.CUR_FREQ_GLOB)
199        initial_governors = self._get_governors()
200        initial_quiet_governor = self._get_quiet_governor()
201
202        with open(self.CPUFREQ_AVAIL_PATH, 'r') as f:
203            available_freqs = [int(x) for x in f.readline().split()]
204
205        max_freq = max(available_freqs)
206        min_freq = min(available_freqs)
207        logging.info('cpu frequency max %d min %d', max_freq, min_freq)
208
209        freqs = [ min_freq, max_freq ]
210        try:
211            for freq in freqs:
212                self._set_freq(freq)
213                for usecs in self.DELAYS:
214                    self._test_udelay(usecs)
215                self._check_freq(freq)
216        finally:
217            self._reset_freq(initial_governors, initial_quiet_governor)
218            utils.unload_module(self.MODULE_NAME)
219