From f452d16f44050364bd1f1d34e978e52489f67782 Mon Sep 17 00:00:00 2001 From: Santosh Reddy Galma Date: Thu, 15 Oct 2020 20:10:31 +0530 Subject: [PATCH] tegra: dce: use wait queue instead of completions - completions uses spin lock and disables irq resulting in processor getting blocked to receive mailbox interrupts during IPC synchronization. - current change uses wait queues instead of completions for IPC synchronization to overcome above possibility of IPC blocked on DCE. JIRA TDS-5691 Change-Id: I12e06ff4d31cf47d87e7a9d76d9915e5e2210de6 Signed-off-by: Santosh Reddy Galma Reviewed-on: https://git-master.nvidia.com/r/c/linux-t23x/+/2428661 Reviewed-by: automaticguardword Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Arun Swain Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions --- drivers/platform/tegra/dce/dce-client-ipc.c | 22 ++++++++++++++++--- .../dce/include/dce-client-ipc-internal.h | 20 +++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/platform/tegra/dce/dce-client-ipc.c b/drivers/platform/tegra/dce/dce-client-ipc.c index 5a50f363..7aec264e 100644 --- a/drivers/platform/tegra/dce/dce-client-ipc.c +++ b/drivers/platform/tegra/dce/dce-client-ipc.c @@ -148,9 +148,16 @@ int tegra_dce_register_ipc_client(u32 type, cl->data = data; cl->int_type = int_type; cl->callback_fn = callback_fn; + atomic_set(&cl->complete, 0); + + ret = dce_cond_init(&cl->recv_wait); + if (ret) { + dce_err(d, "dce condition initialization failed for int_type: [%u]", + int_type); + goto out; + } d->d_clients[type] = cl; - init_completion(&cl->recv_wait); out: if (ret != 0) { @@ -166,6 +173,11 @@ EXPORT_SYMBOL(tegra_dce_register_ipc_client); int tegra_dce_unregister_ipc_client(u32 handle) { + struct tegra_dce_client_ipc *cl; + + cl = &client_handles[client_handle_to_index(handle)]; + dce_cond_destroy(&cl->recv_wait); + return dce_client_ipc_handle_free(handle); } EXPORT_SYMBOL(tegra_dce_unregister_ipc_client); @@ -212,7 +224,10 @@ static int dce_client_ipc_wait_rpc(struct tegra_dce *d, u32 int_type) return -EINVAL; } - wait_for_completion(&cl->recv_wait); + DCE_COND_WAIT_INTERRUPTIBLE(&cl->recv_wait, + atomic_read(&cl->complete) == 1, + 0); + atomic_set(&cl->complete, 0); return 0; } @@ -255,5 +270,6 @@ void dce_client_ipc_wakeup(struct tegra_dce *d, u32 ch_type) return; } - complete(&cl->recv_wait); + atomic_set(&cl->complete, 1); + dce_cond_signal_interruptible(&cl->recv_wait); } diff --git a/drivers/platform/tegra/dce/include/dce-client-ipc-internal.h b/drivers/platform/tegra/dce/include/dce-client-ipc-internal.h index 842b715c..c9ea161e 100644 --- a/drivers/platform/tegra/dce/include/dce-client-ipc-internal.h +++ b/drivers/platform/tegra/dce/include/dce-client-ipc-internal.h @@ -16,14 +16,30 @@ #include +/** + * struct tegra_dce_client_ipc - Data Structure to hold client specific ipc + * data pertaining to IPC type + * + * @valid : Tells if the client ipc data held by data structure is valid + * @data : Pointer to any specific data passed by client during registration + * for corresponding IPC type + * @type : Corresponding 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 + * cluster elements + * @recv_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 + * client during registration + */ struct tegra_dce_client_ipc { bool valid; void *data; uint32_t type; uint32_t int_type; struct tegra_dce *d; - struct dce_ivc_channel *ch; - struct completion recv_wait; + struct dce_cond recv_wait; + atomic_t complete; tegra_dce_client_ipc_callback_t callback_fn; };