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 Jun 12, 2024
1 parent d10020d commit 13578e2
Showing 1 changed file with 135 additions and 0 deletions.
135 changes: 135 additions & 0 deletions tools/sof-fw-boot-test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env python3

"""Module to stress test firmware boot"""

import argparse
import logging
import sys
import time

logging.basicConfig(level=logging.INFO, format="%(message)s")

# set path to the depbugfs entries
debugfs_path = "/sys/kernel/debug/sof/dsp_ops"

# define command line arguments
def parse_cmdline():
"""Function to parse the command line arguments"""
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())


def boot_fw():
"""Power down the DSP and boot firmware using previously set firmware path and filename"""
# put the DSP in D3
debugfs_entry = debugfs_path + "/dsp_power_state"
with open(debugfs_entry, "w", encoding="utf8") as dbgf:
dbgf.write("D3\n")

# check if the DSP is in D3
with open(debugfs_entry, "r", encoding="utf8") as dbgf:
power_state = dbgf.read(1024)
if power_state != "D3":
sys.exit("Failed booting firmware. DSP is not in D3")

# unload current firmware
debugfs_entry = debugfs_path + "/unload_fw"
with open(debugfs_entry, "w", encoding="utf8") as dbgf:
dbgf.write("1\n")

# get current fw_state and continue to boot only if the current state is 'PREPARE'
debugfs_entry = debugfs_path + "/fw_state"
with open(debugfs_entry, "r", encoding="utf8") as dbgf:
fw_state = dbgf.read(1024)
fw_state = fw_state.rstrip()
if fw_state != "PREPARE":
sys.exit("Cannot boot firmware boot from current state {fw_state}")

# load and boot firmware
debugfs_entry = debugfs_path + "/boot_fw"
start = time.time()
with open(debugfs_entry, "w", encoding="utf8") as dbgf:
dbgf.write("1\n")
end = time.time()

# get current fw_state
debugfs_entry = debugfs_path + "/fw_state"
with open(debugfs_entry, "r", encoding="utf8") as dbgf:
fw_state = dbgf.read(1024)
fw_state = fw_state.rstrip()

# calculate boot time
boot_time_ms = round((end - start) * 1000, 3)

return boot_time_ms, fw_state


def main():
"""Main function for stress testing"""
cmd_args = parse_cmdline()

# Get firmware file path
fw_path = cmd_args["fw_path"]

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

num_iter = cmd_args["iter"]
output = f"""==============================================================================
Starting boot stress test with:
Firmware filename: {fw_filename}
Path to firmware file: {fw_path}
Number of Iterations: {num_iter}
=============================================================================="""
logging.info(output)

# set the firmware filename & path
with open(debugfs_path + "/fw_filename", "w", encoding="utf8") as dbgf:
dbgf.write(fw_filename + "\n")
with open(debugfs_path + "/fw_path", "w", encoding="utf8") as dbgf:
dbgf.write(fw_path + "\n")

total_boot_time_ms = 0
min_boot_time_ms = sys.maxsize
max_boot_time_ms = 0

for i in range(num_iter):
boot_time_ms, fw_state = boot_fw()
# check if fw_state is COMPLETE
if fw_state != "COMPLETE":
sys.exit(f"Firmware boot failed at iteration {i}")

total_boot_time_ms += boot_time_ms
min_boot_time_ms = min(min_boot_time_ms, boot_time_ms)
max_boot_time_ms = max(max_boot_time_ms, boot_time_ms)

logging.info(f"Firmware boot iteration {i} completed in {boot_time_ms} ms")

# print firmware boot stats
avg_boot_time_ms = total_boot_time_ms / num_iter
output = f"""==============================================================================
Average firmware boot time {avg_boot_time_ms} ms
Maximum firmware boot time {max_boot_time_ms} ms
Minimum firmware boot time {min_boot_time_ms} ms
=============================================================================="""
logging.info(output)

if __name__ == "__main__":
main()

0 comments on commit 13578e2

Please sign in to comment.