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