普通文本  |  219行  |  6.73 KB

# Copyright (c) 2014 The Chromium 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
import logging
import os

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error

class kernel_Delay(test.test):
    """
    Test to ensure that udelay() delays at least as long as requested
    (as compared to ktime()).

    Test a variety of delays at mininmum and maximum cpu frequencies.

    """
    version = 1

    MIN_KERNEL_VER = '3.8'
    MODULE_NAME = 'udelay_test'
    UDELAY_PATH = '/sys/kernel/debug/udelay_test'
    QUIET_GOVERNOR_PATH = '/sys/devices/system/cpu/cpuquiet/current_governor'
    GOVERNOR_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor'
    SETSPEED_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/scaling_setspeed'
    CUR_FREQ_GLOB = '/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq'
    CPUFREQ_AVAIL_PATH = (
            '/sys/devices/system/cpu/cpu0/cpufreq/'
            'scaling_available_frequencies')

    # Test a variety of delays
    # 1..200, 200..500 (by 10), 500..2000 (by 100)
    DELAYS = range(1, 200) + range(200, 500, 10) + range(500, 2001, 100)
    ITERATIONS = 100

    _governor_paths = []
    _setspeed_paths = []
    _cur_freq_paths = []

    def _set_file(self, contents, filename):
        """
        Write a string to a file.

        @param contents: the contents to write to the file
        @param filename: the filename to use

        """
        logging.debug('setting %s to %s', filename, contents)
        with open(filename, 'w') as f:
            f.write(contents)


    def _get_file(self, filename):
        """
        Read a string from a file.

        @returns: the contents of the file (string)

        """
        with open(filename, 'r') as f:
            return f.read()


    def _get_freqs(self):
        """
        Get the current CPU frequencies.

        @returns: the CPU frequencies of each CPU (list of int)

        """
        return [int(self._get_file(p)) for p in self._cur_freq_paths]


    def _get_freqs_string(self):
        """
        Get the current CPU frequencies.

        @returns: the CPU frequencies of each CPU (string)

        """
        return ' '.join(str(x) for x in self._get_freqs())


    def _get_governors(self):
        """
        Get the current CPU governors.

        @returns: the CPU governors of each CPU (list of string)

        """
        return [self._get_file(p).rstrip() for p in self._governor_paths]


    def _get_quiet_governor(self):
        """
        Get the current CPU quiet governor.

        @returns: the CPU quiet governor or None if it does not exist (string)

        """
        if os.path.isfile(self.QUIET_GOVERNOR_PATH):
            return self._get_file(self.QUIET_GOVERNOR_PATH).rstrip()
        else:
            return None


    def _reset_freq(self, initial_governors, initial_quiet_governor):
        """
        Unlimit the CPU frequency.

        @param initial_governors: list of initial governors to reset state to
        @param initial_quiet_governor: initial quiet governor to reset state to

        """
        for p, g in zip(self._governor_paths, initial_governors):
            self._set_file(g, p)
        if initial_quiet_governor and os.path.isfile(self.QUIET_GOVERNOR_PATH):
            self._set_file(initial_quiet_governor, self.QUIET_GOVERNOR_PATH)


    def _set_freq(self, freq):
        """
        Set the CPU frequency.

        @param freq: desired CPU frequency

        """
        # Prevent CPUs from going up and down during the test if the option
        # is available.
        if os.path.isfile(self.QUIET_GOVERNOR_PATH):
            logging.info('changing to userspace cpuquiet governor');
            self._set_file('userspace', self.QUIET_GOVERNOR_PATH)

        for p in self._governor_paths:
            self._set_file('userspace', p)
        for p in self._setspeed_paths:
            self._set_file(str(freq), p)
        logging.info(
                'cpu frequencies set to %s with userspace governor',
                self._get_freqs_string())
        self._check_freq(freq)


    def _check_freq(self, freq):
        """
        Check the CPU frequencies are set as requested.

        @param freq: desired CPU frequency

        """
        for p in self._governor_paths:
            governor = self._get_file(p).rstrip()
            if governor != 'userspace':
                raise error.TestFail('governor changed from userspace to %s' % (
                        governor))
        for p in self._setspeed_paths:
            speed = int(self._get_file(p))
            if speed != freq:
                raise error.TestFail('setspeed changed from %s to %s' % (
                        freq, speed))
        freqs = self._get_freqs()
        for f in freqs:
            if f != freq:
                raise error.TestFail('frequency set to %s instead of %s' % (
                        f, freq))


    def _test_udelay(self, usecs):
        """
        Test udelay() for a given amount of time.

        @param usecs: number of usecs to delay for each iteration

        """
        self._set_file('%d %d' % (usecs, self.ITERATIONS), self.UDELAY_PATH)
        with open(self.UDELAY_PATH, 'r') as f:
            for line in f:
                line = line.rstrip()
                logging.info('result: %s', line)
                if 'FAIL' in line:
                    raise error.TestFail('udelay failed: %s' % line)


    def run_once(self):
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0:
            logging.info(
                    'skipping test: old kernel %s (min %s) missing module %s',
                    kernel_ver, self.MIN_KERNEL_VER, self.MODULE_NAME)
            return

        utils.load_module(self.MODULE_NAME)

        self._governor_paths = glob.glob(self.GOVERNOR_GLOB)
        self._setspeed_paths = glob.glob(self.SETSPEED_GLOB)
        self._cur_freq_paths = glob.glob(self.CUR_FREQ_GLOB)
        initial_governors = self._get_governors()
        initial_quiet_governor = self._get_quiet_governor()

        with open(self.CPUFREQ_AVAIL_PATH, 'r') as f:
            available_freqs = [int(x) for x in f.readline().split()]

        max_freq = max(available_freqs)
        min_freq = min(available_freqs)
        logging.info('cpu frequency max %d min %d', max_freq, min_freq)

        freqs = [ min_freq, max_freq ]
        try:
            for freq in freqs:
                self._set_freq(freq)
                for usecs in self.DELAYS:
                    self._test_udelay(usecs)
                self._check_freq(freq)
        finally:
            self._reset_freq(initial_governors, initial_quiet_governor)
            utils.unload_module(self.MODULE_NAME)