|
@@ -483,6 +483,11 @@ int synx_native_signal_fence(struct synx_coredata *synx_obj,
|
|
|
return -SYNX_ALREADY;
|
|
|
}
|
|
|
|
|
|
+ synx_obj->status = status;
|
|
|
+
|
|
|
+ if (status >= SYNX_DMA_FENCE_STATE_MAX)
|
|
|
+ status = SYNX_DMA_FENCE_STATE_MAX - 1;
|
|
|
+
|
|
|
/* set fence error to model {signal w/ error} */
|
|
|
if (status != SYNX_STATE_SIGNALED_SUCCESS)
|
|
|
dma_fence_set_error(synx_obj->fence, -status);
|
|
@@ -514,6 +519,7 @@ int synx_native_signal_merged_fence(struct synx_coredata *synx_obj, u32 status)
|
|
|
rc = -SYNX_NOENT;
|
|
|
goto fail;
|
|
|
}
|
|
|
+
|
|
|
mutex_lock(&synx_child_obj[i]->obj_lock);
|
|
|
spin_lock_irqsave(synx_child_obj[i]->fence->lock, flags);
|
|
|
if (synx_util_get_object_status_locked(synx_child_obj[i]) != SYNX_STATE_ACTIVE ||
|
|
@@ -525,6 +531,7 @@ int synx_native_signal_merged_fence(struct synx_coredata *synx_obj, u32 status)
|
|
|
}
|
|
|
spin_unlock_irqrestore(synx_child_obj[i]->fence->lock, flags);
|
|
|
|
|
|
+ status = synx_global_get_status(synx_child_obj[i]->global_idx);
|
|
|
rc = synx_native_signal_fence(synx_child_obj[i], status);
|
|
|
mutex_unlock(&synx_child_obj[i]->obj_lock);
|
|
|
}
|
|
@@ -533,6 +540,80 @@ fail:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+u32 synx_get_child_status(struct synx_coredata *synx_obj)
|
|
|
+{
|
|
|
+ u32 h_child = 0, i = 0;
|
|
|
+ u32 status = SYNX_DMA_FENCE_STATE_MAX - 1, child_status = SYNX_STATE_ACTIVE;
|
|
|
+ struct dma_fence_array *array = NULL;
|
|
|
+ struct synx_map_entry *fence_entry = NULL;
|
|
|
+ struct synx_coredata *synx_child_obj = NULL;
|
|
|
+
|
|
|
+ if (!dma_fence_is_array(synx_obj->fence))
|
|
|
+ return status;
|
|
|
+
|
|
|
+ array = to_dma_fence_array(synx_obj->fence);
|
|
|
+ if (IS_ERR_OR_NULL(array))
|
|
|
+ goto bail;
|
|
|
+
|
|
|
+ for (i = 0; i < array->num_fences; i++) {
|
|
|
+ h_child = synx_util_get_fence_entry((u64)array->fences[i], 1);
|
|
|
+ if (h_child == 0)
|
|
|
+ h_child = synx_util_get_fence_entry((u64)array->fences[i], 0);
|
|
|
+
|
|
|
+ if (h_child == 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ fence_entry = synx_util_get_map_entry(h_child);
|
|
|
+ if (IS_ERR_OR_NULL(fence_entry) || IS_ERR_OR_NULL(fence_entry->synx_obj)) {
|
|
|
+ dprintk(SYNX_ERR, "Invalid handle access %u", h_child);
|
|
|
+ goto bail;
|
|
|
+ }
|
|
|
+ synx_child_obj = fence_entry->synx_obj;
|
|
|
+
|
|
|
+ mutex_lock(&synx_child_obj->obj_lock);
|
|
|
+ if (synx_util_is_global_object(synx_child_obj))
|
|
|
+ child_status = synx_global_get_status(synx_child_obj->global_idx);
|
|
|
+ else
|
|
|
+ child_status = synx_child_obj->status;
|
|
|
+ mutex_unlock(&synx_child_obj->obj_lock);
|
|
|
+ synx_util_release_map_entry(fence_entry);
|
|
|
+
|
|
|
+ dprintk(SYNX_VERB, "Child handle %u status %d", h_child, child_status);
|
|
|
+ if (child_status != SYNX_STATE_ACTIVE &&
|
|
|
+ (status == SYNX_DMA_FENCE_STATE_MAX - 1 ||
|
|
|
+ (child_status > SYNX_STATE_SIGNALED_SUCCESS &&
|
|
|
+ child_status <= SYNX_STATE_SIGNALED_MAX)))
|
|
|
+ status = child_status;
|
|
|
+ }
|
|
|
+bail:
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+u32 synx_custom_get_status(struct synx_coredata *synx_obj, u32 status)
|
|
|
+{
|
|
|
+ u32 custom_status = status;
|
|
|
+ u32 parent_global_status =
|
|
|
+ synx_util_is_global_object(synx_obj) ?
|
|
|
+ synx_global_get_status(synx_obj->global_idx) : SYNX_STATE_ACTIVE;
|
|
|
+
|
|
|
+ if (IS_ERR_OR_NULL(synx_obj))
|
|
|
+ goto bail;
|
|
|
+
|
|
|
+ mutex_lock(&synx_obj->obj_lock);
|
|
|
+ if (synx_util_is_merged_object(synx_obj)) {
|
|
|
+ if (parent_global_status == SYNX_STATE_ACTIVE)
|
|
|
+ synx_obj->status = synx_get_child_status(synx_obj);
|
|
|
+ else
|
|
|
+ synx_obj->status = parent_global_status;
|
|
|
+ }
|
|
|
+
|
|
|
+ custom_status = synx_obj->status;
|
|
|
+ mutex_unlock(&synx_obj->obj_lock);
|
|
|
+
|
|
|
+bail:
|
|
|
+ return custom_status;
|
|
|
+}
|
|
|
+
|
|
|
void synx_signal_handler(struct work_struct *cb_dispatch)
|
|
|
{
|
|
|
int rc = SYNX_SUCCESS;
|
|
@@ -544,6 +625,13 @@ void synx_signal_handler(struct work_struct *cb_dispatch)
|
|
|
u32 h_synx = signal_cb->handle;
|
|
|
u32 status = signal_cb->status;
|
|
|
|
|
|
+ if (signal_cb->flag & SYNX_SIGNAL_FROM_FENCE) {
|
|
|
+ status = synx_custom_get_status(synx_obj, status);
|
|
|
+ dprintk(SYNX_VERB,
|
|
|
+ "handle %d will be updated with status %d\n",
|
|
|
+ h_synx, status);
|
|
|
+ }
|
|
|
+
|
|
|
if ((signal_cb->flag & SYNX_SIGNAL_FROM_FENCE) &&
|
|
|
(synx_util_is_global_handle(h_synx) ||
|
|
|
synx_util_is_global_object(synx_obj))) {
|
|
@@ -590,8 +678,8 @@ void synx_signal_handler(struct work_struct *cb_dispatch)
|
|
|
}
|
|
|
|
|
|
mutex_lock(&synx_obj->obj_lock);
|
|
|
-
|
|
|
- if (signal_cb->flag & SYNX_SIGNAL_FROM_IPC) {
|
|
|
+ if (signal_cb->flag & SYNX_SIGNAL_FROM_IPC &&
|
|
|
+ synx_util_get_object_status(synx_obj) == SYNX_STATE_ACTIVE) {
|
|
|
if (synx_util_is_merged_object(synx_obj))
|
|
|
rc = synx_native_signal_merged_fence(synx_obj, status);
|
|
|
else
|
|
@@ -648,8 +736,12 @@ void synx_fence_callback(struct dma_fence *fence,
|
|
|
*/
|
|
|
if (status == 1)
|
|
|
status = SYNX_STATE_SIGNALED_SUCCESS;
|
|
|
- else if (status < 0)
|
|
|
+ else if (status == -SYNX_STATE_SIGNALED_CANCEL)
|
|
|
+ status = SYNX_STATE_SIGNALED_CANCEL;
|
|
|
+ else if (status < 0 && status >= -SYNX_STATE_SIGNALED_MAX)
|
|
|
status = SYNX_STATE_SIGNALED_EXTERNAL;
|
|
|
+ else
|
|
|
+ status = (u32)-status;
|
|
|
|
|
|
signal_cb->status = status;
|
|
|
|
|
@@ -707,7 +799,10 @@ int synx_signal(struct synx_session *session, u32 h_synx, u32 status)
|
|
|
if (IS_ERR_OR_NULL(client))
|
|
|
return -SYNX_INVALID;
|
|
|
|
|
|
- if (status <= SYNX_STATE_ACTIVE) {
|
|
|
+ if (status <= SYNX_STATE_ACTIVE ||
|
|
|
+ !(status == SYNX_STATE_SIGNALED_SUCCESS ||
|
|
|
+ status == SYNX_STATE_SIGNALED_CANCEL ||
|
|
|
+ status > SYNX_STATE_SIGNALED_MAX)) {
|
|
|
dprintk(SYNX_ERR,
|
|
|
"[sess :%llu] signaling with wrong status: %u\n",
|
|
|
client->id, status);
|
|
@@ -727,7 +822,6 @@ int synx_signal(struct synx_session *session, u32 h_synx, u32 status)
|
|
|
}
|
|
|
|
|
|
mutex_lock(&synx_obj->obj_lock);
|
|
|
-
|
|
|
if (synx_util_is_global_handle(h_synx) ||
|
|
|
synx_util_is_global_object(synx_obj))
|
|
|
rc = synx_global_update_status(
|
|
@@ -997,7 +1091,7 @@ EXPORT_SYMBOL(synx_cancel_async_wait);
|
|
|
int synx_merge(struct synx_session *session,
|
|
|
struct synx_merge_params *params)
|
|
|
{
|
|
|
- int rc, i, num_signaled = 0;
|
|
|
+ int rc = SYNX_SUCCESS, i, num_signaled = 0;
|
|
|
u32 count = 0, h_child, status = SYNX_STATE_ACTIVE;
|
|
|
u32 *h_child_list = NULL, *h_child_idx_list = NULL;
|
|
|
struct synx_client *client;
|
|
@@ -1073,6 +1167,7 @@ int synx_merge(struct synx_session *session,
|
|
|
|
|
|
h_child_idx_list = kzalloc(count*4, GFP_KERNEL);
|
|
|
if (IS_ERR_OR_NULL(h_child_idx_list)) {
|
|
|
+ kfree(h_child_list);
|
|
|
rc = -SYNX_NOMEM;
|
|
|
goto clear;
|
|
|
}
|
|
@@ -1110,10 +1205,14 @@ int synx_merge(struct synx_session *session,
|
|
|
client->id, h_child_list[i]);
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
- rc = synx_native_signal_fence(synx_obj_child, status);
|
|
|
+ mutex_lock(&synx_obj_child->obj_lock);
|
|
|
+ if (synx_obj->status == SYNX_STATE_ACTIVE)
|
|
|
+ rc = synx_native_signal_fence(synx_obj_child, status);
|
|
|
+ mutex_unlock(&synx_obj_child->obj_lock);
|
|
|
if (rc != SYNX_SUCCESS)
|
|
|
dprintk(SYNX_ERR, "h_synx %u failed with status %d\n", h_child_list[i], rc);
|
|
|
+
|
|
|
+ synx_util_release_handle(synx_data_child);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1361,7 +1460,7 @@ EXPORT_SYMBOL(synx_bind);
|
|
|
int synx_get_status(struct synx_session *session,
|
|
|
u32 h_synx)
|
|
|
{
|
|
|
- int rc = 0;
|
|
|
+ int rc = 0, status = 0;
|
|
|
struct synx_client *client;
|
|
|
struct synx_handle_coredata *synx_data;
|
|
|
struct synx_coredata *synx_obj;
|
|
@@ -1381,23 +1480,13 @@ int synx_get_status(struct synx_session *session,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- if (synx_util_is_global_handle(h_synx)) {
|
|
|
- rc = synx_global_get_status(
|
|
|
- synx_util_global_idx(h_synx));
|
|
|
- if (rc != SYNX_STATE_ACTIVE) {
|
|
|
- dprintk(SYNX_VERB,
|
|
|
- "[sess :%llu] handle %u in status %d\n",
|
|
|
- client->id, h_synx, rc);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
mutex_lock(&synx_obj->obj_lock);
|
|
|
- rc = synx_util_get_object_status(synx_obj);
|
|
|
+ status = synx_util_get_object_status(synx_obj);
|
|
|
+ rc = synx_obj->status;
|
|
|
mutex_unlock(&synx_obj->obj_lock);
|
|
|
dprintk(SYNX_VERB,
|
|
|
- "[sess :%llu] handle %u status %d\n",
|
|
|
- client->id, h_synx, rc);
|
|
|
+ "[sess :%llu] handle %u synx coredata status %d and dma fence status %d\n",
|
|
|
+ client->id, h_synx, rc, status);
|
|
|
|
|
|
fail:
|
|
|
synx_util_release_handle(synx_data);
|