Skip to content

Commit

Permalink
tools: Add a new script for firmware boot stress testing
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
ranj063 committed Apr 24, 2024
1 parent d10020d commit 242e7fc
Showing 1 changed file with 130 additions and 0 deletions.
130 changes: 130 additions & 0 deletions tools/sof-fw-boot-test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3

import argparse
import os
import subprocess
import sys
import time

# define command line arguments
def parse_cmdline():
parser = argparse.ArgumentParser(add_help=True, formatter_class=argparse.RawTextHelpFormatter,
description='A script for stress testing firmware boot')

parser.add_argument('-i', '--iter', type=int, default=100, help="number of firmware boot iterations")
parser.add_argument('-f', '--firmware', type=str, required=True, help='firmware filename')
parser.add_argument('-p', '--fw_path', type=str, required=True, help='path to the firmware file relative to /lib/firmware')

return vars(parser.parse_args())

cmd_args = parse_cmdline()

# Get firmware file path
fw_path = cmd_args["fw_path"]
full_fw_path = '/lib/firmware/' + fw_path
if not os.path.exists(full_fw_path):
print("Invalid firmware path: %s" %fw_path)
sys.exit(1)

# Get firmware file name
fw_filename = cmd_args["firmware"]

# check if the firmware binary exists
fw_fullname = '/lib/firmware/' + fw_path + '/' + fw_filename
if not os.path.isfile(fw_fullname):
print("Invalid firmware file: %s" %fw_filename)
sys.exit(1)

num_iter = cmd_args["iter"]
print("=======================================================================================")
print('Starting boot stress test with:')
print('Firmware filename: %s' %fw_filename)
print('Path to firmware file: %s' %fw_path)
print('Number of Iterations: %d' %num_iter)
print("=======================================================================================")

# set path to the depbugfs entries
debugfs_path = '/sys/kernel/debug/sof/dsp_ops'
if not os.path.exists(debugfs_path):
print("Debugfs path '%s' does not exist!" %debugfs_path)
sys.exit(1)

# set the firmware filename & path
os.system('echo %s > %s/fw_filename' %(fw_filename, debugfs_path))
os.system('echo %s > %s/fw_path' %(fw_path, debugfs_path))
total_boot_time = 0
min_boot_time = sys.maxsize
max_boot_time = 0

for i in range(num_iter):
print("Starting firmware boot iteration: %d" %i)

# put the DSP in D3 with a timeout of 1 second
debugfs_entry = debugfs_path + '/dsp_power_state'
cmd = 'echo D3 > ' + debugfs_entry
subprocess.run(cmd, shell=True, check=True, timeout=1)

# check if the DSP is in D3
cmd = 'cat ' + debugfs_entry
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
dsp_power_state = proc.stdout
dsp_power_state = dsp_power_state.rstrip()
if not dsp_power_state == 'D3':
print('Failed booting firmware. DSP is not in D3')
sys.exit(1)

# unload current firmware
debugfs_entry = debugfs_path + '/unload_fw'
cmd = 'echo 1 > ' + debugfs_entry
subprocess.run(cmd, shell=True, check=True)

# get current fw_state and continue to boot only if the current state is 'PREPARE'
debugfs_entry = debugfs_path + '/fw_state'
cmd = 'cat ' + debugfs_entry
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
fw_state = proc.stdout
fw_state = fw_state.rstrip()

if not fw_state == 'PREPARE':
print('Cannot boot firmware boot current state is not PREPARE. Current state: %s.' %fw_state)
sys.exit(1)

# load and boot firmware. Set a 2s timeout for firmware boot
debugfs_entry = debugfs_path + '/boot_fw'
cmd = 'echo 1 > ' + debugfs_entry
start = time.time()
proc = subprocess.run(cmd, shell=True, check=True, timeout=2, capture_output=True, text=True)
end = time.time()

# calculate boot time
boot_time = (end - start) * 1000
total_boot_time += boot_time
if boot_time < min_boot_time:
min_boot_time = boot_time
if boot_time > max_boot_time:
max_boot_time = boot_time

# get current fw_state to make sure the state is COMPLETE
debugfs_entry = debugfs_path + '/fw_state'
cmd = 'cat ' + debugfs_entry
proc = subprocess.run(cmd, shell=True, capture_output=True, check=True, text=True)
fw_state = proc.stdout
fw_state = fw_state.rstrip()
if not fw_state == 'COMPLETE':
print('Invalid firmware boot status: %s' %fw_state)
sys.exit(1)

print('Firmware boot iteration %d completed in %d ms' %(i, boot_time))

# print firmware boot stats
avg_boot_time = total_boot_time / num_iter
print("=======================================================================================")
print('Finished boot stress test with:')
print('Firmware filename: %s' %fw_filename)
print('Path to firmware file: %s' %fw_path)
print('Average firmware boot time after %d iterations: %d ms' %(num_iter, avg_boot_time))
print('Maximum firmware boot time %d ms' %max_boot_time)
print('Minimum firmware boot time %d ms' %min_boot_time)
print("=======================================================================================")


0 comments on commit 242e7fc

Please sign in to comment.