1c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda# Use of this source code is governed by a BSD-style license that can be
3c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda# found in the LICENSE file.
4c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
5c21a372ca10358c41e840700c89be6f20505bda4Sameer Nandaimport glob, logging, os
6c21a372ca10358c41e840700c89be6f20505bda4Sameer Nandafrom autotest_lib.client.bin import test
7c21a372ca10358c41e840700c89be6f20505bda4Sameer Nandafrom autotest_lib.client.common_lib import error, utils
8c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
970824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny ChiuSYSFS_CPUQUIET_ENABLE = '/sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable'
103956655d260d169128da60006e69297db42d2a29Todd BrochSYSFS_INTEL_PSTATE_PATH = '/sys/devices/system/cpu/intel_pstate'
1170824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu
12c21a372ca10358c41e840700c89be6f20505bda4Sameer Nandaclass power_CPUFreq(test.test):
13c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    version = 1
14c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
1570824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu    def initialize(self):
1670824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu        # Store the setting if the system has CPUQuiet feature
1770824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu        if os.path.exists(SYSFS_CPUQUIET_ENABLE):
1870824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu            self.is_cpuquiet_enabled = utils.read_file(SYSFS_CPUQUIET_ENABLE)
1970824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu            utils.write_one_line(SYSFS_CPUQUIET_ENABLE, '0')
2070824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu
21c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def run_once(self):
223956655d260d169128da60006e69297db42d2a29Todd Broch        # TODO(crbug.com/485276) Revisit this exception once we've refactored
233956655d260d169128da60006e69297db42d2a29Todd Broch        # test to account for intel_pstate cpufreq driver
243956655d260d169128da60006e69297db42d2a29Todd Broch        if os.path.exists(SYSFS_INTEL_PSTATE_PATH):
253956655d260d169128da60006e69297db42d2a29Todd Broch            raise error.TestNAError('Test does NOT support intel_pstate driver')
263956655d260d169128da60006e69297db42d2a29Todd Broch
27c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        cpufreq_path = '/sys/devices/system/cpu/cpu*/cpufreq'
28c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
29c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        dirs  = glob.glob(cpufreq_path)
30c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        if not dirs:
31c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            raise error.TestFail('cpufreq not supported')
32c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
33f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        keyvals = {}
34f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        try:
35f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # First attempt to set all frequencies on each core before going
36f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # on to the next core.
37f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            self.test_cores_in_series(dirs)
38f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # Record that it was the first test that passed.
39f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            keyvals['test_cores_in_series'] = 1
40f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        except error.TestFail as exception:
41f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            if str(exception) == 'Unable to set frequency':
42f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                # If test_cores_in_series fails, try to set each frequency for
43f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                # all cores before moving on to the next frequency.
44f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
45f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                self.test_cores_in_parallel(dirs)
46f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                # Record that it was the second test that passed.
47f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                keyvals['test_cores_in_parallel'] = 1
48f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            else:
49f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                raise exception
50f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
51f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        self.write_perf_keyval(keyvals);
52f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
53f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que    def test_cores_in_series(self, dirs):
54c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        for dir in dirs:
55c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            cpu = cpufreq(dir)
56c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
57c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            if 'userspace' not in cpu.get_available_governors():
58c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                raise error.TestError('userspace governor not supported')
59c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
60c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            available_frequencies = cpu.get_available_frequencies()
61c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            if len(available_frequencies) == 1:
62c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                raise error.TestFail('Not enough frequencies supported!')
63c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
64c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            # save cpufreq state so that it can be restored at the end
65c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            # of the test
66c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            cpu.save_state()
67c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
68c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            # set cpufreq governor to userspace
69c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            cpu.set_governor('userspace')
70c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
71c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            # cycle through all available frequencies
72c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            for freq in available_frequencies:
73c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                cpu.set_frequency(freq)
74c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                if freq != cpu.get_current_frequency():
75c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                    cpu.restore_state()
76c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                    raise error.TestFail('Unable to set frequency')
77c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
78c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            # restore cpufreq state
79c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            cpu.restore_state()
80c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
81f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que    def test_cores_in_parallel(self, dirs):
82f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        cpus = [cpufreq(dir) for dir in dirs]
83f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        cpu0 = cpus[0]
84f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
85f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        # Use the first CPU's frequencies for all CPUs.  Assume that they are
86f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        # the same.
87f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        available_frequencies = cpu0.get_available_frequencies()
88f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        if len(available_frequencies) == 1:
89f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            raise error.TestFail('Not enough frequencies supported!')
90f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
91f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        for cpu in cpus:
92f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            if 'userspace' not in cpu.get_available_governors():
93f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                raise error.TestError('userspace governor not supported')
94f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
95f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # save cpufreq state so that it can be restored at the end
96f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # of the test
97f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            cpu.save_state()
98f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
99f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # set cpufreq governor to userspace
100f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            cpu.set_governor('userspace')
101f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
102f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        # cycle through all available frequencies
103f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        for freq in available_frequencies:
104f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            for cpu in cpus:
105f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                cpu.set_frequency(freq)
106f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            for cpu in cpus:
107f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                if freq != cpu.get_current_frequency():
108f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                    cpu.restore_state()
109f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que                    raise error.TestFail('Unable to set frequency')
110f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que
111f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que        for cpu in cpus:
112f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # restore cpufreq state
113f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            cpu.restore_state()
114c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
11570824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu    def cleanup(self):
11670824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu        # Restore the original setting if system has CPUQuiet feature
11770824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu        if os.path.exists(SYSFS_CPUQUIET_ENABLE):
11870824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu            utils.open_write_close(
11970824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu                SYSFS_CPUQUIET_ENABLE, self.is_cpuquiet_enabled)
12070824ac1a0fea6e7aab53b15cdbe30c45960dfd4Penny Chiu
121c21a372ca10358c41e840700c89be6f20505bda4Sameer Nandaclass cpufreq(object):
122c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def __init__(self, path):
123c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        self.__base_path = path
124c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        self.__save_files_list = ['scaling_max_freq', 'scaling_min_freq',
125c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                                  'scaling_governor']
126c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
127c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
128c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def __write_file(self, file_name, data):
129c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        path = os.path.join(self.__base_path, file_name)
130c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        utils.open_write_close(path, data)
131c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
132c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
133c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def __read_file(self, file_name):
134c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        path = os.path.join(self.__base_path, file_name)
135c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        f = open(path, 'r')
136c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        data = f.read()
137c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        f.close()
138c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        return data
139c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
140c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
141c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def save_state(self):
142c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('saving state:')
143c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        for file in self.__save_files_list:
144c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            data = self.__read_file(file)
145c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            setattr(self, file, data)
146c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            logging.info(file + ': '  + data)
147c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
148c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
149c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def restore_state(self):
150c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('restoring state:')
151c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        for file in self.__save_files_list:
152f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # Sometimes a newline gets appended to a data string and it throws
153f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # an error when being written to a sysfs file.  Call strip() to
154f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # eliminateextra whitespace characters so it can be written cleanly
155f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            # to the file.
156f8ed8a26b09ff82fc5e3a806f2865d63f84b3622Simon Que            data = getattr(self, file).strip()
157c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            logging.info(file + ': '  + data)
158c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            self.__write_file(file, data)
159c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
160c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
161c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def get_available_governors(self):
162c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        governors = self.__read_file('scaling_available_governors')
163c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('available governors: %s' % governors)
164c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        return governors.split()
165c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
166c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
167c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def get_current_governor(self):
168c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        governor = self.__read_file('scaling_governor')
169c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('current governor: %s' % governor)
170c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        return governor.split()[0]
171c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
172c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
173c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def set_governor(self, governor):
174c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('setting governor to %s' % governor)
175c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        self.__write_file('scaling_governor', governor)
176c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
177c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
178c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def get_available_frequencies(self):
179c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        frequencies = self.__read_file('scaling_available_frequencies')
180c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('available frequencies: %s' % frequencies)
181c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        return [int(i) for i in frequencies.split()]
182c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
183c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
184c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def get_current_frequency(self):
185c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        freq = int(self.__read_file('scaling_cur_freq'))
186c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('current frequency: %s' % freq)
187c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        return freq
188c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
189c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
190c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda    def set_frequency(self, frequency):
191c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        logging.info('setting frequency to %d' % frequency)
192c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        if frequency >= self.get_current_frequency():
193c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            file_list = ['scaling_max_freq', 'scaling_min_freq',
194c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                         'scaling_setspeed']
195c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        else:
196c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            file_list = ['scaling_min_freq', 'scaling_max_freq',
197c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda                         'scaling_setspeed']
198c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda
199c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda        for file in file_list:
200c21a372ca10358c41e840700c89be6f20505bda4Sameer Nanda            self.__write_file(file, str(frequency))
201