mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 02:01:36 +03:00
nvadsp: Add multi-instance support
ADSP host driver is enhanced to be multi-instance
capable and reentrant:
- Trailing unique identifier string in compatible DT property, like
"adsp", "adsp1" or "aon", is used to identify the driver instances
- Each probed driver instance is inserted into a global list, from
which the handle can be fetched using 'nvadsp_get_handle' API
(passing the above unique identifier as argument)
- Above unique identifier is also used as name for the DBFS
directory (containing files like adsp_console, adsp_logger, etc.)
- 'nvadsp_get_handle' is the only exported API; all other APIs are
accessible via function pointers within 'struct nvadsp_handle'
- APIs above maintain one-is-to-one correspondence with all
legacy APIs, with the addition of a new argument
'struct nvadsp_handle *' at the beginning
- Legacy APIs continue to be supported, but they are hardwired to
work only if the kernel probes just one driver instance
- All driver files are cleaned up to not use any global state
variables (necessary for reentrancy)
Bug 3682950
Change-Id: Id5db49e861b2f81716ae8352b36b406654da2bbd
Signed-off-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3092701
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
9458d6b97f
commit
e2a1904d46
@@ -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 <linux/module.h>
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user