-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
firmware: cs_dsp: Add mock bin file generator for KUnit testing
Add a mock firmware file that emulates what the firmware build tools would normally create. This will be used by KUnit tests to generate a test bin file. The data payload in a bin is an opaque blob, so the mock bin only needs to generate the appropriate file header and description block for each payload blob. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://patch.msgid.link/20241212143725.1381013-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
- Loading branch information
Richard Fitzgerald
authored and
Mark Brown
committed
Dec 13, 2024
1 parent
5cf1b7b
commit 7c052c6
Showing
3 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
// | ||
// bin file builder for cs_dsp KUnit tests. | ||
// | ||
// Copyright (C) 2024 Cirrus Logic, Inc. and | ||
// Cirrus Logic International Semiconductor Ltd. | ||
|
||
#include <kunit/resource.h> | ||
#include <kunit/test.h> | ||
#include <linux/firmware/cirrus/cs_dsp.h> | ||
#include <linux/firmware/cirrus/cs_dsp_test_utils.h> | ||
#include <linux/firmware/cirrus/wmfw.h> | ||
#include <linux/firmware.h> | ||
#include <linux/math.h> | ||
#include <linux/overflow.h> | ||
#include <linux/string.h> | ||
#include <linux/vmalloc.h> | ||
|
||
/* Buffer large enough for bin file content */ | ||
#define CS_DSP_MOCK_BIN_BUF_SIZE 32768 | ||
|
||
KUNIT_DEFINE_ACTION_WRAPPER(vfree_action_wrapper, vfree, void *) | ||
|
||
struct cs_dsp_mock_bin_builder { | ||
struct cs_dsp_test *test_priv; | ||
void *buf; | ||
void *write_p; | ||
size_t bytes_used; | ||
}; | ||
|
||
/** | ||
* cs_dsp_mock_bin_get_firmware() - Get struct firmware wrapper for data. | ||
* | ||
* @builder: Pointer to struct cs_dsp_mock_bin_builder. | ||
* | ||
* Return: Pointer to a struct firmware wrapper for the data. | ||
*/ | ||
struct firmware *cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder *builder) | ||
{ | ||
struct firmware *fw; | ||
|
||
fw = kunit_kzalloc(builder->test_priv->test, sizeof(*fw), GFP_KERNEL); | ||
KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, fw); | ||
|
||
fw->data = builder->buf; | ||
fw->size = builder->bytes_used; | ||
|
||
return fw; | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_get_firmware, "FW_CS_DSP_KUNIT_TEST_UTILS"); | ||
|
||
/** | ||
* cs_dsp_mock_bin_add_raw_block() - Add a data block to the bin file. | ||
* | ||
* @builder: Pointer to struct cs_dsp_mock_bin_builder. | ||
* @alg_ig: Algorithm ID. | ||
* @alg_ver: Algorithm version. | ||
* @type: Type of the block. | ||
* @offset: Offset. | ||
* @payload_data: Pointer to buffer containing the payload data. | ||
* @payload_len_bytes: Length of payload data in bytes. | ||
*/ | ||
void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder, | ||
unsigned int alg_id, unsigned int alg_ver, | ||
int type, unsigned int offset, | ||
const void *payload_data, size_t payload_len_bytes) | ||
{ | ||
struct wmfw_coeff_item *item; | ||
size_t bytes_needed = struct_size_t(struct wmfw_coeff_item, data, payload_len_bytes); | ||
|
||
KUNIT_ASSERT_TRUE(builder->test_priv->test, | ||
(builder->write_p + bytes_needed) < | ||
(builder->buf + CS_DSP_MOCK_BIN_BUF_SIZE)); | ||
|
||
item = builder->write_p; | ||
|
||
item->offset = cpu_to_le16(offset); | ||
item->type = cpu_to_le16(type); | ||
item->id = cpu_to_le32(alg_id); | ||
item->ver = cpu_to_le32(alg_ver << 8); | ||
item->len = cpu_to_le32(payload_len_bytes); | ||
|
||
if (payload_len_bytes) | ||
memcpy(item->data, payload_data, payload_len_bytes); | ||
|
||
builder->write_p += bytes_needed; | ||
builder->bytes_used += bytes_needed; | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_raw_block, "FW_CS_DSP_KUNIT_TEST_UTILS"); | ||
|
||
static void cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder *builder, | ||
const char *info, int type) | ||
{ | ||
size_t info_len = strlen(info); | ||
char *tmp = NULL; | ||
|
||
if (info_len % 4) { | ||
/* Create a padded string with length a multiple of 4 */ | ||
info_len = round_up(info_len, 4); | ||
tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL); | ||
KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp); | ||
memcpy(tmp, info, info_len); | ||
info = tmp; | ||
} | ||
|
||
cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, info, info_len); | ||
kunit_kfree(builder->test_priv->test, tmp); | ||
} | ||
|
||
/** | ||
* cs_dsp_mock_bin_add_info() - Add an info block to the bin file. | ||
* | ||
* @builder: Pointer to struct cs_dsp_mock_bin_builder. | ||
* @info: Pointer to info string to be copied into the file. | ||
* | ||
* The string will be padded to a length that is a multiple of 4 bytes. | ||
*/ | ||
void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder, | ||
const char *info) | ||
{ | ||
cs_dsp_mock_bin_add_name_or_info(builder, info, WMFW_INFO_TEXT); | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_info, "FW_CS_DSP_KUNIT_TEST_UTILS"); | ||
|
||
/** | ||
* cs_dsp_mock_bin_add_name() - Add a name block to the bin file. | ||
* | ||
* @builder: Pointer to struct cs_dsp_mock_bin_builder. | ||
* @name: Pointer to name string to be copied into the file. | ||
*/ | ||
void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder, | ||
const char *name) | ||
{ | ||
cs_dsp_mock_bin_add_name_or_info(builder, name, WMFW_NAME_TEXT); | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_name, "FW_CS_DSP_KUNIT_TEST_UTILS"); | ||
|
||
/** | ||
* cs_dsp_mock_bin_add_patch() - Add a patch data block to the bin file. | ||
* | ||
* @builder: Pointer to struct cs_dsp_mock_bin_builder. | ||
* @alg_ig: Algorithm ID for the patch. | ||
* @alg_ver: Algorithm version for the patch. | ||
* @mem_region: Memory region for the patch. | ||
* @reg_addr_offset: Offset to start of data in register addresses. | ||
* @payload_data: Pointer to buffer containing the payload data. | ||
* @payload_len_bytes: Length of payload data in bytes. | ||
*/ | ||
void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder, | ||
unsigned int alg_id, unsigned int alg_ver, | ||
int mem_region, unsigned int reg_addr_offset, | ||
const void *payload_data, size_t payload_len_bytes) | ||
{ | ||
/* Payload length must be a multiple of 4 */ | ||
KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0); | ||
|
||
cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver, | ||
mem_region, reg_addr_offset, | ||
payload_data, payload_len_bytes); | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS"); | ||
|
||
/** | ||
* cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder. | ||
* | ||
* @priv: Pointer to struct cs_dsp_test. | ||
* @format_version: Required bin format version. | ||
* @fw_version: Firmware version to put in bin file. | ||
* | ||
* Return: Pointer to created struct cs_dsp_mock_bin_builder. | ||
*/ | ||
struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv, | ||
int format_version, | ||
unsigned int fw_version) | ||
{ | ||
struct cs_dsp_mock_bin_builder *builder; | ||
struct wmfw_coeff_hdr *hdr; | ||
|
||
builder = kunit_kzalloc(priv->test, sizeof(*builder), GFP_KERNEL); | ||
KUNIT_ASSERT_NOT_ERR_OR_NULL(priv->test, builder); | ||
builder->test_priv = priv; | ||
|
||
builder->buf = vmalloc(CS_DSP_MOCK_BIN_BUF_SIZE); | ||
KUNIT_ASSERT_NOT_NULL(priv->test, builder->buf); | ||
kunit_add_action_or_reset(priv->test, vfree_action_wrapper, builder->buf); | ||
|
||
/* Create header */ | ||
hdr = builder->buf; | ||
memcpy(hdr->magic, "WMDR", sizeof(hdr->magic)); | ||
hdr->len = cpu_to_le32(offsetof(struct wmfw_coeff_hdr, data)); | ||
hdr->ver = cpu_to_le32(fw_version | (format_version << 24)); | ||
hdr->core_ver = cpu_to_le32(((u32)priv->dsp->type << 24) | priv->dsp->rev); | ||
|
||
builder->write_p = hdr->data; | ||
builder->bytes_used = offsetof(struct wmfw_coeff_hdr, data); | ||
|
||
return builder; | ||
} | ||
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_init, "FW_CS_DSP_KUNIT_TEST_UTILS"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters