diff --git a/drivers/platform/tegra/nvadsp/Makefile b/drivers/platform/tegra/nvadsp/Makefile index 39ec0c17..250840d8 100644 --- a/drivers/platform/tegra/nvadsp/Makefile +++ b/drivers/platform/tegra/nvadsp/Makefile @@ -9,7 +9,7 @@ obj-m := nvadsp.o nvadsp-objs += dev.o os.o app.o app_loader_linker.o\ amc.o nvadsp_shared_sema.o \ hwmailbox.o mailbox.o msgq.o \ - mem_manager.o aram_manager.o dram_app_mem_manager.o \ + mem_manager.o aram_manager.o \ acast.o adsp_console_dbfs.o # T234/T239/T194/T186 diff --git a/drivers/platform/tegra/nvadsp/adsp_console_dbfs.c b/drivers/platform/tegra/nvadsp/adsp_console_dbfs.c index d944c84b..7263a180 100644 --- a/drivers/platform/tegra/nvadsp/adsp_console_dbfs.c +++ b/drivers/platform/tegra/nvadsp/adsp_console_dbfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /** - * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. */ #include @@ -25,15 +25,9 @@ #define USE_RUN_APP_API -static int open_cnt; - -#define ADSP_APP_CTX_MAX 32 - -static uint64_t adsp_app_ctx_vals[ADSP_APP_CTX_MAX]; - #define ACCESS_OK(addr, size) access_ok(addr, size) -static int adsp_app_ctx_add(uint64_t ctx) +static int adsp_app_ctx_add(struct nvadsp_cnsl *console, uint64_t ctx) { int i; @@ -41,15 +35,15 @@ static int adsp_app_ctx_add(uint64_t ctx) return -EINVAL; for (i = 0; i < ADSP_APP_CTX_MAX; i++) { - if (adsp_app_ctx_vals[i] == 0) { - adsp_app_ctx_vals[i] = ctx; + if (console->adsp_app_ctx_vals[i] == 0) { + console->adsp_app_ctx_vals[i] = ctx; return 0; } } return -EINVAL; } -static int adsp_app_ctx_check(uint64_t ctx) +static int adsp_app_ctx_check(struct nvadsp_cnsl *console, uint64_t ctx) { int i; @@ -57,20 +51,20 @@ static int adsp_app_ctx_check(uint64_t ctx) return -EINVAL; for (i = 0; i < ADSP_APP_CTX_MAX; i++) { - if (adsp_app_ctx_vals[i] == ctx) + if (console->adsp_app_ctx_vals[i] == ctx) return 0; } return -EINVAL; } -static void adsp_app_ctx_remove(uint64_t ctx) +static void adsp_app_ctx_remove(struct nvadsp_cnsl *console, uint64_t ctx) { int i; for (i = 0; i < ADSP_APP_CTX_MAX; i++) { - if (adsp_app_ctx_vals[i] == ctx) { - adsp_app_ctx_vals[i] = 0; + if (console->adsp_app_ctx_vals[i] == ctx) { + console->adsp_app_ctx_vals[i] = 0; return; } } @@ -85,21 +79,23 @@ static int adsp_consol_open(struct inode *i, struct file *f) struct device *dev = console->dev; struct platform_device *pdev = to_platform_device(dev); struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; - if (open_cnt) + if (console->open_cnt) return -EBUSY; - open_cnt++; + console->open_cnt++; ret = 0; f->private_data = console; if (!drv_data->adsp_os_running) goto exit_open; - ret = nvadsp_mbox_open(&console->shl_snd_mbox, &snd_mbox_id, + ret = nvadsp_handle->mbox_open(nvadsp_handle, + &console->shl_snd_mbox, &snd_mbox_id, "adsp_send_cnsl", NULL, NULL); if (!ret) goto exit_open; pr_err("adsp_consol: Failed to init adsp_consol send mailbox"); memset(&console->shl_snd_mbox, 0, sizeof(struct nvadsp_mbox)); - open_cnt--; + console->open_cnt--; exit_open: return ret; } @@ -111,11 +107,12 @@ static int adsp_consol_close(struct inode *i, struct file *f) struct device *dev = console->dev; struct platform_device *pdev = to_platform_device(dev); struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; - open_cnt--; + console->open_cnt--; if (!drv_data->adsp_os_running || (0 == mbox->id)) goto exit_close; - ret = nvadsp_mbox_close(mbox); + ret = nvadsp_handle->mbox_close(nvadsp_handle, mbox); if (ret) pr_err("adsp_consol: Failed to close adsp_consol send mailbox)"); memset(mbox, 0, sizeof(struct nvadsp_mbox)); @@ -138,6 +135,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) struct device *dev = console->dev; struct platform_device *pdev = to_platform_device(dev); struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; void __user *uarg = (void __user *)arg; if (_IOC_TYPE(cmd) != NV_ADSP_CONSOLE_MAGIC) @@ -164,17 +162,17 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) break; mbxid = 30; mbox = &console->shl_snd_mbox; - ret = nvadsp_os_load(); + ret = nvadsp_handle->os_load(nvadsp_handle); if (ret) { dev_info(dev, "adsp_consol: Load OS Failed."); break; } - ret = nvadsp_os_start(); + ret = nvadsp_handle->os_start(nvadsp_handle); if (ret) { dev_info(dev, "adsp_consol: Start OS Failed."); break; } - ret = nvadsp_mbox_open(mbox, &mbxid, + ret = nvadsp_handle->mbox_open(nvadsp_handle, mbox, &mbxid, "adsp_send_cnsl", NULL, NULL); if (!ret) break; @@ -182,19 +180,19 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) memset(mbox, 0, sizeof(struct nvadsp_mbox)); break; case _IOC_NR(ADSP_CNSL_SUSPEND): - ret = nvadsp_os_suspend(); + ret = nvadsp_handle->os_suspend(nvadsp_handle); if (ret) dev_info(dev, "adsp_consol: OS Suspend Failed."); break; case _IOC_NR(ADSP_CNSL_STOP): - nvadsp_os_stop(); + nvadsp_handle->os_stop(nvadsp_handle); break; case _IOC_NR(ADSP_CNSL_RESUME): if (!drv_data->adsp_os_suspended) { dev_info(dev, "adsp_consol: OS is not suspended to perform resume."); break; } - ret = nvadsp_os_start(); + ret = nvadsp_handle->os_start(nvadsp_handle); if (ret) dev_info(dev, "adsp_consol: OS Resume Failed."); break; @@ -212,7 +210,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) app_args.app_name[NVADSP_NAME_SZ_MAX] = '\0'; #ifdef USE_RUN_APP_API - app_args.ctx2 = (uint64_t)nvadsp_run_app(NULL, + app_args.ctx2 = (uint64_t)nvadsp_handle->run_app( + nvadsp_handle, NULL, app_args.app_name, (nvadsp_app_args_t *)&app_args.args[0], NULL, 0, app_args.core_id, true); @@ -221,42 +220,43 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) app_args.app_name); return -EINVAL; } - if (adsp_app_ctx_add(app_args.ctx2)) { + if (adsp_app_ctx_add(console, app_args.ctx2)) { dev_info(dev, "adsp_consol: unable to add %s ctx\n", app_args.app_name); return -EINVAL; } #else - app_args.ctx1 = (uint64_t)nvadsp_app_load(app_args.app_path, - app_args.app_name); + app_args.ctx1 = (uint64_t)nvadsp_handle->app_load( + nvadsp_handle, app_args.app_path, + app_args.app_name); if (!app_args.ctx1) { dev_info(dev, "adsp_consol: dynamic app load failed %s\n", app_args.app_name); return -EINVAL; } - if (adsp_app_ctx_add(app_args.ctx1)) { + if (adsp_app_ctx_add(console, app_args.ctx1)) { dev_info(dev, "adsp_consol: unable to add %s ctx\n", app_args.app_name); return -EINVAL; } dev_info(dev, "adsp_consol: calling nvadsp_app_init\n"); - app_args.ctx2 = - (uint64_t)nvadsp_app_init((void *)app_args.ctx1, NULL); + app_args.ctx2 = (uint64_t)nvadsp_handle->app_init( + nvadsp_handle, (void *)app_args.ctx1, NULL); if (!app_args.ctx2) { dev_info(dev, "adsp_consol: unable to initilize the app\n"); return -EINVAL; } - if (adsp_app_ctx_add(app_args.ctx2)) { + if (adsp_app_ctx_add(console, app_args.ctx2)) { dev_info(dev, "adsp_consol: unable to add %s ctx\n", app_args.app_name); return -EINVAL; } dev_info(dev, "adsp_consol: calling nvadsp_app_start\n"); - ret = nvadsp_app_start((void *)app_args.ctx2); + ret = nvadsp_handle->app_start(nvadsp_handle, (void *)app_args.ctx2); if (ret) { dev_info(dev, "adsp_consol: unable to start the app\n"); break; @@ -281,7 +281,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ret = -EACCES; break; } - if (adsp_app_ctx_check(app_args.ctx2)) { + if (adsp_app_ctx_check(console, app_args.ctx2)) { dev_info(dev, "adsp_consol: unable to check %s ctx\n", app_args.app_name); return -EINVAL; @@ -290,28 +290,32 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) app_args.ctx1 = (uint64_t) ((nvadsp_app_info_t *)app_args.ctx2)->handle; - nvadsp_exit_app((nvadsp_app_info_t *)app_args.ctx2, false); - nvadsp_app_unload((const void *)app_args.ctx1); + nvadsp_handle->exit_app(nvadsp_handle, + (nvadsp_app_info_t *)app_args.ctx2, false); + nvadsp_handle->app_unload(nvadsp_handle, + (const void *)app_args.ctx1); - adsp_app_ctx_remove(app_args.ctx2); + adsp_app_ctx_remove(console, app_args.ctx2); #else if ((!app_args.ctx2) || (!app_args.ctx1)) { ret = -EACCES; break; } - if (adsp_app_ctx_check(app_args.ctx2) || - adsp_app_ctx_check(app_args.ctx1)) { + if (adsp_app_ctx_check(console, app_args.ctx2) || + adsp_app_ctx_check(console, app_args.ctx1)) { dev_info(dev, "adsp_consol: unable to check %s ctx\n", app_args.app_name); return -EINVAL; } - nvadsp_app_deinit((void *)app_args.ctx2); - nvadsp_app_unload((void *)app_args.ctx1); + nvadsp_handle->app_deinit(nvadsp_handle, + (void *)app_args.ctx2); + nvadsp_handle->nvadsp_app_unload(nvadsp_handle, + (void *)app_args.ctx1); - adsp_app_ctx_remove(app_args.ctx2); - adsp_app_ctx_remove(app_args.ctx1); + adsp_app_ctx_remove(console, app_args.ctx2); + adsp_app_ctx_remove(console, app_args.ctx1); #endif break; @@ -325,7 +329,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ret = -EACCES; break; } - if (adsp_app_ctx_check(ctx2)) { + if (adsp_app_ctx_check(console, ctx2)) { dev_info(dev, "adsp_consol: unable to check ctx\n"); return -EINVAL; } @@ -338,7 +342,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) mbxid = *mid; } - ret = nvadsp_mbox_open(&console->app_mbox, &mbxid, + ret = nvadsp_handle->mbox_open(nvadsp_handle, + &console->app_mbox, &mbxid, "app_mbox", NULL, NULL); if (ret) { pr_err("adsp_consol: Failed to open app mailbox"); @@ -347,9 +352,10 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) break; case _IOC_NR(ADSP_CNSL_CLOSE_MBX): mbox = &console->app_mbox; - while (!nvadsp_mbox_recv(mbox, &data, 0, 0)) + while (!nvadsp_handle->mbox_recv(nvadsp_handle, + mbox, &data, 0, 0)) ; - ret = nvadsp_mbox_close(mbox); + ret = nvadsp_handle->mbox_close(nvadsp_handle, mbox); if (ret) break; memset(mbox, 0, sizeof(struct nvadsp_mbox)); @@ -363,13 +369,15 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ret = -EACCES; break; } - ret = nvadsp_mbox_send(&console->app_mbox, data, + ret = nvadsp_handle->mbox_send(nvadsp_handle, + &console->app_mbox, data, NVADSP_MBOX_SMSG, 0, 0); break; case _IOC_NR(ADSP_CNSL_GET_MBX): if (!ACCESS_OK(uarg, sizeof(uint32_t))) return -EACCES; - ret = nvadsp_mbox_recv(&console->app_mbox, &data, 0, 0); + ret = nvadsp_handle->mbox_recv(nvadsp_handle, + &console->app_mbox, &data, 0, 0); if (ret) break; ret = copy_to_user(uarg, &data, @@ -385,7 +393,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ret = -EACCES; break; } - return nvadsp_mbox_send(&console->shl_snd_mbox, data, + return nvadsp_handle->mbox_send(nvadsp_handle, + &console->shl_snd_mbox, data, NVADSP_MBOX_SMSG, 0, 0); break; default: diff --git a/drivers/platform/tegra/nvadsp/adsp_console_dbfs.h b/drivers/platform/tegra/nvadsp/adsp_console_dbfs.h index 6008acd1..1d15e63c 100644 --- a/drivers/platform/tegra/nvadsp/adsp_console_dbfs.h +++ b/drivers/platform/tegra/nvadsp/adsp_console_dbfs.h @@ -1,15 +1,19 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /** - * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. */ #ifndef ADSP_CNSL_DBFS_H #define ADSP_CNSL_DBFS_H +#define ADSP_APP_CTX_MAX 32 + struct nvadsp_cnsl { struct device *dev; struct nvadsp_mbox shl_snd_mbox; struct nvadsp_mbox app_mbox; + int open_cnt; + uint64_t adsp_app_ctx_vals[ADSP_APP_CTX_MAX]; }; int diff --git a/drivers/platform/tegra/nvadsp/amc.c b/drivers/platform/tegra/nvadsp/amc.c index 86f26b9f..102f0914 100644 --- a/drivers/platform/tegra/nvadsp/amc.c +++ b/drivers/platform/tegra/nvadsp/amc.c @@ -10,19 +10,17 @@ #include "dev.h" #include "amc.h" -static struct platform_device *nvadsp_pdev; -static struct nvadsp_drv_data *nvadsp_drv_data; - -static inline u32 amc_readl(u32 reg) +static inline u32 amc_readl(struct nvadsp_drv_data *drv, u32 reg) { - return readl(nvadsp_drv_data->base_regs[AMC] + reg); + return readl(drv->base_regs[AMC] + reg); } -static inline void amc_writel(u32 val, u32 reg) +static inline void amc_writel(struct nvadsp_drv_data *drv, u32 val, u32 reg) { - writel(val, nvadsp_drv_data->base_regs[AMC] + reg); + writel(val, drv->base_regs[AMC] + reg); } +#ifdef CONFIG_AMC_SAVE_RESTORE static void wmemcpy_to_aram(u32 to_aram, const u32 *from_mem, size_t wlen) { u32 base, offset; @@ -116,20 +114,23 @@ int nvadsp_amc_restore(struct platform_device *pdev) return 0; } +#endif /* CONFIG_AMC_SAVE_RESTORE */ static irqreturn_t nvadsp_amc_error_int_handler(int irq, void *devid) { + struct platform_device *pdev = devid; + struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); u32 val, addr, status, intr = 0; - status = amc_readl(AMC_INT_STATUS); - addr = amc_readl(AMC_ERROR_ADDR); + status = amc_readl(drv, AMC_INT_STATUS); + addr = amc_readl(drv, AMC_ERROR_ADDR); if (status & AMC_INT_STATUS_ARAM) { /* * Ignore addresses lesser than AMC_ERROR_ADDR_IGNORE (4k) * as those are spurious ones due a hardware issue. */ - if (!(nvadsp_drv_data->chip_data->amc_err_war) || + if (!(drv->chip_data->amc_err_war) || (addr > AMC_ERROR_ADDR_IGNORE)) pr_info("nvadsp: invalid ARAM access. address: 0x%x\n", addr); @@ -143,9 +144,9 @@ static irqreturn_t nvadsp_amc_error_int_handler(int irq, void *devid) intr |= AMC_INT_INVALID_REG_ACCESS; } - val = amc_readl(AMC_INT_CLR); + val = amc_readl(drv, AMC_INT_CLR); val |= intr; - amc_writel(val, AMC_INT_CLR); + amc_writel(drv, val, AMC_INT_CLR); return IRQ_HANDLED; } @@ -154,13 +155,10 @@ void nvadsp_free_amc_interrupts(struct platform_device *pdev) { struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - struct device_node *node; if (drv->chip_data->amc_not_avlbl) return; - node = dev->of_node; - if (!is_tegra_hypervisor_mode()) devm_free_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ], pdev); } @@ -169,16 +167,11 @@ int nvadsp_setup_amc_interrupts(struct platform_device *pdev) { struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - struct device_node *node; int ret = 0; if (drv->chip_data->amc_not_avlbl) return ret; - node = dev->of_node; - nvadsp_pdev = pdev; - nvadsp_drv_data = drv; - if (!is_tegra_hypervisor_mode()) ret = devm_request_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ], nvadsp_amc_error_int_handler, 0, diff --git a/drivers/platform/tegra/nvadsp/app.c b/drivers/platform/tegra/nvadsp/app.c index ea7ef30c..05c56b97 100644 --- a/drivers/platform/tegra/nvadsp/app.c +++ b/drivers/platform/tegra/nvadsp/app.c @@ -50,9 +50,8 @@ struct nvadsp_app_priv_struct { #endif }; -static struct nvadsp_app_priv_struct priv; - -static void delete_app_instance(nvadsp_app_info_t *); +static void delete_app_instance(struct nvadsp_app_priv_struct *, + nvadsp_app_info_t *); #ifdef CONFIG_DEBUG_FS static int dump_binary_in_2bytes_app_file_node(struct seq_file *s, void *data) @@ -219,17 +218,18 @@ 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) +static int create_adsp_app_debugfs(struct nvadsp_app_priv_struct *priv, + 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 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); + priv->adsp_app_debugfs_root); if (IS_ERR_OR_NULL(root)) { ret = -EINVAL; goto err_out; @@ -256,19 +256,27 @@ err_out: return ret; } -static int __init adsp_app_debug_init(struct dentry *root) +static int __init adsp_app_debug_init(struct nvadsp_app_priv_struct *priv, + 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; + 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) +static void _nvadsp_set_app_complete_cb(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info, app_complete_status_notifier notifier) { - struct device *dev = &priv.pdev->dev; + info->complete_status_notifier = notifier; +} + +static struct nvadsp_app_service *get_loaded_service( + struct nvadsp_app_priv_struct *priv, const char *appfile) +{ + struct device *dev = &priv->pdev->dev; struct nvadsp_app_service *ser; - list_for_each_entry(ser, &priv.service_list, node) { + 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; @@ -287,18 +295,18 @@ static inline void extract_appname(char *appname, const char *appfile) appname[len] = '\0'; } -static nvadsp_app_handle_t app_load(const char *appfile, - struct adsp_shared_app *shared_app, bool dynamic) +static nvadsp_app_handle_t app_load(struct nvadsp_app_priv_struct *priv, + const char *appfile, struct adsp_shared_app *shared_app, bool dynamic) { struct nvadsp_drv_data *drv_data; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; char appname[NVADSP_NAME_SZ] = { }; struct nvadsp_app_service *ser; - drv_data = platform_get_drvdata(priv.pdev); + drv_data = platform_get_drvdata(priv->pdev); extract_appname(appname, appfile); - mutex_lock(&priv.service_lock_list); - ser = get_loaded_service(appname); + mutex_lock(&priv->service_lock_list); + ser = get_loaded_service(priv, appname); if (!ser) { /* dynamic loading is disabled when running in secure mode */ @@ -329,78 +337,85 @@ static nvadsp_app_handle_t app_load(const char *appfile, INIT_LIST_HEAD(&ser->app_head); /* add the app instance service to the list */ - list_add_tail(&ser->node, &priv.service_list); + list_add_tail(&ser->node, &priv->service_list); #ifdef CONFIG_DEBUG_FS - create_adsp_app_debugfs(ser); + create_adsp_app_debugfs(priv, ser); #endif dev_dbg(dev, "loaded app %s\n", ser->name); } - mutex_unlock(&priv.service_lock_list); + mutex_unlock(&priv->service_lock_list); return ser; err_free_service: devm_kfree(dev, ser); err: - mutex_unlock(&priv.service_lock_list); + mutex_unlock(&priv->service_lock_list); return NULL; } - -nvadsp_app_handle_t nvadsp_app_load(const char *appname, const char *appfile) +static nvadsp_app_handle_t _nvadsp_app_load(struct nvadsp_handle *nvadsp_handle, + const char *appname, const char *appfile) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; - if (IS_ERR_OR_NULL(priv.pdev)) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { 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); + return app_load(drv_data->app_priv, appfile, NULL, true); } -EXPORT_SYMBOL(nvadsp_app_load); -static void free_instance_memory(nvadsp_app_info_t *app, - const struct app_mem_size *sz) +static void free_instance_memory(struct nvadsp_app_priv_struct *priv, + 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; + struct nvadsp_drv_data *drv_data; + struct nvadsp_handle *nvadsp_handle; + + drv_data = platform_get_drvdata(priv->pdev); + nvadsp_handle = &drv_data->nvadsp_handle; if (mem->dram) { - nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram); + nvadsp_handle->free_coherent(nvadsp_handle, + 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, + nvadsp_handle->free_coherent(nvadsp_handle, + 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, + nvadsp_handle->free_coherent(nvadsp_handle, + sz->dram_shared_wc, mem->shared_wc, iova_mem->shared_wc); mem->shared_wc = NULL; iova_mem->shared_wc = 0; } if (mem->aram_flag) - nvadsp_aram_release(mem->aram); + nvadsp_aram_release(drv_data->aram_handle, mem->aram); else if (mem->aram) - nvadsp_free_coherent(sz->aram, mem->aram, iova_mem->aram); + nvadsp_handle->free_coherent(nvadsp_handle, + sz->aram, mem->aram, iova_mem->aram); mem->aram = NULL; iova_mem->aram = 0; mem->aram_flag = 0; if (mem->aram_x_flag) { - nvadsp_aram_release(mem->aram_x); + nvadsp_aram_release(drv_data->aram_handle, mem->aram_x); mem->aram_x = NULL; iova_mem->aram_x = 0; mem->aram_flag = 0; @@ -408,12 +423,14 @@ static void free_instance_memory(nvadsp_app_info_t *app, } -static int create_instance_memory(nvadsp_app_info_t *app, - const struct app_mem_size *sz) +static int create_instance_memory(struct nvadsp_app_priv_struct *priv, + 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; + struct device *dev = &priv->pdev->dev; adsp_app_mem_t *mem = &app->mem; + struct nvadsp_drv_data *drv_data; + struct nvadsp_handle *nvadsp_handle; char name[NVADSP_NAME_SZ]; void *aram_handle; dma_addr_t da; @@ -425,8 +442,12 @@ static int create_instance_memory(nvadsp_app_info_t *app, return -EINVAL; } + drv_data = platform_get_drvdata(priv->pdev); + nvadsp_handle = &drv_data->nvadsp_handle; + if (sz->dram) { - mem->dram = nvadsp_alloc_coherent(sz->dram, &da, GFP_KERNEL); + mem->dram = nvadsp_handle->alloc_coherent(nvadsp_handle, + sz->dram, &da, GFP_KERNEL); iova_mem->dram = (uint32_t)da; if (!mem->dram) { dev_err(dev, "app %s dram alloc failed\n", @@ -438,8 +459,8 @@ static int create_instance_memory(nvadsp_app_info_t *app, } if (sz->dram_shared) { - mem->shared = nvadsp_alloc_coherent(sz->dram_shared, - &da, GFP_KERNEL); + mem->shared = nvadsp_handle->alloc_coherent(nvadsp_handle, + sz->dram_shared, &da, GFP_KERNEL); if (!mem->shared) { dev_err(dev, "app %s shared dram alloc failed\n", name); @@ -451,8 +472,8 @@ static int create_instance_memory(nvadsp_app_info_t *app, } if (sz->dram_shared_wc) { - mem->shared_wc = nvadsp_alloc_coherent(sz->dram_shared_wc, - &da, GFP_KERNEL); + mem->shared_wc = nvadsp_handle->alloc_coherent(nvadsp_handle, + sz->dram_shared_wc, &da, GFP_KERNEL); if (!mem->shared_wc) { dev_err(dev, "app %s shared dram wc alloc failed\n", name); @@ -464,7 +485,8 @@ static int create_instance_memory(nvadsp_app_info_t *app, } if (sz->aram) { - aram_handle = nvadsp_aram_request(name, sz->aram); + aram_handle = nvadsp_aram_request(drv_data->aram_handle, + name, sz->aram); if (!IS_ERR_OR_NULL(aram_handle)) { iova_mem->aram = nvadsp_aram_get_address(aram_handle); mem->aram = aram_handle; @@ -473,8 +495,9 @@ static int create_instance_memory(nvadsp_app_info_t *app, } else { dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n", name); - mem->aram = nvadsp_alloc_coherent(sz->aram, - &da, GFP_KERNEL); + mem->aram = nvadsp_handle->alloc_coherent( + nvadsp_handle, sz->aram, + &da, GFP_KERNEL); if (!mem->aram) { iova_mem->aram_flag = mem->aram_flag = 0; dev_err(dev, @@ -489,7 +512,8 @@ static int create_instance_memory(nvadsp_app_info_t *app, } if (sz->aram_x) { - aram_handle = nvadsp_aram_request(name, sz->aram); + aram_handle = nvadsp_aram_request(drv_data->aram_handle, + name, sz->aram); if (!IS_ERR_OR_NULL(aram_handle)) { iova_mem->aram_x = nvadsp_aram_get_address(aram_handle); mem->aram_x = aram_handle; @@ -505,7 +529,7 @@ static int create_instance_memory(nvadsp_app_info_t *app, return 0; end: - free_instance_memory(app, sz); + free_instance_memory(priv, app, sz); return -ENOMEM; } @@ -538,14 +562,17 @@ static void fill_app_instance_data(nvadsp_app_info_t *app, 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, +static nvadsp_app_info_t *create_app_instance( + struct nvadsp_app_priv_struct *priv, 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, uint32_t core_id) { struct nvadsp_app_service *ser = (void *)handle; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; nvadsp_app_info_t *app; + struct nvadsp_drv_data *drv_data; + struct nvadsp_handle *nvadsp_handle; int *state; int *id; @@ -565,8 +592,11 @@ static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle, */ app->handle = ser; + drv_data = platform_get_drvdata(priv->pdev); + nvadsp_handle = &drv_data->nvadsp_handle; + /* create the instance memory required by the app instance */ - if (create_instance_memory(app, ser->mem_size)) { + if (create_instance_memory(priv, app, ser->mem_size)) { dev_err(dev, "instance creation failed for app %s:%d\n", app->name, app->instance_id); goto free_app; @@ -591,7 +621,7 @@ static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle, init_completion(&app->wait_for_app_start); init_completion(&app->wait_for_app_complete); - set_app_complete_notifier(app, notifier); + _nvadsp_set_app_complete_cb(nvadsp_handle, app, notifier); dev_dbg(dev, "app %s instance %d initilized\n", app->name, app->instance_id); @@ -606,25 +636,27 @@ end: return app; } -nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle, - nvadsp_app_args_t *args) +static nvadsp_app_info_t *_nvadsp_app_init(struct nvadsp_handle *nvadsp_handle, + 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 nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_app_priv_struct *priv; struct app_loader_data *data; nvadsp_app_info_t *app; msgq_t *msgq_send; int *state; unsigned long flags, ret = 0; - if (IS_ERR_OR_NULL(priv.pdev)) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { pr_err("ADSP Driver is not initialized\n"); goto err; } - drv_data = platform_get_drvdata(priv.pdev); + priv = drv_data->app_priv; if (!drv_data->adsp_os_running) { pr_err("ADSP is not running\n"); @@ -648,7 +680,8 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle, data = &message->data; /* Pinning app to core 0 by default */ - app = create_app_instance(handle, args, &data->app_init, NULL, 0, 0); + app = create_app_instance(drv_data->app_priv, handle, + args, &data->app_init, NULL, 0, 0); if (IS_ERR_OR_NULL(app)) { pr_err("Failed to create APP instance\n"); kfree(message); @@ -668,12 +701,13 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle, *state = NVADSP_APP_STATE_STARTED; } - nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0); + nvadsp_handle->mbox_send(nvadsp_handle, &priv->mbox, + 0, NVADSP_MBOX_SMSG, false, 0); ret = wait_for_completion_timeout(&app->wait_for_app_start, msecs_to_jiffies(ADSP_APP_INIT_TIMEOUT)); if (!ret) { - delete_app_instance(app); + delete_app_instance(drv_data->app_priv, app); return NULL; } init_completion(&app->wait_for_app_start); @@ -681,20 +715,23 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle, 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) +static int start_app_on_adsp(struct nvadsp_app_priv_struct *priv, + 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 device *dev = &priv->pdev->dev; struct nvadsp_shared_mem *shared_mem; - struct nvadsp_drv_data *drv_data; msgq_t *msgq_send; + struct nvadsp_drv_data *drv_data; + struct nvadsp_handle *nvadsp_handle; int *state; unsigned long flags; - drv_data = platform_get_drvdata(priv.pdev); + drv_data = platform_get_drvdata(priv->pdev); + nvadsp_handle = &drv_data->nvadsp_handle; + 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; @@ -708,7 +745,8 @@ static int start_app_on_adsp(nvadsp_app_info_t *app, state = (int *)&app->state; *state = NVADSP_APP_STATE_STARTED; - nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0); + nvadsp_handle->mbox_send(nvadsp_handle, &priv->mbox, + 0, NVADSP_MBOX_SMSG, false, 0); if (block) { wait_for_completion(&app->wait_for_app_start); @@ -723,56 +761,58 @@ static int start_app_on_adsp(nvadsp_app_info_t *app, return app->return_status; } -int nvadsp_app_start(nvadsp_app_info_t *app) +static int _nvadsp_app_start(struct nvadsp_handle *nvadsp_handle, + 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; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; int ret = -EINVAL; if (IS_ERR_OR_NULL(app)) return -EINVAL; - if (IS_ERR_OR_NULL(priv.pdev)) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { 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); + ret = start_app_on_adsp(drv_data->app_priv, 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, - uint32_t core_id, bool block) +static nvadsp_app_info_t *_nvadsp_run_app(struct nvadsp_handle *nvadsp_handle, + nvadsp_os_handle_t os_handle, + const char *appfile, nvadsp_app_args_t *app_args, + app_complete_status_notifier notifier, uint32_t stack_sz, + uint32_t core_id, bool block) { union app_loader_message message = {}; nvadsp_app_handle_t service_handle; - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_app_priv_struct *priv; nvadsp_app_info_t *info = NULL; struct app_loader_data *data; struct device *dev; int ret; - if (IS_ERR_OR_NULL(priv.pdev)) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { 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; + priv = drv_data->app_priv; + dev = &priv->pdev->dev; if (!drv_data->adsp_os_running) goto end; @@ -781,13 +821,13 @@ nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle, goto end; data = &message.data; - service_handle = app_load(appfile, NULL, true); + service_handle = app_load(priv, 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, + info = create_app_instance(priv, service_handle, app_args, &data->app_init, notifier, stack_sz, core_id); if (IS_ERR_OR_NULL(info)) { dev_err(dev, "unable to create instance for app %s\n", appfile); @@ -795,21 +835,21 @@ nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle, } data->app_init.message = RUN_ADSP_APP; - ret = start_app_on_adsp(info, &message, block); + ret = start_app_on_adsp(priv, info, &message, block); if (ret) { - delete_app_instance(info); + delete_app_instance(priv, info); info = NULL; } end: return info; } -EXPORT_SYMBOL(nvadsp_run_app); -static void delete_app_instance(nvadsp_app_info_t *app) +static void delete_app_instance(struct nvadsp_app_priv_struct *priv, + nvadsp_app_info_t *app) { struct nvadsp_app_service *ser = (struct nvadsp_app_service *)app->handle; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; dev_dbg(dev, "%s:freeing app %s:%d\n", __func__, app->name, app->instance_id); @@ -821,16 +861,19 @@ static void delete_app_instance(nvadsp_app_info_t *app) mutex_unlock(&ser->lock); /* free instance memory */ - free_instance_memory(app, ser->mem_size); + free_instance_memory(priv, app, ser->mem_size); kfree(app->priv); kfree(app); } -void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate) +static void _nvadsp_exit_app(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app, bool terminate) { + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; int *state; - if (IS_ERR_OR_NULL(priv.pdev)) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { pr_err("ADSP Driver is not initialized\n"); return; } @@ -844,36 +887,38 @@ void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate) state = (int *)&app->state; *state = NVADSP_APP_STATE_INITIALIZED; } - delete_app_instance(app); + delete_app_instance(drv_data->app_priv, app); } -EXPORT_SYMBOL(nvadsp_exit_app); -int nvadsp_app_deinit(nvadsp_app_info_t *app) +static int _nvadsp_app_deinit(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app) { - nvadsp_exit_app(app, false); + _nvadsp_exit_app(nvadsp_handle, app, false); return 0; } -EXPORT_SYMBOL(nvadsp_app_deinit); -int nvadsp_app_stop(nvadsp_app_info_t *app) +static int _nvadsp_app_stop(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app) { return -ENOENT; } -EXPORT_SYMBOL(nvadsp_app_stop); -void nvadsp_app_unload(nvadsp_app_handle_t handle) +static void _nvadsp_app_unload(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_handle_t handle) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_app_priv_struct *priv; struct nvadsp_app_service *ser; struct device *dev; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->app_priv) { pr_err("ADSP Driver is not initialized\n"); return; } - drv_data = platform_get_drvdata(priv.pdev); - dev = &priv.pdev->dev; + priv = drv_data->app_priv; + dev = &priv->pdev->dev; if (!drv_data->adsp_os_running) return; @@ -886,7 +931,7 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle) return; #ifdef CONFIG_ADSP_DYNAMIC_APP - mutex_lock(&priv.service_lock_list); + mutex_lock(&priv->service_lock_list); if (ser->instance) { dev_err(dev, "cannot unload app %s, has instances %d\n", ser->name, ser->instance); @@ -899,10 +944,9 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle) #endif unload_adsp_module(ser->mod); devm_kfree(dev, ser); - mutex_unlock(&priv.service_lock_list); + mutex_unlock(&priv->service_lock_list); #endif // CONFIG_ADSP_DYNAMIC_APP } -EXPORT_SYMBOL(nvadsp_app_unload); static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata) { @@ -954,19 +998,13 @@ static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata) return 0; } -int load_adsp_static_apps(void) +int load_adsp_static_apps(struct nvadsp_drv_data *drv_data) { 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; + struct device *dev = &drv_data->pdev->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; if (!shared_mem) return 0; @@ -993,37 +1031,88 @@ int load_adsp_static_apps(void) /* Skip Start on boot apps */ if (shared_app->flags & ADSP_APP_FLAG_START_ON_BOOT) continue; - app_load(name, shared_app, false); + app_load(drv_data->app_priv, name, shared_app, false); } return 0; } +static void _nvadsp_wait_for_app_complete(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info) +{ + /* + * wait_for_complete must be called only after app has started + */ + if (info->state == NVADSP_APP_STATE_STARTED) + wait_for_completion(&info->wait_for_app_complete); +} + +static long _nvadsp_wait_for_app_complete_timeout( + struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info, unsigned long timeout) +{ + int ret = -EINVAL; + /* + * wait_for_complete must be called only after app has started + */ + if (info->state == NVADSP_APP_STATE_STARTED) + ret = wait_for_completion_interruptible_timeout( + &info->wait_for_app_complete, timeout); + + return ret; +} + 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 + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; uint16_t mbox_id = APP_LOADER_MBOX_ID; struct device *dev = &pdev->dev; + struct nvadsp_app_priv_struct *priv; int ret; dev_info(dev, "%s\n", __func__); - ret = nvadsp_mbox_open(&priv.mbox, &mbox_id, + priv = devm_kzalloc(dev, + sizeof(struct nvadsp_app_priv_struct), GFP_KERNEL); + if (!priv) { + dev_err(dev, "Failed to allocate app_priv\n"); + ret = -ENOMEM; + goto end; + } + drv_data->app_priv = priv; + + ret = nvadsp_handle->mbox_open(nvadsp_handle, &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); + 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"); + if (adsp_app_debug_init(priv, drv_data->adsp_debugfs_root)) + dev_err(dev, "unable to create adsp apps debugfs\n"); #endif end: + if (ret == 0) { + nvadsp_handle->app_load = _nvadsp_app_load; + nvadsp_handle->app_init = _nvadsp_app_init; + nvadsp_handle->app_start = _nvadsp_app_start; + nvadsp_handle->run_app = _nvadsp_run_app; + nvadsp_handle->app_stop = _nvadsp_app_stop; + nvadsp_handle->app_deinit = _nvadsp_app_deinit; + nvadsp_handle->exit_app = _nvadsp_exit_app; + nvadsp_handle->app_unload = _nvadsp_app_unload; + nvadsp_handle->set_app_complete_cb = + _nvadsp_set_app_complete_cb; + nvadsp_handle->wait_for_app_complete = + _nvadsp_wait_for_app_complete; + nvadsp_handle->wait_for_app_complete_timeout = + _nvadsp_wait_for_app_complete_timeout; + } + return ret; } diff --git a/drivers/platform/tegra/nvadsp/app_loader_linker.c b/drivers/platform/tegra/nvadsp/app_loader_linker.c index d8092c5e..63588826 100644 --- a/drivers/platform/tegra/nvadsp/app_loader_linker.c +++ b/drivers/platform/tegra/nvadsp/app_loader_linker.c @@ -3,7 +3,6 @@ #include #include "os.h" -#include "dram_app_mem_manager.h" #include "adsp_shared_struct.h" #ifdef CONFIG_ADSP_DYNAMIC_APP @@ -17,6 +16,7 @@ #include #include #include +#include "dram_app_mem_manager.h" #ifdef CONFIG_DEBUG_SET_MODULE_RONX # define debug_align(X) ALIGN(X, PAGE_SIZE) diff --git a/drivers/platform/tegra/nvadsp/aram_manager.c b/drivers/platform/tegra/nvadsp/aram_manager.c index 21f80ff8..5ba96722 100644 --- a/drivers/platform/tegra/nvadsp/aram_manager.c +++ b/drivers/platform/tegra/nvadsp/aram_manager.c @@ -10,22 +10,17 @@ #include "aram_manager.h" -static void *aram_handle; - -static LIST_HEAD(aram_alloc_list); -static LIST_HEAD(aram_free_list); - -void nvadsp_aram_print(void) +void nvadsp_aram_print(void *aram_handle) { mem_print(aram_handle); } -void *nvadsp_aram_request(const char *name, size_t size) +void *nvadsp_aram_request(void *aram_handle, const char *name, size_t size) { return mem_request(aram_handle, name, size); } -bool nvadsp_aram_release(void *handle) +bool nvadsp_aram_release(void *aram_handle, void *handle) { return mem_release(aram_handle, handle); } @@ -35,11 +30,11 @@ unsigned long nvadsp_aram_get_address(void *handle) return mem_get_address(handle); } -static struct dentry *aram_dump_debugfs_file; - static int nvadsp_aram_dump(struct seq_file *s, void *data) { - mem_dump(aram_handle, s); + struct nvadsp_drv_data *drv_data = data; + + mem_dump(drv_data->aram_handle, s); return 0; } @@ -55,29 +50,31 @@ static const struct file_operations aram_dump_fops = { .release = single_release, }; -int nvadsp_aram_init(unsigned long addr, unsigned long size) +int nvadsp_aram_init(struct nvadsp_drv_data *drv_data, + unsigned long addr, unsigned long size) { - aram_handle = create_mem_manager("ARAM", addr, size); - if (IS_ERR(aram_handle)) { + drv_data->aram_handle = create_mem_manager("ARAM", addr, size); + if (IS_ERR(drv_data->aram_handle)) { pr_err("ERROR: failed to create aram memory_manager"); - return PTR_ERR(aram_handle); + return PTR_ERR(drv_data->aram_handle); } if (debugfs_initialized()) { - aram_dump_debugfs_file = debugfs_create_file("aram_dump", - S_IRUSR, NULL, NULL, &aram_dump_fops); - if (!aram_dump_debugfs_file) { + drv_data->aram_dump_debugfs_file = debugfs_create_file("aram_dump", + S_IRUSR, drv_data->adsp_debugfs_root, + drv_data, &aram_dump_fops); + if (!drv_data->aram_dump_debugfs_file) { pr_err("ERROR: failed to create aram_dump debugfs"); - destroy_mem_manager(aram_handle); + destroy_mem_manager(drv_data->aram_handle); return -ENOMEM; } } return 0; } -void nvadsp_aram_exit(void) +void nvadsp_aram_exit(struct nvadsp_drv_data *drv_data) { - debugfs_remove(aram_dump_debugfs_file); - destroy_mem_manager(aram_handle); + debugfs_remove(drv_data->aram_dump_debugfs_file); + destroy_mem_manager(drv_data->aram_handle); } diff --git a/drivers/platform/tegra/nvadsp/aram_manager.h b/drivers/platform/tegra/nvadsp/aram_manager.h index ccb6ffc2..5de83556 100644 --- a/drivers/platform/tegra/nvadsp/aram_manager.h +++ b/drivers/platform/tegra/nvadsp/aram_manager.h @@ -1,13 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /** - * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. */ #ifndef __TEGRA_NVADSP_ARAM_MANAGER_H #define __TEGRA_NVADSP_ARAM_MANAGER_H #include "mem_manager.h" +#include "dev.h" + +int nvadsp_aram_init(struct nvadsp_drv_data *drv_data, + unsigned long addr, unsigned long size); +void nvadsp_aram_exit(struct nvadsp_drv_data *drv_data); -int nvadsp_aram_init(unsigned long addr, unsigned long size); -void nvadsp_aram_exit(void); #endif /* __TEGRA_NVADSP_ARAM_MANAGER_H */ diff --git a/drivers/platform/tegra/nvadsp/dev.c b/drivers/platform/tegra/nvadsp/dev.c index a3ec90c4..86acca01 100644 --- a/drivers/platform/tegra/nvadsp/dev.c +++ b/drivers/platform/tegra/nvadsp/dev.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -13,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +21,7 @@ #include #include "dev.h" +#include "hwmailbox.h" #include "os.h" #include "amc.h" #include "ape_actmon.h" @@ -28,12 +29,69 @@ #include "dev-t18x.h" -static struct nvadsp_drv_data *nvadsp_drv_data; +#define MAX_DEV_STR_LEN (20) + +struct nvadsp_handle_node { + char dev_str[MAX_DEV_STR_LEN]; + struct nvadsp_handle *nvadsp_handle; + struct list_head list; +}; + +/* Global list of driver instance handles */ +static LIST_HEAD(nvadsp_handle_list); +static DEFINE_MUTEX(nvadsp_handle_mutex); + +/** + * nvadsp_get_handle: Fetch driver instance using unique identfier + * + * @dev_str : Unique identifier string for the driver instance + * (trailing unique identifer in compatible DT property, + * e.g. "adsp", "adsp1", etc.) + * + * Return : Driver instance handle on success, else NULL + */ +struct nvadsp_handle *nvadsp_get_handle(const char *dev_str) +{ + struct nvadsp_handle_node *handle_node; + struct nvadsp_handle *nvadsp_handle = NULL; + uint32_t num_devs = 0; + + mutex_lock(&nvadsp_handle_mutex); + + if (list_empty(&nvadsp_handle_list)) + goto out; + + list_for_each_entry(handle_node, &nvadsp_handle_list, list) { + num_devs++; + + if (!strcmp(dev_str, handle_node->dev_str)) { + nvadsp_handle = handle_node->nvadsp_handle; + goto out; + } + } + + if ((num_devs == 1) && !strcmp(dev_str, "")) { + handle_node = list_first_entry( + &nvadsp_handle_list, + struct nvadsp_handle_node, list); + nvadsp_handle = handle_node->nvadsp_handle; + } + +out: + mutex_unlock(&nvadsp_handle_mutex); + + if (!nvadsp_handle) + pr_err("Unable to find device %s in list\n", dev_str); + + return nvadsp_handle; +} +EXPORT_SYMBOL(nvadsp_get_handle); #ifdef CONFIG_DEBUG_FS -static int __init adsp_debug_init(struct nvadsp_drv_data *drv_data) +static int __init adsp_debug_init(struct nvadsp_drv_data *drv_data, + const char *dev_str) { - drv_data->adsp_debugfs_root = debugfs_create_dir("tegra_ape", NULL); + drv_data->adsp_debugfs_root = debugfs_create_dir(dev_str, NULL); if (!drv_data->adsp_debugfs_root) return -ENOMEM; return 0; @@ -107,7 +165,6 @@ uint64_t nvadsp_get_timestamp_counter(void) { return __arch_counter_get_cntvct_stable(); } -EXPORT_SYMBOL(nvadsp_get_timestamp_counter); int nvadsp_set_bw(struct nvadsp_drv_data *drv_data, u32 efreq) { @@ -343,13 +400,45 @@ static int __init nvadsp_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res = NULL; void __iomem *base = NULL; - uint32_t aram_addr; - uint32_t aram_size; - int irq_iter, iter; - int irq_num; + uint32_t aram_addr, aram_size; + int irq_iter, iter, irq_num; + const char *compat, *dev_str; + struct nvadsp_handle_node *handle_node; int ret = 0; - dev_info(dev, "in probe()...\n"); + mutex_lock(&nvadsp_handle_mutex); + + ret = of_property_read_string(dev->of_node, "compatible", &compat); + if (ret) + goto out; + + /** + * Trailing part of compatible string after the + * last '-' is taken as unique device string + */ + dev_str = strrchr(compat, '-'); + if (strlen(dev_str) < 2) { + dev_err(dev, "Unable to extract device string\n"); + ret = -EINVAL; + goto out; + } + dev_str += 1; + + if (strlen(dev_str) >= MAX_DEV_STR_LEN) { + dev_err(dev, "Device string %s out of bound\n", dev_str); + ret = -EINVAL; + goto out; + } + + list_for_each_entry(handle_node, &nvadsp_handle_list, list) { + if (!strcmp(dev_str, handle_node->dev_str)) { + dev_err(dev, "Device %s already probed\n", dev_str); + ret = -EEXIST; + goto out; + } + } + + dev_info(dev, "in probe()...%s\n", dev_str); drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); @@ -376,9 +465,9 @@ static int __init nvadsp_probe(struct platform_device *pdev) #endif #ifdef CONFIG_DEBUG_FS - if (adsp_debug_init(drv_data)) + if (adsp_debug_init(drv_data, dev_str)) dev_err(dev, - "unable to create tegra_ape debug fs directory\n"); + "unable to create %s debug fs directory\n", dev_str); #endif drv_data->base_regs = @@ -408,8 +497,9 @@ static int __init nvadsp_probe(struct platform_device *pdev) goto out; } drv_data->base_regs[iter] = base; - nvadsp_add_load_mappings(res->start, (void __force *)base, - resource_size(res)); + nvadsp_add_load_mappings(drv_data, + res->start, (void __force *)base, + resource_size(res)); } drv_data->base_regs_saved = drv_data->base_regs; @@ -425,8 +515,6 @@ static int __init nvadsp_probe(struct platform_device *pdev) drv_data->agic_irqs[irq_iter] = irq_num; } - nvadsp_drv_data = drv_data; - #ifdef CONFIG_PM pm_runtime_enable(dev); @@ -465,7 +553,7 @@ static int __init nvadsp_probe(struct platform_device *pdev) aram_addr = drv_data->adsp_mem[ARAM_ALIAS_0_ADDR]; aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE]; if (aram_size) { - ret = nvadsp_aram_init(aram_addr, aram_size); + ret = nvadsp_aram_init(drv_data, aram_addr, aram_size); if (ret) dev_err(dev, "Failed to init aram\n"); } @@ -478,6 +566,20 @@ static int __init nvadsp_probe(struct platform_device *pdev) goto err; } + handle_node = kzalloc(sizeof(struct nvadsp_handle_node), + GFP_KERNEL); + if (!handle_node) { + dev_err(dev, "Failed to allocate node mem for %s\n", dev_str); + ret = -ENOMEM; + goto err; + } + + /* Add probed device into list of handles */ + strcpy(handle_node->dev_str, dev_str); + handle_node->nvadsp_handle = (struct nvadsp_handle *)drv_data; + INIT_LIST_HEAD(&handle_node->list); + list_add_tail(&handle_node->list, &nvadsp_handle_list); + err: #ifdef CONFIG_PM ret = pm_runtime_put_sync(dev); @@ -485,6 +587,8 @@ err: dev_err(dev, "pm_runtime_put_sync failed\n"); #endif out: + mutex_unlock(&nvadsp_handle_mutex); + return ret; } @@ -492,11 +596,12 @@ static int nvadsp_remove(struct platform_device *pdev) { struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); uint32_t aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE]; + struct nvadsp_handle_node *handle_node; nvadsp_bw_unregister(drv_data); if (aram_size) - nvadsp_aram_exit(); + nvadsp_aram_exit(drv_data); #ifdef CONFIG_PM pm_runtime_disable(&pdev->dev); @@ -505,6 +610,18 @@ static int nvadsp_remove(struct platform_device *pdev) nvadsp_runtime_suspend(&pdev->dev); #endif + mutex_lock(&nvadsp_handle_mutex); + + list_for_each_entry(handle_node, &nvadsp_handle_list, list) { + if (handle_node->nvadsp_handle == + (struct nvadsp_handle *)drv_data) { + list_del(&handle_node->list); + kfree(handle_node); + } + } + + mutex_unlock(&nvadsp_handle_mutex); + return 0; } diff --git a/drivers/platform/tegra/nvadsp/dev.h b/drivers/platform/tegra/nvadsp/dev.h index a746a0ba..d24acd6f 100644 --- a/drivers/platform/tegra/nvadsp/dev.h +++ b/drivers/platform/tegra/nvadsp/dev.h @@ -16,7 +16,6 @@ #endif #include -#include "hwmailbox.h" #include "amc.h" /* @@ -119,6 +118,9 @@ struct nvadsp_hwmb { u32 empty_int_ie; }; +/* Max SW mailboxes */ +#define NVADSP_MAILBOX_MAX 1024 + /* Max no. of entries in "nvidia,cluster_mem" */ #define MAX_CLUSTER_MEM 3 @@ -163,14 +165,33 @@ struct nvadsp_chipdata { size_t num_regs; }; +/* Maximum number of LOAD MAPPINGS supported */ +#define NM_LOAD_MAPPINGS 20 + +struct nvadsp_mappings { + phys_addr_t da; + void *va; + int len; +}; + struct nvadsp_drv_data { + /** + * API handle exposed to caller + * MUST BE THE FIRST FIELD IN THIS STRUCTURE + */ + struct nvadsp_handle nvadsp_handle; + void __iomem **base_regs; void __iomem **base_regs_saved; struct platform_device *pdev; - struct hwmbox_queue hwmbox_send_queue; - struct nvadsp_mbox **mboxes; - unsigned long *mbox_ids; + /* Memories allocated by subsidiary modules */ + void *hwmbox_send_queue; /* struct hwmbox_queue */ + void *os_priv; /* struct nvadsp_os_data */ + void *app_priv; /* struct nvadsp_app_priv_struct */ + + struct nvadsp_mbox *mboxes[NVADSP_MAILBOX_MAX]; + unsigned long mbox_ids[BITS_TO_LONGS(NVADSP_MAILBOX_MAX)]; spinlock_t mbox_lock; #ifdef CONFIG_DEBUG_FS @@ -259,6 +280,13 @@ struct nvadsp_drv_data { /* "nvidia,dram_map" */ struct nvadsp_reg_map dram_map[MAX_DRAM_MAP]; + + struct nvadsp_mappings adsp_map[NM_LOAD_MAPPINGS]; + int map_idx; + + /* ARAM manager */ + void *aram_handle; + struct dentry *aram_dump_debugfs_file; }; #define ADSP_CONFIG 0x04 diff --git a/drivers/platform/tegra/nvadsp/hwmailbox.c b/drivers/platform/tegra/nvadsp/hwmailbox.c index 860c36dc..5eb1af3f 100644 --- a/drivers/platform/tegra/nvadsp/hwmailbox.c +++ b/drivers/platform/tegra/nvadsp/hwmailbox.c @@ -9,63 +9,50 @@ #include #include "dev.h" - - -static struct platform_device *nvadsp_pdev; -static struct nvadsp_drv_data *nvadsp_drv_data; -/* Initialized to false by default */ -static bool is_hwmbox_busy; -#ifdef CONFIG_MBOX_ACK_HANDLER -static int hwmbox_last_msg; -#endif +#include "hwmailbox.h" /* * Mailbox 0 is for receiving messages * from ADSP i.e. CPU <-- ADSP. */ -#define INT_RECV_HWMBOX INT_AMISC_MBOX_FULL0 - -static inline u32 recv_hwmbox(void) +static inline u32 recv_hwmbox(struct nvadsp_drv_data *drv) { - return nvadsp_drv_data->chip_data->hwmb.hwmbox0_reg; + return drv->chip_data->hwmb.hwmbox0_reg; } /* * Mailbox 1 is for sending messages * to ADSP i.e. CPU --> ADSP */ -#define INT_SEND_HWMBOX INT_AMISC_MBOX_EMPTY1 - -static inline u32 send_hwmbox(void) +static inline u32 send_hwmbox(struct nvadsp_drv_data *drv) { - return nvadsp_drv_data->chip_data->hwmb.hwmbox1_reg; + return drv->chip_data->hwmb.hwmbox1_reg; +} + +static u32 hwmb_reg_idx(struct nvadsp_drv_data *drv) +{ + return drv->chip_data->hwmb.reg_idx; +} + +u32 hwmbox_readl(struct nvadsp_drv_data *drv, u32 reg) +{ + return readl(drv->base_regs[hwmb_reg_idx(drv)] + reg); +} + +void hwmbox_writel(struct nvadsp_drv_data *drv, u32 val, u32 reg) +{ + writel(val, drv->base_regs[hwmb_reg_idx(drv)] + reg); } -u32 hwmb_reg_idx(void) +#define PRINT_HWMBOX(d, x) \ + pr_err("%s: 0x%x\n", #x, hwmbox_readl(d, x)) + +void dump_mailbox_regs(struct nvadsp_drv_data *drv) { - return nvadsp_drv_data->chip_data->hwmb.reg_idx; -} - -u32 hwmbox_readl(u32 reg) -{ - return readl(nvadsp_drv_data->base_regs[hwmb_reg_idx()] + reg); -} - -void hwmbox_writel(u32 val, u32 reg) -{ - writel(val, nvadsp_drv_data->base_regs[hwmb_reg_idx()] + reg); -} - - -#define PRINT_HWMBOX(x) \ - dev_info(&nvadsp_pdev->dev, "%s: 0x%x\n", #x, hwmbox_readl(x)) - -void dump_mailbox_regs(void) -{ - dev_info(&nvadsp_pdev->dev, "dumping hwmailbox registers ...\n"); - PRINT_HWMBOX(recv_hwmbox()); - PRINT_HWMBOX(send_hwmbox()); + pr_err("dumping hwmailbox registers ...\n"); + PRINT_HWMBOX(drv, recv_hwmbox(drv)); + PRINT_HWMBOX(drv, send_hwmbox(drv)); } static void hwmboxq_init(struct hwmbox_queue *queue) @@ -75,6 +62,8 @@ static void hwmboxq_init(struct hwmbox_queue *queue) queue->count = 0; init_completion(&queue->comp); spin_lock_init(&queue->lock); + queue->is_hwmbox_busy = false; + queue->hwmbox_last_msg = 0; } /* Must be called with queue lock held in non-interrupt context */ @@ -116,10 +105,12 @@ static status_t hwmboxq_enqueue(struct hwmbox_queue *queue, return ret; } -status_t nvadsp_hwmbox_send_data(uint16_t mid, uint32_t data, uint32_t flags) +status_t nvadsp_hwmbox_send_data(struct nvadsp_drv_data *drv, + uint16_t mid, uint32_t data, uint32_t flags) { - spinlock_t *lock = &nvadsp_drv_data->hwmbox_send_queue.lock; - u32 empty_int_ie = nvadsp_drv_data->chip_data->hwmb.empty_int_ie; + struct hwmbox_queue *hwmbox_send_queue = drv->hwmbox_send_queue; + spinlock_t *lock = &hwmbox_send_queue->lock; + u32 empty_int_ie = drv->chip_data->hwmb.empty_int_ie; unsigned long lockflags; int ret = 0; @@ -132,19 +123,18 @@ status_t nvadsp_hwmbox_send_data(uint16_t mid, uint32_t data, uint32_t flags) spin_lock_irqsave(lock, lockflags); - if (!is_hwmbox_busy) { - is_hwmbox_busy = true; + if (!hwmbox_send_queue->is_hwmbox_busy) { + hwmbox_send_queue->is_hwmbox_busy = true; pr_debug("nvadsp_mbox_send: empty mailbox. write to mailbox.\n"); -#ifdef CONFIG_MBOX_ACK_HANDLER - hwmbox_last_msg = data; -#endif - hwmbox_writel(data, send_hwmbox()); - if (empty_int_ie) - hwmbox_writel(INT_ENABLE, send_hwmbox() + empty_int_ie); + hwmbox_send_queue->hwmbox_last_msg = data; + hwmbox_writel(drv, data, send_hwmbox(drv)); + if (empty_int_ie) { + hwmbox_writel(drv, INT_ENABLE, + send_hwmbox(drv) + empty_int_ie); + } } else { pr_debug("nvadsp_mbox_send: enqueue data\n"); - ret = hwmboxq_enqueue(&nvadsp_drv_data->hwmbox_send_queue, - data); + ret = hwmboxq_enqueue(hwmbox_send_queue, data); } spin_unlock_irqrestore(lock, lockflags); return ret; @@ -162,7 +152,7 @@ static status_t hwmboxq_dequeue(struct hwmbox_queue *queue, } if (is_hwmboxq_full(queue)) - complete_all(&nvadsp_drv_data->hwmbox_send_queue.comp); + complete_all(&queue->comp); *data = queue->array[queue->head]; queue->head = (queue->head + 1) & HWMBOX_QUEUE_SIZE_MASK; @@ -174,51 +164,51 @@ static status_t hwmboxq_dequeue(struct hwmbox_queue *queue, static irqreturn_t hwmbox_send_empty_int_handler(int irq, void *devid) { - spinlock_t *lock = &nvadsp_drv_data->hwmbox_send_queue.lock; - struct device *dev = &nvadsp_pdev->dev; - u32 empty_int_ie = nvadsp_drv_data->chip_data->hwmb.empty_int_ie; + struct platform_device *pdev = devid; + struct device *dev = &pdev->dev; + struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); + struct hwmbox_queue *hwmbox_send_queue = drv->hwmbox_send_queue; + spinlock_t *lock = &hwmbox_send_queue->lock; + u32 empty_int_ie = drv->chip_data->hwmb.empty_int_ie; unsigned long lockflags; - uint32_t data; + uint32_t data, hwmbox_last_msg; + uint16_t last_mboxid; + struct nvadsp_mbox *mbox; int ret; - if (!is_hwmbox_busy) + if (!hwmbox_send_queue->is_hwmbox_busy) return IRQ_HANDLED; spin_lock_irqsave(lock, lockflags); - data = hwmbox_readl(send_hwmbox()); + data = hwmbox_readl(drv, send_hwmbox(drv)); if (data != PREPARE_HWMBOX_EMPTY_MSG()) dev_err(dev, "last mailbox sent failed with 0x%x\n", data); -#ifdef CONFIG_MBOX_ACK_HANDLER - { - uint16_t last_mboxid = HWMBOX_SMSG_MID(hwmbox_last_msg); - struct nvadsp_mbox *mbox = nvadsp_drv_data->mboxes[last_mboxid]; + hwmbox_last_msg = hwmbox_send_queue->hwmbox_last_msg; + last_mboxid = HWMBOX_SMSG_MID(hwmbox_last_msg); + mbox = drv->mboxes[last_mboxid]; - if (mbox) { - nvadsp_mbox_handler_t ack_handler = mbox->ack_handler; + if (mbox) { + nvadsp_mbox_handler_t ack_handler = mbox->ack_handler; - if (ack_handler) { - uint32_t msg = HWMBOX_SMSG_MSG(hwmbox_last_msg); + if (ack_handler) { + uint32_t msg = HWMBOX_SMSG_MSG(hwmbox_last_msg); - ack_handler(msg, mbox->hdata); - } + ack_handler(msg, mbox->hdata); } } -#endif - ret = hwmboxq_dequeue(&nvadsp_drv_data->hwmbox_send_queue, - &data); + + ret = hwmboxq_dequeue(hwmbox_send_queue, &data); if (ret == 0) { -#ifdef CONFIG_MBOX_ACK_HANDLER - hwmbox_last_msg = data; -#endif - hwmbox_writel(data, send_hwmbox()); + hwmbox_send_queue->hwmbox_last_msg = data; + hwmbox_writel(drv, data, send_hwmbox(drv)); dev_dbg(dev, "Writing 0x%x to SEND_HWMBOX\n", data); } else { - is_hwmbox_busy = false; + hwmbox_send_queue->is_hwmbox_busy = false; if (empty_int_ie) - hwmbox_writel(INT_DISABLE, - send_hwmbox() + empty_int_ie); + hwmbox_writel(drv, INT_DISABLE, + send_hwmbox(drv) + empty_int_ie); } spin_unlock_irqrestore(lock, lockflags); @@ -227,18 +217,21 @@ static irqreturn_t hwmbox_send_empty_int_handler(int irq, void *devid) static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid) { + struct platform_device *pdev = devid; + struct device *dev = &pdev->dev; + struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); uint32_t data; int ret; - data = hwmbox_readl(recv_hwmbox()); - hwmbox_writel(PREPARE_HWMBOX_EMPTY_MSG(), recv_hwmbox()); + data = hwmbox_readl(drv, recv_hwmbox(drv)); + hwmbox_writel(drv, PREPARE_HWMBOX_EMPTY_MSG(), recv_hwmbox(drv)); if (IS_HWMBOX_MSG_SMSG(data)) { uint16_t mboxid = HWMBOX_SMSG_MID(data); - struct nvadsp_mbox *mbox = nvadsp_drv_data->mboxes[mboxid]; + struct nvadsp_mbox *mbox = drv->mboxes[mboxid]; if (!mbox) { - dev_info(&nvadsp_pdev->dev, + dev_info(dev, "Failed to get mbox for mboxid: %u\n", mboxid); goto out; @@ -250,7 +243,7 @@ static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid) ret = nvadsp_mboxq_enqueue(&mbox->recv_queue, HWMBOX_SMSG_MSG(data)); if (ret) { - dev_info(&nvadsp_pdev->dev, + dev_info(dev, "Failed to deliver msg 0x%x to" " mbox id %u\n", HWMBOX_SMSG_MSG(data), mboxid); @@ -266,7 +259,6 @@ static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid) void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev) { - struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; int recv_virq, send_virq; @@ -301,8 +293,8 @@ int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev) goto err; if (empty_int_ie) - hwmbox_writel(INT_DISABLE, - send_hwmbox() + empty_int_ie); + hwmbox_writel(drv, INT_DISABLE, + send_hwmbox(drv) + empty_int_ie); ret = devm_request_irq(dev, send_virq, hwmbox_send_empty_int_handler, IRQF_TRIGGER_RISING, "hwmbox1_send_empty", pdev); @@ -320,12 +312,19 @@ int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev) int __init nvadsp_hwmbox_init(struct platform_device *pdev) { struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; int ret = 0; - nvadsp_pdev = pdev; - nvadsp_drv_data = drv; + drv->hwmbox_send_queue = devm_kzalloc(dev, + sizeof(struct hwmbox_queue), GFP_KERNEL); + if (!drv->hwmbox_send_queue) { + dev_err(dev, "Failed to allocate hwmbox_send_queue\n"); + ret = -ENOMEM; + goto exit; + } - hwmboxq_init(&drv->hwmbox_send_queue); + hwmboxq_init(drv->hwmbox_send_queue); +exit: return ret; } diff --git a/drivers/platform/tegra/nvadsp/hwmailbox.h b/drivers/platform/tegra/nvadsp/hwmailbox.h index c0322cc7..80f0cb8d 100644 --- a/drivers/platform/tegra/nvadsp/hwmailbox.h +++ b/drivers/platform/tegra/nvadsp/hwmailbox.h @@ -95,15 +95,17 @@ struct hwmbox_queue { uint16_t count; struct completion comp; spinlock_t lock; + bool is_hwmbox_busy; + uint32_t hwmbox_last_msg; }; -u32 hwmb_reg_idx(void); -u32 hwmbox_readl(u32 reg); -void hwmbox_writel(u32 val, u32 reg); -int nvadsp_hwmbox_init(struct platform_device *); -status_t nvadsp_hwmbox_send_data(uint16_t, uint32_t, uint32_t); -void dump_mailbox_regs(void); +u32 hwmbox_readl(struct nvadsp_drv_data *, u32 reg); +void hwmbox_writel(struct nvadsp_drv_data *, u32 val, u32 reg); +status_t nvadsp_hwmbox_send_data(struct nvadsp_drv_data *, + uint16_t, uint32_t, uint32_t); +void dump_mailbox_regs(struct nvadsp_drv_data *); +int nvadsp_hwmbox_init(struct platform_device *); int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev); void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev); diff --git a/drivers/platform/tegra/nvadsp/mailbox.c b/drivers/platform/tegra/nvadsp/mailbox.c index 79228050..0daa289e 100644 --- a/drivers/platform/tegra/nvadsp/mailbox.c +++ b/drivers/platform/tegra/nvadsp/mailbox.c @@ -1,19 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only /** - * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. */ #include "dev.h" +#include "hwmailbox.h" #include #include #define NVADSP_MAILBOX_START 512 -#define NVADSP_MAILBOX_MAX 1024 -#define NVADSP_MAILBOX_OS_MAX 16 - -static struct nvadsp_mbox *nvadsp_mboxes[NVADSP_MAILBOX_MAX]; -static DECLARE_BITMAP(nvadsp_mbox_ids, NVADSP_MAILBOX_MAX); -static struct nvadsp_drv_data *nvadsp_drv_data; static inline bool is_mboxq_empty(struct nvadsp_mbox_queue *queue) { @@ -123,7 +118,8 @@ static void mboxq_dump(struct nvadsp_mbox_queue *queue) spin_unlock_irqrestore(&queue->lock, flags); } -static uint16_t nvadsp_mbox_alloc_mboxid(void) +static uint16_t nvadsp_mbox_alloc_mboxid( + struct nvadsp_drv_data *nvadsp_drv_data) { unsigned long start = NVADSP_MAILBOX_START; unsigned int nr = 1; @@ -138,20 +134,31 @@ static uint16_t nvadsp_mbox_alloc_mboxid(void) return mid; } -static status_t nvadsp_mbox_free_mboxid(uint16_t mid) +static status_t nvadsp_mbox_free_mboxid( + struct nvadsp_drv_data *nvadsp_drv_data, uint16_t mid) { bitmap_clear(nvadsp_drv_data->mbox_ids, mid, 1); return 0; } -status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid, - const char *name, nvadsp_mbox_handler_t handler, - void *hdata) +static void _nvadsp_mbox_set_ack_handler(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, + nvadsp_mbox_handler_t handler) { + mbox->ack_handler = handler; +} + +static status_t _nvadsp_mbox_open(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, + uint16_t *mid, const char *name, + nvadsp_mbox_handler_t handler, void *hdata) +{ + struct nvadsp_drv_data *nvadsp_drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; unsigned long flags; int ret = 0; - if (!nvadsp_drv_data) { + if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) { ret = -ENOSYS; goto err; } @@ -164,7 +171,7 @@ status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid, } if (*mid == 0) { - mbox->id = nvadsp_mbox_alloc_mboxid(); + mbox->id = nvadsp_mbox_alloc_mboxid(nvadsp_drv_data); if (mbox->id >= NVADSP_MAILBOX_MAX) { ret = -ENOMEM; mbox->id = 0; @@ -201,14 +208,18 @@ status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid, err: return ret; } -EXPORT_SYMBOL(nvadsp_mbox_open); -status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data, - uint32_t flags, bool block, unsigned int timeout) +static status_t _nvadsp_mbox_send(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, uint32_t data, + uint32_t flags, bool block, unsigned int timeout) { + struct nvadsp_drv_data *nvadsp_drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct hwmbox_queue *hwmbox_send_queue; int ret = 0; - if (!nvadsp_drv_data) { + if (!nvadsp_drv_data || !nvadsp_drv_data->pdev || + !nvadsp_drv_data->hwmbox_send_queue) { pr_err("ADSP drv_data is NULL\n"); ret = -ENOSYS; goto out; @@ -220,16 +231,18 @@ status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data, goto out; } + hwmbox_send_queue = nvadsp_drv_data->hwmbox_send_queue; + retry: - ret = nvadsp_hwmbox_send_data(mbox->id, data, flags); + ret = nvadsp_hwmbox_send_data(nvadsp_drv_data, mbox->id, data, flags); if (!ret) goto out; if (ret == -EBUSY) { if (block) { ret = wait_for_completion_timeout( - &nvadsp_drv_data->hwmbox_send_queue.comp, - msecs_to_jiffies(timeout)); + &hwmbox_send_queue->comp, + msecs_to_jiffies(timeout)); if (ret) { pr_warn("ADSP HWMBOX send retry\n"); block = false; @@ -250,14 +263,16 @@ status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data, out: return ret; } -EXPORT_SYMBOL(nvadsp_mbox_send); -status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block, - unsigned int timeout) +static status_t _nvadsp_mbox_recv(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, uint32_t *data, + bool block, unsigned int timeout) { + struct nvadsp_drv_data *nvadsp_drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; int ret = 0; - if (!nvadsp_drv_data) { + if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) { ret = -ENOSYS; goto out; } @@ -294,14 +309,16 @@ status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block, out: return ret; } -EXPORT_SYMBOL(nvadsp_mbox_recv); -status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox) +static status_t _nvadsp_mbox_close(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox) { + struct nvadsp_drv_data *nvadsp_drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; unsigned long flags; int ret = 0; - if (!nvadsp_drv_data) { + if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) { ret = -ENOSYS; goto err; } @@ -318,7 +335,7 @@ status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox) goto out; } - nvadsp_mbox_free_mboxid(mbox->id); + nvadsp_mbox_free_mboxid(nvadsp_drv_data, mbox->id); mboxq_destroy(&mbox->recv_queue); nvadsp_drv_data->mboxes[mbox->id] = NULL; out: @@ -326,18 +343,22 @@ status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox) err: return ret; } -EXPORT_SYMBOL(nvadsp_mbox_close); status_t __init nvadsp_mbox_init(struct platform_device *pdev) { struct nvadsp_drv_data *drv = platform_get_drvdata(pdev); + struct nvadsp_handle *nvadsp_handle = &drv->nvadsp_handle; - drv->mboxes = nvadsp_mboxes; - drv->mbox_ids = nvadsp_mbox_ids; + memset(drv->mboxes, 0, sizeof(drv->mboxes)); + memset(drv->mbox_ids, 0, sizeof(drv->mbox_ids)); spin_lock_init(&drv->mbox_lock); - nvadsp_drv_data = drv; + nvadsp_handle->mbox_open = _nvadsp_mbox_open; + nvadsp_handle->mbox_close = _nvadsp_mbox_close; + nvadsp_handle->mbox_send = _nvadsp_mbox_send; + nvadsp_handle->mbox_recv = _nvadsp_mbox_recv; + nvadsp_handle->mbox_set_ack_handler = _nvadsp_mbox_set_ack_handler; return 0; } diff --git a/drivers/platform/tegra/nvadsp/os-t18x.c b/drivers/platform/tegra/nvadsp/os-t18x.c index 2ab8e55f..69d26aef 100644 --- a/drivers/platform/tegra/nvadsp/os-t18x.c +++ b/drivers/platform/tegra/nvadsp/os-t18x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /** - * Copyright (c) 2015-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include #include "dev.h" +#include "hwmailbox.h" #include "os.h" #include "dev-t18x.h" @@ -78,10 +79,12 @@ int nvadsp_os_t18x_init(struct platform_device *pdev) val = val | (adma_ch_page << ADSP_CONFIG_DMA_PAGE_SHIFT); /* Write to HWMBOX5 */ - hwmbox_writel(val, drv_data->chip_data->adsp_os_config_hwmbox); + hwmbox_writel(drv_data, val, + drv_data->chip_data->adsp_os_config_hwmbox); /* Clear HWMBOX0 for ADSP Guest reset handling */ - hwmbox_writel(0, drv_data->chip_data->hwmb.hwmbox0_reg); + hwmbox_writel(drv_data, 0, + drv_data->chip_data->hwmb.hwmbox0_reg); return 0; } diff --git a/drivers/platform/tegra/nvadsp/os.c b/drivers/platform/tegra/nvadsp/os.c index f08a0655..6be15b78 100644 --- a/drivers/platform/tegra/nvadsp/os.c +++ b/drivers/platform/tegra/nvadsp/os.c @@ -40,9 +40,6 @@ #define MAILBOX_REGION ".mbox_shared_data" #define DEBUG_RAM_REGION ".debug_mem_logs" -/* Maximum number of LOAD MAPPINGS supported */ -#define NM_LOAD_MAPPINGS 20 - #define EOT 0x04 /* End of Transmission */ #define SOH 0x01 /* Start of Header */ #define BELL 0x07 /* Bell character */ @@ -87,7 +84,6 @@ struct nvadsp_os_data { const struct firmware *os_firmware; struct platform_device *pdev; struct global_sym_info *adsp_glo_sym_tbl; - void __iomem *hwmailbox_base; struct nvadsp_debug_log logger; struct nvadsp_cnsl console; struct work_struct restart_os_work; @@ -101,46 +97,31 @@ struct nvadsp_os_data { dma_addr_t app_alloc_addr; size_t app_size; int num_start; /* registers number of time start called */ + bool cold_start; + struct nvadsp_mbox adsp_com_mbox; + struct completion entered_wfi; + void (*adma_dump_ch_reg)(void); }; -static struct nvadsp_os_data priv; - -struct nvadsp_mappings { - phys_addr_t da; - void *va; - int len; -}; - -static struct nvadsp_mappings adsp_map[NM_LOAD_MAPPINGS]; -static int map_idx; -static struct nvadsp_mbox adsp_com_mbox; - -static DECLARE_COMPLETION(entered_wfi); - -static void __nvadsp_os_stop(bool); +static void __nvadsp_os_stop(struct nvadsp_os_data *, bool); static irqreturn_t adsp_wdt_handler(int irq, void *arg); static irqreturn_t adsp_wfi_handler(int irq, void *arg); -/* - * set by adsp audio driver through exported api nvadsp_set_adma_dump_reg - * used to dump adma registers incase of failures for debug - */ -static void (*nvadsp_tegra_adma_dump_ch_reg)(void); - #ifdef CONFIG_DEBUG_FS static int adsp_logger_open(struct inode *inode, struct file *file) { - struct nvadsp_debug_log *logger = inode->i_private; + struct nvadsp_os_data *priv = inode->i_private; + struct nvadsp_debug_log *logger = &priv->logger; int ret = -EBUSY; char *start; int i; - mutex_lock(&priv.os_run_lock); - if (!priv.num_start) { - mutex_unlock(&priv.os_run_lock); + mutex_lock(&priv->os_run_lock); + if (!priv->num_start) { + mutex_unlock(&priv->os_run_lock); goto err_ret; } - mutex_unlock(&priv.os_run_lock); + mutex_unlock(&priv->os_run_lock); /* * checks if is_opened is 0, if yes, set 1 and proceed, @@ -265,10 +246,10 @@ static const struct file_operations adsp_logger_operations = { .flush = adsp_logger_flush, }; -static int adsp_create_debug_logger(struct dentry *adsp_debugfs_root) +static int adsp_create_debug_logger(struct nvadsp_os_data *priv, + struct dentry *adsp_debugfs_root) { - struct nvadsp_debug_log *logger = &priv.logger; - struct device *dev = &priv.pdev->dev; + struct nvadsp_debug_log *logger = &priv->logger; int ret = 0; if (IS_ERR_OR_NULL(adsp_debugfs_root)) { @@ -280,9 +261,9 @@ static int adsp_create_debug_logger(struct dentry *adsp_debugfs_root) init_waitqueue_head(&logger->wait_queue); init_completion(&logger->complete); if (!debugfs_create_file("adsp_logger", S_IRUGO, - adsp_debugfs_root, logger, + adsp_debugfs_root, priv, &adsp_logger_operations)) { - dev_err(dev, "unable to create adsp logger debug fs file\n"); + pr_err("unable to create adsp logger debug fs file\n"); ret = -ENOENT; } @@ -291,10 +272,9 @@ err_out: } #endif -bool is_adsp_dram_addr(u64 addr) +static bool is_adsp_dram_addr(struct nvadsp_drv_data *drv_data, u64 addr) { int i; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); for (i = 0; i < MAX_DRAM_MAP; i++) { struct nvadsp_reg_map *dram = &drv_data->dram_map[i]; @@ -310,10 +290,9 @@ bool is_adsp_dram_addr(u64 addr) return false; } -static int is_cluster_mem_addr(u64 addr) +static int is_cluster_mem_addr(struct nvadsp_drv_data *drv_data, u64 addr) { int clust_id; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); for (clust_id = 0; clust_id < MAX_CLUSTER_MEM; clust_id++) { struct nvadsp_cluster_mem *cluster_mem; @@ -331,82 +310,96 @@ static int is_cluster_mem_addr(u64 addr) return -1; } -int nvadsp_add_load_mappings(phys_addr_t pa, void *mapping, int len) +int nvadsp_add_load_mappings(struct nvadsp_drv_data *drv_data, + phys_addr_t pa, void *mapping, int len) { + int map_idx = drv_data->map_idx; + if (map_idx < 0 || map_idx >= NM_LOAD_MAPPINGS) return -EINVAL; - adsp_map[map_idx].da = pa; - adsp_map[map_idx].va = mapping; - adsp_map[map_idx].len = len; - map_idx++; + drv_data->adsp_map[map_idx].da = pa; + drv_data->adsp_map[map_idx].va = mapping; + drv_data->adsp_map[map_idx].len = len; + drv_data->map_idx++; return 0; } -void *nvadsp_da_to_va_mappings(u64 da, int len) +void *nvadsp_da_to_va_mappings(struct nvadsp_drv_data *drv_data, + u64 da, int len) { void *ptr = NULL; int i; - for (i = 0; i < map_idx; i++) { - int offset = da - adsp_map[i].da; + for (i = 0; i < drv_data->map_idx; i++) { + int offset = da - drv_data->adsp_map[i].da; /* try next carveout if da is too small */ if (offset < 0) continue; /* try next carveout if da is too large */ - if (offset + len > adsp_map[i].len) + if (offset + len > drv_data->adsp_map[i].len) continue; - ptr = adsp_map[i].va + offset; + ptr = drv_data->adsp_map[i].va + offset; break; } return ptr; } -void *nvadsp_alloc_coherent(size_t size, dma_addr_t *da, gfp_t flags) +static void *_nvadsp_alloc_coherent(struct nvadsp_handle *nvadsp_handle, + size_t size, dma_addr_t *da, gfp_t flags) { + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; struct device *dev; void *va = NULL; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); goto end; } - dev = &priv.pdev->dev; + priv = drv_data->os_priv; + dev = &priv->pdev->dev; + va = dma_alloc_coherent(dev, size, da, flags); if (!va) { dev_err(dev, "unable to allocate the memory for size %lu\n", size); goto end; } - WARN(!is_adsp_dram_addr(*da), "bus addr %llx beyond %x\n", + WARN(!is_adsp_dram_addr(drv_data, *da), "bus addr %llx beyond %x\n", *da, UINT_MAX); end: return va; } -EXPORT_SYMBOL(nvadsp_alloc_coherent); -void nvadsp_free_coherent(size_t size, void *va, dma_addr_t da) +static void _nvadsp_free_coherent(struct nvadsp_handle *nvadsp_handle, + size_t size, void *va, dma_addr_t da) { + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; struct device *dev; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); return; } - dev = &priv.pdev->dev; + + priv = drv_data->os_priv; + dev = &priv->pdev->dev; + dma_free_coherent(dev, size, va, da); } -EXPORT_SYMBOL(nvadsp_free_coherent); struct elf32_shdr * nvadsp_get_section(const struct firmware *fw, char *sec_name) { int i; - struct device *dev = &priv.pdev->dev; const u8 *elf_data = fw->data; struct elf32_hdr *ehdr = (struct elf32_hdr *)elf_data; struct elf32_shdr *shdr; @@ -418,17 +411,18 @@ nvadsp_get_section(const struct firmware *fw, char *sec_name) for (i = 0; i < ehdr->e_shnum; i++, shdr++) if (!strcmp(name_table + shdr->sh_name, sec_name)) { - dev_dbg(dev, "found the section %s\n", + pr_debug("found the section %s\n", name_table + shdr->sh_name); return shdr; } return NULL; } -static inline void __maybe_unused dump_global_symbol_table(void) +static inline void __maybe_unused dump_global_symbol_table( + struct nvadsp_os_data *priv) { - struct device *dev = &priv.pdev->dev; - struct global_sym_info *table = priv.adsp_glo_sym_tbl; + struct device *dev = &priv->pdev->dev; + struct global_sym_info *table = priv->adsp_glo_sym_tbl; int num_ent; int i; @@ -449,10 +443,11 @@ static inline void __maybe_unused dump_global_symbol_table(void) #ifdef CONFIG_ANDROID static int -__maybe_unused create_global_symbol_table(const struct firmware *fw) +__maybe_unused create_global_symbol_table(struct nvadsp_os_data *priv, + const struct firmware *fw) { int i; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; struct elf32_shdr *sym_shdr = nvadsp_get_section(fw, ".symtab"); struct elf32_shdr *str_shdr = nvadsp_get_section(fw, ".strtab"); const u8 *elf_data = fw->data; @@ -471,9 +466,9 @@ __maybe_unused create_global_symbol_table(const struct firmware *fw) name_table = elf_data + str_shdr->sh_offset; num_ent += sym_shdr->sh_size / sizeof(struct elf32_sym); - priv.adsp_glo_sym_tbl = devm_kzalloc(dev, + priv->adsp_glo_sym_tbl = devm_kzalloc(dev, sizeof(struct global_sym_info) * num_ent, GFP_KERNEL); - if (!priv.adsp_glo_sym_tbl) + if (!priv->adsp_glo_sym_tbl) return -ENOMEM; last_sym = sym + num_ent; @@ -483,23 +478,26 @@ __maybe_unused create_global_symbol_table(const struct firmware *fw) unsigned char type = ELF32_ST_TYPE(info); if ((ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) && ((type == STT_OBJECT) || (type == STT_FUNC))) { - char *name = priv.adsp_glo_sym_tbl[i].name; + char *name = priv->adsp_glo_sym_tbl[i].name; strscpy(name, name_table + sym->st_name, SYM_NAME_SZ); - priv.adsp_glo_sym_tbl[i].addr = sym->st_value; - priv.adsp_glo_sym_tbl[i].info = info; + priv->adsp_glo_sym_tbl[i].addr = sym->st_value; + priv->adsp_glo_sym_tbl[i].info = info; i++; } } - priv.adsp_glo_sym_tbl[0].addr = i; + priv->adsp_glo_sym_tbl[0].addr = i; return 0; } #endif /* CONFIG_ANDROID */ -struct global_sym_info * __maybe_unused find_global_symbol(const char *sym_name) +struct global_sym_info * __maybe_unused find_global_symbol( + struct nvadsp_drv_data *drv_data, + const char *sym_name) { - struct device *dev = &priv.pdev->dev; - struct global_sym_info *table = priv.adsp_glo_sym_tbl; + struct nvadsp_os_data *priv = drv_data->os_priv; + struct device *dev = &priv->pdev->dev; + struct global_sym_info *table = priv->adsp_glo_sym_tbl; int num_ent; int i; @@ -516,20 +514,21 @@ struct global_sym_info * __maybe_unused find_global_symbol(const char *sym_name) return NULL; } -static void *get_mailbox_shared_region(const struct firmware *fw) +static void *get_mailbox_shared_region(struct nvadsp_os_data *priv, + const struct firmware *fw) { struct device *dev; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); struct elf32_shdr *shdr; int addr; int size; - if (!priv.pdev) { + if (!priv->pdev) { pr_err("ADSP Driver is not initialized\n"); return ERR_PTR(-EINVAL); } - dev = &priv.pdev->dev; + dev = &priv->pdev->dev; shdr = nvadsp_get_section(fw, MAILBOX_REGION); if (!shdr) { @@ -541,7 +540,7 @@ static void *get_mailbox_shared_region(const struct firmware *fw) addr = shdr->sh_addr; size = shdr->sh_size; drv_data->shared_adsp_os_data_iova = addr; - return nvadsp_da_to_va_mappings(addr, size); + return nvadsp_da_to_va_mappings(drv_data, addr, size); } static void copy_io_in_l(void *to, const void *from, int sz) @@ -553,10 +552,11 @@ static void copy_io_in_l(void *to, const void *from, int sz) } } -static int nvadsp_os_elf_load(const struct firmware *fw) +static int nvadsp_os_elf_load(struct nvadsp_os_data *priv, + const struct firmware *fw) { - struct device *dev = &priv.pdev->dev; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); + struct device *dev = &priv->pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); struct elf32_hdr *ehdr; struct elf32_phdr *phdr; int i, ret = 0, clust_id; @@ -597,8 +597,9 @@ static int nvadsp_os_elf_load(const struct firmware *fw) goto end; } - nvadsp_add_load_mappings((phys_addr_t)cluster_mem->dsp_addr, - shadow_buf[i], (int)cluster_mem->size); + nvadsp_add_load_mappings(drv_data, + (phys_addr_t)cluster_mem->dsp_addr, + shadow_buf[i], (int)cluster_mem->size); } ehdr = (struct elf32_hdr *)elf_data; @@ -618,7 +619,7 @@ static int nvadsp_os_elf_load(const struct firmware *fw) dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", phdr->p_type, da, memsz, filesz); - va = nvadsp_da_to_va_mappings(da, filesz); + va = nvadsp_da_to_va_mappings(drv_data, da, filesz); if (!va) { dev_err(dev, "no va for da 0x%x filesz 0x%x\n", da, filesz); @@ -642,11 +643,11 @@ static int nvadsp_os_elf_load(const struct firmware *fw) /* put the segment where the remote processor expects it */ if (filesz) { - clust_id = is_cluster_mem_addr(da); + clust_id = is_cluster_mem_addr(drv_data, da); if (clust_id != -1) { cluster_mem_active[clust_id] = true; memcpy(va, elf_data + offset, filesz); - } else if (is_adsp_dram_addr(da)) { + } else if (is_adsp_dram_addr(drv_data, da)) { memcpy(va, elf_data + offset, filesz); } else if ((da == drv_data->evp_base[ADSP_EVP_BASE]) && (filesz == drv_data->evp_base[ADSP_EVP_SIZE])) { @@ -792,11 +793,10 @@ fail_dma_alloc: } #endif -static int allocate_memory_for_adsp_os(void) +static int allocate_memory_for_adsp_os(struct nvadsp_os_data *priv) { - struct platform_device *pdev = priv.pdev; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; struct resource *co_mem = &drv_data->co_mem; #ifdef CONFIG_IOMMU_API_EXPORTED dma_addr_t addr; @@ -807,8 +807,8 @@ static int allocate_memory_for_adsp_os(void) size_t size; int ret = 0; - addr = priv.adsp_os_addr; - size = priv.adsp_os_size; + addr = priv->adsp_os_addr; + size = priv->adsp_os_size; if (size == 0) return 0; @@ -826,7 +826,8 @@ static int allocate_memory_for_adsp_os(void) } #ifdef CONFIG_IOMMU_API_EXPORTED - dram_va = nvadsp_dma_alloc_and_map_at(pdev, size, addr, GFP_KERNEL); + dram_va = nvadsp_dma_alloc_and_map_at(priv->pdev, size, addr, + GFP_KERNEL); if (!dram_va) { dev_err(dev, "unable to allocate SMMU pages\n"); ret = -ENOMEM; @@ -842,23 +843,22 @@ static int allocate_memory_for_adsp_os(void) #endif map_and_end: - nvadsp_add_load_mappings(addr, dram_va, size); + nvadsp_add_load_mappings(drv_data, addr, dram_va, size); end: return ret; } -static void deallocate_memory_for_adsp_os(void) +static void deallocate_memory_for_adsp_os(struct nvadsp_os_data *priv) { - struct platform_device *pdev = priv.pdev; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - size_t size = priv.adsp_os_size; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; + size_t size = priv->adsp_os_size; void *va; if (size == 0) return; - va = nvadsp_da_to_va_mappings(priv.adsp_os_addr, size); + va = nvadsp_da_to_va_mappings(drv_data, priv->adsp_os_addr, size); if (drv_data->co_mem.start) { devm_memunmap(dev, va); @@ -866,25 +866,25 @@ static void deallocate_memory_for_adsp_os(void) } #ifdef CONFIG_IOMMU_API_EXPORTED - dma_free_coherent(dev, priv.adsp_os_size, va, priv.adsp_os_addr); + dma_free_coherent(dev, priv->adsp_os_size, va, priv->adsp_os_addr); #endif } -static void nvadsp_set_shared_mem(struct platform_device *pdev, +static void nvadsp_set_shared_mem(struct nvadsp_os_data *priv, struct nvadsp_shared_mem *shared_mem, uint32_t dynamic_app_support) { - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; struct nvadsp_os_args *os_args; u32 chip_id; shared_mem->os_args.dynamic_app_support = dynamic_app_support; /* set logger strcuture with required properties */ - priv.logger.debug_ram_rdr = shared_mem->os_args.logger; - priv.logger.debug_ram_sz = sizeof(shared_mem->os_args.logger); - priv.logger.dev = dev; - priv.adsp_os_fw_loaded = true; + priv->logger.debug_ram_rdr = shared_mem->os_args.logger; + priv->logger.debug_ram_sz = sizeof(shared_mem->os_args.logger); + priv->logger.dev = dev; + priv->adsp_os_fw_loaded = true; chip_id = (u32)__tegra_get_chip_id(); if (drv_data->chip_data->chipid_ext) @@ -906,12 +906,13 @@ static void nvadsp_set_shared_mem(struct platform_device *pdev, drv_data->shared_adsp_os_data = shared_mem; } -static int __nvadsp_os_secload(struct platform_device *pdev) +static int __nvadsp_os_secload(struct nvadsp_os_data *priv) { - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); dma_addr_t addr = drv_data->adsp_mem[ACSR_ADDR]; size_t size = drv_data->adsp_mem[ACSR_SIZE]; - struct device *dev = &pdev->dev; + struct device *dev = &priv->pdev->dev; + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; void *dram_va; if (size == 0) { @@ -920,14 +921,15 @@ static int __nvadsp_os_secload(struct platform_device *pdev) } if (drv_data->chip_data->adsp_shared_mem_hwmbox != 0) { - dram_va = nvadsp_alloc_coherent(size, &addr, GFP_KERNEL); + dram_va = _nvadsp_alloc_coherent(nvadsp_handle, + size, &addr, GFP_KERNEL); if (dram_va == NULL) { dev_err(dev, "unable to allocate shared region\n"); return -ENOMEM; } } else { #ifdef CONFIG_IOMMU_API_EXPORTED - dram_va = nvadsp_dma_alloc_and_map_at(pdev, size, addr, + dram_va = nvadsp_dma_alloc_and_map_at(priv->pdev, size, addr, GFP_KERNEL); if (dram_va == NULL) { dev_err(dev, "unable to allocate shared region\n"); @@ -943,18 +945,19 @@ static int __nvadsp_os_secload(struct platform_device *pdev) } drv_data->shared_adsp_os_data_iova = addr; - nvadsp_set_shared_mem(pdev, dram_va, 0); + nvadsp_set_shared_mem(priv, dram_va, 0); return 0; } -static int nvadsp_firmware_load(struct platform_device *pdev) +static int __nvadsp_firmware_load(struct nvadsp_os_data *priv) { struct nvadsp_shared_mem *shared_mem; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); dma_addr_t shrd_mem_iova = 0; size_t acsr_size = drv_data->adsp_mem[ACSR_SIZE]; - struct device *dev = &pdev->dev; + struct device *dev = &priv->pdev->dev; + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; const struct firmware *fw; int ret = 0; @@ -965,13 +968,13 @@ static int nvadsp_firmware_load(struct platform_device *pdev) goto end; } #ifdef CONFIG_ANDROID - ret = create_global_symbol_table(fw); + ret = create_global_symbol_table(priv, fw); if (ret) { dev_err(dev, "unable to create global symbol table\n"); goto release_firmware; } #endif - ret = allocate_memory_for_adsp_os(); + ret = allocate_memory_for_adsp_os(priv); if (ret) { dev_err(dev, "unable to allocate memory for adsp os\n"); goto release_firmware; @@ -979,16 +982,16 @@ static int nvadsp_firmware_load(struct platform_device *pdev) dev_info(dev, "Loading ADSP OS firmware %s\n", drv_data->adsp_elf); - ret = nvadsp_os_elf_load(fw); + ret = nvadsp_os_elf_load(priv, fw); if (ret) { dev_err(dev, "failed to load %s\n", drv_data->adsp_elf); goto deallocate_os_memory; } - shared_mem = get_mailbox_shared_region(fw); + shared_mem = get_mailbox_shared_region(priv, fw); if (IS_ERR_OR_NULL(shared_mem) && acsr_size) { if (drv_data->adsp_mem[ACSR_ADDR] == 0) { - shared_mem = nvadsp_alloc_coherent( + shared_mem = _nvadsp_alloc_coherent(nvadsp_handle, acsr_size, &shrd_mem_iova, GFP_KERNEL); if (!shared_mem) { dev_err(dev, "unable to allocate shared region\n"); @@ -1001,37 +1004,40 @@ static int nvadsp_firmware_load(struct platform_device *pdev) * If not dynamic memory allocation then assume shared * memory to be placed at the start of OS memory */ - shared_mem = nvadsp_da_to_va_mappings( - priv.adsp_os_addr, priv.adsp_os_size); + shared_mem = nvadsp_da_to_va_mappings(drv_data, + priv->adsp_os_addr, priv->adsp_os_size); if (!shared_mem) { dev_err(dev, "Failed to get VA for ADSP OS\n"); ret = -ENOMEM; goto deallocate_os_memory; } - drv_data->shared_adsp_os_data_iova = priv.adsp_os_addr; + drv_data->shared_adsp_os_data_iova = priv->adsp_os_addr; } } if (!IS_ERR_OR_NULL(shared_mem)) - nvadsp_set_shared_mem(pdev, shared_mem, 1); + nvadsp_set_shared_mem(priv, shared_mem, 1); else dev_warn(dev, "no shared mem requested\n"); - if (priv.app_size) { - ret = dram_app_mem_init(priv.app_alloc_addr, priv.app_size); +#ifdef CONFIG_ADSP_DYNAMIC_APP + if (priv->app_size) { + ret = dram_app_mem_init(priv->app_alloc_addr, priv->app_size); if (ret) { dev_err(dev, "Memory allocation dynamic apps failed\n"); goto deallocate_os_memory; } } +#endif /* CONFIG_ADSP_DYNAMIC_APP */ - priv.os_firmware = fw; + priv->os_firmware = fw; return 0; deallocate_os_memory: if (shrd_mem_iova) - nvadsp_free_coherent(acsr_size, shared_mem, shrd_mem_iova); - deallocate_memory_for_adsp_os(); + _nvadsp_free_coherent(nvadsp_handle, + acsr_size, shared_mem, shrd_mem_iova); + deallocate_memory_for_adsp_os(priv); release_firmware: release_firmware(fw); end: @@ -1045,10 +1051,11 @@ end: dma_addr_t mfw_smem_iova[MFW_MAX_OTHER_CORES]; void *mfw_hsp_va[MFW_MAX_OTHER_CORES]; -static int nvadsp_load_multi_fw(struct platform_device *pdev) +static int nvadsp_load_multi_fw(struct nvadsp_os_data *priv) { - struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; int i, j, ret; void *dram_va, *hsp_va; dma_addr_t shrd_mem_iova; @@ -1074,7 +1081,7 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) * the FW for all the cores; only shared * memory neeeds to be allocated and set */ - dram_va = nvadsp_alloc_coherent( + dram_va = _nvadsp_alloc_coherent(nvadsp_handle, acsr_size, &shrd_mem_iova, GFP_KERNEL); if (!dram_va) { dev_err(dev, @@ -1127,18 +1134,18 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) } #endif - nvadsp_add_load_mappings((phys_addr_t)os_mem, + nvadsp_add_load_mappings(drv_data, (phys_addr_t)os_mem, dram_va, (size_t)os_size); dev_info(dev, "Loading ADSP OS firmware %s\n", adsp_elf); - ret = nvadsp_os_elf_load(fw); + ret = nvadsp_os_elf_load(priv, fw); if (ret) { dev_err(dev, "failed to load %s\n", adsp_elf); continue; } if (drv_data->adsp_mem[ACSR_ADDR] == 0) { - dram_va = nvadsp_alloc_coherent( + dram_va = _nvadsp_alloc_coherent(nvadsp_handle, acsr_size, &shrd_mem_iova, GFP_KERNEL); if (!dram_va) { dev_err(dev, @@ -1151,7 +1158,7 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) } } - nvadsp_set_shared_mem(pdev, dram_va, 0); + nvadsp_set_shared_mem(priv, dram_va, 0); /* Store shared mem IOVA for writing into MBOX (for ADSP) */ hsp_va = devm_ioremap_resource(dev, &hsp_inst); @@ -1211,47 +1218,48 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) } #endif // CONFIG_TEGRA_ADSP_MULTIPLE_FW -int nvadsp_os_load(void) +static int _nvadsp_os_load(struct nvadsp_handle *nvadsp_handle) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; struct device *dev; int ret = 0; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); return -EINVAL; } - mutex_lock(&priv.fw_load_lock); - if (priv.adsp_os_fw_loaded) - goto end; + priv = drv_data->os_priv; + dev = &priv->pdev->dev; - drv_data = platform_get_drvdata(priv.pdev); - dev = &priv.pdev->dev; + mutex_lock(&priv->fw_load_lock); + if (priv->adsp_os_fw_loaded) + goto end; #ifdef CONFIG_TEGRA_ADSP_MULTIPLE_FW dev_info(dev, "Loading multiple ADSP FW....\n"); - nvadsp_load_multi_fw(priv.pdev); + nvadsp_load_multi_fw(priv); #endif // CONFIG_TEGRA_ADSP_MULTIPLE_FW if (drv_data->adsp_os_secload) { dev_info(dev, "ADSP OS firmware already loaded\n"); - ret = __nvadsp_os_secload(priv.pdev); + ret = __nvadsp_os_secload(priv); } else { - ret = nvadsp_firmware_load(priv.pdev); + ret = __nvadsp_firmware_load(priv); } if (ret == 0) { - priv.adsp_os_fw_loaded = true; + priv->adsp_os_fw_loaded = true; #ifdef CONFIG_DEBUG_FS - wake_up(&priv.logger.wait_queue); + wake_up(&priv->logger.wait_queue); #endif } end: - mutex_unlock(&priv.fw_load_lock); + mutex_unlock(&priv->fw_load_lock); return ret; } -EXPORT_SYMBOL(nvadsp_os_load); /* * Static adsp freq to emc freq lookup table @@ -1279,7 +1287,7 @@ u32 adsp_to_emc_freq(u32 adspfreq) static int nvadsp_set_ape_emc_freq(struct nvadsp_drv_data *drv_data) { unsigned long ape_emc_freq; - struct device *dev = &priv.pdev->dev; + struct device *dev = &drv_data->pdev->dev; int ret; #ifdef CONFIG_TEGRA_ADSP_DFS @@ -1310,7 +1318,7 @@ static int nvadsp_set_ape_emc_freq(struct nvadsp_drv_data *drv_data) static int nvadsp_set_ape_freq(struct nvadsp_drv_data *drv_data) { unsigned long ape_freq = drv_data->ape_freq * 1000; /* in Hz*/ - struct device *dev = &priv.pdev->dev; + struct device *dev = &drv_data->pdev->dev; int ret; #ifdef CONFIG_TEGRA_ADSP_ACTMON @@ -1330,9 +1338,10 @@ static int nvadsp_set_ape_freq(struct nvadsp_drv_data *drv_data) static int nvadsp_t210_set_clks_and_prescalar(struct nvadsp_drv_data *drv_data) { + struct nvadsp_os_data *priv = drv_data->os_priv; struct nvadsp_shared_mem *shared_mem = drv_data->shared_adsp_os_data; struct nvadsp_os_args *os_args = &shared_mem->os_args; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; unsigned long max_adsp_freq; unsigned long adsp_freq; u32 max_index; @@ -1504,7 +1513,8 @@ static int nvadsp_set_boot_vec(struct nvadsp_drv_data *drv_data) static int nvadsp_set_boot_freqs(struct nvadsp_drv_data *drv_data) { - struct device *dev = &priv.pdev->dev; + struct nvadsp_os_data *priv = drv_data->os_priv; + struct device *dev = &priv->pdev->dev; struct device_node *node = dev->of_node; int ret = 0; @@ -1549,10 +1559,11 @@ end: return ret; } -static int wait_for_adsp_os_load_complete(void) +static int wait_for_adsp_os_load_complete(struct nvadsp_os_data *priv) { - struct device *dev = &priv.pdev->dev; - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); + struct device *dev = &priv->pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; uint32_t timeout, data; status_t ret; @@ -1560,8 +1571,8 @@ static int wait_for_adsp_os_load_complete(void) if (!timeout) timeout = ADSP_OS_LOAD_TIMEOUT; - ret = nvadsp_mbox_recv(&adsp_com_mbox, &data, - true, timeout); + ret = nvadsp_handle->mbox_recv(nvadsp_handle, &priv->adsp_com_mbox, + &data, true, timeout); if (ret) { dev_err(dev, "ADSP OS loading timed out\n"); goto end; @@ -1571,7 +1582,7 @@ static int wait_for_adsp_os_load_complete(void) switch (data) { case ADSP_OS_BOOT_COMPLETE: - ret = load_adsp_static_apps(); + ret = load_adsp_static_apps(drv_data); break; case ADSP_OS_RESUME: default: @@ -1581,16 +1592,12 @@ end: return ret; } -static int __nvadsp_os_start(void) +static int __nvadsp_os_start(struct nvadsp_os_data *priv) { - struct nvadsp_drv_data *drv_data; - struct device *dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; int ret = 0; - dev = &priv.pdev->dev; - drv_data = platform_get_drvdata(priv.pdev); - - dev_dbg(dev, "ADSP is booting on %s\n", drv_data->adsp_unit_fpga ? "UNIT-FPGA" : "SILICON"); @@ -1620,7 +1627,7 @@ static int __nvadsp_os_start(void) dev_dbg(dev, "Waiting for ADSP OS to boot up...\n"); - ret = wait_for_adsp_os_load_complete(); + ret = wait_for_adsp_os_load_complete(priv); if (ret) { dev_err(dev, "Unable to start ADSP OS\n"); goto end; @@ -1628,7 +1635,7 @@ static int __nvadsp_os_start(void) dev_dbg(dev, "ADSP OS boot up... Done!\n"); #ifdef CONFIG_TEGRA_ADSP_DFS - ret = adsp_dfs_core_init(priv.pdev); + ret = adsp_dfs_core_init(priv->pdev); if (ret) { dev_err(dev, "adsp dfs initialization failed\n"); goto err; @@ -1636,7 +1643,7 @@ static int __nvadsp_os_start(void) #endif #ifdef CONFIG_TEGRA_ADSP_ACTMON - ret = ape_actmon_init(priv.pdev); + ret = ape_actmon_init(priv->pdev); if (ret) { dev_err(dev, "ape actmon initialization failed\n"); goto err; @@ -1644,7 +1651,7 @@ static int __nvadsp_os_start(void) #endif #ifdef CONFIG_TEGRA_ADSP_CPUSTAT - ret = adsp_cpustat_init(priv.pdev); + ret = adsp_cpustat_init(priv->pdev); if (ret) { dev_err(dev, "adsp cpustat initialisation failed\n"); goto err; @@ -1655,19 +1662,19 @@ end: #if defined(CONFIG_TEGRA_ADSP_DFS) || defined(CONFIG_TEGRA_ADSP_CPUSTAT) err: - __nvadsp_os_stop(true); + __nvadsp_os_stop(priv, true); return ret; #endif } -static void dump_adsp_logs(void) +static void dump_adsp_logs(struct nvadsp_os_data *priv) { int i = 0; char buff[DUMP_BUFF] = { }; int buff_iter = 0; char last_char; - struct nvadsp_debug_log *logger = &priv.logger; - struct device *dev = &priv.pdev->dev; + struct nvadsp_debug_log *logger = &priv->logger; + struct device *dev = &priv->pdev->dev; char *ptr = logger->debug_ram_rdr; dev_err(dev, "Dumping ADSP logs ........\n"); @@ -1688,13 +1695,13 @@ static void dump_adsp_logs(void) dev_err(dev, "End of ADSP log dump .....\n"); } -static void print_agic_irq_states(void) +static void print_agic_irq_states(struct nvadsp_os_data *priv) { #ifdef CONFIG_AGIC_EXT_API - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); int start_irq = drv_data->chip_data->start_irq; int end_irq = drv_data->chip_data->end_irq; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; int i; for (i = start_irq; i < end_irq; i++) { @@ -1707,16 +1714,16 @@ static void print_agic_irq_states(void) #endif // CONFIG_AGIC_EXT_APIS } -static void print_arm_mode_regs(void) +static void print_arm_mode_regs(struct nvadsp_os_data *priv) { struct nvadsp_exception_context *excep_context; struct arm_fault_frame_shared *shared_frame; struct arm_mode_regs_shared *shared_regs; struct nvadsp_shared_mem *shared_mem; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; struct nvadsp_drv_data *drv_data; - drv_data = platform_get_drvdata(priv.pdev); + drv_data = platform_get_drvdata(priv->pdev); shared_mem = drv_data->shared_adsp_os_data; excep_context = &shared_mem->exception_context; shared_frame = &excep_context->frame; @@ -1743,15 +1750,15 @@ static void print_arm_mode_regs(void) shared_regs->abt_r13, shared_regs->abt_r14); } -static void print_arm_fault_frame(void) +static void print_arm_fault_frame(struct nvadsp_os_data *priv) { struct nvadsp_exception_context *excep_context; struct arm_fault_frame_shared *shared_frame; struct nvadsp_shared_mem *shared_mem; - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; struct nvadsp_drv_data *drv_data; - drv_data = platform_get_drvdata(priv.pdev); + drv_data = platform_get_drvdata(priv->pdev); shared_mem = drv_data->shared_adsp_os_data; excep_context = &shared_mem->exception_context; shared_frame = &excep_context->frame; @@ -1787,27 +1794,27 @@ static void dump_irq_num(struct platform_device *pdev, u32 val) __func__, val); } -static void get_adsp_state(void) +static void get_adsp_state(struct nvadsp_os_data *priv) { struct nvadsp_drv_data *drv_data; struct device *dev; uint32_t val; const char *msg; - if (!priv.pdev) { + if (!priv->pdev) { pr_err("ADSP Driver is not initialized\n"); return; } - drv_data = platform_get_drvdata(priv.pdev); - dev = &priv.pdev->dev; + drv_data = platform_get_drvdata(priv->pdev); + dev = &priv->pdev->dev; if (drv_data->chip_data->adsp_state_hwmbox == 0) { dev_info(dev, "%s: No state hwmbox available\n", __func__); return; } - val = hwmbox_readl(drv_data->chip_data->adsp_state_hwmbox); + val = hwmbox_readl(drv_data, drv_data->chip_data->adsp_state_hwmbox); dev_info(dev, "%s: adsp state hwmbox value: 0x%X\n", __func__, val); switch (val) { @@ -1958,31 +1965,35 @@ static void get_adsp_state(void) dev_info(dev, "%s: %s\n", __func__, msg); - val = hwmbox_readl(drv_data->chip_data->adsp_thread_hwmbox); - dump_thread_name(priv.pdev, val); + val = hwmbox_readl(drv_data, drv_data->chip_data->adsp_thread_hwmbox); + dump_thread_name(priv->pdev, val); - val = hwmbox_readl(drv_data->chip_data->adsp_irq_hwmbox); - dump_irq_num(priv.pdev, val); + val = hwmbox_readl(drv_data, drv_data->chip_data->adsp_irq_hwmbox); + dump_irq_num(priv->pdev, val); } - -void dump_adsp_sys(void) +static void _nvadsp_dump_adsp_sys(struct nvadsp_handle *nvadsp_handle) { - if (!priv.pdev) { + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; + + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); return; } - dump_adsp_logs(); - dump_mailbox_regs(); - print_arm_fault_frame(); - print_arm_mode_regs(); - get_adsp_state(); - if (nvadsp_tegra_adma_dump_ch_reg) - (*nvadsp_tegra_adma_dump_ch_reg)(); - print_agic_irq_states(); + priv = drv_data->os_priv; + + dump_adsp_logs(priv); + dump_mailbox_regs(drv_data); + print_arm_fault_frame(priv); + print_arm_mode_regs(priv); + get_adsp_state(priv); + if (priv->adma_dump_ch_reg) + (*priv->adma_dump_ch_reg)(); + print_agic_irq_states(priv); } -EXPORT_SYMBOL(dump_adsp_sys); static void nvadsp_free_os_interrupts(struct nvadsp_os_data *priv) { @@ -2058,52 +2069,64 @@ static int setup_interrupts(struct nvadsp_os_data *priv) return ret; } -void nvadsp_set_adma_dump_reg(void (*cb_adma_regdump)(void)) +static void _nvadsp_set_adma_dump_reg(struct nvadsp_handle *nvadsp_handle, + void (*cb_adma_regdump)(void)) { - nvadsp_tegra_adma_dump_ch_reg = cb_adma_regdump; - pr_info("%s: callback for adma reg dump is sent to %p\n", - __func__, nvadsp_tegra_adma_dump_ch_reg); -} -EXPORT_SYMBOL(nvadsp_set_adma_dump_reg); + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; -int nvadsp_os_start(void) + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { + pr_err("ADSP Driver is not initialized\n"); + return; + } + + priv = drv_data->os_priv; + + priv->adma_dump_ch_reg = cb_adma_regdump; + pr_info("%s: callback for adma reg dump is sent to %p\n", + __func__, priv->adma_dump_ch_reg); +} + +static int _nvadsp_os_start(struct nvadsp_handle *nvadsp_handle) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; struct device *dev; int ret = 0; - static int cold_start = 1; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); ret = -EINVAL; goto end; } - drv_data = platform_get_drvdata(priv.pdev); - dev = &priv.pdev->dev; + priv = drv_data->os_priv; + dev = &priv->pdev->dev; /* check if fw is loaded then start the adsp os */ - if (!priv.adsp_os_fw_loaded) { + if (!priv->adsp_os_fw_loaded) { dev_err(dev, "Call to nvadsp_os_load not made\n"); ret = -EINVAL; goto end; } - mutex_lock(&priv.os_run_lock); + mutex_lock(&priv->os_run_lock); /* if adsp is started/running exit gracefully */ - if (priv.os_running) + if (priv->os_running) goto unlock; #ifdef CONFIG_PM - ret = pm_runtime_get_sync(&priv.pdev->dev); + ret = pm_runtime_get_sync(dev); if (ret < 0) goto unlock; #endif - ret = setup_interrupts(&priv); + ret = setup_interrupts(priv); if (ret < 0) goto unlock; - if (cold_start) { + if (priv->cold_start) { if (drv_data->chip_data->adsp_shared_mem_hwmbox != 0) { #ifdef CONFIG_TEGRA_ADSP_MULTIPLE_FW int i; @@ -2118,7 +2141,7 @@ int nvadsp_os_start(void) } #endif // CONFIG_TEGRA_ADSP_MULTIPLE_FW - hwmbox_writel( + hwmbox_writel(drv_data, (uint32_t)drv_data->shared_adsp_os_data_iova, drv_data->chip_data->adsp_shared_mem_hwmbox); } @@ -2130,12 +2153,12 @@ int nvadsp_os_start(void) ADSP_CONFIG_DECOMPRESS_SHIFT); /* Write to HWMBOX5 */ - hwmbox_writel(val, + hwmbox_writel(drv_data, val, drv_data->chip_data->adsp_os_config_hwmbox); } /* Write ACSR base address and decompr enable flag only once */ - cold_start = 0; + priv->cold_start = false; } if (drv_data->chip_data->adsp_boot_config_hwmbox != 0) { @@ -2147,40 +2170,40 @@ int nvadsp_os_start(void) * adsp_os_secload flag. It could be extended in * future to pass more information. */ - hwmbox_writel( + hwmbox_writel(drv_data, (uint32_t)drv_data->adsp_os_secload, drv_data->chip_data->adsp_boot_config_hwmbox); } - ret = __nvadsp_os_start(); + ret = __nvadsp_os_start(priv); if (ret) { - priv.os_running = drv_data->adsp_os_running = false; + priv->os_running = drv_data->adsp_os_running = false; /* if start fails call pm suspend of adsp driver */ dev_err(dev, "adsp failed to boot with ret = %d\n", ret); - dump_adsp_sys(); - free_interrupts(&priv); + _nvadsp_dump_adsp_sys(nvadsp_handle); + free_interrupts(priv); #ifdef CONFIG_PM - pm_runtime_put_sync(&priv.pdev->dev); + pm_runtime_put_sync(dev); #endif goto unlock; } - priv.os_running = drv_data->adsp_os_running = true; - priv.num_start++; + priv->os_running = drv_data->adsp_os_running = true; + priv->num_start++; #if defined(CONFIG_TEGRA_ADSP_FILEIO) if ((drv_data->adsp_os_secload) && (!drv_data->adspff_init)) { - int adspff_status = adspff_init(priv.pdev); + int adspff_status = adspff_init(priv->pdev); if (adspff_status) { if (adspff_status != -ENOENT) { - priv.os_running = drv_data->adsp_os_running = false; + priv->os_running = drv_data->adsp_os_running = false; dev_err(dev, "adsp boot failed at adspff init with ret = %d", adspff_status); - dump_adsp_sys(); - free_interrupts(&priv); + _nvadsp_dump_adsp_sys(nvadsp_handle); + free_interrupts(priv); #ifdef CONFIG_PM - pm_runtime_put_sync(&priv.pdev->dev); + pm_runtime_put_sync(dev); #endif ret = adspff_status; goto unlock; @@ -2192,7 +2215,7 @@ int nvadsp_os_start(void) #ifdef CONFIG_TEGRA_ADSP_LPTHREAD if (!drv_data->lpthread_initialized) { - ret = adsp_lpthread_entry(priv.pdev); + ret = adsp_lpthread_entry(priv->pdev); if (ret) dev_err(dev, "adsp_lpthread_entry failed ret = %d\n", ret); @@ -2201,7 +2224,7 @@ int nvadsp_os_start(void) drv_data->adsp_os_suspended = false; #ifdef CONFIG_DEBUG_FS - wake_up(&priv.logger.wait_queue); + wake_up(&priv->logger.wait_queue); #endif #ifdef CONFIG_TEGRA_ADSP_LPTHREAD @@ -2209,11 +2232,10 @@ int nvadsp_os_start(void) #endif unlock: - mutex_unlock(&priv.os_run_lock); + mutex_unlock(&priv->os_run_lock); end: return ret; } -EXPORT_SYMBOL(nvadsp_os_start); static bool nvadsp_check_wfi_status(struct nvadsp_drv_data *drv_data) { @@ -2247,36 +2269,36 @@ static bool nvadsp_check_wfi_status(struct nvadsp_drv_data *drv_data) return wfi_status; } -static int __nvadsp_os_suspend(void) +static int __nvadsp_os_suspend(struct nvadsp_os_data *priv) { - struct device *dev = &priv.pdev->dev; - struct nvadsp_drv_data *drv_data; + struct device *dev = &priv->pdev->dev; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; int ret; bool status = false; - drv_data = platform_get_drvdata(priv.pdev); - #ifdef CONFIG_TEGRA_ADSP_ACTMON - ape_actmon_exit(priv.pdev); + ape_actmon_exit(priv->pdev); #endif #ifdef CONFIG_TEGRA_ADSP_DFS - adsp_dfs_core_exit(priv.pdev); + adsp_dfs_core_exit(priv->pdev); #endif #ifdef CONFIG_TEGRA_ADSP_CPUSTAT - adsp_cpustat_exit(priv.pdev); + adsp_cpustat_exit(priv->pdev); #endif - ret = nvadsp_mbox_send(&adsp_com_mbox, ADSP_OS_SUSPEND, - NVADSP_MBOX_SMSG, true, UINT_MAX); + ret = nvadsp_handle->mbox_send(nvadsp_handle, &priv->adsp_com_mbox, + ADSP_OS_SUSPEND, + NVADSP_MBOX_SMSG, true, UINT_MAX); if (ret) { dev_err(dev, "failed to send with adsp com mbox\n"); goto out; } dev_dbg(dev, "Waiting for ADSP OS suspend...\n"); - ret = wait_for_completion_timeout(&entered_wfi, + ret = wait_for_completion_timeout(&priv->entered_wfi, msecs_to_jiffies(ADSP_WFI_TIMEOUT)); if (WARN_ON(ret <= 0)) { dev_err(dev, "Unable to suspend ADSP OS err = %d\n", ret); @@ -2305,26 +2327,24 @@ static int __nvadsp_os_suspend(void) return ret; } -static void __nvadsp_os_stop(bool reload) +static void __nvadsp_os_stop(struct nvadsp_os_data *priv, bool reload) { - const struct firmware *fw = priv.os_firmware; - struct nvadsp_drv_data *drv_data; - struct device *dev; + const struct firmware *fw = priv->os_firmware; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); + struct device *dev = &priv->pdev->dev; + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; int err = 0; - dev = &priv.pdev->dev; - drv_data = platform_get_drvdata(priv.pdev); - #ifdef CONFIG_TEGRA_ADSP_ACTMON - ape_actmon_exit(priv.pdev); + ape_actmon_exit(priv->pdev); #endif #ifdef CONFIG_TEGRA_ADSP_DFS - adsp_dfs_core_exit(priv.pdev); + adsp_dfs_core_exit(priv->pdev); #endif #ifdef CONFIG_TEGRA_ADSP_CPUSTAT - adsp_cpustat_exit(priv.pdev); + adsp_cpustat_exit(priv->pdev); #endif #if defined(CONFIG_TEGRA_ADSP_FILEIO) if (drv_data->adspff_init) { @@ -2333,12 +2353,12 @@ static void __nvadsp_os_stop(bool reload) } #endif - err = nvadsp_mbox_send(&adsp_com_mbox, + err = nvadsp_handle->mbox_send(nvadsp_handle, &priv->adsp_com_mbox, ADSP_OS_STOP, NVADSP_MBOX_SMSG, true, UINT_MAX); if (err) dev_err(dev, "failed to send stop msg to adsp\n"); - err = wait_for_completion_timeout(&entered_wfi, + err = wait_for_completion_timeout(&priv->entered_wfi, msecs_to_jiffies(ADSP_WFI_TIMEOUT)); /* @@ -2358,7 +2378,7 @@ static void __nvadsp_os_stop(bool reload) } if (reload && !drv_data->adsp_os_secload) { - struct nvadsp_debug_log *logger = &priv.logger; + struct nvadsp_debug_log *logger = &priv->logger; #ifdef CONFIG_DEBUG_FS wake_up(&logger->wait_queue); @@ -2373,7 +2393,7 @@ static void __nvadsp_os_stop(bool reload) logger->debug_ram_rdr[0] = EOT; logger->ram_iter = 0; /* load a fresh copy of adsp.elf */ - if (nvadsp_os_elf_load(fw)) + if (nvadsp_os_elf_load(priv, fw)) dev_err(dev, "failed to reload %s\n", drv_data->adsp_elf); } @@ -2382,78 +2402,79 @@ static void __nvadsp_os_stop(bool reload) return; } - -void nvadsp_os_stop(void) +static void _nvadsp_os_stop(struct nvadsp_handle *nvadsp_handle) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; struct device *dev; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); return; } - dev = &priv.pdev->dev; - drv_data = platform_get_drvdata(priv.pdev); + priv = drv_data->os_priv; + dev = &priv->pdev->dev; - mutex_lock(&priv.os_run_lock); + mutex_lock(&priv->os_run_lock); /* check if os is running else exit */ - if (!priv.os_running) + if (!priv->os_running) goto end; - __nvadsp_os_stop(true); + __nvadsp_os_stop(priv, true); - priv.os_running = drv_data->adsp_os_running = false; + priv->os_running = drv_data->adsp_os_running = false; - free_interrupts(&priv); + free_interrupts(priv); #ifdef CONFIG_PM if (pm_runtime_put_sync(dev) < 0) dev_err(dev, "failed in pm_runtime_put_sync\n"); #endif end: - mutex_unlock(&priv.os_run_lock); + mutex_unlock(&priv->os_run_lock); } -EXPORT_SYMBOL(nvadsp_os_stop); -int nvadsp_os_suspend(void) +static int _nvadsp_os_suspend(struct nvadsp_handle *nvadsp_handle) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; + struct nvadsp_os_data *priv; + struct device *dev; int ret = -EINVAL; - if (!priv.pdev) { + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) { pr_err("ADSP Driver is not initialized\n"); goto end; } - drv_data = platform_get_drvdata(priv.pdev); + priv = drv_data->os_priv; + dev = &priv->pdev->dev; - mutex_lock(&priv.os_run_lock); + mutex_lock(&priv->os_run_lock); /* check if os is running else exit */ - if (!priv.os_running) { + if (!priv->os_running) { ret = 0; goto unlock; } - ret = __nvadsp_os_suspend(); + ret = __nvadsp_os_suspend(priv); if (!ret) { #ifdef CONFIG_PM - struct device *dev = &priv.pdev->dev; - - free_interrupts(&priv); - ret = pm_runtime_put_sync(&priv.pdev->dev); + free_interrupts(priv); + ret = pm_runtime_put_sync(dev); if (ret < 0) dev_err(dev, "failed in pm_runtime_put_sync\n"); #endif - priv.os_running = drv_data->adsp_os_running = false; + priv->os_running = drv_data->adsp_os_running = false; } else { - dev_err(&priv.pdev->dev, "suspend failed with %d\n", ret); - dump_adsp_sys(); + dev_err(dev, "suspend failed with %d\n", ret); + _nvadsp_dump_adsp_sys(nvadsp_handle); } unlock: - mutex_unlock(&priv.os_run_lock); + mutex_unlock(&priv->os_run_lock); end: return ret; } -EXPORT_SYMBOL(nvadsp_os_suspend); static void nvadsp_os_restart(struct work_struct *work) { @@ -2485,7 +2506,7 @@ static void nvadsp_os_restart(struct work_struct *work) data->adsp_num_crashes++; if (data->adsp_num_crashes >= ALLOWED_CRASHES) { /* making pdev NULL so that externally start is not called */ - priv.pdev = NULL; + data->pdev = NULL; dev_crit(dev, "ADSP has crashed too many times(%d)\n", data->adsp_num_crashes); return; @@ -2502,7 +2523,7 @@ static irqreturn_t adsp_wfi_handler(int irq, void *arg) struct device *dev = &data->pdev->dev; dev_dbg(dev, "%s\n", __func__); - complete(&entered_wfi); + complete(&data->entered_wfi); return IRQ_HANDLED; } @@ -2527,18 +2548,19 @@ static irqreturn_t adsp_wdt_handler(int irq, void *arg) return IRQ_HANDLED; } -void nvadsp_get_os_version(char *buf, int buf_size) +static void _nvadsp_get_os_version(struct nvadsp_handle *nvadsp_handle, + char *buf, int buf_size) { - struct nvadsp_drv_data *drv_data; + struct nvadsp_drv_data *drv_data = + (struct nvadsp_drv_data *)nvadsp_handle; struct nvadsp_shared_mem *shared_mem; struct nvadsp_os_info *os_info; memset(buf, 0, buf_size); - if (!priv.pdev) + if (!drv_data || !drv_data->pdev || !drv_data->os_priv) return; - drv_data = platform_get_drvdata(priv.pdev); shared_mem = drv_data->shared_adsp_os_data; if (shared_mem) { os_info = &shared_mem->os_info; @@ -2547,14 +2569,19 @@ void nvadsp_get_os_version(char *buf, int buf_size) strscpy(buf, "unavailable", buf_size); } } -EXPORT_SYMBOL(nvadsp_get_os_version); #ifdef CONFIG_DEBUG_FS static int show_os_version(struct seq_file *s, void *data) { + struct nvadsp_os_data *priv = data; + struct nvadsp_drv_data *drv_data; + struct nvadsp_handle *nvadsp_handle; char ver_buf[MAX_OS_VERSION_BUF] = ""; - nvadsp_get_os_version(ver_buf, MAX_OS_VERSION_BUF); + drv_data = platform_get_drvdata(priv->pdev); + nvadsp_handle = &drv_data->nvadsp_handle; + + _nvadsp_get_os_version(nvadsp_handle, ver_buf, MAX_OS_VERSION_BUF); seq_printf(s, "version=\"%s\"\n", ver_buf); return 0; @@ -2574,13 +2601,14 @@ static const struct file_operations version_fops = { #define RO_MODE S_IRUSR -static int adsp_create_os_version(struct dentry *adsp_debugfs_root) +static int adsp_create_os_version(struct nvadsp_os_data *priv, + struct dentry *adsp_debugfs_root) { - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; struct dentry *d; d = debugfs_create_file("adspos_version", RO_MODE, adsp_debugfs_root, - NULL, &version_fops); + priv, &version_fops); if (!d) { dev_err(dev, "failed to create adsp_version\n"); return -EINVAL; @@ -2588,10 +2616,17 @@ static int adsp_create_os_version(struct dentry *adsp_debugfs_root) return 0; } +static int adsp_health_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + static __poll_t adsp_health_poll(struct file *file, poll_table *wait) { - struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); + struct nvadsp_os_data *priv = file->private_data; + struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv->pdev); poll_wait(file, &drv_data->adsp_health_waitq, wait); @@ -2602,16 +2637,18 @@ static __poll_t adsp_health_poll(struct file *file, } static const struct file_operations adsp_health_fops = { + .open = adsp_health_open, .poll = adsp_health_poll, }; -static int adsp_create_adsp_health(struct dentry *adsp_debugfs_root) +static int adsp_create_adsp_health(struct nvadsp_os_data *priv, + struct dentry *adsp_debugfs_root) { - struct device *dev = &priv.pdev->dev; + struct device *dev = &priv->pdev->dev; struct dentry *d; d = debugfs_create_file("adsp_health", RO_MODE, adsp_debugfs_root, - NULL, &adsp_health_fops); + priv, &adsp_health_fops); if (!d) { dev_err(dev, "failed to create adsp_health\n"); return -EINVAL; @@ -2623,23 +2660,36 @@ static int adsp_create_adsp_health(struct dentry *adsp_debugfs_root) static ssize_t tegrafw_read_adsp(struct device *dev, char *data, size_t size) { - nvadsp_get_os_version(data, size); + /* TBD - address the NULL below */ + _nvadsp_get_os_version(NULL, data, size); return strlen(data); } int __init nvadsp_os_probe(struct platform_device *pdev) { struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - uint16_t com_mid = ADSP_COM_MBOX_ID; + struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle; struct device *dev = &pdev->dev; + struct nvadsp_os_data *priv; + uint16_t com_mid = ADSP_COM_MBOX_ID; int ret = 0; - priv.hwmailbox_base = drv_data->base_regs[hwmb_reg_idx()]; + priv = devm_kzalloc(dev, + sizeof(struct nvadsp_os_data), GFP_KERNEL); + if (!priv) { + dev_err(dev, "Failed to allocate os_priv\n"); + ret = -ENOMEM; + goto end; + } + drv_data->os_priv = priv; - priv.adsp_os_addr = drv_data->adsp_mem[ADSP_OS_ADDR]; - priv.adsp_os_size = drv_data->adsp_mem[ADSP_OS_SIZE]; - priv.app_alloc_addr = drv_data->adsp_mem[ADSP_APP_ADDR]; - priv.app_size = drv_data->adsp_mem[ADSP_APP_SIZE]; + priv->adsp_os_addr = drv_data->adsp_mem[ADSP_OS_ADDR]; + priv->adsp_os_size = drv_data->adsp_mem[ADSP_OS_SIZE]; + priv->app_alloc_addr = drv_data->adsp_mem[ADSP_APP_ADDR]; + priv->app_size = drv_data->adsp_mem[ADSP_APP_SIZE]; + + priv->cold_start = true; + init_completion(&priv->entered_wfi); if (of_device_is_compatible(dev->of_node, "nvidia,tegra210-adsp")) { drv_data->assert_adsp = __assert_adsp; @@ -2652,31 +2702,31 @@ int __init nvadsp_os_probe(struct platform_device *pdev) goto end; } - ret = nvadsp_mbox_open(&adsp_com_mbox, &com_mid, "adsp_com_mbox", - NULL, NULL); + ret = nvadsp_handle->mbox_open(nvadsp_handle, &priv->adsp_com_mbox, + &com_mid, "adsp_com_mbox", NULL, NULL); if (ret) { dev_err(dev, "failed to open adsp com mbox\n"); goto end; } - INIT_WORK(&priv.restart_os_work, nvadsp_os_restart); - mutex_init(&priv.fw_load_lock); - mutex_init(&priv.os_run_lock); + INIT_WORK(&priv->restart_os_work, nvadsp_os_restart); + mutex_init(&priv->fw_load_lock); + mutex_init(&priv->os_run_lock); - priv.pdev = pdev; + priv->pdev = pdev; #ifdef CONFIG_DEBUG_FS - priv.logger.dev = &pdev->dev; - if (adsp_create_debug_logger(drv_data->adsp_debugfs_root)) + priv->logger.dev = &pdev->dev; + if (adsp_create_debug_logger(priv, drv_data->adsp_debugfs_root)) dev_err(dev, "unable to create adsp debug logger file\n"); - priv.console.dev = &pdev->dev; - if (adsp_create_cnsl(drv_data->adsp_debugfs_root, &priv.console)) + priv->console.dev = &pdev->dev; + if (adsp_create_cnsl(drv_data->adsp_debugfs_root, &priv->console)) dev_err(dev, "unable to create adsp console file\n"); - if (adsp_create_os_version(drv_data->adsp_debugfs_root)) + if (adsp_create_os_version(priv, drv_data->adsp_debugfs_root)) dev_err(dev, "unable to create adsp_version file\n"); - if (adsp_create_adsp_health(drv_data->adsp_debugfs_root)) + if (adsp_create_adsp_health(priv, drv_data->adsp_debugfs_root)) dev_err(dev, "unable to create adsp_health file\n"); drv_data->adsp_crashed = false; @@ -2687,5 +2737,17 @@ int __init nvadsp_os_probe(struct platform_device *pdev) devm_tegrafw_register(dev, NULL, TFW_DONT_CACHE, tegrafw_read_adsp, NULL); end: + if (ret == 0) { + nvadsp_handle->get_os_version = _nvadsp_get_os_version; + nvadsp_handle->os_load = _nvadsp_os_load; + nvadsp_handle->os_start = _nvadsp_os_start; + nvadsp_handle->os_suspend = _nvadsp_os_suspend; + nvadsp_handle->os_stop = _nvadsp_os_stop; + nvadsp_handle->set_adma_dump_reg = _nvadsp_set_adma_dump_reg; + nvadsp_handle->dump_adsp_sys = _nvadsp_dump_adsp_sys; + nvadsp_handle->alloc_coherent = _nvadsp_alloc_coherent; + nvadsp_handle->free_coherent = _nvadsp_free_coherent; + } + return ret; } diff --git a/drivers/platform/tegra/nvadsp/os.h b/drivers/platform/tegra/nvadsp/os.h index f8e16c46..48c4b379 100644 --- a/drivers/platform/tegra/nvadsp/os.h +++ b/drivers/platform/tegra/nvadsp/os.h @@ -168,11 +168,12 @@ static inline int nvadsp_os_init(struct platform_device *pdev) int nvadsp_os_probe(struct platform_device *); int nvadsp_app_module_probe(struct platform_device *); -void *nvadsp_da_to_va_mappings(u64 da, int len); -int nvadsp_add_load_mappings(phys_addr_t pa, void *mapping, int len); +void *nvadsp_da_to_va_mappings(struct nvadsp_drv_data *, u64 da, int len); +int nvadsp_add_load_mappings(struct nvadsp_drv_data *, + phys_addr_t pa, void *mapping, int len); struct elf32_shdr *nvadsp_get_section(const struct firmware *, char *); -struct global_sym_info *find_global_symbol(const char *); -void update_nvadsp_app_shared_ptr(void *); +struct global_sym_info *find_global_symbol(struct nvadsp_drv_data *, + const char *); struct adsp_module *load_adsp_dynamic_module(const char *, const char *, struct device *); @@ -180,7 +181,6 @@ struct adsp_module *load_adsp_static_module(const char *, struct adsp_shared_app *, struct device *); void unload_adsp_module(struct adsp_module *); -int allocate_memory_from_adsp(void **, unsigned int); -bool is_adsp_dram_addr(u64); -int load_adsp_static_apps(void); +int load_adsp_static_apps(struct nvadsp_drv_data *); + #endif /* __TEGRA_NVADSP_OS_H */ diff --git a/include/linux/tegra_nvadsp.h b/include/linux/tegra_nvadsp.h index fe3cfd16..efa75ab0 100644 --- a/include/linux/tegra_nvadsp.h +++ b/include/linux/tegra_nvadsp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /** - * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. */ #ifndef __LINUX_TEGRA_NVADSP_H @@ -16,11 +16,6 @@ #include #include -struct nvadsp_platform_data { - phys_addr_t co_pa; - unsigned long co_size; -}; - typedef int status_t; /* @@ -83,32 +78,13 @@ struct nvadsp_mbox { char name[NVADSP_MBOX_NAME_MAX_STR]; struct nvadsp_mbox_queue recv_queue; nvadsp_mbox_handler_t handler; -#ifdef CONFIG_MBOX_ACK_HANDLER nvadsp_mbox_handler_t ack_handler; -#endif void *hdata; }; #define NVADSP_MBOX_SMSG 0x1 #define NVADSP_MBOX_LMSG 0x2 -status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid, - const char *name, nvadsp_mbox_handler_t handler, - void *hdata); -status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data, - uint32_t flags, bool block, unsigned int timeout); -status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block, - unsigned int timeout); -status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox); - -#ifdef CONFIG_MBOX_ACK_HANDLER -static inline void register_ack_handler(struct nvadsp_mbox *mbox, - nvadsp_mbox_handler_t handler) -{ - mbox->ack_handler = handler; -} -#endif - /* * Circular Message Queue */ @@ -142,54 +118,12 @@ int32_t msgq_queue_message(msgq_t *msgq, const msgq_message_t *message); int32_t msgq_dequeue_message(msgq_t *msgq, msgq_message_t *message); #define msgq_discard_message(msgq) msgq_dequeue_message(msgq, NULL) -/* - * DRAM Sharing - */ -typedef dma_addr_t nvadsp_iova_addr_t; -typedef enum dma_data_direction nvadsp_data_direction_t; - -nvadsp_iova_addr_t -nvadsp_dram_map_single(struct device *nvadsp_dev, - void *cpu_addr, size_t size, - nvadsp_data_direction_t direction); -void -nvadsp_dram_unmap_single(struct device *nvadsp_dev, - nvadsp_iova_addr_t iova_addr, size_t size, - nvadsp_data_direction_t direction); - -nvadsp_iova_addr_t -nvadsp_dram_map_page(struct device *nvadsp_dev, - struct page *page, unsigned long offset, size_t size, - nvadsp_data_direction_t direction); -void -nvadsp_dram_unmap_page(struct device *nvadsp_dev, - nvadsp_iova_addr_t iova_addr, size_t size, - nvadsp_data_direction_t direction); - -void -nvadsp_dram_sync_single_for_cpu(struct device *nvadsp_dev, - nvadsp_iova_addr_t iova_addr, size_t size, - nvadsp_data_direction_t direction); -void -nvadsp_dram_sync_single_for_device(struct device *nvadsp_dev, - nvadsp_iova_addr_t iova_addr, size_t size, - nvadsp_data_direction_t direction); - /* * ADSP OS */ typedef const void *nvadsp_os_handle_t; -void nvadsp_adsp_init(void); -int __must_check nvadsp_os_load(void); -int __must_check nvadsp_os_start(void); -void nvadsp_os_stop(void); -int __must_check nvadsp_os_suspend(void); -void dump_adsp_sys(void); -void nvadsp_get_os_version(char *, int); -int adsp_usage_set(unsigned int val); -unsigned int adsp_usage_get(void); /* * ADSP TSC */ @@ -287,71 +221,6 @@ typedef struct nvadsp_app_info { void *priv; } nvadsp_app_info_t; -nvadsp_app_handle_t __must_check nvadsp_app_load(const char *, const char *); -nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t, - nvadsp_app_args_t *); -void nvadsp_app_unload(nvadsp_app_handle_t); -int __must_check nvadsp_app_start(nvadsp_app_info_t *); -int nvadsp_app_stop(nvadsp_app_info_t *); -int nvadsp_app_deinit(nvadsp_app_info_t *); -void *nvadsp_alloc_coherent(size_t, dma_addr_t *, gfp_t); -void nvadsp_free_coherent(size_t, void *, dma_addr_t); -nvadsp_app_info_t __must_check *nvadsp_run_app(nvadsp_os_handle_t, const char *, - nvadsp_app_args_t *, app_complete_status_notifier, - uint32_t, uint32_t, bool); -void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate); - -static inline void -set_app_complete_notifier( - nvadsp_app_info_t *info, app_complete_status_notifier notifier) -{ - info->complete_status_notifier = notifier; -} - -static inline void wait_for_nvadsp_app_complete(nvadsp_app_info_t *info) -{ - /* - * wait_for_complete must be called only after app has started - */ - if (info->state == NVADSP_APP_STATE_STARTED) - wait_for_completion(&info->wait_for_app_complete); -} - -/** - * wait_for_nvadsp_app_complete_timeout: - * @info: pointer to nvadsp_app_info_t - * @timeout: timeout value in jiffies - * - * This waits for either a completion of a specific app to be signaled or for a - * specified timeout to expire. It is interruptible. The timeout is in jiffies. - * - * The return value is -ERESTARTSYS if interrupted, 0 if timed out, - * positive (at least 1, or number of jiffies left till timeout) if completed. - */ -static inline long wait_for_nvadsp_app_complete_timeout(nvadsp_app_info_t *info, - unsigned long timeout) -{ - int ret = -EINVAL; - /* - * wait_for_complete must be called only after app has started - */ - if (info->state == NVADSP_APP_STATE_STARTED) - ret = wait_for_completion_interruptible_timeout( - &info->wait_for_app_complete, timeout); - - return ret; -} - -/* - * set adma reg dump callback function pointer - * @cb_adma_regdump: function pointer for callback - * - * This api is exported and can be accessed by adsp audio driver, - * which during adsp init, calls this api to set the callback - * function pointer - */ -void nvadsp_set_adma_dump_reg(void (*cb_adma_regdump)(void)); - #ifdef CONFIG_TEGRA_ADSP_DFS /* * Override adsp freq and reinit actmon counters @@ -384,10 +253,284 @@ static inline void adsp_update_dfs(bool enable) } #endif -void *nvadsp_aram_request(const char *name, size_t size); -bool nvadsp_aram_release(void *handle); +void *nvadsp_aram_request(void *aram_handle, const char *name, size_t size); +bool nvadsp_aram_release(void *aram_handle, void *handle); unsigned long nvadsp_aram_get_address(void *handle); -void nvadsp_aram_print(void); +void nvadsp_aram_print(void *aram_handle); + +int adsp_usage_set(unsigned int val); +unsigned int adsp_usage_get(void); + + +/* Multi-instance capable interface - START */ + +/** + * nvadsp_get_handle: Fetch driver instance using unique identfier + * + * @dev_str : Unique identifier string for the driver instance + * (trailing unique identifer in compatible DT property, + * e.g. "adsp", "adsp1", etc.) + * + * Return : Driver instance handle on success, else NULL + */ +struct nvadsp_handle *nvadsp_get_handle(const char *dev_str); + +/** + * struct nvadsp_handle: + * - Function interfaces exposed on the driver handle + * - First argument to each API is the handle + * returned from nvadsp_get_handle() + */ +struct nvadsp_handle { + /* Mailbox interfaces */ + status_t (*mbox_open)(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, + uint16_t *mid, const char *name, + nvadsp_mbox_handler_t handler, void *hdata); + status_t (*mbox_close)(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox); + status_t (*mbox_send)(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, uint32_t data, + uint32_t flags, bool block, unsigned int timeout); + status_t (*mbox_recv)(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, uint32_t *data, + bool block, unsigned int timeout); + void (*mbox_set_ack_handler)(struct nvadsp_handle *nvadsp_handle, + struct nvadsp_mbox *mbox, + nvadsp_mbox_handler_t handler); + + /* OS interfaces */ + void (*get_os_version)(struct nvadsp_handle *nvadsp_handle, + char *buf, int buf_size); + int (*os_load)(struct nvadsp_handle *nvadsp_handle); + int (*os_start)(struct nvadsp_handle *nvadsp_handle); + int (*os_suspend)(struct nvadsp_handle *nvadsp_handle); + void (*os_stop)(struct nvadsp_handle *nvadsp_handle); + + /* Debug interfaces */ + void (*set_adma_dump_reg)(struct nvadsp_handle *nvadsp_handle, + void (*cb_adma_regdump)(void)); + void (*dump_adsp_sys)(struct nvadsp_handle *nvadsp_handle); + + /* Memory interfaces */ + void *(*alloc_coherent)(struct nvadsp_handle *nvadsp_handle, + size_t size, dma_addr_t *da, gfp_t flags); + void (*free_coherent)(struct nvadsp_handle *nvadsp_handle, + size_t size, void *va, dma_addr_t da); + + /* App interfaces */ + nvadsp_app_handle_t (*app_load)(struct nvadsp_handle *nvadsp_handle, + const char *appname, const char *appfile); + nvadsp_app_info_t *(*app_init)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_handle_t handle, nvadsp_app_args_t *args); + int (*app_start)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app); + nvadsp_app_info_t *(*run_app)(struct nvadsp_handle *nvadsp_handle, + nvadsp_os_handle_t os_handle, + const char *appfile, nvadsp_app_args_t *app_args, + app_complete_status_notifier notifier, uint32_t stack_sz, + uint32_t core_id, bool block); + int (*app_stop)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app); + int (*app_deinit)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app); + void (*exit_app)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *app, bool terminate); + void (*app_unload)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_handle_t handle); + void (*set_app_complete_cb)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info, app_complete_status_notifier notifier); + void (*wait_for_app_complete)(struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info); + long (*wait_for_app_complete_timeout)( + struct nvadsp_handle *nvadsp_handle, + nvadsp_app_info_t *info, unsigned long timeout); +}; + +/* Multi-instance capable interface - END */ + + +/* Legacy interface - START (works if only one driver instance is probed) */ + +static inline status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, + uint16_t *mid, const char *name, + nvadsp_mbox_handler_t handler, void *hdata) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->mbox_open(h, mbox, mid, name, handler, hdata); +} + +static inline status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->mbox_close(h, mbox); +} + +static inline status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, + uint32_t data, uint32_t flags, + bool block, unsigned int timeout) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->mbox_send(h, mbox, data, flags, block, timeout); +} + +static inline status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, + uint32_t *data, bool block, + unsigned int timeout) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->mbox_recv(h, mbox, data, block, timeout); +} + +static inline void register_ack_handler(struct nvadsp_mbox *mbox, + nvadsp_mbox_handler_t handler) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->mbox_set_ack_handler(h, mbox, handler); +} + +static inline void nvadsp_get_os_version(char *buf, int buf_size) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->get_os_version(h, buf, buf_size); +} + +static inline int nvadsp_os_load(void) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->os_load(h); +} + +static inline int nvadsp_os_start(void) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->os_start(h); +} + +static inline int nvadsp_os_suspend(void) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->os_suspend(h); +} + +static inline void nvadsp_os_stop(void) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->os_stop(h); +} + +static inline void nvadsp_set_adma_dump_reg(void (*cb_adma_regdump)(void)) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->set_adma_dump_reg(h, cb_adma_regdump); +} + +static inline void dump_adsp_sys(void) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->dump_adsp_sys(h); +} + +static inline void *nvadsp_alloc_coherent( + size_t size, dma_addr_t *da, gfp_t flags) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->alloc_coherent(h, size, da, flags); +} + +static inline void nvadsp_free_coherent(size_t size, void *va, dma_addr_t da) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->free_coherent(h, size, va, da); +} + +static inline nvadsp_app_handle_t nvadsp_app_load( + const char *appname, const char *appfile) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_load(h, appname, appfile); +} + +static inline nvadsp_app_info_t *nvadsp_app_init( + nvadsp_app_handle_t handle, nvadsp_app_args_t *args) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_init(h, handle, args); +} + +static inline int nvadsp_app_start(nvadsp_app_info_t *app) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_start(h, app); +} + +static inline 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, uint32_t core_id, bool block) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->run_app(h, os_handle, appfile, app_args, + notifier, stack_sz, core_id, block); +} + +static inline int nvadsp_app_stop(nvadsp_app_info_t *app) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_stop(h, app); +} + +static inline int nvadsp_app_deinit(nvadsp_app_info_t *app) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_deinit(h, app); +} + +static inline void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->exit_app(h, app, terminate); +} + +static inline void nvadsp_app_unload(nvadsp_app_handle_t handle) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->app_unload(h, handle); +} + +static inline void set_app_complete_notifier( + nvadsp_app_info_t *info, + app_complete_status_notifier notifier) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->set_app_complete_cb(h, info, notifier); +} + +static inline void wait_for_nvadsp_app_complete(nvadsp_app_info_t *info) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->wait_for_app_complete(h, info); +} + +/** + * wait_for_nvadsp_app_complete_timeout: + * @info: pointer to nvadsp_app_info_t + * @timeout: timeout value in jiffies + * + * This waits for either a completion of a specific app to be signaled or for a + * specified timeout to expire. It is interruptible. The timeout is in jiffies. + * + * The return value is -ERESTARTSYS if interrupted, 0 if timed out, + * positive (at least 1, or number of jiffies left till timeout) if completed. + */ +static inline long wait_for_nvadsp_app_complete_timeout( + nvadsp_app_info_t *info, unsigned long timeout) +{ + struct nvadsp_handle *h = nvadsp_get_handle(""); + return h->wait_for_app_complete_timeout(h, info, timeout); +} + +/* Legacy interface - END */ #endif /* __LINUX_TEGRA_NVADSP_H */