msm: synx: async_wait timeout changes

Adding timeout parameter for async wait so the callback
will be invoked on timer expiry if not signalled.

Change-Id: Ia31f59021f00befed5317fdac262d823c659c6bf
Signed-off-by: Ram Nagesh <quic_ramnages@quicinc.com>
Signed-off-by: Urvesh Rathod <quic_urathod@quicinc.com>
This commit is contained in:
Urvesh Rathod
2023-04-18 14:51:32 +05:30
committed by Gerrit - the friendly Code Review server
parent 26a5a7df0d
commit d87e10c694
4 changed files with 82 additions and 4 deletions

View File

@@ -882,6 +882,52 @@ static int synx_match_payload(struct synx_kernel_payload *cb_payload,
return rc; return rc;
} }
/* Timer Callback function. This will be called when timer expires */
void synx_timer_cb(struct timer_list *data)
{
struct synx_client *client;
struct synx_handle_coredata *synx_data;
struct synx_coredata *synx_obj;
struct synx_cb_data *synx_cb = container_of(data, struct synx_cb_data, synx_timer);
client = synx_get_client(synx_cb->session);
if (IS_ERR_OR_NULL(client)) {
dprintk(SYNX_ERR,
"invalid session data 0x%x in cb payload\n",
synx_cb->session);
return;
}
synx_data = synx_util_acquire_handle(client, synx_cb->h_synx);
synx_obj = synx_util_obtain_object(synx_data);
if (IS_ERR_OR_NULL(synx_obj)) {
dprintk(SYNX_ERR,
"[sess :0x%llx] invalid handle access 0x%x\n",
synx_cb->session, synx_cb->h_synx);
return;
}
dprintk(SYNX_VERB,
"Timer expired for synx_cb 0x%x timeout 0x%llx. Deleting the timer.\n",
synx_cb, synx_cb->timeout);
synx_cb->status = SYNX_STATE_TIMEOUT;
del_timer(&synx_cb->synx_timer);
list_del_init(&synx_cb->node);
queue_work(synx_dev->wq_cb, &synx_cb->cb_dispatch);
}
static int synx_start_timer(struct synx_cb_data *synx_cb)
{
int rc = 0;
timer_setup(&synx_cb->synx_timer, synx_timer_cb, 0);
rc = mod_timer(&synx_cb->synx_timer, jiffies + msecs_to_jiffies(synx_cb->timeout));
dprintk(SYNX_VERB,
"Timer started for synx_cb 0x%x timeout 0x%llx\n",
synx_cb, synx_cb->timeout);
return rc;
}
int synx_async_wait(struct synx_session *session, int synx_async_wait(struct synx_session *session,
struct synx_callback_params *params) struct synx_callback_params *params)
{ {
@@ -897,9 +943,6 @@ int synx_async_wait(struct synx_session *session,
if (IS_ERR_OR_NULL(session) || IS_ERR_OR_NULL(params)) if (IS_ERR_OR_NULL(session) || IS_ERR_OR_NULL(params))
return -SYNX_INVALID; return -SYNX_INVALID;
if (params->timeout_ms != SYNX_NO_TIMEOUT)
return -SYNX_NOSUPPORT;
client = synx_get_client(session); client = synx_get_client(session);
if (IS_ERR_OR_NULL(client)) if (IS_ERR_OR_NULL(client))
return -SYNX_INVALID; return -SYNX_INVALID;
@@ -952,6 +995,8 @@ int synx_async_wait(struct synx_session *session,
synx_cb->session = session; synx_cb->session = session;
synx_cb->idx = idx; synx_cb->idx = idx;
synx_cb->h_synx = params->h_synx;
INIT_WORK(&synx_cb->cb_dispatch, synx_util_cb_dispatch); INIT_WORK(&synx_cb->cb_dispatch, synx_util_cb_dispatch);
/* add callback if object still ACTIVE, dispatch if SIGNALED */ /* add callback if object still ACTIVE, dispatch if SIGNALED */
@@ -959,6 +1004,17 @@ int synx_async_wait(struct synx_session *session,
dprintk(SYNX_VERB, dprintk(SYNX_VERB,
"[sess :%llu] callback added for handle %u\n", "[sess :%llu] callback added for handle %u\n",
client->id, params->h_synx); client->id, params->h_synx);
synx_cb->timeout = params->timeout_ms;
if (params->timeout_ms != SYNX_NO_TIMEOUT) {
rc = synx_start_timer(synx_cb);
if (rc != SYNX_SUCCESS) {
dprintk(SYNX_ERR,
"[sess :%llu] timer start failed - synx_cb: 0x%x, params->timeout_ms: 0x%llx, handle: 0x%x, ret : %d\n",
client->id, synx_cb, params->timeout_ms,
params->h_synx, rc);
goto release;
}
}
list_add(&synx_cb->node, &synx_obj->reg_cbs_list); list_add(&synx_cb->node, &synx_obj->reg_cbs_list);
} else { } else {
synx_cb->status = status; synx_cb->status = status;
@@ -1024,7 +1080,7 @@ int synx_cancel_async_wait(
status = synx_util_get_object_status(synx_obj); status = synx_util_get_object_status(synx_obj);
if (status != SYNX_STATE_ACTIVE) { if (status != SYNX_STATE_ACTIVE) {
dprintk(SYNX_ERR, dprintk(SYNX_ERR,
"handle %u already signaled cannot cancel\n", "handle %u already signaled or timed out, cannot cancel\n",
params->h_synx); params->h_synx);
rc = -SYNX_INVALID; rc = -SYNX_INVALID;
goto release; goto release;
@@ -1052,6 +1108,12 @@ int synx_cancel_async_wait(
cb_payload = &client->cb_table[synx_cb->idx]; cb_payload = &client->cb_table[synx_cb->idx];
ret = synx_match_payload(&cb_payload->kernel_cb, &payload); ret = synx_match_payload(&cb_payload->kernel_cb, &payload);
if (synx_cb->timeout != SYNX_NO_TIMEOUT) {
dprintk(SYNX_VERB,
"Deleting timer synx_cb 0x%x, timeout 0x%llx\n",
synx_cb, synx_cb->timeout);
del_timer(&synx_cb->synx_timer);
}
switch (ret) { switch (ret) {
case 1: case 1:
/* queue the cancel cb work */ /* queue the cancel cb work */

View File

@@ -53,6 +53,7 @@ enum synx_core_id {
#define SYNX_STATE_SIGNALED_ERROR 3 #define SYNX_STATE_SIGNALED_ERROR 3
#define SYNX_STATE_SIGNALED_EXTERNAL 5 #define SYNX_STATE_SIGNALED_EXTERNAL 5
#define SYNX_STATE_SIGNALED_SSR 6 #define SYNX_STATE_SIGNALED_SSR 6
#define SYNX_STATE_TIMEOUT 7
/* dma fence states */ /* dma fence states */
#define SYNX_DMA_FENCE_STATE_MAX 4096 #define SYNX_DMA_FENCE_STATE_MAX 4096

View File

@@ -101,7 +101,10 @@ struct synx_kernel_payload {
struct synx_cb_data { struct synx_cb_data {
struct synx_session *session; struct synx_session *session;
u32 idx; u32 idx;
u32 h_synx;
u32 status; u32 status;
struct timer_list synx_timer;
u64 timeout;
struct work_struct cb_dispatch; struct work_struct cb_dispatch;
struct list_head node; struct list_head node;
}; };

View File

@@ -301,6 +301,12 @@ void synx_util_object_destroy(struct synx_coredata *synx_obj)
"dipatching un-released callbacks of session %pK\n", "dipatching un-released callbacks of session %pK\n",
synx_cb->session); synx_cb->session);
synx_cb->status = SYNX_STATE_SIGNALED_CANCEL; synx_cb->status = SYNX_STATE_SIGNALED_CANCEL;
if (synx_cb->timeout != SYNX_NO_TIMEOUT) {
dprintk(SYNX_VERB,
"Deleting timer synx_cb 0x%x, timeout 0x%llx\n",
synx_cb, synx_cb->timeout);
del_timer(&synx_cb->synx_timer);
}
list_del_init(&synx_cb->node); list_del_init(&synx_cb->node);
queue_work(synx_dev->wq_cb, queue_work(synx_dev->wq_cb,
&synx_cb->cb_dispatch); &synx_cb->cb_dispatch);
@@ -1175,6 +1181,12 @@ void synx_util_callback_dispatch(struct synx_coredata *synx_obj, u32 status)
list_for_each_entry_safe(synx_cb, list_for_each_entry_safe(synx_cb,
synx_cb_temp, &synx_obj->reg_cbs_list, node) { synx_cb_temp, &synx_obj->reg_cbs_list, node) {
synx_cb->status = status; synx_cb->status = status;
if (synx_cb->timeout != SYNX_NO_TIMEOUT) {
dprintk(SYNX_VERB,
"Deleting timer synx_cb 0x%x, timeout 0x%llx\n",
synx_cb, synx_cb->timeout);
del_timer(&synx_cb->synx_timer);
}
list_del_init(&synx_cb->node); list_del_init(&synx_cb->node);
queue_work(synx_dev->wq_cb, queue_work(synx_dev->wq_cb,
&synx_cb->cb_dispatch); &synx_cb->cb_dispatch);