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:
Viswanath L
2024-03-08 21:07:39 +00:00
committed by mobile promotions
parent 9458d6b97f
commit e2a1904d46
17 changed files with 1332 additions and 862 deletions

View File

@@ -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: