mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
DCE-KMD: Refactor dce-os-worker.c/.h
- dce-os-worker.c/.h module exposes functionality which allows
DCE KMD clients to wait/signal events.
- The current abstraction of this module has following drawbacks
which this change attempts to address:
* Name: dce-os-worker is a misnomer
- Rename to dce-wait-cond.c/.h and make it a dce-kmd core file.
- Rename functions accordingly.
* dce-os-worker module initializes data structures from tegra_dce
which makes it ineligible for re-use.
- dce-client-ipc can re-use this module as it uses exact
same functionality.
- But this module is tied with DCE-KMD core such that it has
functions that operate on fixed known inputs.
- dce_os_work_cond_sw_resource_init/deinit()
Inits/Deinits most but not all condition var resources
from tegra_dce. Eg. dce-client-ipc resources
are not initialized.
- Move this function to new core file:dce-waiters.c
- All other functions require msg_id as input and can only
operate on DCE_WAIT* resources making it ineligible
to be used by other clients like dce-client-ipc.
- Refactor these fucntions to operate on
individual wait conditions so that all DCE-KMD
core modules can reuse them.
- Additionally, this change will also remove unused functions
and macros from dce-os-cond.c/.h
- dce-client-ipc will also switch to use dce-wait-cond interface
for client ipc waits.
- Make dce-os-cond.h a common file and move OS specific impl
to dce-os-cond-internal.h
JIRA TDS-16581
Change-Id: Ie8c6ec724e48cde66917fab4aa43e7da464ef8fb
Signed-off-by: anupamg <anupamg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3258562
Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com>
Reviewed-by: Arun Swain <arswain@nvidia.com>
This commit is contained in:
@@ -22,7 +22,8 @@ tegra-dce-$(CONFIG_TEGRA_DCE) += dce-ast.o
|
|||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-reset.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-reset.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-smb.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-smb.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-ss.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-ss.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-worker.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-wait-cond.o
|
||||||
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-waiters.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-fsm.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-fsm.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-init-deinit.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-init-deinit.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-mailbox.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-mailbox.o
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ int dce_admin_ipc_wait(struct tegra_dce *d)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ret = dce_os_wait_interruptible(d, DCE_WAIT_ADMIN_IPC);
|
ret = dce_wait_cond_wait_interruptible(d, &d->ipc_waits[DCE_WAIT_ADMIN_IPC], true, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/**
|
/**
|
||||||
* TODO: Add error handling for abort and retry
|
* TODO: Add error handling for abort and retry
|
||||||
@@ -623,7 +623,7 @@ int dce_admin_handle_ipc_received_event(struct tegra_dce *d, void *params)
|
|||||||
{
|
{
|
||||||
DCE_WARN_ON_NOT_NULL(params);
|
DCE_WARN_ON_NOT_NULL(params);
|
||||||
|
|
||||||
dce_os_wakeup_interruptible(d, DCE_WAIT_ADMIN_IPC);
|
dce_wait_cond_signal_interruptible(d, &d->ipc_waits[DCE_WAIT_ADMIN_IPC]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,7 +833,7 @@ int dce_admin_send_enter_sc7(struct tegra_dce *d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for SC7 Enter done */
|
/* Wait for SC7 Enter done */
|
||||||
ret = dce_os_wait_interruptible(d, DCE_WAIT_SC7_ENTER);
|
ret = dce_wait_cond_wait_interruptible(d, &d->ipc_waits[DCE_WAIT_SC7_ENTER], true, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dce_os_err(d, "SC7 Enter wait was interrupted with err:%d", ret);
|
dce_os_err(d, "SC7 Enter wait was interrupted with err:%d", ret);
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ int dce_handle_boot_cmd_received_event(struct tegra_dce *d, void *params)
|
|||||||
{
|
{
|
||||||
DCE_WARN_ON_NOT_NULL(params);
|
DCE_WARN_ON_NOT_NULL(params);
|
||||||
|
|
||||||
dce_os_wakeup_interruptible(d, DCE_WAIT_BOOT_CMD);
|
dce_wait_cond_signal_interruptible(d, &d->ipc_waits[DCE_WAIT_BOOT_CMD]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ int dce_handle_boot_complete_requested_event(struct tegra_dce *d, void *params)
|
|||||||
if (ret)
|
if (ret)
|
||||||
dce_os_err(d, "failed to send DCE_BOOT_COMPLETE_RECEIVED event");
|
dce_os_err(d, "failed to send DCE_BOOT_COMPLETE_RECEIVED event");
|
||||||
|
|
||||||
dce_os_cond_wait_reset(d, DCE_WAIT_BOOT_COMPLETE);
|
dce_wait_cond_reset(d, &d->ipc_waits[DCE_WAIT_BOOT_COMPLETE]);
|
||||||
goto boot_done;
|
goto boot_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ int dce_handle_boot_complete_requested_event(struct tegra_dce *d, void *params)
|
|||||||
|
|
||||||
dce_os_debug(d, "Waiting for dce fw to boot...");
|
dce_os_debug(d, "Waiting for dce fw to boot...");
|
||||||
|
|
||||||
ret = dce_os_wait_interruptible(d, DCE_WAIT_BOOT_COMPLETE);
|
ret = dce_wait_cond_wait_interruptible(d, &d->ipc_waits[DCE_WAIT_BOOT_COMPLETE], true, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/**
|
/**
|
||||||
* TODO: Add error handling for abort and retry
|
* TODO: Add error handling for abort and retry
|
||||||
@@ -139,7 +139,7 @@ int dce_handle_boot_complete_received_event(struct tegra_dce *d, void *params)
|
|||||||
{
|
{
|
||||||
DCE_WARN_ON_NOT_NULL(params);
|
DCE_WARN_ON_NOT_NULL(params);
|
||||||
|
|
||||||
dce_os_wakeup_interruptible(d, DCE_WAIT_BOOT_COMPLETE);
|
dce_wait_cond_signal_interruptible(d, &d->ipc_waits[DCE_WAIT_BOOT_COMPLETE]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ static void dce_handle_irq_status(struct tegra_dce *d, u32 status)
|
|||||||
|
|
||||||
if (status & DCE_IRQ_LOG_READY) {
|
if (status & DCE_IRQ_LOG_READY) {
|
||||||
dce_os_info(d, "DCE trace log buffers available");
|
dce_os_info(d, "DCE trace log buffers available");
|
||||||
dce_os_wakeup_interruptible(d, DCE_WAIT_LOG);
|
dce_wait_cond_signal_interruptible(d, &d->ipc_waits[DCE_WAIT_LOG]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -370,7 +370,7 @@ static int dce_mailbox_wait_boot_interface(struct tegra_dce *d)
|
|||||||
u32 status;
|
u32 status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dce_os_wait_interruptible(d, DCE_WAIT_BOOT_CMD);
|
ret = dce_wait_cond_wait_interruptible(d, &d->ipc_waits[DCE_WAIT_BOOT_CMD], true, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/**
|
/**
|
||||||
* TODO: Add error handling for abort and retry
|
* TODO: Add error handling for abort and retry
|
||||||
|
|||||||
@@ -180,9 +180,8 @@ int tegra_dce_register_ipc_client(u32 type,
|
|||||||
cl->handle = handle;
|
cl->handle = handle;
|
||||||
cl->int_type = int_type;
|
cl->int_type = int_type;
|
||||||
cl->callback_fn = callback_fn;
|
cl->callback_fn = callback_fn;
|
||||||
dce_os_atomic_set(&cl->complete, 0);
|
|
||||||
|
|
||||||
ret = dce_os_cond_init(&cl->recv_wait);
|
ret = dce_wait_cond_init(d, &cl->recv_wait);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dce_os_err(d, "dce condition initialization failed for int_type: [%u]",
|
dce_os_err(d, "dce condition initialization failed for int_type: [%u]",
|
||||||
int_type);
|
int_type);
|
||||||
@@ -213,8 +212,7 @@ int tegra_dce_unregister_ipc_client(u32 handle)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dce_os_cond_destroy(&cl->recv_wait);
|
dce_wait_cond_deinit(cl->d, &cl->recv_wait);
|
||||||
dce_os_atomic_set(&cl->complete, 0);
|
|
||||||
|
|
||||||
return dce_client_ipc_handle_free(cl);
|
return dce_client_ipc_handle_free(cl);
|
||||||
}
|
}
|
||||||
@@ -302,30 +300,38 @@ int dce_client_ipc_wait(struct tegra_dce *d, u32 int_type)
|
|||||||
{
|
{
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
struct tegra_dce_client_ipc *cl;
|
struct tegra_dce_client_ipc *cl;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
type = dce_client_get_type(int_type);
|
type = dce_client_get_type(int_type);
|
||||||
if (type >= DCE_CLIENT_IPC_TYPE_MAX) {
|
if (type >= DCE_CLIENT_IPC_TYPE_MAX) {
|
||||||
dce_os_err(d, "Failed to retrieve client info for int_type: [%d]",
|
dce_os_err(d, "Failed to retrieve client info for int_type: [%d]",
|
||||||
int_type);
|
int_type);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl = d->d_clients[type];
|
cl = d->d_clients[type];
|
||||||
if ((cl == NULL) || (cl->int_type != int_type)) {
|
if ((cl == NULL) || (cl->int_type != int_type)) {
|
||||||
dce_os_err(d, "Failed to retrieve client info for int_type: [%d]",
|
dce_os_err(d, "Failed to retrieve client info for int_type: [%d]",
|
||||||
int_type);
|
int_type);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
retry_wait:
|
retry_wait:
|
||||||
DCE_OS_COND_WAIT_INTERRUPTIBLE(&cl->recv_wait,
|
ret = dce_wait_cond_wait_interruptible(d, &cl->recv_wait, true, 0);
|
||||||
dce_os_atomic_read(&cl->complete) == 1);
|
if (ret) {
|
||||||
if (dce_os_atomic_read(&cl->complete) != 1)
|
if (ret == -ERESTARTSYS) { /* Interrupt. */
|
||||||
|
dce_os_debug(d, "Client [%u] wait interrupted: retrying.", type);
|
||||||
goto retry_wait;
|
goto retry_wait;
|
||||||
|
} else { /* Unexpected error. */
|
||||||
|
dce_os_err(d, "Client [%u] unexpected err: [%d]", type, ret);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dce_os_atomic_set(&cl->complete, 0);
|
fail:
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dce_client_process_event_ipc(struct tegra_dce *d,
|
static void dce_client_process_event_ipc(struct tegra_dce *d,
|
||||||
@@ -417,6 +423,5 @@ void dce_client_ipc_wakeup(struct tegra_dce *d, u32 ch_type)
|
|||||||
if (type == DCE_CLIENT_IPC_TYPE_RM_EVENT)
|
if (type == DCE_CLIENT_IPC_TYPE_RM_EVENT)
|
||||||
return dce_client_schedule_event_work(d);
|
return dce_client_schedule_event_work(d);
|
||||||
|
|
||||||
dce_os_atomic_set(&cl->complete, 1);
|
dce_wait_cond_signal_interruptible(d, &cl->recv_wait);
|
||||||
dce_os_cond_signal_interruptible(&cl->recv_wait);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dce.h>
|
#include <dce.h>
|
||||||
@@ -71,7 +71,7 @@ int dce_driver_init(struct tegra_dce *d)
|
|||||||
goto err_pm_init;
|
goto err_pm_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dce_os_work_cond_sw_resource_init(d);
|
ret = dce_waiters_init(d);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dce_os_err(d, "dce sw resource init failed");
|
dce_os_err(d, "dce sw resource init failed");
|
||||||
goto err_sw_init;
|
goto err_sw_init;
|
||||||
@@ -86,7 +86,7 @@ int dce_driver_init(struct tegra_dce *d)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_fsm_init:
|
err_fsm_init:
|
||||||
dce_os_work_cond_sw_resource_deinit(d);
|
dce_waiters_deinit(d);
|
||||||
err_sw_init:
|
err_sw_init:
|
||||||
dce_pm_deinit(d);
|
dce_pm_deinit(d);
|
||||||
err_pm_init:
|
err_pm_init:
|
||||||
@@ -115,7 +115,7 @@ void dce_driver_deinit(struct tegra_dce *d)
|
|||||||
|
|
||||||
dce_fsm_deinit_unlocked(d);
|
dce_fsm_deinit_unlocked(d);
|
||||||
|
|
||||||
dce_os_work_cond_sw_resource_deinit(d);
|
dce_waiters_deinit(d);
|
||||||
|
|
||||||
dce_pm_deinit(d);
|
dce_pm_deinit(d);
|
||||||
|
|
||||||
|
|||||||
@@ -272,13 +272,6 @@ void dce_os_log_msg(struct tegra_dce *d, const char *func_name, int line,
|
|||||||
dce_print(func_name, line, type, log);
|
dce_print(func_name, line, type, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_init - Initialize a condition variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to initialize
|
|
||||||
*
|
|
||||||
* Initialize a condition variable before using it.
|
|
||||||
*/
|
|
||||||
int dce_os_cond_init(struct dce_os_cond *cond)
|
int dce_os_cond_init(struct dce_os_cond *cond)
|
||||||
{
|
{
|
||||||
init_waitqueue_head(&cond->wq);
|
init_waitqueue_head(&cond->wq);
|
||||||
@@ -287,43 +280,11 @@ int dce_os_cond_init(struct dce_os_cond *cond)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_destroy - Destroy a condition variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to destroy
|
|
||||||
*/
|
|
||||||
void dce_os_cond_destroy(struct dce_os_cond *cond)
|
void dce_os_cond_destroy(struct dce_os_cond *cond)
|
||||||
{
|
{
|
||||||
cond->initialized = false;
|
cond->initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_signal - Signal a condition variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to signal
|
|
||||||
*
|
|
||||||
* Wake up a waiter for a condition variable to check if its condition has been
|
|
||||||
* satisfied.
|
|
||||||
*
|
|
||||||
* The waiter is using an uninterruptible wait.
|
|
||||||
*/
|
|
||||||
void dce_os_cond_signal(struct dce_os_cond *cond)
|
|
||||||
{
|
|
||||||
WARN_ON(!cond->initialized);
|
|
||||||
|
|
||||||
wake_up(&cond->wq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_signal_interruptible - Signal a condition variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to signal
|
|
||||||
*
|
|
||||||
* Wake up a waiter for a condition variable to check if its condition has been
|
|
||||||
* satisfied.
|
|
||||||
*
|
|
||||||
* The waiter is using an interruptible wait.
|
|
||||||
*/
|
|
||||||
void dce_os_cond_signal_interruptible(struct dce_os_cond *cond)
|
void dce_os_cond_signal_interruptible(struct dce_os_cond *cond)
|
||||||
{
|
{
|
||||||
WARN_ON(!cond->initialized);
|
WARN_ON(!cond->initialized);
|
||||||
@@ -331,37 +292,6 @@ void dce_os_cond_signal_interruptible(struct dce_os_cond *cond)
|
|||||||
wake_up_interruptible(&cond->wq);
|
wake_up_interruptible(&cond->wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_broadcast - Signal all waiters of a condition variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to signal
|
|
||||||
*
|
|
||||||
* Wake up all waiters for a condition variable to check if their conditions
|
|
||||||
* have been satisfied.
|
|
||||||
*
|
|
||||||
* The waiters are using an uninterruptible wait.
|
|
||||||
*/
|
|
||||||
int dce_os_cond_broadcast(struct dce_os_cond *cond)
|
|
||||||
{
|
|
||||||
if (!cond->initialized)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
wake_up_all(&cond->wq);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_cond_broadcast_interruptible - Signal all waiters of a condition
|
|
||||||
* variable
|
|
||||||
*
|
|
||||||
* @cond - The condition variable to signal
|
|
||||||
*
|
|
||||||
* Wake up all waiters for a condition variable to check if their conditions
|
|
||||||
* have been satisfied.
|
|
||||||
*
|
|
||||||
* The waiters are using an interruptible wait.
|
|
||||||
*/
|
|
||||||
int dce_os_cond_broadcast_interruptible(struct dce_os_cond *cond)
|
int dce_os_cond_broadcast_interruptible(struct dce_os_cond *cond)
|
||||||
{
|
{
|
||||||
if (!cond->initialized)
|
if (!cond->initialized)
|
||||||
|
|||||||
@@ -1,163 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dce.h>
|
|
||||||
#include <dce-os-cond.h>
|
|
||||||
#include <dce-os-lock.h>
|
|
||||||
#include <dce-os-worker.h>
|
|
||||||
#include <dce-os-utils.h>
|
|
||||||
#include <interface/dce-admin-cmds.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dce_os_wait_interruptible : Wait for a given condition
|
|
||||||
*
|
|
||||||
* @d : Pointer to tegra_dce struct.
|
|
||||||
* @msg_id : index of wait condition
|
|
||||||
*
|
|
||||||
* Return : 0 if successful else error code
|
|
||||||
*/
|
|
||||||
int dce_os_wait_interruptible(struct tegra_dce *d, u32 msg_id)
|
|
||||||
{
|
|
||||||
struct dce_wait_cond *wait;
|
|
||||||
|
|
||||||
if (msg_id >= DCE_MAX_WAIT) {
|
|
||||||
dce_os_err(d, "Invalid wait requested %u", msg_id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait = &d->ipc_waits[msg_id];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is possible that we received the ACK from DCE even before we
|
|
||||||
* start waiting. But that should not be an issue as wait->complete
|
|
||||||
* Will be "1" and we immediately exit from the wait.
|
|
||||||
*/
|
|
||||||
DCE_OS_COND_WAIT_INTERRUPTIBLE(&wait->cond_wait,
|
|
||||||
dce_os_atomic_read(&wait->complete) == 1);
|
|
||||||
|
|
||||||
if (dce_os_atomic_read(&wait->complete) != 1)
|
|
||||||
return -EINTR;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear wait->complete as soon as we exit from wait (consume the wake call)
|
|
||||||
* So that when the next dce_os_wait_interruptible is called, it doesn't see old
|
|
||||||
* wait->complete state.
|
|
||||||
*/
|
|
||||||
dce_os_atomic_set(&wait->complete, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dce_os_wakeup_interruptible : Wakeup waiting task on given condition
|
|
||||||
*
|
|
||||||
* @d : Pointer to tegra_dce struct.
|
|
||||||
* @msg_id : index of wait condition
|
|
||||||
*
|
|
||||||
* Return : void
|
|
||||||
*/
|
|
||||||
void dce_os_wakeup_interruptible(struct tegra_dce *d, u32 msg_id)
|
|
||||||
{
|
|
||||||
struct dce_wait_cond *wait;
|
|
||||||
|
|
||||||
if (msg_id >= DCE_MAX_WAIT) {
|
|
||||||
dce_os_err(d, "Invalid wait requested %u", msg_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait = &d->ipc_waits[msg_id];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set wait->complete to "1", so if the wait is called even after
|
|
||||||
* "dce_os_cond_signal_interruptible", it'll see the complete variable
|
|
||||||
* as "1" and exit the wait immediately.
|
|
||||||
*/
|
|
||||||
dce_os_atomic_set(&wait->complete, 1);
|
|
||||||
dce_os_cond_signal_interruptible(&wait->cond_wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dce_os_cond_wait_reset : reset condition wait variable to zero
|
|
||||||
*
|
|
||||||
* @d : Pointer to tegra_dce struct.
|
|
||||||
* @msg_id : index of wait condition
|
|
||||||
*
|
|
||||||
* Return : void
|
|
||||||
*/
|
|
||||||
void dce_os_cond_wait_reset(struct tegra_dce *d, u32 msg_id)
|
|
||||||
{
|
|
||||||
struct dce_wait_cond *wait;
|
|
||||||
|
|
||||||
if (msg_id >= DCE_MAX_WAIT) {
|
|
||||||
dce_os_err(d, "Invalid wait requested %u", msg_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait = &d->ipc_waits[msg_id];
|
|
||||||
dce_os_atomic_set(&wait->complete, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_work_cond_sw_resource_init : Init dce workqueues related resources
|
|
||||||
*
|
|
||||||
* @d : Pointer to tegra_dce struct.
|
|
||||||
*
|
|
||||||
* Return : 0 if successful else error code
|
|
||||||
*/
|
|
||||||
int dce_os_work_cond_sw_resource_init(struct tegra_dce *d)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dce_os_cond_init(&d->dce_bootstrap_done)) {
|
|
||||||
dce_os_err(d, "dce boot wait condition init failed");
|
|
||||||
ret = -1;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < DCE_MAX_WAIT; i++) {
|
|
||||||
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
|
||||||
|
|
||||||
if (dce_os_cond_init(&wait->cond_wait)) {
|
|
||||||
dce_os_err(d, "dce wait condition %d init failed", i);
|
|
||||||
ret = -1;
|
|
||||||
goto init_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
dce_os_atomic_set(&wait->complete, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
init_error:
|
|
||||||
while (i >= 0) {
|
|
||||||
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
|
||||||
|
|
||||||
dce_os_cond_destroy(&wait->cond_wait);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
dce_os_cond_destroy(&d->dce_bootstrap_done);
|
|
||||||
exit:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dce_os_work_cond_sw_resource_deinit : de-init dce workqueues related resources
|
|
||||||
*
|
|
||||||
* @d : Pointer to tegra_dce struct.
|
|
||||||
*
|
|
||||||
* Return : void
|
|
||||||
*/
|
|
||||||
void dce_os_work_cond_sw_resource_deinit(struct tegra_dce *d)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < DCE_MAX_WAIT; i++) {
|
|
||||||
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
|
||||||
|
|
||||||
dce_os_cond_destroy(&wait->cond_wait);
|
|
||||||
dce_os_atomic_set(&wait->complete, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
dce_os_cond_destroy(&d->dce_bootstrap_done);
|
|
||||||
}
|
|
||||||
@@ -101,7 +101,7 @@ int dce_pm_handle_sc7_enter_received_event(struct tegra_dce *d, void *params)
|
|||||||
{
|
{
|
||||||
DCE_WARN_ON_NOT_NULL(params);
|
DCE_WARN_ON_NOT_NULL(params);
|
||||||
|
|
||||||
dce_os_wakeup_interruptible(d, DCE_WAIT_SC7_ENTER);
|
dce_wait_cond_signal_interruptible(d, &d->ipc_waits[DCE_WAIT_SC7_ENTER]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
156
drivers/platform/tegra/dce/dce-wait-cond.c
Normal file
156
drivers/platform/tegra/dce/dce-wait-cond.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dce-os-cond.h>
|
||||||
|
#include <dce-wait-cond.h>
|
||||||
|
#include <dce-os-utils.h>
|
||||||
|
#include <dce-os-log.h>
|
||||||
|
#include <dce.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dce_wait_cond_wait_interruptible : Wait for a given condition
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to init.
|
||||||
|
* @reset : Boolean input to indicate if to reset condition.
|
||||||
|
* If reset is set to true, clear wait->complete as soon as we exit from wait (consume wake).
|
||||||
|
* Client can use this, if they want the next dce_wait_cond_wait_interruptible call to
|
||||||
|
* not see the old wait->complete state.
|
||||||
|
* @timeout_ms : Wait timeout in ms. 0 for no timeout.
|
||||||
|
*
|
||||||
|
* Return : 0 if successful, -ETIMEOUT on timeout, -ERESTARTSYS on interrupt.
|
||||||
|
* -EINVAL if invalid input args.
|
||||||
|
*
|
||||||
|
* Note: Since multiple clients wait on a broadcast event, the user is responsible
|
||||||
|
* to reset the condition only when all clients have consumed the call.
|
||||||
|
*/
|
||||||
|
int dce_wait_cond_wait_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait,
|
||||||
|
bool reset, u32 timeout_ms)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
DCE_WARN_ON_NULL(d);
|
||||||
|
|
||||||
|
if (timeout_ms == 0) {
|
||||||
|
ret = DCE_OS_COND_WAIT_INTERRUPTIBLE(&wait->cond_wait,
|
||||||
|
dce_os_atomic_read(&wait->complete) == 1);
|
||||||
|
} else {
|
||||||
|
ret = DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT(&wait->cond_wait,
|
||||||
|
dce_os_atomic_read(&wait->complete) == 1,
|
||||||
|
timeout_ms);
|
||||||
|
/**
|
||||||
|
* DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT returns remaining jiffies
|
||||||
|
* if condition was evaluated to true before timeout.
|
||||||
|
* Set return value to SUCCESS in this case.
|
||||||
|
*/
|
||||||
|
if (ret > 0)
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip reset if interrupted by a signal or any other error. */
|
||||||
|
if ((ret == 0) && reset)
|
||||||
|
dce_os_atomic_set(&wait->complete, 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dce_wait_cond_signal_interruptible : Wakeup waiting task on given condition
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to init.
|
||||||
|
*
|
||||||
|
* Return : void
|
||||||
|
*/
|
||||||
|
void dce_wait_cond_signal_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait)
|
||||||
|
{
|
||||||
|
DCE_WARN_ON_NULL(d);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set wait->complete to "1", so if the wait is called even after
|
||||||
|
* "dce_os_cond_signal_interruptible", it'll see the complete variable
|
||||||
|
* as "1" and exit the wait immediately.
|
||||||
|
*/
|
||||||
|
dce_os_atomic_set(&wait->complete, 1);
|
||||||
|
dce_os_cond_signal_interruptible(&wait->cond_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dce_wait_cond_reset : reset condition wait variable to zero
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to init.
|
||||||
|
*
|
||||||
|
* Return : void
|
||||||
|
*/
|
||||||
|
void dce_wait_cond_reset(struct tegra_dce *d, struct dce_wait_cond *wait)
|
||||||
|
{
|
||||||
|
DCE_WARN_ON_NULL(d);
|
||||||
|
|
||||||
|
dce_os_atomic_set(&wait->complete, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_wait_cond_init : Init DCE OS wait condition
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to init.
|
||||||
|
*
|
||||||
|
* Return : 0 if successful else error code
|
||||||
|
*/
|
||||||
|
int dce_wait_cond_init(struct tegra_dce *d, struct dce_wait_cond *wait)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (dce_os_cond_init(&wait->cond_wait)) {
|
||||||
|
dce_os_err(d, "dce boot wait condition init failed");
|
||||||
|
ret = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dce_os_atomic_set(&wait->complete, 0);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_wait_cond_deinit : de-init dce workqueues related resources
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to init.
|
||||||
|
*
|
||||||
|
* Return : void
|
||||||
|
*/
|
||||||
|
void dce_wait_cond_deinit(struct tegra_dce *d, struct dce_wait_cond *wait)
|
||||||
|
{
|
||||||
|
DCE_WARN_ON_NULL(d);
|
||||||
|
|
||||||
|
dce_os_atomic_set(&wait->complete, 0);
|
||||||
|
dce_os_cond_destroy(&wait->cond_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_wait_cond_broadcast_interruptible - Signal all waiters of a condition
|
||||||
|
* variable
|
||||||
|
*
|
||||||
|
* @d : Pointer to tegra_dce struct.
|
||||||
|
* @wait : DCE OS wait condition to signal.
|
||||||
|
*
|
||||||
|
* Wake up all waiters for a condition variable.
|
||||||
|
*
|
||||||
|
* The waiters are using an interruptible wait.
|
||||||
|
*/
|
||||||
|
void dce_wait_cond_broadcast_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait)
|
||||||
|
{
|
||||||
|
DCE_WARN_ON_NULL(d);
|
||||||
|
/*
|
||||||
|
* Set wait->complete to "1", so if the wait is called even after
|
||||||
|
* "dce_wait_cond_broadcast_interruptible", it'll see the complete variable
|
||||||
|
* as "1" and exit the wait immediately.
|
||||||
|
*/
|
||||||
|
dce_os_atomic_set(&wait->complete, 1);
|
||||||
|
dce_os_cond_broadcast_interruptible(&wait->cond_wait);
|
||||||
|
}
|
||||||
53
drivers/platform/tegra/dce/dce-waiters.c
Normal file
53
drivers/platform/tegra/dce/dce-waiters.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dce.h>
|
||||||
|
|
||||||
|
int dce_waiters_init(struct tegra_dce *d)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (dce_os_cond_init(&d->dce_bootstrap_done)) {
|
||||||
|
dce_os_err(d, "dce boot wait condition init failed");
|
||||||
|
ret = -1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < DCE_MAX_WAIT; i++) {
|
||||||
|
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
||||||
|
|
||||||
|
if (dce_wait_cond_init(d, wait)) {
|
||||||
|
dce_os_err(d, "dce wait condition %d init failed", i);
|
||||||
|
ret = -1;
|
||||||
|
goto init_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
init_error:
|
||||||
|
while (i >= 0) {
|
||||||
|
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
||||||
|
|
||||||
|
dce_wait_cond_deinit(d, wait);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
dce_os_cond_destroy(&d->dce_bootstrap_done);
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dce_waiters_deinit(struct tegra_dce *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < DCE_MAX_WAIT; i++) {
|
||||||
|
struct dce_wait_cond *wait = &d->ipc_waits[i];
|
||||||
|
|
||||||
|
dce_wait_cond_deinit(d, wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
dce_os_cond_destroy(&d->dce_bootstrap_done);
|
||||||
|
}
|
||||||
@@ -22,8 +22,7 @@
|
|||||||
* @int_type : IPC interface type for above IPC type as defined in CPU driver
|
* @int_type : IPC interface type for above IPC type as defined in CPU driver
|
||||||
* @d : pointer to OS agnostic dce struct. Stores all runtime info for dce
|
* @d : pointer to OS agnostic dce struct. Stores all runtime info for dce
|
||||||
* cluster elements
|
* cluster elements
|
||||||
* @recv_wait : condition variable used for IPC synchronization
|
* @recv_wait : wait condition variable used for IPC synchronization
|
||||||
* @complete : atomic variable used for IPC synchronization
|
|
||||||
* @callback_fn : function pointer to the callback function passed by the
|
* @callback_fn : function pointer to the callback function passed by the
|
||||||
* client during registration
|
* client during registration
|
||||||
*/
|
*/
|
||||||
@@ -34,8 +33,7 @@ struct tegra_dce_client_ipc {
|
|||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
uint32_t int_type;
|
uint32_t int_type;
|
||||||
struct tegra_dce *d;
|
struct tegra_dce *d;
|
||||||
struct dce_os_cond recv_wait;
|
struct dce_wait_cond recv_wait;
|
||||||
dce_os_atomic_t complete;
|
|
||||||
tegra_dce_client_ipc_callback_t callback_fn;
|
tegra_dce_client_ipc_callback_t callback_fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
28
drivers/platform/tegra/dce/include/dce-wait-cond.h
Normal file
28
drivers/platform/tegra/dce/include/dce-wait-cond.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DCE_WAIT_COND_H
|
||||||
|
#define DCE_WAIT_COND_H
|
||||||
|
|
||||||
|
#include <dce-os-cond.h>
|
||||||
|
#include <dce-os-lock.h>
|
||||||
|
#include <dce-os-atomic.h>
|
||||||
|
|
||||||
|
struct tegra_dce;
|
||||||
|
|
||||||
|
struct dce_wait_cond {
|
||||||
|
dce_os_atomic_t complete;
|
||||||
|
struct dce_os_cond cond_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
int dce_wait_cond_init(struct tegra_dce *d, struct dce_wait_cond *wait);
|
||||||
|
void dce_wait_cond_deinit(struct tegra_dce *d, struct dce_wait_cond *wait);
|
||||||
|
int dce_wait_cond_wait_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait,
|
||||||
|
bool reset, u32 timeout_ms);
|
||||||
|
void dce_wait_cond_signal_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait);
|
||||||
|
void dce_wait_cond_reset(struct tegra_dce *d, struct dce_wait_cond *wait);
|
||||||
|
void dce_wait_cond_broadcast_interruptible(struct tegra_dce *d, struct dce_wait_cond *wait);
|
||||||
|
|
||||||
|
#endif /* DCE_WAIT_COND_H */
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <dce-os-lock.h>
|
#include <dce-os-lock.h>
|
||||||
#include <dce-os-cond.h>
|
#include <dce-os-cond.h>
|
||||||
#include <dce-regs.h>
|
#include <dce-regs.h>
|
||||||
#include <dce-os-worker.h>
|
#include <dce-wait-cond.h>
|
||||||
#include <dce-fsm.h>
|
#include <dce-fsm.h>
|
||||||
#include <dce-pm.h>
|
#include <dce-pm.h>
|
||||||
#include <dce-mailbox.h>
|
#include <dce-mailbox.h>
|
||||||
@@ -27,6 +27,13 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define DCE_WARN_ON_NULL(x) \
|
||||||
|
do { \
|
||||||
|
if (x == NULL) { \
|
||||||
|
dce_os_warn(d, "Unexpected NULL value for " #x "\n"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define DCE_MAX_CPU_IRQS 4
|
#define DCE_MAX_CPU_IRQS 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +86,16 @@
|
|||||||
#define DCE_ADMIN_CH_CL_DBG_BUFF_COUNT 1U
|
#define DCE_ADMIN_CH_CL_DBG_BUFF_COUNT 1U
|
||||||
#define DCE_ADMIN_CH_CL_DBG_PERF_BUFF_COUNT 1U
|
#define DCE_ADMIN_CH_CL_DBG_PERF_BUFF_COUNT 1U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DCE Wait condition IDs.
|
||||||
|
*/
|
||||||
|
#define DCE_WAIT_BOOT_COMPLETE 0
|
||||||
|
#define DCE_WAIT_BOOT_CMD 1
|
||||||
|
#define DCE_WAIT_ADMIN_IPC 2
|
||||||
|
#define DCE_WAIT_SC7_ENTER 3
|
||||||
|
#define DCE_WAIT_LOG 4
|
||||||
|
#define DCE_MAX_WAIT 5
|
||||||
|
|
||||||
struct tegra_dce;
|
struct tegra_dce;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -398,6 +415,9 @@ struct dce_ipc_message *dce_admin_channel_client_buffer_get(
|
|||||||
void dce_admin_channel_client_buffer_put(
|
void dce_admin_channel_client_buffer_put(
|
||||||
struct tegra_dce *d, struct dce_ipc_message *pmsg);
|
struct tegra_dce *d, struct dce_ipc_message *pmsg);
|
||||||
|
|
||||||
|
int dce_waiters_init(struct tegra_dce *d);
|
||||||
|
void dce_waiters_deinit(struct tegra_dce *d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions to be used in debug mode only.
|
* Functions to be used in debug mode only.
|
||||||
*
|
*
|
||||||
|
|||||||
82
drivers/platform/tegra/dce/os/include/dce-os-cond.h
Normal file
82
drivers/platform/tegra/dce/os/include/dce-os-cond.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DCE_OS_COND_H
|
||||||
|
#define DCE_OS_COND_H
|
||||||
|
|
||||||
|
#include <dce-os-cond-internal.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DCE_OS_COND_WAIT_INTERRUPTIBLE - Wait for a condition to be true
|
||||||
|
*
|
||||||
|
* @c - The condition variable to sleep on
|
||||||
|
* @condition - The condition that needs to be true
|
||||||
|
*
|
||||||
|
* Wait for a condition to become true. Returns -ERESTARTSYS
|
||||||
|
* on signal.
|
||||||
|
*/
|
||||||
|
#define DCE_OS_COND_WAIT_INTERRUPTIBLE(c, condition) \
|
||||||
|
DCE_OS_COND_WAIT_INTERRUPTIBLE_INTERNAL(c, condition)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT - Wait for a condition to be true
|
||||||
|
*
|
||||||
|
* @c - The condition variable to sleep on
|
||||||
|
* @condition - The condition that needs to be true
|
||||||
|
* @timeout_ms - Timeout in milliseconds, or 0 for infinite wait.
|
||||||
|
* This parameter must be a u32. Since this is a macro, this is
|
||||||
|
* enforced by assigning a typecast NULL pointer to a u32 tmp
|
||||||
|
* variable which will generate a compiler warning (or error if
|
||||||
|
* the warning is configured as an error).
|
||||||
|
*
|
||||||
|
* Wait for a condition to become true. Returns -ETIMEOUT if
|
||||||
|
* the wait timed out with condition false or -ERESTARTSYS on
|
||||||
|
* signal.
|
||||||
|
*/
|
||||||
|
#define DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT(c, condition, timeout_ms) \
|
||||||
|
DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT_INTERNAL(c, condition, timeout_ms)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_os_cond_init - Initialize a condition variable
|
||||||
|
*
|
||||||
|
* @cond - The condition variable to initialize
|
||||||
|
*
|
||||||
|
* Initialize a condition variable before using it.
|
||||||
|
*/
|
||||||
|
int dce_os_cond_init(struct dce_os_cond *cond);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_os_cond_destroy - Destroy a condition variable
|
||||||
|
*
|
||||||
|
* @cond - The condition variable to destroy
|
||||||
|
*/
|
||||||
|
void dce_os_cond_signal_interruptible(struct dce_os_cond *cond);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_os_cond_signal_interruptible - Signal a condition variable
|
||||||
|
*
|
||||||
|
* @cond - The condition variable to signal
|
||||||
|
*
|
||||||
|
* Wake up a waiter for a condition variable to check if its condition has been
|
||||||
|
* satisfied.
|
||||||
|
*
|
||||||
|
* The waiter is using an interruptible wait.
|
||||||
|
*/
|
||||||
|
int dce_os_cond_broadcast_interruptible(struct dce_os_cond *cond);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dce_os_cond_broadcast_interruptible - Signal all waiters of a condition
|
||||||
|
* variable
|
||||||
|
*
|
||||||
|
* @cond - The condition variable to signal
|
||||||
|
*
|
||||||
|
* Wake up all waiters for a condition variable to check if their conditions
|
||||||
|
* have been satisfied.
|
||||||
|
*
|
||||||
|
* The waiters are using an interruptible wait.
|
||||||
|
*/
|
||||||
|
void dce_os_cond_destroy(struct dce_os_cond *cond);
|
||||||
|
|
||||||
|
#endif /* DCE_OS_COND_H */
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DCE_OS_WORKER_H
|
|
||||||
#define DCE_OS_WORKER_H
|
|
||||||
|
|
||||||
#include <dce-os-cond.h>
|
|
||||||
#include <dce-os-lock.h>
|
|
||||||
#include <dce-os-atomic.h>
|
|
||||||
|
|
||||||
struct tegra_dce;
|
|
||||||
|
|
||||||
#define DCE_WAIT_BOOT_COMPLETE 0
|
|
||||||
#define DCE_WAIT_BOOT_CMD 1
|
|
||||||
#define DCE_WAIT_ADMIN_IPC 2
|
|
||||||
#define DCE_WAIT_SC7_ENTER 3
|
|
||||||
#define DCE_WAIT_LOG 4
|
|
||||||
#define DCE_MAX_WAIT 5
|
|
||||||
|
|
||||||
struct dce_wait_cond {
|
|
||||||
dce_os_atomic_t complete;
|
|
||||||
struct dce_os_cond cond_wait;
|
|
||||||
};
|
|
||||||
|
|
||||||
int dce_os_work_cond_sw_resource_init(struct tegra_dce *d);
|
|
||||||
void dce_os_work_cond_sw_resource_deinit(struct tegra_dce *d);
|
|
||||||
int dce_os_wait_interruptible(struct tegra_dce *d, u32 msg_id);
|
|
||||||
void dce_os_wakeup_interruptible(struct tegra_dce *d, u32 msg_id);
|
|
||||||
void dce_os_cond_wait_reset(struct tegra_dce *d, u32 msg_id);
|
|
||||||
|
|
||||||
#endif /* DCE_OS_WORKER_H */
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DCE_OS_COND_INTERNAL_H
|
||||||
|
#define DCE_OS_COND_INTERNAL_H
|
||||||
|
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
struct dce_os_cond {
|
||||||
|
bool initialized;
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DCE_OS_COND_WAIT_INTERRUPTIBLE_INTERNAL(c, condition) \
|
||||||
|
({ \
|
||||||
|
int ret = 0; \
|
||||||
|
ret = wait_event_interruptible((c)->wq, condition); \
|
||||||
|
ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT_INTERNAL(c, condition, timeout_ms) \
|
||||||
|
({ \
|
||||||
|
int ret = 0; \
|
||||||
|
/* This is the assignment to enforce a u32 for timeout_ms */ \
|
||||||
|
u32 *tmp = (typeof(timeout_ms) *)NULL; \
|
||||||
|
(void)tmp; \
|
||||||
|
if (timeout_ms > 0U) { \
|
||||||
|
long _ret = wait_event_interruptible_timeout((c)->wq, \
|
||||||
|
condition, msecs_to_jiffies(timeout_ms)); \
|
||||||
|
if (_ret == 0) \
|
||||||
|
ret = -ETIMEDOUT; \
|
||||||
|
else if (_ret == -ERESTARTSYS) \
|
||||||
|
ret = -ERESTARTSYS; \
|
||||||
|
} else { \
|
||||||
|
ret = wait_event_interruptible((c)->wq, condition); \
|
||||||
|
} \
|
||||||
|
ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif /* DCE_OS_COND_INTERNAL_H */
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DCE_OS_COND_H
|
|
||||||
#define DCE_OS_COND_H
|
|
||||||
|
|
||||||
#include <linux/wait.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
|
|
||||||
struct dce_os_cond {
|
|
||||||
bool initialized;
|
|
||||||
wait_queue_head_t wq;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DCE_OS_COND_WAIT - Wait for a condition to be true
|
|
||||||
*
|
|
||||||
* @c - The condition variable to sleep on
|
|
||||||
* @condition - The condition that needs to be true
|
|
||||||
*
|
|
||||||
* Wait for a condition to become true.
|
|
||||||
*/
|
|
||||||
#define DCE_OS_COND_WAIT(c, condition) \
|
|
||||||
({\
|
|
||||||
int ret = 0; \
|
|
||||||
wait_event((c)->wq, condition); \
|
|
||||||
ret;\
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DCE_OS_COND_WAIT_INTERRUPTIBLE - Wait for a condition to be true
|
|
||||||
*
|
|
||||||
* @c - The condition variable to sleep on
|
|
||||||
* @condition - The condition that needs to be true
|
|
||||||
*
|
|
||||||
* Wait for a condition to become true. Returns -ERESTARTSYS
|
|
||||||
* on signal.
|
|
||||||
*/
|
|
||||||
#define DCE_OS_COND_WAIT_INTERRUPTIBLE(c, condition) \
|
|
||||||
({ \
|
|
||||||
int ret = 0; \
|
|
||||||
ret = wait_event_interruptible((c)->wq, condition); \
|
|
||||||
ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DCE_OS_COND_WAIT_TIMEOUT - Wait for a condition to be true
|
|
||||||
*
|
|
||||||
* @c - The condition variable to sleep on
|
|
||||||
* @condition - The condition that needs to be true
|
|
||||||
* @timeout_ms - Timeout in milliseconds, or 0 for infinite wait.
|
|
||||||
* This parameter must be a u32. Since this is a macro, this is
|
|
||||||
* enforced by assigning a typecast NULL pointer to a u32 tmp
|
|
||||||
* variable which will generate a compiler warning (or error if
|
|
||||||
* the warning is configured as an error).
|
|
||||||
*
|
|
||||||
* Wait for a condition to become true. Returns -ETIMEOUT if
|
|
||||||
* the wait timed out with condition false.
|
|
||||||
*/
|
|
||||||
#define DCE_OS_COND_WAIT_TIMEOUT(c, condition, timeout_ms) \
|
|
||||||
({\
|
|
||||||
int ret = 0; \
|
|
||||||
/* This is the assignment to enforce a u32 for timeout_ms */ \
|
|
||||||
u32 *tmp = (typeof(timeout_ms) *)NULL; \
|
|
||||||
(void)tmp; \
|
|
||||||
if (timeout_ms > 0U) { \
|
|
||||||
long _ret = wait_event_timeout((c)->wq, condition, \
|
|
||||||
msecs_to_jiffies(timeout_ms)); \
|
|
||||||
if (_ret == 0) \
|
|
||||||
ret = -ETIMEDOUT; \
|
|
||||||
} else { \
|
|
||||||
wait_event((c)->wq, condition); \
|
|
||||||
} \
|
|
||||||
ret;\
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT - Wait for a condition to be true
|
|
||||||
*
|
|
||||||
* @c - The condition variable to sleep on
|
|
||||||
* @condition - The condition that needs to be true
|
|
||||||
* @timeout_ms - Timeout in milliseconds, or 0 for infinite wait.
|
|
||||||
* This parameter must be a u32. Since this is a macro, this is
|
|
||||||
* enforced by assigning a typecast NULL pointer to a u32 tmp
|
|
||||||
* variable which will generate a compiler warning (or error if
|
|
||||||
* the warning is configured as an error).
|
|
||||||
*
|
|
||||||
* Wait for a condition to become true. Returns -ETIMEOUT if
|
|
||||||
* the wait timed out with condition false or -ERESTARTSYS on
|
|
||||||
* signal.
|
|
||||||
*/
|
|
||||||
#define DCE_OS_COND_WAIT_INTERRUPTIBLE_TIMEOUT(c, condition, timeout_ms) \
|
|
||||||
({ \
|
|
||||||
int ret = 0; \
|
|
||||||
/* This is the assignment to enforce a u32 for timeout_ms */ \
|
|
||||||
u32 *tmp = (typeof(timeout_ms) *)NULL; \
|
|
||||||
(void)tmp; \
|
|
||||||
if (timeout_ms > 0U) { \
|
|
||||||
long _ret = wait_event_interruptible_timeout((c)->wq, \
|
|
||||||
condition, msecs_to_jiffies(timeout_ms)); \
|
|
||||||
if (_ret == 0) \
|
|
||||||
ret = -ETIMEDOUT; \
|
|
||||||
else if (_ret == -ERESTARTSYS) \
|
|
||||||
ret = -ERESTARTSYS; \
|
|
||||||
} else { \
|
|
||||||
ret = wait_event_interruptible((c)->wq, condition); \
|
|
||||||
} \
|
|
||||||
ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
int dce_os_cond_init(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
void dce_os_cond_signal(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
void dce_os_cond_signal_interruptible(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
int dce_os_cond_broadcast(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
int dce_os_cond_broadcast_interruptible(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
void dce_os_cond_destroy(struct dce_os_cond *cond);
|
|
||||||
|
|
||||||
#endif /* DCE_OS_COND_H */
|
|
||||||
Reference in New Issue
Block a user