lib_manager: Add libcode modules support

A loadable library can contain a several modules marked as lib_code. This
modules contains code shared by a multiple modules.

Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
This commit is contained in:
Adrian Warecki 2023-12-07 16:28:02 +01:00 committed by Liam Girdwood
parent 6cf723fc7d
commit fec50da244
3 changed files with 95 additions and 0 deletions

View File

@ -81,7 +81,9 @@ struct ipc_lib_msg {
struct ext_library { struct ext_library {
struct k_spinlock lock; /* last locking CPU record */ struct k_spinlock lock; /* last locking CPU record */
struct sof_man_fw_desc *desc[LIB_MANAGER_MAX_LIBS]; struct sof_man_fw_desc *desc[LIB_MANAGER_MAX_LIBS];
#ifdef CONFIG_LIBCODE_MODULE_SUPPORT
uint32_t mods_exec_load_cnt; uint32_t mods_exec_load_cnt;
#endif
struct ipc_lib_msg *lib_notif_pool; struct ipc_lib_msg *lib_notif_pool;
uint32_t lib_notif_count; uint32_t lib_notif_count;

View File

@ -13,4 +13,17 @@ config LIBRARY_MANAGER
Externally developed modules both for SOF and Zephyr Externally developed modules both for SOF and Zephyr
could be used if enabled. could be used if enabled.
If unsure say N. If unsure say N.
config LIBCODE_MODULE_SUPPORT
bool "Add support for libcode modules"
default n
depends on LIBRARY_MANAGER
help
A loadable library can contain a several modules marked
as lib_code. This modules contains code shared by
a multiple modules. This option adds support for modules
of this type.
If unsure say N.
endmenu endmenu

View File

@ -140,6 +140,71 @@ static int lib_manager_unload_module(const struct sof_man_module *const mod)
return 0; return 0;
} }
#ifdef CONFIG_LIBCODE_MODULE_SUPPORT
/* There are modules marked as lib_code. This is code shared between several modules inside
* the library. Load all lib_code modules with first none lib_code module load.
*/
static int lib_manager_load_libcode_modules(const uint32_t module_id,
const struct sof_man_fw_desc *const desc)
{
struct ext_library *const ext_lib = ext_lib_get();
const struct sof_man_module *module_entry = (struct sof_man_module *)
((char *)desc + SOF_MAN_MODULE_OFFSET(0));
const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id);
int ret, idx;
if (++ext_lib->mods_exec_load_cnt > 1)
return 0;
for (idx = 0; idx < desc->header.num_module_entries; ++idx, ++module_entry) {
if (module_entry->type.lib_code) {
ret = lib_manager_load_module(lib_id << LIB_MANAGER_LIB_ID_SHIFT | idx,
module_entry);
if (ret < 0)
goto err;
}
}
return 0;
err:
for (--idx, --module_entry; idx >= 0; --idx, --module_entry) {
if (module_entry->type.lib_code) {
ret = lib_manager_unload_module(module_entry);
if (ret < 0)
goto err;
}
}
return ret;
}
/* There are modules marked as lib_code. This is code shared between several modules inside
* the library. Unload all lib_code modules with last none lib_code module unload.
*/
static int lib_manager_unload_libcode_modules(const uint32_t module_id,
const struct sof_man_fw_desc *const desc)
{
struct ext_library *const ext_lib = ext_lib_get();
const struct sof_man_module *module_entry = (struct sof_man_module *)
((char *)desc + SOF_MAN_MODULE_OFFSET(0));
int ret, idx;
if (--ext_lib->mods_exec_load_cnt > 0)
return 0;
for (idx = 0; idx < desc->header.num_module_entries; ++idx, ++module_entry) {
if (module_entry->type.lib_code) {
ret = lib_manager_unload_module(module_entry);
if (ret < 0)
return ret;
}
}
return 0;
}
#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */
static void __sparse_cache *lib_manager_get_instance_bss_address(uint32_t module_id, static void __sparse_cache *lib_manager_get_instance_bss_address(uint32_t module_id,
uint32_t instance_id, uint32_t instance_id,
struct sof_man_module *mod) struct sof_man_module *mod)
@ -227,11 +292,20 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv,
if (ret < 0) if (ret < 0)
return 0; return 0;
#ifdef CONFIG_LIBCODE_MODULE_SUPPORT
ret = lib_manager_load_libcode_modules(module_id, desc);
if (ret < 0)
goto err;
#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */
ret = lib_manager_allocate_module_instance(module_id, IPC4_INST_ID(ipc_config->id), ret = lib_manager_allocate_module_instance(module_id, IPC4_INST_ID(ipc_config->id),
base_cfg->is_pages, mod); base_cfg->is_pages, mod);
if (ret < 0) { if (ret < 0) {
tr_err(&lib_manager_tr, tr_err(&lib_manager_tr,
"lib_manager_allocate_module(): module allocation failed: %d", ret); "lib_manager_allocate_module(): module allocation failed: %d", ret);
#ifdef CONFIG_LIBCODE_MODULE_SUPPORT
lib_manager_unload_libcode_modules(module_id, desc);
#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */
goto err; goto err;
} }
return mod->entry_point; return mod->entry_point;
@ -259,6 +333,12 @@ int lib_manager_free_module(const struct comp_driver *drv,
if (ret < 0) if (ret < 0)
return ret; return ret;
#ifdef CONFIG_LIBCODE_MODULE_SUPPORT
ret = lib_manager_unload_libcode_modules(module_id, desc);
if (ret < 0)
return ret;
#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */
ret = lib_manager_free_module_instance(module_id, IPC4_INST_ID(ipc_config->id), mod); ret = lib_manager_free_module_instance(module_id, IPC4_INST_ID(ipc_config->id), mod);
if (ret < 0) { if (ret < 0) {
tr_err(&lib_manager_tr, tr_err(&lib_manager_tr,