mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +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.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_TEGRA_NVADSP_H
|
||||
@@ -16,11 +16,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
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 */
|
||||
|
||||
Reference in New Issue
Block a user