Skip to content

Commit a20ca97

Browse files
committed
tools: Add a new script for firmware boot stress testing
This requires the kernel changes that expose the debugfs entries for executing the different DSP ops and reading the current DSP firmware and power states. The script takes the firmware name and the path as inputs along with the number of iterations of firmware boot. It takes care of putting the DSP in the D3 state and unloading any existing firmware before starting firmware boot. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent d10020d commit a20ca97

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

tools/sof-fw-boot-test.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import subprocess
6+
import sys
7+
import time
8+
9+
# define command line arguments
10+
def parse_cmdline():
11+
parser = argparse.ArgumentParser(add_help=True, formatter_class=argparse.RawTextHelpFormatter,
12+
description='A script for stress testing firmware boot')
13+
14+
parser.add_argument('-i', '--iter', type=int, default=100, help="number of firmware boot iterations")
15+
parser.add_argument('-f', '--firmware', type=str, required=True, help='firmware filename')
16+
parser.add_argument('-p', '--fw_path', type=str, required=True, help='path to the firmware file relative to /lib/firmware')
17+
18+
return vars(parser.parse_args())
19+
20+
cmd_args = parse_cmdline()
21+
22+
# Get firmware file path
23+
fw_path = cmd_args["fw_path"]
24+
full_fw_path = '/lib/firmware/' + fw_path
25+
if not os.path.exists(full_fw_path):
26+
print("Invalid firmware path: %s" %fw_path)
27+
sys.exit(1)
28+
29+
# Get firmware file name
30+
fw_filename = cmd_args["firmware"]
31+
32+
# check if the firmware binary exists
33+
fw_fullname = '/lib/firmware/' + fw_path + '/' + fw_filename
34+
if not os.path.isfile(fw_fullname):
35+
print("Invalid firmware file: %s" %fw_filename)
36+
sys.exit(1)
37+
38+
num_iter = cmd_args["iter"]
39+
print("=======================================================================================")
40+
print('Starting boot stress test with:')
41+
print('Firmware filename: %s' %fw_filename)
42+
print('Path to firmware file: %s' %fw_path)
43+
print('Number of Iterations: %d' %num_iter)
44+
print("=======================================================================================")
45+
46+
# set path to the depbugfs entries
47+
debugfs_path = '/sys/kernel/debug/sof/dsp_ops'
48+
if not os.path.exists(debugfs_path):
49+
print("Debugfs path '%s' does not exist!" %debugfs_path)
50+
sys.exit(1)
51+
52+
# set the firmware filename & path
53+
os.system('echo %s > %s/fw_filename' %(fw_filename, debugfs_path))
54+
os.system('echo %s > %s/fw_path' %(fw_path, debugfs_path))
55+
total_boot_time = 0
56+
min_boot_time = sys.maxsize
57+
max_boot_time = 0
58+
59+
for i in range(num_iter):
60+
print("Starting firmware boot iteration: %d" %i)
61+
62+
# put the DSP in D3 with a timeout of 1 second
63+
debugfs_entry = debugfs_path + '/dsp_power_state'
64+
cmd = 'echo D3 > ' + debugfs_entry
65+
subprocess.run(cmd, shell=True, check=True, timeout=1)
66+
67+
# check if the DSP is in D3
68+
cmd = 'cat ' + debugfs_entry
69+
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
70+
dsp_power_state = proc.stdout
71+
dsp_power_state = dsp_power_state.rstrip()
72+
if not dsp_power_state == 'D3':
73+
print('Failed booting firmware. DSP is not in D3')
74+
sys.exit(1)
75+
76+
# unload current firmware
77+
debugfs_entry = debugfs_path + '/unload_fw'
78+
cmd = 'echo 1 > ' + debugfs_entry
79+
subprocess.run(cmd, shell=True, check=True)
80+
81+
# get current fw_state and continue to boot only if the current state is 'PREPARE'
82+
debugfs_entry = debugfs_path + '/fw_state'
83+
cmd = 'cat ' + debugfs_entry
84+
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
85+
fw_state = proc.stdout
86+
fw_state = fw_state.rstrip()
87+
88+
if not fw_state == 'PREPARE':
89+
print('Cannot boot firmware boot current state is not PREPARE. Current state: %s.' %fw_state)
90+
sys.exit(1)
91+
92+
# load and boot firmware. Set a 2s timeout for firmware boot
93+
debugfs_entry = debugfs_path + '/boot_fw'
94+
cmd = 'echo 1 > ' + debugfs_entry
95+
start = time.time()
96+
proc = subprocess.run(cmd, shell=True, check=True, timeout=2, capture_output=True, text=True)
97+
end = time.time()
98+
99+
# calculate boot time
100+
boot_time = (end - start) * 1000
101+
total_boot_time += boot_time
102+
if boot_time < min_boot_time:
103+
min_boot_time = boot_time
104+
if boot_time > max_boot_time:
105+
max_boot_time = boot_time
106+
107+
# get current fw_state to make sure the state is COMPLETE
108+
debugfs_entry = debugfs_path + '/fw_state'
109+
cmd = 'cat ' + debugfs_entry
110+
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
111+
fw_state = proc.stdout
112+
fw_state = fw_state.rstrip()
113+
if not fw_state == 'COMPLETE':
114+
print('Invalid firmware boot status: %s' %fw_state)
115+
sys.exit(1)
116+
117+
print('Firmware boot iteration %d completed in %d ms' %(i, boot_time))
118+
119+
# print firmware boot stats
120+
avg_boot_time = total_boot_time / num_iter
121+
print("=======================================================================================")
122+
print('Finished boot stress test with:')
123+
print('Firmware filename: %s' %fw_filename)
124+
print('Path to firmware file: %s' %fw_path)
125+
print('Average firmware boot time after %d iterations: %d ms' %(num_iter, avg_boot_time))
126+
print('Maximum firmware boot time %d ms' %max_boot_time)
127+
print('Minimum firmware boot time %d ms' %min_boot_time)
128+
print("=======================================================================================")

0 commit comments

Comments
 (0)