synx: Propagating changes from msm-5.10

Includes param change for async_wait(timeout) and other fixes

Change-Id: If8ff795538bbfaf53ee1758561fbd2841e5a71c7
Signed-off-by: Pravin Kumar Ravi <quic_pravinku@quicinc.com>
This commit is contained in:
Pravin Kumar Ravi
2023-02-17 15:30:20 -08:00
کامیت شده توسط Gerrit - the friendly Code Review server
والد a1529349b1
کامیت 33788f7297
5فایلهای تغییر یافته به همراه122 افزوده شده و 8 حذف شده

مشاهده پرونده

@@ -519,6 +519,13 @@ void synx_signal_handler(struct work_struct *cb_dispatch)
dprintk(SYNX_ERR,
"global status update of %u failed=%d\n",
h_synx, rc);
/*
* We are decrementing the reference here assuming this code will be
* executed after handle is released. But in case if clients signal
* dma fence in middle of execution sequence, then we will put
* one reference thus deleting the global idx. As of now clients cannot
* signal dma fence.
*/
synx_global_put_ref(idx);
}
@@ -573,6 +580,7 @@ fail:
void synx_fence_callback(struct dma_fence *fence,
struct dma_fence_cb *cb)
{
s32 status;
struct synx_signal_cb *signal_cb =
container_of(cb, struct synx_signal_cb, fence_cb);
@@ -581,7 +589,19 @@ void synx_fence_callback(struct dma_fence *fence,
fence, signal_cb->handle);
/* other signal_cb members would be set during cb registration */
signal_cb->status = dma_fence_get_status_locked(fence);
status = dma_fence_get_status_locked(fence);
/*
* dma_fence_get_status_locked API returns 1 if signaled,
* 0 if ACTIVE,
* and negative error code in case of any failure
*/
if (status == 1)
status = SYNX_STATE_SIGNALED_SUCCESS;
else if (status < 0)
status = SYNX_STATE_SIGNALED_EXTERNAL;
signal_cb->status = status;
INIT_WORK(&signal_cb->cb_dispatch, synx_signal_handler);
queue_work(synx_dev->wq_cb, &signal_cb->cb_dispatch);
@@ -2427,7 +2447,7 @@ int synx_ipc_callback(u32 client_id,
if (IS_ERR_OR_NULL(signal_cb))
return -SYNX_NOMEM;
dprintk(SYNX_INFO,
dprintk(SYNX_DBG,
"signal notification for %u received with status %u\n",
handle, status);

مشاهده پرونده

@@ -12,6 +12,8 @@
#include "synx_err.h"
#define SYNX_NO_TIMEOUT ((u64)-1)
/**
* enum synx_create_flags - Flags passed during synx_create call
*
@@ -87,7 +89,7 @@ typedef void (*synx_callback)(s32 sync_obj, int status, void *data);
* synx_user_callback - Callback function registered by clients
*
* User callback registered for non-blocking wait. Dispatched when
* synx object is signaled.
* synx object is signaled or timeout has expired.
*/
typedef void (*synx_user_callback_t)(u32 h_synx, int status, void *data);
@@ -330,12 +332,14 @@ struct synx_import_params {
* @cb_func : Pointer to callback func to be invoked
* @userdata : Opaque pointer passed back with callback
* @cancel_cb_func : Pointer to callback to ack cancellation (optional)
* @timeout_ms : Timeout in ms. SYNX_NO_TIMEOUT if no timeout.
*/
struct synx_callback_params {
u32 h_synx;
synx_user_callback_t cb_func;
void *userdata;
synx_user_callback_t cancel_cb_func;
u64 timeout_ms;
};
/* Kernel APIs */

مشاهده پرونده

@@ -208,6 +208,24 @@ int synx_global_init_coredata(u32 h_synx)
if (rc)
return rc;
synx_g_obj = &synx_gmem.table[idx];
if (synx_g_obj->status != 0 || synx_g_obj->refcount != 0 ||
synx_g_obj->subscribers != 0 || synx_g_obj->handle != 0 ||
synx_g_obj->parents[0] != 0) {
dprintk(SYNX_ERR,
"entry not cleared for idx %u,\n"
"synx_g_obj->status %d,\n"
"synx_g_obj->refcount %d,\n"
"synx_g_obj->subscribers %d,\n"
"synx_g_obj->handle %u,\n"
"synx_g_obj->parents[0] %d\n",
idx, synx_g_obj->status,
synx_g_obj->refcount,
synx_g_obj->subscribers,
synx_g_obj->handle,
synx_g_obj->parents[0]);
synx_gmem_unlock(idx, &flags);
return -SYNX_INVALID;
}
memset(synx_g_obj, 0, sizeof(*synx_g_obj));
/* set status to active */
synx_g_obj->status = SYNX_STATE_ACTIVE;
@@ -332,6 +350,28 @@ int synx_global_set_subscribed_core(u32 idx, enum synx_core_id id)
return SYNX_SUCCESS;
}
int synx_global_clear_subscribed_core(u32 idx, enum synx_core_id id)
{
int rc;
unsigned long flags;
struct synx_global_coredata *synx_g_obj;
if (!synx_gmem.table)
return -SYNX_NOMEM;
if (id >= SYNX_CORE_MAX || !synx_is_valid_idx(idx))
return -SYNX_INVALID;
rc = synx_gmem_lock(idx, &flags);
if (rc)
return rc;
synx_g_obj = &synx_gmem.table[idx];
synx_g_obj->subscribers &= ~(1UL << id);
synx_gmem_unlock(idx, &flags);
return SYNX_SUCCESS;
}
u32 synx_global_get_parents_num(u32 idx)
{
int rc;
@@ -528,7 +568,18 @@ static int synx_global_update_status_core(u32 idx,
/* notify waiting clients on signal */
if (data) {
/* notify wait client */
for (i = 1; i < SYNX_CORE_MAX; i++) {
/* In case of SSR, someone might be waiting on same core
* However, in other cases, synx_signal API will take care
* of signaling handles on same core and thus we don't need
* to send interrupt
*/
if (status == SYNX_STATE_SIGNALED_SSR)
i = 0;
else
i = 1;
for (; i < SYNX_CORE_MAX ; i++) {
if (!wait_cores[i])
continue;
dprintk(SYNX_DBG,
@@ -735,7 +786,7 @@ int synx_global_recover(enum synx_core_id core_id)
const u32 size = SYNX_GLOBAL_MAX_OBJS;
unsigned long flags;
struct synx_global_coredata *synx_g_obj;
bool update;
int *clear_idx = NULL;
if (!synx_gmem.table)

مشاهده پرونده

@@ -179,6 +179,16 @@ int synx_global_get_subscribed_cores(u32 idx, bool *cores);
*/
int synx_global_set_subscribed_core(u32 idx, enum synx_core_id id);
/**
* synx_global_clear_subscribed_core - Clear core as a subscriber core on global entry
*
* @param idx : Global entry index
* @param id : Core to be added as subscriber
*
* @return SYNX_SUCCESS on success. Negative error on failure.
*/
int synx_global_clear_subscribed_core(u32 idx, enum synx_core_id id);
/**
* synx_global_get_status - Get status of the global entry
*

مشاهده پرونده

@@ -223,11 +223,17 @@ int synx_util_init_group_coredata(struct synx_coredata *synx_obj,
static void synx_util_destroy_coredata(struct kref *kref)
{
int rc;
struct synx_coredata *synx_obj =
container_of(kref, struct synx_coredata, refcount);
if (synx_util_is_global_object(synx_obj))
if (synx_util_is_global_object(synx_obj)) {
rc = synx_global_clear_subscribed_core(synx_obj->global_idx, SYNX_CORE_APSS);
if (rc)
dprintk(SYNX_ERR, "Failed to clear subscribers");
synx_global_put_ref(synx_obj->global_idx);
}
synx_util_object_destroy(synx_obj);
}
@@ -247,6 +253,7 @@ void synx_util_object_destroy(struct synx_coredata *synx_obj)
u32 i;
s32 sync_id;
u32 type;
unsigned long flags;
struct synx_cb_data *synx_cb, *synx_cb_temp;
struct synx_bind_desc *bind_desc;
struct bind_operations *bind_ops;
@@ -297,6 +304,29 @@ void synx_util_object_destroy(struct synx_coredata *synx_obj)
mutex_destroy(&synx_obj->obj_lock);
synx_util_release_fence_entry((u64)synx_obj->fence);
/* dma fence framework expects handles are signaled before release,
* so signal if active handle and has last refcount. Synx handles
* on other cores are still active to carry out usual callflow.
*/
if (!IS_ERR_OR_NULL(synx_obj->fence)) {
spin_lock_irqsave(synx_obj->fence->lock, flags);
if (kref_read(&synx_obj->fence->refcount) == 1 &&
(synx_util_get_object_status_locked(synx_obj) ==
SYNX_STATE_ACTIVE)) {
// set fence error to cancel
dma_fence_set_error(synx_obj->fence,
-SYNX_STATE_SIGNALED_CANCEL);
rc = dma_fence_signal_locked(synx_obj->fence);
if (rc)
dprintk(SYNX_ERR,
"signaling fence %pK failed=%d\n",
synx_obj->fence, rc);
}
spin_unlock_irqrestore(synx_obj->fence->lock, flags);
}
dma_fence_put(synx_obj->fence);
kfree(synx_obj);
dprintk(SYNX_MEM, "released synx object %pK\n", synx_obj);
@@ -873,7 +903,6 @@ static void synx_util_cleanup_fence(
if (synx_util_get_object_status_locked(synx_obj) ==
SYNX_STATE_ACTIVE) {
signal_cb->synx_obj = NULL;
signal_cb->handle = synx_obj->global_idx;
synx_obj->signal_cb = NULL;
/*
* release reference held by signal cb and
@@ -1162,7 +1191,7 @@ void synx_util_cb_dispatch(struct work_struct *cb_dispatch)
client->id);
}
dprintk(SYNX_INFO,
dprintk(SYNX_DBG,
"callback dispatched for handle %u, status %u, data %pK\n",
payload.h_synx, payload.status, payload.data);