mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
Import tegra platform drivers from linux-4.4. These files
are introduced or touched by the following commits in
linux-4.4:
5798930 arm: mach-tegra: Get rid of apbio.{c,h}
618d424 platform: tegra: enable denver_serr only for t18x
c9f681e arm: tegra: get rid of nct header
14cb7cf platform: tegra: nvdumper: Remove code which need NCT
46adb21 platform: tegra: mc: make mc-sid driver scalable and upstreamable
b0ea9ac usb: phy: Move header files to include/linux
7d63191 platform: tegra: mc: allow modules to access mc registers
1d5ac46 soc/tegra: Add GPU EDP Management
09166fd soc/tegra: Add CPU EDP Management
7118c16 platform: powergate: tegra: update ISPA name
59cebf1 bwmgr: Add tegra21 specific bwmgr functionality
e91ada2 bwmgr: merge dram specific functionality to common code
19fb2fe drivers: platform: tegra: remove TEGRA_21x defconfig
b87f6739 platform: nvadsp: fix is_mboxq_full check
b11cdba platform: tegra: powergate: do not handle SATA clk
8324487 platform: tegra: mc: remove cl34000094 hacks
a77d415 platform: tegra: mc: rename mc-sid.c to tegra-mc-sid.c
df6d5a8 platform: tegra: remove support for soctherm
e96ddb9 Merge "Merge branch 'dev/praithatha/k4.4_mc_sid' into dev-kernel-4.4" into dev-kernel-4.4
2f69aa5 Merge branch 'dev/praithatha/k4.4_mc_sid' into dev-kernel-4.4
e171bb1 adsp: dfs: override adsp dfs and reinit actmon
b7ca294 platform: tegra: mc: Add streamID configuration
457e747 nvdumper: fixed Coverity defects
e12c0c0 platform: tegra: Use ARCH_TEGRA_APE for APE PD code
40eba0d platform: tegra: drop flowctrl code
568ad6e central actmon: fix extra interrupt
944bdbf clk: tegra: Correct some nvenc clock names
5c957fe driver: platform: tegra: GR support
5af5163 coverity: Fix the error reported by Coverity
576ea23 tegra-virt-alt: Add adsp virtualization support
7407552 platform: tegra: nvadsp: Fix coverity defect
d11b6a0 platform: tegra: nvadsp: Fix coverity defect
6c41ef0 tegra: nvadsp: fix compilation when CONFIG_PM=n
4262e32 adsp: Add virtualization check
85384e2 Fix an uninitialized local value error
44a8d9c tegra: mc: export symbol tegra_set_latency_allowance
f699ce7 platform: nvadsp: disable app loading for secload
5ed4b72 drivers: tegra: allow to get "version" from dt
9b6fe36 tegra: add path to allow include
60d96e4 platform: tegra: nvadsp: nvadsp_os_get_version fix
79622a2 drivers: tegra: ape firmware version
27fb719 platform: tegra: iommu: enable linear map setup
b77bade platform: nvadsp: fix adsp clock handle
110b085 platform: tegra: Remove code for shared pad control
b770e0e bwmgr: pmqos: fix sparse warning
dd0400a platform: tegra: remove unused tegra_map_common_io
b343db9 platform: tegra: remove Tegra core voltage cap support
df9df6b platform/tegra: remove PMC wakeup support codes
c669b9a platform/tegra: pmc-iopower: switch to upstream PMC driver
688b6a6 platform/tegra: bootrom-pmc: switch to upstream PMC driver
d7d34e6 platform/tegra: remove reboot.c
60b4a47 soc/tegra: pmc: switch to upstream PMC driver
2c9409f bootprof: Separate discontinuous regions
e0cb4d2 arm64: tegra186: remove unused register nodes
12c2ba4 fiq reverts
65d8ccb platform: nvadsp: fix clk checks
b2eb017 platform: tegra: remove support for auto power detection
c403625 tegra: powergate: cleanup code for unsupported platform
589fecb platform: tegra: Removing unsupported platform sources
5f578a8 irqchip: gic: use CPU_PM only when registering
d45c1ea platform: tegra: remove nvdump support for t12x/t13x
9b0b6de Revert "Revert "android: fiq_debugger: FIQ glue for ARM64 CPUs""
d5351a1 Revert "Revert "drivers: platform: enumerate fiq_debugger device""
27af58f Revert "Revert "platform: tegra: clean up fiq_enable() implementation""
688e514 platform: tegra: Remove support for Tegra clock framework
c15896d tegra: denver-knobs: Remove nvmstat_pg stats
019f065 platform: tegra: Remove support for TEGRA_13x_SOC
207db5f drivers: platform: iommu: add linear mapping on lut
1bc0602 denver: hardwood: use device tree to find IRQ number
b11f182 isomgr: Apply ISO client's BW limit
132843c platform: tegra: Remove the API tegra_gpio_to_wake()
8a2892d platform: tegra: deprecate APIs to change waketable runtime
e2f5924 prod: Add support for masked write in partially prod config
e94ac08 platform: tegra: powergate: Remove support for TEGRA_12x_SOC
6b4c4cb platform: tegra: mc: Remove support for TEGRA_12x_SOC
39977fb platform: tegra: Remove drivers for TEGRA_12x_SOC
e17670c drivers: platform: fix denver_mca driver
61c6f5e tegra: powergate: add clocks for XUSBB
bb10919 tegra: powergate: cleanup clock and reset handling
73b944e tegra: powergate: correct xusbb partition reset ID
b3dc4f4 iommu: arm-smmu: add linear mapping support
6c9bcbb platform: tegra: support disabling CONFIG_PM
98d04a5 platform: tegra: remove legacy speedo files
c6b9acf platform: tegra: APIs to set prod based on name/index/offset/mask
a04d242 platform: tegra: mc: fix build error
1d8c939 platform: tegra: Remove miscellaneous platform specific drivers
daab9eb tegra: powergate: shorten some con ids
229a25f platform: tegra: remove tegra common support
3e71442 bwmgr: Remove checks to limit emc_freq
9f3f176 tegra: powergate: use new reset API and use ioremap
11cd9c8 platform: tegra: Disable T210 TCF cpufreq driver
224ecab platform: tegra: Remove the common board support
1813dd1 ivc: fix missing peer notification
a56ac67 ivc: fix incorrect counter reset
844c7a1 ivc: Remove nframes power of two check
5a3ec3a bwmgr: Add more information to clients info sysfs
522777c platform: tegra: remove raydium touch support
251660a platform: tegra: remove unneccessary panel file
0915b9a bwmgr: Add API to get core emc rate
c66f6bc platform: tegra: Add pmqos emc floor handling
a7b51df Add CONFIG_TEGRA_BOND_OUT and disable by default
29cd4ee Stubbed out tegra_periph_reset
3c07fd4 iommu: smmu: Changed the chip ids for 4.4 naming
3d780a1 platform: nvadsp: fix MAXCLKLATENCY offset
e470cdd platform: tegra: bwmgr: add a disable knob
1d8e851 tegra: denver-knobs: Use correct CPU id for bgallowed
db9711f bwmgr: Add errno to debug print
96ed52e drivers: usb: pmc: rebase pmc driver for kernel-4.4
6510703 tegra: denver-knobs: add tracer_control support
3a285a9 tegra: actmon: missing sysfs_attr_init()
0c83659 tegra: actmon: add sysfs node for emc load
2477286 platform: tegra: pmc: add usb2 sleepwalk APIs
8bcf839 pinctrl: add Tegra21x PADCTL/UPHY driver
acaa486 platform: nvadsp: make version func static
6028232 Revert "platform: tegra: clean up fiq_enable() implementation"
cc80660 Revert "drivers: platform: enumerate fiq_debugger device"
ab2cc4c Revert "android: fiq_debugger: FIQ glue for ARM64 CPUs"
38ff9fd drivers: platform: enumerate fiq_debugger device
1dd509c platform: tegra: clean up fiq_enable() implementation
0a87d11 android: fiq_debugger: FIQ glue for ARM64 CPUs
74ec787 platform: nvadsp: add adsp os version
9bd6a7f platform: tegra: Remove use of is_partition_clk_disabled
a56b821 drivers: class 'tegra-firmwares'
c859a13 Kconfig: Rename included Kconfigs
804f706 platform: tegra: add kfuse sensing for hdcp 1.x
9b3510f drivers: platform: tegra: only compile tegra_irq_to_wake for Tegra186
fb5394c drivers: platform: tegra: switch powergating driver to CCF
66d0faf tegra: mc: declare tegra_get_chip_id and use in mc
eb90d56 drivers: platform: Move DPD IO control into pmc driver
3816cef arm64: enable CCF
a196e10 soc/tegra: Add TEGRA148 and TEGRA186 chip id
8354256 drivers: platform: tegra: switch powergate driver to tegra_get_chip_id()
473ce73 platform: tegra: mc: adapt la driver to upstream tegra_get_chip_id()
0f2668b Kconfig: replace source with trysource for external projects
266255a platform: tegra: Add support to find prod setting
ac65ac1 platfor: tegra: prod: Do not use kmemleak_not_leak() for managed allocation
96358ea platform: tegra: prod: use devm_ for allocation
53933ed platform: tegra: Add sysfs entry for suspend/resume time
bfef5bc drivers: platform: tegra: add tegra_wake_to_gpio() interface
4409ca6 tegra: central_actmon: fix DEBUG_FS=n build
80aa543 platform:tegra:bwmgr: fix build issue.
f97d139 tegra: denver-knobs: fix build issue.
bcfc89c platform: tegra: prod: Add managed version of tegra_prod_get_from_node
85288f1 platform: tegra: prod: Add support for nested prod nodes.
0be37d5 platform: tegra: prod: Get rid of tegra_prod_release()
753f71d platform: tegra: prod: Remove unused APIs from public header
5b92965 platform: tegra: pmc: Use devm for tegra_prod allocation
21af9cb platform: tegra: prod: Add APIs to managed allocation of prod_list
2d9312b platform: tegra: move definition of tegra_prod_list structure to private
0d1efe1 platform: tegra: prod: Use for_each_available_child_of_node()
3014a93 tegra:nvadsp:fix issue with CONFIG_DEBUG_FS=n
edd37fd platform: tegra: prod: Use proper variable name
168ec7b platform: tegra: prod: Fix parsing of prod setting for package/board
bc8cd66 platform: tegra: prod: Make allocated memory as kmemleak_not_leak()
380f89f PM/Domains: Remove use of 'need_save' and 'need_restore'
fdf13ea platform: nvadsp: change perms of debugfs files
bc34a73 nvadsp: console: keep track of app context
62d0040 nvadsp: console: fix app name handling
f113a66 platform: nvadsp: export adsp dump sys
e0e907b platform: tegra: nvadsp: fix setting boot freqs
c7fb6ee Revert "drivers: platform: tegra: add proper config check"
c5b1e8b platform:tegra:bwmgr: Fix bwmgr floor aggregation
584b06e platform: tegra: bwmgr: Add Security Engine Client
f63d36d tegra: gpo: move gpio-tegra
8171ecb security: Use a common secure monitor interface
1359955 platform: nvadsp: fix unused function build issue
aa55e67 platform: tegra: Remove unused functions
6f2d8d8 platform: tegra: Change value of need_save to 'true'
0c28fab Merge "Merge agic changes" into dev-kernel
0174199 platform: nvadsp: Correct AGIC irqs state dumps
0d7fec4 irqchip: Move AGIC Kconfig from nvadsp
b7ce47f kernel: change kernel path
7627eeb platform: tegra: mc: fix coverity defects
d4afd62 platform: tegra: remove platform emc driver for Tegra210
93e504f platform: tegra: mc: include module.h
4a3d8fa platform: tegra: add thermal throttling config
b99e994 platform: tegra: move tegra_fiq_debugger from mach-tegra
b89bbf4b tegra: t21x: restore irqs-t21x.h file
3ec5fa9 arm64: Copy over more T210 files
0c3285d platform: tegra: mc: enable latency allowance code compile
80b090f platform: tegra: mc: add T18x PTSA vars
345b7ee tegra: mc: add set LA funcion pointers
26c3314 platform: tegra: Add support for mask with 1s
62e11eb platform: tegra: mc: Don't compile latency_allowance for k4.4
dc9cafc platform: tegra: Add protection to code
55dabeb drivers: platform: tegra: add proper config check
99a65ef platform: tegra: tegra_usb_pmc depends on T210
eae2a6d tegra: denver-knobs: fix seq_printf return value
74467a6 TEMP: drivers: Kconfig: Use source instead of trysource
000acb1 platform: tegra: add missing headers and build fixes
e228595 kconfig: add trysource to kernel-t18x
94daaaa drivers: platform: tegra: Initialize drivers/platform/tegra inside kernel-next
c5c90b8 drivers: platform: tegra: Add miscellaneous platform specific drivers
3faa2fe drivers: platform: tegra: PTM driver for t12x and t21x
8953022 drivers: platform: tegra: Add kfuse driver
19a844c drivers: platform: tegra: Tegra USB Padctrl driver
4596579 drivers: platform: tegra: Add nvdumper source for platforms
a03e4b0 drivers: platform: tegra: Add wakeup related source
363b7ee drivers: platform: tegra: central_actmon: Add common and support for T21x
9fe72d5 drivers: platform: tegra: mc: Add platform specific MC source
6c2b078 drivers: platform: tegra: Adding denver specific drivers
976c8b9 drivers: platform: tegra: Add bootloader drivers
a97be5b drivers: platform: tegra: nvadsp: Add platform specific nvadsp drivers
b29af75 drivers: platform: tegra: Add powergating drivers
899dddd platform: tegra: Add Tegra Clocks drivers for various platforms
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: Ic232ac71a09fe5176247692630db5bc6107573fa
Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1537316
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
989 lines
25 KiB
C
989 lines
25 KiB
C
/*
|
|
* run_app.c
|
|
*
|
|
* ADSP OS App management
|
|
*
|
|
* Copyright (C) 2014-2016, NVIDIA Corporation. All rights reserved.
|
|
*
|
|
* This software is licensed under the terms of the GNU General Public
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
* may be copied, distributed, and modified under those terms.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#include <linux/platform_device.h>
|
|
#include <linux/tegra_nvadsp.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/dma-buf.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/elf.h>
|
|
|
|
#include "aram_manager.h"
|
|
#include "os.h"
|
|
#include "dev.h"
|
|
#include "adsp_shared_struct.h"
|
|
|
|
#define DYN_APP_EXTN ".elf"
|
|
|
|
/*
|
|
* structure to hold the list of app binaries loaded and
|
|
* its associated instances.
|
|
*/
|
|
struct nvadsp_app_service {
|
|
char name[NVADSP_NAME_SZ];
|
|
struct list_head node;
|
|
int instance;
|
|
struct mutex lock;
|
|
struct list_head app_head;
|
|
const uint32_t token;
|
|
const struct app_mem_size *mem_size;
|
|
int generated_instance_id;
|
|
struct adsp_module *mod;
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *debugfs;
|
|
#endif
|
|
};
|
|
|
|
/* nvadsp app loader private structure */
|
|
struct nvadsp_app_priv_struct {
|
|
struct platform_device *pdev;
|
|
struct completion os_load_complete;
|
|
struct nvadsp_mbox mbox;
|
|
struct list_head service_list;
|
|
struct mutex service_lock_list;
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *adsp_app_debugfs_root;
|
|
#endif
|
|
};
|
|
|
|
static struct nvadsp_app_priv_struct priv;
|
|
|
|
static void delete_app_instance(nvadsp_app_info_t *);
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
static int dump_binary_in_2bytes_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
struct nvadsp_app_service *ser = s->private;
|
|
struct adsp_module *mod = ser->mod;
|
|
u32 adsp_ptr;
|
|
u16 *ptr;
|
|
int i;
|
|
|
|
adsp_ptr = mod->adsp_module_ptr;
|
|
ptr = (u16 *)mod->module_ptr;
|
|
for (i = 0; i < mod->size; i += 2)
|
|
seq_printf(s, "0x%x : 0x%04x\n", adsp_ptr + i, *(ptr + i));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int dump_binary_in_words_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
struct nvadsp_app_service *ser = s->private;
|
|
struct adsp_module *mod = ser->mod;
|
|
u32 adsp_ptr;
|
|
u32 *ptr;
|
|
int i;
|
|
|
|
adsp_ptr = mod->adsp_module_ptr;
|
|
ptr = (u32 *)mod->module_ptr;
|
|
for (i = 0; i < mod->size; i += 4)
|
|
seq_printf(s, "0x%x : 0x%08x\n", adsp_ptr + i, *(ptr + i));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int host_load_addr_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
struct nvadsp_app_service *ser = s->private;
|
|
struct adsp_module *mod = ser->mod;
|
|
|
|
seq_printf(s, "%p\n", mod->module_ptr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_load_addr_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
struct nvadsp_app_service *ser = s->private;
|
|
struct adsp_module *mod = ser->mod;
|
|
|
|
seq_printf(s, "0x%x\n", mod->adsp_module_ptr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int size_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
struct nvadsp_app_service *ser = s->private;
|
|
struct adsp_module *mod = ser->mod;
|
|
|
|
seq_printf(s, "%lu\n", mod->size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dram_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
const struct app_mem_size *mem_size = s->private;
|
|
|
|
seq_printf(s, "%llu\n", mem_size->dram);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dram_shared_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
const struct app_mem_size *mem_size = s->private;
|
|
|
|
seq_printf(s, "%llu\n", mem_size->dram_shared);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dram_shared_wc_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
const struct app_mem_size *mem_size = s->private;
|
|
|
|
seq_printf(s, "%llu\n", mem_size->dram_shared_wc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int aram_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
const struct app_mem_size *mem_size = s->private;
|
|
|
|
seq_printf(s, "%llu\n", mem_size->aram);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int aram_exclusive_app_file_node(struct seq_file *s, void *data)
|
|
{
|
|
const struct app_mem_size *mem_size = s->private;
|
|
|
|
seq_printf(s, "%llu\n", mem_size->aram_x);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define ADSP_APP_CREATE_FOLDER(x, root) \
|
|
do {\
|
|
x = debugfs_create_dir(#x, root); \
|
|
if (IS_ERR_OR_NULL(x)) { \
|
|
dev_err(dev, "unable to create app %s folder\n", #x); \
|
|
ret = -ENOENT; \
|
|
goto rm_debug_root; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define ADSP_APP_CREATE_FILE(x, priv, root) \
|
|
do { \
|
|
if (IS_ERR_OR_NULL(debugfs_create_file(#x, S_IRUSR, root, \
|
|
priv, &x##_node_operations))) { \
|
|
dev_err(dev, "unable tp create app %s file\n", #x); \
|
|
ret = -ENOENT; \
|
|
goto rm_debug_root; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define ADSP_APP_FILE_OPERATION(x) \
|
|
static int x##_open(struct inode *inode, struct file *file) \
|
|
{ \
|
|
return single_open(file, x##_app_file_node, inode->i_private); \
|
|
} \
|
|
\
|
|
static const struct file_operations x##_node_operations = { \
|
|
.open = x##_open, \
|
|
.read = seq_read, \
|
|
.llseek = seq_lseek, \
|
|
.release = single_release, \
|
|
};
|
|
|
|
ADSP_APP_FILE_OPERATION(dump_binary_in_2bytes);
|
|
ADSP_APP_FILE_OPERATION(dump_binary_in_words);
|
|
ADSP_APP_FILE_OPERATION(host_load_addr);
|
|
ADSP_APP_FILE_OPERATION(adsp_load_addr);
|
|
ADSP_APP_FILE_OPERATION(size);
|
|
|
|
ADSP_APP_FILE_OPERATION(dram);
|
|
ADSP_APP_FILE_OPERATION(dram_shared);
|
|
ADSP_APP_FILE_OPERATION(dram_shared_wc);
|
|
ADSP_APP_FILE_OPERATION(aram);
|
|
ADSP_APP_FILE_OPERATION(aram_exclusive);
|
|
|
|
static int create_adsp_app_debugfs(struct nvadsp_app_service *ser)
|
|
{
|
|
|
|
struct app_mem_size *mem_size = (struct app_mem_size *)ser->mem_size;
|
|
struct device *dev = &priv.pdev->dev;
|
|
struct dentry *instance_mem_sizes;
|
|
struct dentry *root;
|
|
int ret = 0;
|
|
|
|
root = debugfs_create_dir(ser->name,
|
|
priv.adsp_app_debugfs_root);
|
|
if (IS_ERR_OR_NULL(root)) {
|
|
ret = -EINVAL;
|
|
goto err_out;
|
|
}
|
|
|
|
ADSP_APP_CREATE_FILE(dump_binary_in_2bytes, ser, root);
|
|
ADSP_APP_CREATE_FILE(dump_binary_in_words, ser, root);
|
|
ADSP_APP_CREATE_FILE(host_load_addr, ser, root);
|
|
ADSP_APP_CREATE_FILE(adsp_load_addr, ser, root);
|
|
ADSP_APP_CREATE_FILE(size, ser, root);
|
|
ADSP_APP_CREATE_FOLDER(instance_mem_sizes, root);
|
|
ADSP_APP_CREATE_FILE(dram, mem_size, instance_mem_sizes);
|
|
ADSP_APP_CREATE_FILE(dram_shared, mem_size, instance_mem_sizes);
|
|
ADSP_APP_CREATE_FILE(dram_shared_wc, mem_size, instance_mem_sizes);
|
|
ADSP_APP_CREATE_FILE(aram, mem_size, instance_mem_sizes);
|
|
ADSP_APP_CREATE_FILE(aram_exclusive, mem_size, instance_mem_sizes);
|
|
|
|
root = ser->debugfs;
|
|
return 0;
|
|
rm_debug_root:
|
|
debugfs_remove_recursive(root);
|
|
err_out:
|
|
return ret;
|
|
}
|
|
|
|
static int __init adsp_app_debug_init(struct dentry *root)
|
|
{
|
|
priv.adsp_app_debugfs_root = debugfs_create_dir("adsp_apps", root);
|
|
return IS_ERR_OR_NULL(priv.adsp_app_debugfs_root) ? -ENOMEM : 0;
|
|
}
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
static struct nvadsp_app_service *get_loaded_service(const char *appfile)
|
|
{
|
|
struct device *dev = &priv.pdev->dev;
|
|
struct nvadsp_app_service *ser;
|
|
|
|
list_for_each_entry(ser, &priv.service_list, node) {
|
|
if (!strcmp(appfile, ser->name)) {
|
|
dev_dbg(dev, "module %s already loaded\n", appfile);
|
|
return ser;
|
|
}
|
|
}
|
|
dev_dbg(dev, "module %s will be loaded\n", appfile);
|
|
return NULL;
|
|
}
|
|
|
|
static inline void extract_appname(char *appname, const char *appfile)
|
|
{
|
|
char *token = strstr(appfile, DYN_APP_EXTN);
|
|
int len = token ? token - appfile : strlen(appfile);
|
|
|
|
strncpy(appname, appfile, len);
|
|
appname[len] = '\0';
|
|
}
|
|
|
|
static nvadsp_app_handle_t app_load(const char *appfile,
|
|
struct adsp_shared_app *shared_app, bool dynamic)
|
|
{
|
|
struct nvadsp_drv_data *drv_data;
|
|
struct device *dev = &priv.pdev->dev;
|
|
char appname[NVADSP_NAME_SZ] = { };
|
|
struct nvadsp_app_service *ser;
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
extract_appname(appname, appfile);
|
|
mutex_lock(&priv.service_lock_list);
|
|
ser = get_loaded_service(appname);
|
|
if (!ser) {
|
|
|
|
/* dynamic loading is disabled when running in secure mode */
|
|
if (drv_data->adsp_os_secload && dynamic)
|
|
goto err;
|
|
dev_dbg(dev, "loading app %s %s\n", appfile, appname);
|
|
ser = devm_kzalloc(dev, sizeof(*ser), GFP_KERNEL);
|
|
if (!ser)
|
|
goto err;
|
|
strlcpy(ser->name, appname, NVADSP_NAME_SZ);
|
|
|
|
/*load the module in to memory */
|
|
ser->mod = dynamic ?
|
|
load_adsp_dynamic_module(appfile, appfile, dev) :
|
|
load_adsp_static_module(appfile, shared_app, dev);
|
|
if (IS_ERR_OR_NULL(ser->mod))
|
|
goto err_free_service;
|
|
ser->mem_size = &ser->mod->mem_size;
|
|
|
|
mutex_init(&ser->lock);
|
|
INIT_LIST_HEAD(&ser->app_head);
|
|
|
|
/* add the app instance service to the list */
|
|
list_add_tail(&ser->node, &priv.service_list);
|
|
#ifdef CONFIG_DEBUG_FS
|
|
create_adsp_app_debugfs(ser);
|
|
#endif
|
|
dev_dbg(dev, "loaded app %s\n", ser->name);
|
|
}
|
|
mutex_unlock(&priv.service_lock_list);
|
|
|
|
return ser;
|
|
|
|
err_free_service:
|
|
devm_kfree(dev, ser);
|
|
err:
|
|
mutex_unlock(&priv.service_lock_list);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
nvadsp_app_handle_t nvadsp_app_load(const char *appname, const char *appfile)
|
|
{
|
|
struct nvadsp_drv_data *drv_data;
|
|
|
|
if (IS_ERR_OR_NULL(priv.pdev)) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
return NULL;
|
|
}
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
|
|
if (!drv_data->adsp_os_running)
|
|
return NULL;
|
|
|
|
return app_load(appfile, NULL, true);
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_load);
|
|
|
|
static void free_instance_memory(nvadsp_app_info_t *app,
|
|
const struct app_mem_size *sz)
|
|
{
|
|
adsp_app_mem_t *mem = &app->mem;
|
|
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
|
|
|
if (mem->dram) {
|
|
nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
|
|
mem->dram = NULL;
|
|
iova_mem->dram = 0;
|
|
}
|
|
|
|
if (mem->shared) {
|
|
nvadsp_free_coherent(sz->dram_shared, mem->shared,
|
|
iova_mem->shared);
|
|
mem->shared = NULL;
|
|
iova_mem->shared = 0;
|
|
}
|
|
|
|
if (mem->shared_wc) {
|
|
nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
|
|
iova_mem->shared_wc);
|
|
mem->shared_wc = NULL;
|
|
iova_mem->shared_wc = 0;
|
|
}
|
|
|
|
if (mem->aram_flag)
|
|
aram_release(mem->aram);
|
|
else if (mem->aram)
|
|
nvadsp_free_coherent(sz->aram, mem->aram, iova_mem->aram);
|
|
mem->aram = NULL;
|
|
iova_mem->aram = 0;
|
|
mem->aram_flag = 0;
|
|
|
|
if (mem->aram_x_flag) {
|
|
aram_release(mem->aram_x);
|
|
mem->aram_x = NULL;
|
|
iova_mem->aram_x = 0;
|
|
mem->aram_flag = 0;
|
|
}
|
|
|
|
}
|
|
|
|
static int create_instance_memory(nvadsp_app_info_t *app,
|
|
const struct app_mem_size *sz)
|
|
{
|
|
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
|
struct device *dev = &priv.pdev->dev;
|
|
adsp_app_mem_t *mem = &app->mem;
|
|
char name[NVADSP_NAME_SZ];
|
|
void *aram_handle;
|
|
dma_addr_t da;
|
|
|
|
snprintf(name, NVADSP_NAME_SZ, "%s:%d", app->name, app->instance_id);
|
|
|
|
if (sz->dram) {
|
|
mem->dram = nvadsp_alloc_coherent(sz->dram, &da, GFP_KERNEL);
|
|
iova_mem->dram = (uint32_t)da;
|
|
if (!mem->dram) {
|
|
dev_err(dev, "app %s dram alloc failed\n",
|
|
name);
|
|
goto end;
|
|
}
|
|
dev_dbg(dev, "%s :: mem.dram %p 0x%x\n", name,
|
|
mem->dram, iova_mem->dram);
|
|
}
|
|
|
|
if (sz->dram_shared) {
|
|
mem->shared = nvadsp_alloc_coherent(sz->dram_shared,
|
|
&da, GFP_KERNEL);
|
|
if (!mem->shared) {
|
|
dev_err(dev, "app %s shared dram alloc failed\n",
|
|
name);
|
|
goto end;
|
|
}
|
|
iova_mem->shared = (uint32_t)da;
|
|
dev_dbg(dev, "%s :: mem.shared %p 0x%x\n", name,
|
|
mem->shared, iova_mem->shared);
|
|
}
|
|
|
|
if (sz->dram_shared_wc) {
|
|
mem->shared_wc = nvadsp_alloc_coherent(sz->dram_shared_wc,
|
|
&da, GFP_KERNEL);
|
|
if (!mem->shared_wc) {
|
|
dev_err(dev, "app %s shared dram wc alloc failed\n",
|
|
name);
|
|
goto end;
|
|
}
|
|
iova_mem->shared_wc = (uint32_t)da;
|
|
dev_dbg(dev, "%s :: mem.shared_wc %p 0x%x\n", name,
|
|
mem->shared_wc, iova_mem->shared_wc);
|
|
}
|
|
|
|
if (sz->aram) {
|
|
aram_handle = aram_request(name, sz->aram);
|
|
if (!IS_ERR_OR_NULL(aram_handle)) {
|
|
iova_mem->aram = aram_get_address(aram_handle);
|
|
mem->aram = aram_handle;
|
|
iova_mem->aram_flag = mem->aram_flag = 1;
|
|
dev_dbg(dev, "%s aram %x\n", name, iova_mem->aram);
|
|
} else {
|
|
dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n",
|
|
name);
|
|
mem->aram = nvadsp_alloc_coherent(sz->aram,
|
|
&da, GFP_KERNEL);
|
|
if (!mem->aram) {
|
|
iova_mem->aram_flag = mem->aram_flag = 0;
|
|
dev_err(dev,
|
|
"app %s aram memory alloc failed\n",
|
|
name);
|
|
goto end;
|
|
}
|
|
iova_mem->aram = (uint32_t)da;
|
|
dev_dbg(dev, "%s :: mem.aram %p 0x%x\n", name,
|
|
mem->aram, iova_mem->aram);
|
|
}
|
|
}
|
|
|
|
if (sz->aram_x) {
|
|
aram_handle = aram_request(name, sz->aram);
|
|
if (!IS_ERR_OR_NULL(aram_handle)) {
|
|
iova_mem->aram_x = aram_get_address(aram_handle);
|
|
mem->aram_x = aram_handle;
|
|
iova_mem->aram_x_flag = mem->aram_x_flag = 1;
|
|
dev_dbg(dev, "aram_x %x\n", iova_mem->aram_x);
|
|
} else {
|
|
iova_mem->aram_x = 0;
|
|
iova_mem->aram_x_flag = mem->aram_x_flag = 0;
|
|
dev_err(dev, "app %s aram x memory alloc failed\n",
|
|
name);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
end:
|
|
free_instance_memory(app, sz);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static void fill_app_instance_data(nvadsp_app_info_t *app,
|
|
struct nvadsp_app_service *ser, nvadsp_app_args_t *app_args,
|
|
struct run_app_instance_data *data, uint32_t stack_sz)
|
|
{
|
|
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
|
|
|
data->adsp_mod_ptr = ser->mod->adsp_module_ptr;
|
|
/* copy the iova address to adsp so that adsp can access the memory */
|
|
data->dram_data_ptr = iova_mem->dram;
|
|
data->dram_shared_ptr = iova_mem->shared;
|
|
data->dram_shared_wc_ptr = iova_mem->shared_wc;
|
|
data->aram_ptr = iova_mem->aram;
|
|
data->aram_flag = iova_mem->aram_flag;
|
|
data->aram_x_ptr = iova_mem->aram_x;
|
|
data->aram_x_flag = iova_mem->aram_x_flag;
|
|
|
|
if (app_args)
|
|
memcpy(&data->app_args, app_args, sizeof(nvadsp_app_args_t));
|
|
/*
|
|
* app on adsp holds the reference of host app instance to communicate
|
|
* back when completed. This way we do not need to iterate through the
|
|
* list to find the instance.
|
|
*/
|
|
data->host_ref = (uint64_t)app;
|
|
|
|
/* copy instance mem_size */
|
|
memcpy(&data->mem_size, ser->mem_size, sizeof(struct app_mem_size));
|
|
}
|
|
|
|
static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
|
|
nvadsp_app_args_t *app_args, struct run_app_instance_data *data,
|
|
app_complete_status_notifier notifier, uint32_t stack_size)
|
|
{
|
|
struct nvadsp_app_service *ser = (void *)handle;
|
|
struct device *dev = &priv.pdev->dev;
|
|
nvadsp_app_info_t *app;
|
|
int *state;
|
|
int *id;
|
|
|
|
app = kzalloc(sizeof(*app), GFP_KERNEL);
|
|
if (unlikely(!app)) {
|
|
dev_err(dev, "cannot allocate memory for app %s instance\n",
|
|
ser->name);
|
|
goto err_value;
|
|
}
|
|
/* set the instance name with the app name */
|
|
app->name = ser->name;
|
|
/* associate a unique id */
|
|
id = (int *)&app->instance_id;
|
|
*id = ser->generated_instance_id++;
|
|
/*
|
|
* hold the pointer to the service, to dereference later during deinit
|
|
*/
|
|
app->handle = ser;
|
|
|
|
/* create the instance memory required by the app instance */
|
|
if (create_instance_memory(app, ser->mem_size)) {
|
|
dev_err(dev, "instance creation failed for app %s:%d\n",
|
|
app->name, app->instance_id);
|
|
goto free_app;
|
|
}
|
|
|
|
/* assign the stack that is needed by the app */
|
|
data->stack_size = stack_size;
|
|
|
|
/* set the state to INITIALIZED. No need to do it in a spin lock */
|
|
state = (int *)&app->state;
|
|
*state = NVADSP_APP_STATE_INITIALIZED;
|
|
|
|
/* increment instance count and add the app instance to service list */
|
|
mutex_lock(&ser->lock);
|
|
list_add_tail(&app->node, &ser->app_head);
|
|
ser->instance++;
|
|
mutex_unlock(&ser->lock);
|
|
|
|
fill_app_instance_data(app, ser, app_args, data, stack_size);
|
|
|
|
init_completion(&app->wait_for_app_start);
|
|
init_completion(&app->wait_for_app_complete);
|
|
set_app_complete_notifier(app, notifier);
|
|
|
|
dev_dbg(dev, "app %s instance %d initilized\n",
|
|
app->name, app->instance_id);
|
|
dev_dbg(dev, "app %s has %d instances\n", ser->name, ser->instance);
|
|
goto end;
|
|
|
|
free_app:
|
|
kfree(app);
|
|
err_value:
|
|
app = ERR_PTR(-ENOMEM);
|
|
end:
|
|
return app;
|
|
}
|
|
|
|
nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
|
|
nvadsp_app_args_t *args)
|
|
{
|
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
|
struct nvadsp_shared_mem *shared_mem;
|
|
union app_loader_message *message;
|
|
struct nvadsp_drv_data *drv_data;
|
|
struct app_loader_data *data;
|
|
nvadsp_app_info_t *app;
|
|
msgq_t *msgq_send;
|
|
int *state;
|
|
|
|
if (IS_ERR_OR_NULL(priv.pdev)) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
goto err;
|
|
}
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
|
|
if (!drv_data->adsp_os_running)
|
|
goto err;
|
|
|
|
if (IS_ERR_OR_NULL(handle))
|
|
goto err;
|
|
|
|
message = kzalloc(sizeof(*message), GFP_KERNEL);
|
|
if (!message)
|
|
goto err;
|
|
|
|
shared_mem = drv_data->shared_adsp_os_data;
|
|
msg_pool = &shared_mem->app_shared_msg_pool;
|
|
msgq_send = &msg_pool->app_loader_send_message.msgq;
|
|
data = &message->data;
|
|
|
|
app = create_app_instance(handle, args, &data->app_init, NULL, 0);
|
|
if (IS_ERR_OR_NULL(app)) {
|
|
kfree(message);
|
|
goto err;
|
|
}
|
|
app->priv = data;
|
|
data->app_init.message = ADSP_APP_INIT;
|
|
|
|
message->msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*message);
|
|
msgq_queue_message(msgq_send, &message->msgq_msg);
|
|
|
|
if (app->return_status) {
|
|
state = (int *)&app->state;
|
|
*state = NVADSP_APP_STATE_STARTED;
|
|
}
|
|
|
|
nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
|
|
|
|
wait_for_completion(&app->wait_for_app_start);
|
|
init_completion(&app->wait_for_app_start);
|
|
return app;
|
|
err:
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_init);
|
|
|
|
static int start_app_on_adsp(nvadsp_app_info_t *app,
|
|
union app_loader_message *message, bool block)
|
|
{
|
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
|
struct device *dev = &priv.pdev->dev;
|
|
struct nvadsp_shared_mem *shared_mem;
|
|
struct nvadsp_drv_data *drv_data;
|
|
msgq_t *msgq_send;
|
|
int *state;
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
shared_mem = drv_data->shared_adsp_os_data;
|
|
msg_pool = &shared_mem->app_shared_msg_pool;
|
|
msgq_send = &msg_pool->app_loader_send_message.msgq;
|
|
|
|
message->msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*message);
|
|
msgq_queue_message(msgq_send, &message->msgq_msg);
|
|
|
|
state = (int *)&app->state;
|
|
*state = NVADSP_APP_STATE_STARTED;
|
|
|
|
nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
|
|
|
|
if (block) {
|
|
wait_for_completion(&app->wait_for_app_start);
|
|
if (app->return_status) {
|
|
dev_err(dev, "%s app instance %d failed to start\n",
|
|
app->name, app->instance_id);
|
|
state = (int *)&app->state;
|
|
*state = NVADSP_APP_STATE_INITIALIZED;
|
|
}
|
|
}
|
|
|
|
return app->return_status;
|
|
}
|
|
|
|
int nvadsp_app_start(nvadsp_app_info_t *app)
|
|
{
|
|
union app_loader_message *message = app->priv;
|
|
struct app_loader_data *data = &message->data;
|
|
struct nvadsp_drv_data *drv_data;
|
|
int ret = -EINVAL;
|
|
|
|
if (IS_ERR_OR_NULL(app))
|
|
return -EINVAL;
|
|
|
|
if (IS_ERR_OR_NULL(priv.pdev)) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
goto err;
|
|
}
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
|
|
if (!drv_data->adsp_os_running)
|
|
goto err;
|
|
|
|
data->app_init.message = ADSP_APP_START;
|
|
data->app_init.adsp_ref = app->token;
|
|
data->app_init.stack_size = app->stack_size;
|
|
ret = start_app_on_adsp(app, app->priv, true);
|
|
err:
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_start);
|
|
|
|
nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
|
|
const char *appfile, nvadsp_app_args_t *app_args,
|
|
app_complete_status_notifier notifier, uint32_t stack_sz, bool block)
|
|
{
|
|
union app_loader_message message = {};
|
|
nvadsp_app_handle_t service_handle;
|
|
struct nvadsp_drv_data *drv_data;
|
|
nvadsp_app_info_t *info = NULL;
|
|
struct app_loader_data *data;
|
|
struct device *dev;
|
|
int ret;
|
|
|
|
if (IS_ERR_OR_NULL(priv.pdev)) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
info = ERR_PTR(-EINVAL);
|
|
goto end;
|
|
}
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
dev = &priv.pdev->dev;
|
|
|
|
if (!drv_data->adsp_os_running)
|
|
goto end;
|
|
|
|
if (IS_ERR_OR_NULL(appfile))
|
|
goto end;
|
|
|
|
data = &message.data;
|
|
service_handle = app_load(appfile, NULL, true);
|
|
if (!service_handle) {
|
|
dev_err(dev, "unable to load the app %s\n", appfile);
|
|
goto end;
|
|
}
|
|
|
|
info = create_app_instance(service_handle, app_args,
|
|
&data->app_init, notifier, stack_sz);
|
|
if (IS_ERR_OR_NULL(info)) {
|
|
dev_err(dev, "unable to create instance for app %s\n", appfile);
|
|
goto end;
|
|
}
|
|
data->app_init.message = RUN_ADSP_APP;
|
|
|
|
ret = start_app_on_adsp(info, &message, block);
|
|
if (ret) {
|
|
delete_app_instance(info);
|
|
info = NULL;
|
|
}
|
|
end:
|
|
return info;
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_run_app);
|
|
|
|
static void delete_app_instance(nvadsp_app_info_t *app)
|
|
{
|
|
struct nvadsp_app_service *ser =
|
|
(struct nvadsp_app_service *)app->handle;
|
|
struct device *dev = &priv.pdev->dev;
|
|
|
|
dev_dbg(dev, "%s:freeing app %s:%d\n",
|
|
__func__, app->name, app->instance_id);
|
|
|
|
/* update the service app instance manager atomically */
|
|
mutex_lock(&ser->lock);
|
|
ser->instance--;
|
|
list_del(&app->node);
|
|
mutex_unlock(&ser->lock);
|
|
|
|
/* free instance memory */
|
|
free_instance_memory(app, ser->mem_size);
|
|
kfree(app->priv);
|
|
kfree(app);
|
|
}
|
|
|
|
void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
|
|
{
|
|
int *state;
|
|
|
|
if (IS_ERR_OR_NULL(priv.pdev)) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
return;
|
|
}
|
|
|
|
if (IS_ERR_OR_NULL(app))
|
|
return;
|
|
|
|
/* TODO: add termination if possible to kill thread on adsp */
|
|
if (app->state == NVADSP_APP_STATE_STARTED) {
|
|
wait_for_completion(&app->wait_for_app_complete);
|
|
state = (int *)&app->state;
|
|
*state = NVADSP_APP_STATE_INITIALIZED;
|
|
}
|
|
delete_app_instance(app);
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_exit_app);
|
|
|
|
int nvadsp_app_deinit(nvadsp_app_info_t *app)
|
|
{
|
|
nvadsp_exit_app(app, false);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_deinit);
|
|
|
|
int nvadsp_app_stop(nvadsp_app_info_t *app)
|
|
{
|
|
return -ENOENT;
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_stop);
|
|
|
|
void nvadsp_app_unload(nvadsp_app_handle_t handle)
|
|
{
|
|
struct nvadsp_drv_data *drv_data;
|
|
struct nvadsp_app_service *ser;
|
|
struct device *dev;
|
|
|
|
if (!priv.pdev) {
|
|
pr_err("ADSP Driver is not initialized\n");
|
|
return;
|
|
}
|
|
|
|
drv_data = platform_get_drvdata(priv.pdev);
|
|
dev = &priv.pdev->dev;
|
|
|
|
if (!drv_data->adsp_os_running)
|
|
return;
|
|
|
|
if (IS_ERR_OR_NULL(handle))
|
|
return;
|
|
|
|
ser = (struct nvadsp_app_service *)handle;
|
|
if (!ser->mod->dynamic)
|
|
return;
|
|
|
|
mutex_lock(&priv.service_lock_list);
|
|
if (ser->instance) {
|
|
dev_err(dev, "cannot unload app %s, has instances %d\n",
|
|
ser->name, ser->instance);
|
|
return;
|
|
}
|
|
|
|
list_del(&ser->node);
|
|
#ifdef CONFIG_DEBUG_FS
|
|
debugfs_remove_recursive(ser->debugfs);
|
|
#endif
|
|
unload_adsp_module(ser->mod);
|
|
devm_kfree(dev, ser);
|
|
mutex_unlock(&priv.service_lock_list);
|
|
}
|
|
EXPORT_SYMBOL(nvadsp_app_unload);
|
|
|
|
static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
|
|
{
|
|
union app_complete_status_message message = { };
|
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
|
struct app_complete_status_data *data;
|
|
struct nvadsp_shared_mem *shared_mem;
|
|
struct nvadsp_drv_data *drv_data;
|
|
struct platform_device *pdev;
|
|
nvadsp_app_info_t *app;
|
|
struct device *dev;
|
|
msgq_t *msgq_recv;
|
|
uint32_t *token;
|
|
|
|
pdev = hdata;
|
|
dev = &pdev->dev;
|
|
drv_data = platform_get_drvdata(pdev);
|
|
shared_mem = drv_data->shared_adsp_os_data;
|
|
msg_pool = &shared_mem->app_shared_msg_pool;
|
|
msgq_recv = &msg_pool->app_loader_recv_message.msgq;
|
|
data = &message.complete_status_data;
|
|
|
|
message.msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*data);
|
|
if (msgq_dequeue_message(msgq_recv, &message.msgq_msg)) {
|
|
dev_err(dev, "unable to dequeue app status message\n");
|
|
return 0;
|
|
}
|
|
|
|
app = (nvadsp_app_info_t *)data->host_ref;
|
|
app->return_status = data->status;
|
|
app->status_msg = data->header.message;
|
|
token = (uint32_t *)&app->token;
|
|
*token = data->adsp_ref;
|
|
|
|
if (app->complete_status_notifier) {
|
|
app->complete_status_notifier(app,
|
|
app->status_msg, app->return_status);
|
|
}
|
|
|
|
switch (data->header.message) {
|
|
case ADSP_APP_START_STATUS:
|
|
complete_all(&app->wait_for_app_start);
|
|
break;
|
|
case ADSP_APP_COMPLETE_STATUS:
|
|
complete_all(&app->wait_for_app_complete);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int load_adsp_static_apps(void)
|
|
{
|
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
|
struct nvadsp_shared_mem *shared_mem;
|
|
struct nvadsp_drv_data *drv_data;
|
|
struct platform_device *pdev;
|
|
struct device *dev;
|
|
msgq_t *msgq_recv;
|
|
|
|
pdev = priv.pdev;
|
|
dev = &pdev->dev;
|
|
drv_data = platform_get_drvdata(pdev);
|
|
shared_mem = drv_data->shared_adsp_os_data;
|
|
msg_pool = &shared_mem->app_shared_msg_pool;
|
|
msgq_recv = &msg_pool->app_loader_recv_message.msgq;
|
|
|
|
while (1) {
|
|
union app_complete_status_message message = { };
|
|
struct adsp_static_app_data *data;
|
|
struct adsp_shared_app *shared_app;
|
|
char *name;
|
|
|
|
data = &message.static_app_data;
|
|
message.msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*data);
|
|
if (msgq_dequeue_message(msgq_recv, &message.msgq_msg)) {
|
|
dev_err(dev, "dequeue of static apps failed\n");
|
|
return -EINVAL;
|
|
}
|
|
shared_app = &data->shared_app;
|
|
name = shared_app->name;
|
|
if (!shared_app->mod_ptr)
|
|
break;
|
|
/* Skip Start on boot apps */
|
|
if (shared_app->flags & ADSP_APP_FLAG_START_ON_BOOT)
|
|
continue;
|
|
app_load(name, shared_app, false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int __init nvadsp_app_module_probe(struct platform_device *pdev)
|
|
{
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
|
#endif
|
|
uint16_t mbox_id = APP_LOADER_MBOX_ID;
|
|
struct device *dev = &pdev->dev;
|
|
int ret;
|
|
|
|
dev_info(dev, "%s\n", __func__);
|
|
|
|
ret = nvadsp_mbox_open(&priv.mbox, &mbox_id,
|
|
"app_service", nvadsp_app_receive_handler, pdev);
|
|
if (ret) {
|
|
dev_err(dev, "unable to open mailbox\n");
|
|
goto end;
|
|
}
|
|
priv.pdev = pdev;
|
|
INIT_LIST_HEAD(&priv.service_list);
|
|
init_completion(&priv.os_load_complete);
|
|
mutex_init(&priv.service_lock_list);
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
if (adsp_app_debug_init(drv_data->adsp_debugfs_root))
|
|
dev_err(&pdev->dev, "unable to create adsp apps debugfs\n");
|
|
#endif
|
|
end:
|
|
return ret;
|
|
}
|