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