mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
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>
This commit is contained in:
parent
5cf1b7b471
commit
7c052c6615
@ -3,6 +3,7 @@
|
||||
|
||||
cs_dsp_test_utils-objs := \
|
||||
cs_dsp_mock_mem_maps.o \
|
||||
cs_dsp_mock_bin.o \
|
||||
cs_dsp_mock_regmap.o \
|
||||
cs_dsp_mock_utils.o \
|
||||
cs_dsp_mock_wmfw.o
|
||||
|
199
drivers/firmware/cirrus/test/cs_dsp_mock_bin.c
Normal file
199
drivers/firmware/cirrus/test/cs_dsp_mock_bin.c
Normal file
@ -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");
|
@ -78,6 +78,7 @@ struct cs_dsp_mock_xm_header {
|
||||
};
|
||||
|
||||
struct cs_dsp_mock_wmfw_builder;
|
||||
struct cs_dsp_mock_bin_builder;
|
||||
|
||||
extern const unsigned int cs_dsp_mock_adsp2_32bit_sysbase;
|
||||
extern const unsigned int cs_dsp_mock_adsp2_16bit_sysbase;
|
||||
@ -121,6 +122,23 @@ void cs_dsp_mock_regmap_drop_bytes(struct cs_dsp_test *priv,
|
||||
void cs_dsp_mock_regmap_drop_system_regs(struct cs_dsp_test *priv);
|
||||
bool cs_dsp_mock_regmap_is_dirty(struct cs_dsp_test *priv, bool drop_system_regs);
|
||||
|
||||
struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
|
||||
int format_version,
|
||||
unsigned int fw_version);
|
||||
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);
|
||||
void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
|
||||
const char *info);
|
||||
void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder,
|
||||
const char *name);
|
||||
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);
|
||||
struct firmware *cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder *builder);
|
||||
|
||||
struct cs_dsp_mock_wmfw_builder *cs_dsp_mock_wmfw_init(struct cs_dsp_test *priv,
|
||||
int format_version);
|
||||
void cs_dsp_mock_wmfw_add_raw_block(struct cs_dsp_mock_wmfw_builder *builder,
|
||||
|
Loading…
Reference in New Issue
Block a user