普通文本  |  201行  |  7.09 KB

# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import glob, logging, os
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error, utils

SYSFS_CPUQUIET_ENABLE = '/sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable'
SYSFS_INTEL_PSTATE_PATH = '/sys/devices/system/cpu/intel_pstate'

class power_CPUFreq(test.test):
    version = 1

    def initialize(self):
        # Store the setting if the system has CPUQuiet feature
        if os.path.exists(SYSFS_CPUQUIET_ENABLE):
            self.is_cpuquiet_enabled = utils.read_file(SYSFS_CPUQUIET_ENABLE)
            utils.write_one_line(SYSFS_CPUQUIET_ENABLE, '0')

    def run_once(self):
        # TODO(crbug.com/485276) Revisit this exception once we've refactored
        # test to account for intel_pstate cpufreq driver
        if os.path.exists(SYSFS_INTEL_PSTATE_PATH):
            raise error.TestNAError('Test does NOT support intel_pstate driver')

        cpufreq_path = '/sys/devices/system/cpu/cpu*/cpufreq'

        dirs  = glob.glob(cpufreq_path)
        if not dirs:
            raise error.TestFail('cpufreq not supported')

        keyvals = {}
        try:
            # First attempt to set all frequencies on each core before going
            # on to the next core.
            self.test_cores_in_series(dirs)
            # Record that it was the first test that passed.
            keyvals['test_cores_in_series'] = 1
        except error.TestFail as exception:
            if str(exception) == 'Unable to set frequency':
                # If test_cores_in_series fails, try to set each frequency for
                # all cores before moving on to the next frequency.

                self.test_cores_in_parallel(dirs)
                # Record that it was the second test that passed.
                keyvals['test_cores_in_parallel'] = 1
            else:
                raise exception

        self.write_perf_keyval(keyvals);

    def test_cores_in_series(self, dirs):
        for dir in dirs:
            cpu = cpufreq(dir)

            if 'userspace' not in cpu.get_available_governors():
                raise error.TestError('userspace governor not supported')

            available_frequencies = cpu.get_available_frequencies()
            if len(available_frequencies) == 1:
                raise error.TestFail('Not enough frequencies supported!')

            # save cpufreq state so that it can be restored at the end
            # of the test
            cpu.save_state()

            # set cpufreq governor to userspace
            cpu.set_governor('userspace')

            # cycle through all available frequencies
            for freq in available_frequencies:
                cpu.set_frequency(freq)
                if freq != cpu.get_current_frequency():
                    cpu.restore_state()
                    raise error.TestFail('Unable to set frequency')

            # restore cpufreq state
            cpu.restore_state()

    def test_cores_in_parallel(self, dirs):
        cpus = [cpufreq(dir) for dir in dirs]
        cpu0 = cpus[0]

        # Use the first CPU's frequencies for all CPUs.  Assume that they are
        # the same.
        available_frequencies = cpu0.get_available_frequencies()
        if len(available_frequencies) == 1:
            raise error.TestFail('Not enough frequencies supported!')

        for cpu in cpus:
            if 'userspace' not in cpu.get_available_governors():
                raise error.TestError('userspace governor not supported')

            # save cpufreq state so that it can be restored at the end
            # of the test
            cpu.save_state()

            # set cpufreq governor to userspace
            cpu.set_governor('userspace')

        # cycle through all available frequencies
        for freq in available_frequencies:
            for cpu in cpus:
                cpu.set_frequency(freq)
            for cpu in cpus:
                if freq != cpu.get_current_frequency():
                    cpu.restore_state()
                    raise error.TestFail('Unable to set frequency')

        for cpu in cpus:
            # restore cpufreq state
            cpu.restore_state()

    def cleanup(self):
        # Restore the original setting if system has CPUQuiet feature
        if os.path.exists(SYSFS_CPUQUIET_ENABLE):
            utils.open_write_close(
                SYSFS_CPUQUIET_ENABLE, self.is_cpuquiet_enabled)

class cpufreq(object):
    def __init__(self, path):
        self.__base_path = path
        self.__save_files_list = ['scaling_max_freq', 'scaling_min_freq',
                                  'scaling_governor']


    def __write_file(self, file_name, data):
        path = os.path.join(self.__base_path, file_name)
        utils.open_write_close(path, data)


    def __read_file(self, file_name):
        path = os.path.join(self.__base_path, file_name)
        f = open(path, 'r')
        data = f.read()
        f.close()
        return data


    def save_state(self):
        logging.info('saving state:')
        for file in self.__save_files_list:
            data = self.__read_file(file)
            setattr(self, file, data)
            logging.info(file + ': '  + data)


    def restore_state(self):
        logging.info('restoring state:')
        for file in self.__save_files_list:
            # Sometimes a newline gets appended to a data string and it throws
            # an error when being written to a sysfs file.  Call strip() to
            # eliminateextra whitespace characters so it can be written cleanly
            # to the file.
            data = getattr(self, file).strip()
            logging.info(file + ': '  + data)
            self.__write_file(file, data)


    def get_available_governors(self):
        governors = self.__read_file('scaling_available_governors')
        logging.info('available governors: %s' % governors)
        return governors.split()


    def get_current_governor(self):
        governor = self.__read_file('scaling_governor')
        logging.info('current governor: %s' % governor)
        return governor.split()[0]


    def set_governor(self, governor):
        logging.info('setting governor to %s' % governor)
        self.__write_file('scaling_governor', governor)


    def get_available_frequencies(self):
        frequencies = self.__read_file('scaling_available_frequencies')
        logging.info('available frequencies: %s' % frequencies)
        return [int(i) for i in frequencies.split()]


    def get_current_frequency(self):
        freq = int(self.__read_file('scaling_cur_freq'))
        logging.info('current frequency: %s' % freq)
        return freq


    def set_frequency(self, frequency):
        logging.info('setting frequency to %d' % frequency)
        if frequency >= self.get_current_frequency():
            file_list = ['scaling_max_freq', 'scaling_min_freq',
                         'scaling_setspeed']
        else:
            file_list = ['scaling_min_freq', 'scaling_max_freq',
                         'scaling_setspeed']

        for file in file_list:
            self.__write_file(file, str(frequency))