xref: /aosp_15_r20/external/autotest/client/site_tests/power_SuspendToIdle/power_SuspendToIdle.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright (c) 2018 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7import time
8
9from contextlib import contextmanager
10
11from autotest_lib.client.bin import test
12from autotest_lib.client.bin import utils
13from autotest_lib.client.common_lib import error
14from autotest_lib.client.cros.power import power_suspend
15from autotest_lib.client.cros.power import power_status
16from autotest_lib.client.cros.power import power_utils
17
18
19class power_SuspendToIdle(test.test):
20    """class for power_SuspendToIdle test."""
21    version = 1
22    _pch_powergating_max_retry = 5
23    _pch_powergating_retry_delay_secs = 1
24
25    @contextmanager
26    def _log_error_message(self):
27        """Suppress exception and log the message."""
28        try:
29            yield
30        except Exception as e:
31            self._error_count += 1
32            self._error_message.append(str(e))
33
34    def run_once(self, force_suspend_to_idle=False):
35        """Main test method.
36        """
37        if utils.get_cpu_arch() != 'x86_64':
38            raise error.TestNAError('This test only supports x86_64 CPU.')
39
40        if power_utils.get_sleep_state() != 'freeze':
41            if not force_suspend_to_idle:
42                raise error.TestNAError(
43                    'System default config is not suspend to idle.')
44            else:
45                logging.info('System default config is suspend to ram. '
46                             'Force suspend to idle')
47
48        self._error_count = 0
49        self._error_message = []
50        dmc_firmware_stats = None
51        s0ix_residency_stats = None
52        cpu_packages_stats = None
53        rc6_residency_stats = None
54
55        with self._log_error_message():
56            dmc_firmware_stats = power_status.DMCFirmwareStats()
57            if not dmc_firmware_stats.check_fw_loaded():
58                raise error.TestFail('DMC firmware not loaded.')
59
60        with self._log_error_message():
61            pch_powergating_stats = power_status.PCHPowergatingStats()
62
63            on_pch = None
64            # Allow |_pch_powergating_max_retry| tries of PCH powergating
65            # because we check this in S0 idle instead of S0ix and background
66            # process may make this flakiness.
67            for try_count in range(1, self._pch_powergating_max_retry + 1):
68                pch_powergating_stats.read_pch_powergating_info()
69                on_pch = pch_powergating_stats.check_s0ix_requirement()
70                if not on_pch:
71                    break
72                logging.info('PCH powergating check#%d  failed: %s', try_count,
73                             ', '.join(on_pch))
74                time.sleep(self._pch_powergating_retry_delay_secs)
75            else:
76                raise error.TestFail('PCH powergating check failed: ',
77                                     ', '.join(on_pch))
78
79        with self._log_error_message():
80            s0ix_residency_stats = power_status.S0ixResidencyStats()
81
82        with self._log_error_message():
83            cpu_packages_stats = power_status.CPUPackageStats()
84
85        with self._log_error_message():
86            rc6_residency_stats = power_status.RC6ResidencyStats()
87
88        with self._log_error_message():
89            suspender = power_suspend.Suspender(self.resultsdir,
90                                                suspend_state='freeze')
91            suspender.suspend()
92
93        with self._log_error_message():
94            if (dmc_firmware_stats and
95                dmc_firmware_stats.is_dc6_supported() and
96                dmc_firmware_stats.get_accumulated_dc6_entry() <= 0):
97                raise error.TestFail('DC6 entry check failed.')
98
99        with self._log_error_message():
100            if (s0ix_residency_stats and
101                s0ix_residency_stats.get_accumulated_residency_secs() <= 0):
102                raise error.TestFail('S0ix residency check failed.')
103
104        with self._log_error_message():
105            if (cpu_packages_stats and
106                cpu_packages_stats.refresh().get('C10', 0) <= 0):
107                raise error.TestFail('C10 state check failed.')
108
109        with self._log_error_message():
110            if (rc6_residency_stats and
111                rc6_residency_stats.get_accumulated_residency_msecs() <= 0):
112                raise error.TestFail('RC6 residency check failed.')
113
114        if self._error_count > 0:
115            raise error.TestFail('Found %d errors: ' % self._error_count,
116                                 ', '.join(self._error_message))
117