Loading drivers/media/platform/msm/synx/synx.c +64 −49 Original line number Diff line number Diff line Loading @@ -18,10 +18,12 @@ struct synx_device *synx_dev; void synx_external_callback(s32 sync_obj, int status, void *data) { s32 synx_obj; struct synx_table_row *row = NULL; struct synx_external_data *bind_data = data; if (bind_data) { synx_obj = bind_data->synx_obj; row = synx_from_key(bind_data->synx_obj, bind_data->secure_key); kfree(bind_data); } Loading @@ -32,7 +34,7 @@ void synx_external_callback(s32 sync_obj, int status, void *data) spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_debug("signaling synx 0x%x from external callback %d\n", row->synx_obj, sync_obj); synx_obj, sync_obj); synx_signal_core(row, status); } else { pr_err("invalid callback from sync external obj %d\n", Loading Loading @@ -115,10 +117,10 @@ int synx_create(s32 *synx_obj, const char *name) return -EINVAL; } *synx_obj = row->synx_obj; *synx_obj = id; pr_debug("row: synx id: 0x%x, index: %d\n", row->synx_obj, row->index); id, row->index); pr_debug("Exit %s\n", __func__); return rc; Loading @@ -144,7 +146,7 @@ int synx_register_callback(s32 synx_obj, if (temp_cb_info->callback_func == cb_func && temp_cb_info->cb_data == userdata) { pr_err("duplicate registration for synx 0x%x\n", row->synx_obj); synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); return -EALREADY; } Loading Loading @@ -198,7 +200,7 @@ int synx_deregister_callback(s32 synx_obj, state = synx_status_locked(row); pr_debug("de-registering callback for synx 0x%x\n", row->synx_obj); synx_obj); list_for_each_entry_safe(synx_cb, temp, &row->callback_list, list) { if (synx_cb->callback_func == cb_func && synx_cb->cb_data == userdata) { Loading Loading @@ -243,8 +245,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) } if (is_merged_synx(row)) { pr_err("signaling a composite synx object 0x%x\n", row->synx_obj); pr_err("signaling a composite synx object at %d\n", row->index); return -EINVAL; } Loading @@ -252,8 +254,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) if (synx_status_locked(row) != SYNX_STATE_ACTIVE) { spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_err("object already signaled synx = 0x%x\n", row->synx_obj); pr_err("object already signaled synx at %d\n", row->index); return -EALREADY; } Loading @@ -263,8 +265,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) rc = dma_fence_signal_locked(row->fence); if (rc < 0) { pr_err("unable to signal synx 0x%x, err: %d\n", row->synx_obj, rc); pr_err("unable to signal synx at %d, err: %d\n", row->index, rc); if (status != SYNX_STATE_SIGNALED_ERROR) { dma_fence_set_error(row->fence, -EINVAL); status = SYNX_STATE_SIGNALED_ERROR; Loading Loading @@ -414,10 +416,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged) goto clear; } *synx_merged = row->synx_obj; *synx_merged = id; pr_debug("row (merged): synx 0x%x, index: %d\n", row->synx_obj, row->index); id, row->index); pr_debug("Exit %s\n", __func__); return 0; Loading @@ -431,19 +433,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged) return rc; } int synx_release(s32 synx_obj) static int synx_release_core(struct synx_table_row *row) { s32 idx; struct dma_fence *fence = NULL; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } /* * metadata might be cleared after invoking dma_fence_put Loading @@ -453,13 +446,6 @@ int synx_release(s32 synx_obj) fence = row->fence; idx = row->index; spin_lock_bh(&synx_dev->row_spinlocks[idx]); if (synx_status_locked(row) == SYNX_STATE_ACTIVE) { pr_err("need to signal before release synx = 0x%x\n", synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[idx]); return -EINVAL; } /* * we need to clear the metadata for merged synx obj upon synx_release * itself as it does not invoke the synx_fence_release function. Loading @@ -476,6 +462,21 @@ int synx_release(s32 synx_obj) return 0; } int synx_release(s32 synx_obj) { struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } return synx_release_core(row); } int synx_wait(s32 synx_obj, u64 timeout_ms) { unsigned long timeleft; Loading Loading @@ -568,7 +569,7 @@ int synx_bind(s32 synx_obj, struct synx_external_desc external_sync) } /* data passed to external callback */ data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; data->secure_key = synx_generate_secure_key(row); rc = bind_ops->register_callback(synx_external_callback, Loading Loading @@ -637,6 +638,7 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) { s32 id; struct dma_fence *fence; struct synx_obj_node *obj_node; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); Loading @@ -648,6 +650,10 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) if (!row) return -EINVAL; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) return -ENOMEM; /* new global synx id */ id = synx_create_handle(row); if (id < 0) { Loading @@ -658,10 +664,15 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) } /* release the reference obtained during export */ dma_fence_put(fence); kfree(obj_node); return -EINVAL; } row->synx_obj = id; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); obj_node->synx_obj = id; list_add(&obj_node->list, &row->synx_obj_list); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); *new_synx_obj = id; pr_debug("Exit %s\n", __func__); Loading @@ -679,7 +690,7 @@ int synx_export(s32 synx_obj, u32 *import_key) if (!row) return -EINVAL; rc = synx_generate_import_key(row, import_key); rc = synx_generate_import_key(row, synx_obj, import_key); if (rc < 0) return rc; Loading Loading @@ -881,6 +892,7 @@ static int synx_handle_wait(struct synx_private_ioctl_arg *k_ioctl) static int synx_handle_register_user_payload( struct synx_private_ioctl_arg *k_ioctl) { s32 synx_obj; u32 state = SYNX_STATE_INVALID; struct synx_userpayload_info userpayload_info; struct synx_cb_data *user_payload_kernel; Loading @@ -898,9 +910,10 @@ static int synx_handle_register_user_payload( k_ioctl->size)) return -EFAULT; row = synx_from_handle(userpayload_info.synx_obj); synx_obj = userpayload_info.synx_obj; row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj); pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } Loading @@ -918,7 +931,7 @@ static int synx_handle_register_user_payload( return -ENOMEM; user_payload_kernel->client = client; user_payload_kernel->data.synx_obj = row->synx_obj; user_payload_kernel->data.synx_obj = synx_obj; memcpy(user_payload_kernel->data.payload_data, userpayload_info.payload, SYNX_PAYLOAD_WORDS * sizeof(__u64)); Loading @@ -944,7 +957,7 @@ static int synx_handle_register_user_payload( user_payload_iter->data.payload_data[1] == user_payload_kernel->data.payload_data[1]) { pr_err("callback already registered on 0x%x\n", row->synx_obj); synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); kfree(user_payload_kernel); return -EALREADY; Loading @@ -961,6 +974,7 @@ static int synx_handle_register_user_payload( static int synx_handle_deregister_user_payload( struct synx_private_ioctl_arg *k_ioctl) { s32 synx_obj; u32 state = SYNX_STATE_INVALID; struct synx_client *client = NULL; struct synx_userpayload_info userpayload_info; Loading @@ -978,9 +992,10 @@ static int synx_handle_deregister_user_payload( k_ioctl->size)) return -EFAULT; row = synx_from_handle(userpayload_info.synx_obj); synx_obj = userpayload_info.synx_obj; row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj); pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } Loading Loading @@ -1028,7 +1043,7 @@ static int synx_handle_deregister_user_payload( SYNX_PAYLOAD_WORDS * sizeof(__u64)); user_payload_kernel->client = client; data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; data->status = SYNX_CALLBACK_RESULT_CANCELED; spin_lock_bh(&client->eventq_lock); Loading Loading @@ -1299,15 +1314,15 @@ static int synx_close(struct inode *inode, struct file *filep) * signal all ACTIVE objects as ERR, but we don't care * about the return status here apart from logging it. */ if (row->synx_obj && !is_merged_synx(row) && if (row->index && !is_merged_synx(row) && (synx_status(row) == SYNX_STATE_ACTIVE)) { pr_debug("synx 0x%x still active at shutdown\n", row->synx_obj); pr_debug("synx still active at shutdown at %d\n", row->index); rc = synx_signal_core(row, SYNX_STATE_SIGNALED_ERROR); if (rc < 0) pr_err("cleanup signal fail idx:0x%x\n", row->synx_obj); pr_err("cleanup signal fail at %d\n", row->index); } } Loading @@ -1325,11 +1340,11 @@ static int synx_close(struct inode *inode, struct file *filep) struct synx_table_row *row = synx_dev->synx_table + i; if (row->synx_obj) { rc = synx_release(row->synx_obj); if (row->index) { rc = synx_release_core(row); if (rc < 0) { pr_err("cleanup destroy fail idx:0x%x\n", row->synx_obj); pr_err("cleanup destroy fail at %d\n", row->index); } } } Loading drivers/media/platform/msm/synx/synx_debugfs.c +11 −6 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ static ssize_t synx_table_read(struct file *file, struct error_node *err_node, *err_node_tmp; struct synx_table_row *row; char *dbuf, *cur, *end; struct synx_obj_node *obj_node; int i = 0; int state = SYNX_STATE_INVALID; Loading @@ -60,26 +61,23 @@ static ssize_t synx_table_read(struct file *file, end = cur + MAX_DBG_BUF_SIZE; if (columns & NAME_COLUMN) cur += scnprintf(cur, end - cur, "| Name |"); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "| ID |"); if (columns & BOUND_COLUMN) cur += scnprintf(cur, end - cur, "| Bound |"); if (columns & STATE_COLUMN) cur += scnprintf(cur, end - cur, "| Status |"); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "| ID |"); cur += scnprintf(cur, end - cur, "\n"); for (i = 0; i < SYNX_MAX_OBJS; i++) { row = &dev->synx_table[i]; if (!row || !row->synx_obj) if (!row->index) continue; spin_lock_bh(&dev->row_spinlocks[row->index]); if (columns & NAME_COLUMN) cur += scnprintf(cur, end - cur, "|%10s|", row->name); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "|%10d|", row->synx_obj); if (columns & BOUND_COLUMN) cur += scnprintf(cur, end - cur, "|%11d|", row->num_bound_synxs); Loading @@ -96,6 +94,13 @@ static ssize_t synx_table_read(struct file *file, cur, end); } if (columns & ID_COLUMN) { list_for_each_entry(obj_node, &row->synx_obj_list, list) { cur += scnprintf(cur, end - cur, "|0x%8x|", obj_node->synx_obj); } } spin_unlock_bh(&dev->row_spinlocks[row->index]); cur += scnprintf(cur, end - cur, "\n"); } Loading drivers/media/platform/msm/synx/synx_private.h +14 −2 Original line number Diff line number Diff line Loading @@ -111,13 +111,25 @@ struct synx_cb_data { struct list_head list; }; /** * struct synx_obj_node - Single node of info for the synx handle * mapped to synx object metadata * * @synx_obj : Synx integer handle * @list : List member used to append to synx handle list */ struct synx_obj_node { s32 synx_obj; struct list_head list; }; /** * struct synx_table_row - Single row of information about a synx object, used * for internal book keeping in the synx driver * * @name : Optional string representation of the synx object * @fence : dma fence backing the synx object * @synx_obj : Integer id representing this synx object * @synx_obj_list : List of synx integer handles mapped * @index : Index of the spin lock table associated with synx obj * @num_bound_synxs : Number of external bound synx objects * @signaling_id : ID of the external sync object invoking the callback Loading @@ -129,7 +141,7 @@ struct synx_cb_data { struct synx_table_row { char name[SYNX_OBJ_NAME_LEN]; struct dma_fence *fence; s32 synx_obj; struct list_head synx_obj_list; s32 index; u32 num_bound_synxs; s32 signaling_id; Loading drivers/media/platform/msm/synx/synx_util.c +81 −31 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ int synx_init_object(struct synx_table_row *table, { struct dma_fence *fence = NULL; struct synx_table_row *row = table + idx; struct synx_obj_node *obj_node; if (!table || idx <= 0 || idx >= SYNX_MAX_OBJS) return -EINVAL; Loading @@ -39,20 +40,28 @@ int synx_init_object(struct synx_table_row *table, if (!fence) return -ENOMEM; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) { kfree(fence); return -ENOMEM; } dma_fence_init(fence, ops, &synx_dev->row_spinlocks[idx], synx_dev->dma_context, 1); row->fence = fence; row->synx_obj = id; obj_node->synx_obj = id; row->index = idx; INIT_LIST_HEAD(&row->synx_obj_list); INIT_LIST_HEAD(&row->callback_list); INIT_LIST_HEAD(&row->user_payload_list); list_add(&obj_node->list, &row->synx_obj_list); if (name) strlcpy(row->name, name, sizeof(row->name)); pr_debug("synx obj init: id:0x%x state:%u fence: 0x%pK\n", row->synx_obj, synx_status_locked(row), fence); synx_status_locked(row), fence); return 0; } Loading @@ -65,20 +74,27 @@ int synx_init_group_object(struct synx_table_row *table, { struct synx_table_row *row = table + idx; struct dma_fence_array *array; struct synx_obj_node *obj_node; array = dma_fence_array_create(num_objs, fences, synx_dev->dma_context, 1, false); if (!array) return -EINVAL; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) return -ENOMEM; row->fence = &array->base; row->synx_obj = id; obj_node->synx_obj = id; row->index = idx; INIT_LIST_HEAD(&row->synx_obj_list); INIT_LIST_HEAD(&row->callback_list); INIT_LIST_HEAD(&row->user_payload_list); pr_debug("synx group obj init: id:0x%x state:%u fence: 0x%pK\n", row->synx_obj, synx_status_locked(row), row->fence); list_add(&obj_node->list, &row->synx_obj_list); pr_debug("synx group obj init: id:%d state:%u fence: 0x%pK\n", id, synx_status_locked(row), row->fence); return 0; } Loading Loading @@ -139,23 +155,31 @@ int synx_activate(struct synx_table_row *row) int synx_deinit_object(struct synx_table_row *row) { s32 synx_obj; s32 index; struct synx_client *client; struct synx_callback_info *synx_cb, *temp_cb; struct synx_cb_data *upayload_info, *temp_upayload; struct synx_obj_node *obj_node, *temp_obj_node; if (!row || !synx_dev) return -EINVAL; synx_obj = row->synx_obj; index = row->index; spin_lock_bh(&synx_dev->idr_lock); list_for_each_entry_safe(obj_node, temp_obj_node, &row->synx_obj_list, list) { if ((struct synx_table_row *)idr_remove(&synx_dev->synx_ids, row->synx_obj) != row) { obj_node->synx_obj) != row) { pr_err("removing data in idr table failed 0x%x\n", row->synx_obj); obj_node->synx_obj); spin_unlock_bh(&synx_dev->idr_lock); return -EINVAL; } pr_debug("removed synx obj at 0x%x successful\n", obj_node->synx_obj); list_del_init(&obj_node->list); kfree(obj_node); } spin_unlock_bh(&synx_dev->idr_lock); /* Loading @@ -163,27 +187,51 @@ int synx_deinit_object(struct synx_table_row *row) * dma fence array will release all the allocated mem * in its registered release function. */ if (!is_merged_synx(row)) if (!is_merged_synx(row)) { kfree(row->fence); /* * invoke remaining userspace and kernel callbacks on * synx obj destroyed, not signaled, with cancellation * event. */ list_for_each_entry_safe(upayload_info, temp_upayload, &row->user_payload_list, list) { pr_err("pending user callback payload\n"); list_del_init(&upayload_info->list); kfree(upayload_info); upayload_info->data.status = SYNX_CALLBACK_RESULT_CANCELED; memcpy(&upayload_info->data.payload_data[2], &upayload_info->data.payload_data[0], sizeof(u64)); client = upayload_info->client; if (!client) { pr_err("invalid client member in cb list\n"); continue; } spin_lock_bh(&client->eventq_lock); list_move_tail(&upayload_info->list, &client->eventq); spin_unlock_bh(&client->eventq_lock); /* * since cb can be registered by multiple clients, * wake the process right away */ wake_up_all(&client->wq); pr_debug("dispatched user cb\n"); } list_for_each_entry_safe(synx_cb, temp_cb, &row->callback_list, list) { pr_err("pending kernel callback payload\n"); synx_cb->status = SYNX_CALLBACK_RESULT_CANCELED; list_del_init(&synx_cb->list); kfree(synx_cb); queue_work(synx_dev->work_queue, &synx_cb->cb_dispatch_work); pr_debug("dispatched kernel cb\n"); } } clear_bit(row->index, synx_dev->bitmap); memset(row, 0, sizeof(*row)); pr_debug("destroying synx obj: 0x%x successful\n", synx_obj); pr_debug("destroying synx obj at %d successful\n", index); return 0; } Loading Loading @@ -570,8 +618,8 @@ struct synx_table_row *synx_from_fence(struct dma_fence *fence) for (idx = 0; idx < SYNX_MAX_OBJS; idx++) { if (table[idx].fence == fence) { row = table + idx; pr_debug("synx global data found for 0x%x\n", row->synx_obj); pr_debug("synx global data found at %d\n", row->index); break; } } Loading Loading @@ -602,6 +650,7 @@ struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key) } int synx_generate_import_key(struct synx_table_row *row, s32 synx_obj, u32 *key) { bool bit; Loading @@ -623,7 +672,7 @@ int synx_generate_import_key(struct synx_table_row *row, } while (!*key); data->key = *key; data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; /* * Reason for separate metadata (for merged synx) * being dma fence array has separate release func Loading Loading @@ -657,6 +706,7 @@ int synx_generate_import_key(struct synx_table_row *row, /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; INIT_LIST_HEAD(&new_row->synx_obj_list); INIT_LIST_HEAD(&new_row->callback_list); INIT_LIST_HEAD(&new_row->user_payload_list); data->row = new_row; Loading @@ -665,7 +715,7 @@ int synx_generate_import_key(struct synx_table_row *row, } list_add(&data->list, &synx_dev->import_list); pr_debug("allocated import key for 0x%x\n", row->synx_obj); synx_obj); mutex_unlock(&synx_dev->table_lock); return 0; Loading drivers/media/platform/msm/synx/synx_util.h +4 −2 Original line number Diff line number Diff line Loading @@ -234,11 +234,13 @@ int synx_generate_secure_key(struct synx_table_row *row); * verified during import. * * @param row : Pointer to the synx object row * @param synx_obj : Synx handle * @param key : Pointer to key (filled by the function) * * @return Status of operation. Negative in case of error. Zero otherwise. */ int synx_generate_import_key(struct synx_table_row *row, s32 synx_obj, u32 *key); /** Loading Loading
drivers/media/platform/msm/synx/synx.c +64 −49 Original line number Diff line number Diff line Loading @@ -18,10 +18,12 @@ struct synx_device *synx_dev; void synx_external_callback(s32 sync_obj, int status, void *data) { s32 synx_obj; struct synx_table_row *row = NULL; struct synx_external_data *bind_data = data; if (bind_data) { synx_obj = bind_data->synx_obj; row = synx_from_key(bind_data->synx_obj, bind_data->secure_key); kfree(bind_data); } Loading @@ -32,7 +34,7 @@ void synx_external_callback(s32 sync_obj, int status, void *data) spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_debug("signaling synx 0x%x from external callback %d\n", row->synx_obj, sync_obj); synx_obj, sync_obj); synx_signal_core(row, status); } else { pr_err("invalid callback from sync external obj %d\n", Loading Loading @@ -115,10 +117,10 @@ int synx_create(s32 *synx_obj, const char *name) return -EINVAL; } *synx_obj = row->synx_obj; *synx_obj = id; pr_debug("row: synx id: 0x%x, index: %d\n", row->synx_obj, row->index); id, row->index); pr_debug("Exit %s\n", __func__); return rc; Loading @@ -144,7 +146,7 @@ int synx_register_callback(s32 synx_obj, if (temp_cb_info->callback_func == cb_func && temp_cb_info->cb_data == userdata) { pr_err("duplicate registration for synx 0x%x\n", row->synx_obj); synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); return -EALREADY; } Loading Loading @@ -198,7 +200,7 @@ int synx_deregister_callback(s32 synx_obj, state = synx_status_locked(row); pr_debug("de-registering callback for synx 0x%x\n", row->synx_obj); synx_obj); list_for_each_entry_safe(synx_cb, temp, &row->callback_list, list) { if (synx_cb->callback_func == cb_func && synx_cb->cb_data == userdata) { Loading Loading @@ -243,8 +245,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) } if (is_merged_synx(row)) { pr_err("signaling a composite synx object 0x%x\n", row->synx_obj); pr_err("signaling a composite synx object at %d\n", row->index); return -EINVAL; } Loading @@ -252,8 +254,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) if (synx_status_locked(row) != SYNX_STATE_ACTIVE) { spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_err("object already signaled synx = 0x%x\n", row->synx_obj); pr_err("object already signaled synx at %d\n", row->index); return -EALREADY; } Loading @@ -263,8 +265,8 @@ int synx_signal_core(struct synx_table_row *row, u32 status) rc = dma_fence_signal_locked(row->fence); if (rc < 0) { pr_err("unable to signal synx 0x%x, err: %d\n", row->synx_obj, rc); pr_err("unable to signal synx at %d, err: %d\n", row->index, rc); if (status != SYNX_STATE_SIGNALED_ERROR) { dma_fence_set_error(row->fence, -EINVAL); status = SYNX_STATE_SIGNALED_ERROR; Loading Loading @@ -414,10 +416,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged) goto clear; } *synx_merged = row->synx_obj; *synx_merged = id; pr_debug("row (merged): synx 0x%x, index: %d\n", row->synx_obj, row->index); id, row->index); pr_debug("Exit %s\n", __func__); return 0; Loading @@ -431,19 +433,10 @@ int synx_merge(s32 *synx_objs, u32 num_objs, s32 *synx_merged) return rc; } int synx_release(s32 synx_obj) static int synx_release_core(struct synx_table_row *row) { s32 idx; struct dma_fence *fence = NULL; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } /* * metadata might be cleared after invoking dma_fence_put Loading @@ -453,13 +446,6 @@ int synx_release(s32 synx_obj) fence = row->fence; idx = row->index; spin_lock_bh(&synx_dev->row_spinlocks[idx]); if (synx_status_locked(row) == SYNX_STATE_ACTIVE) { pr_err("need to signal before release synx = 0x%x\n", synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[idx]); return -EINVAL; } /* * we need to clear the metadata for merged synx obj upon synx_release * itself as it does not invoke the synx_fence_release function. Loading @@ -476,6 +462,21 @@ int synx_release(s32 synx_obj) return 0; } int synx_release(s32 synx_obj) { struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } return synx_release_core(row); } int synx_wait(s32 synx_obj, u64 timeout_ms) { unsigned long timeleft; Loading Loading @@ -568,7 +569,7 @@ int synx_bind(s32 synx_obj, struct synx_external_desc external_sync) } /* data passed to external callback */ data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; data->secure_key = synx_generate_secure_key(row); rc = bind_ops->register_callback(synx_external_callback, Loading Loading @@ -637,6 +638,7 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) { s32 id; struct dma_fence *fence; struct synx_obj_node *obj_node; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); Loading @@ -648,6 +650,10 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) if (!row) return -EINVAL; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) return -ENOMEM; /* new global synx id */ id = synx_create_handle(row); if (id < 0) { Loading @@ -658,10 +664,15 @@ int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) } /* release the reference obtained during export */ dma_fence_put(fence); kfree(obj_node); return -EINVAL; } row->synx_obj = id; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); obj_node->synx_obj = id; list_add(&obj_node->list, &row->synx_obj_list); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); *new_synx_obj = id; pr_debug("Exit %s\n", __func__); Loading @@ -679,7 +690,7 @@ int synx_export(s32 synx_obj, u32 *import_key) if (!row) return -EINVAL; rc = synx_generate_import_key(row, import_key); rc = synx_generate_import_key(row, synx_obj, import_key); if (rc < 0) return rc; Loading Loading @@ -881,6 +892,7 @@ static int synx_handle_wait(struct synx_private_ioctl_arg *k_ioctl) static int synx_handle_register_user_payload( struct synx_private_ioctl_arg *k_ioctl) { s32 synx_obj; u32 state = SYNX_STATE_INVALID; struct synx_userpayload_info userpayload_info; struct synx_cb_data *user_payload_kernel; Loading @@ -898,9 +910,10 @@ static int synx_handle_register_user_payload( k_ioctl->size)) return -EFAULT; row = synx_from_handle(userpayload_info.synx_obj); synx_obj = userpayload_info.synx_obj; row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj); pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } Loading @@ -918,7 +931,7 @@ static int synx_handle_register_user_payload( return -ENOMEM; user_payload_kernel->client = client; user_payload_kernel->data.synx_obj = row->synx_obj; user_payload_kernel->data.synx_obj = synx_obj; memcpy(user_payload_kernel->data.payload_data, userpayload_info.payload, SYNX_PAYLOAD_WORDS * sizeof(__u64)); Loading @@ -944,7 +957,7 @@ static int synx_handle_register_user_payload( user_payload_iter->data.payload_data[1] == user_payload_kernel->data.payload_data[1]) { pr_err("callback already registered on 0x%x\n", row->synx_obj); synx_obj); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); kfree(user_payload_kernel); return -EALREADY; Loading @@ -961,6 +974,7 @@ static int synx_handle_register_user_payload( static int synx_handle_deregister_user_payload( struct synx_private_ioctl_arg *k_ioctl) { s32 synx_obj; u32 state = SYNX_STATE_INVALID; struct synx_client *client = NULL; struct synx_userpayload_info userpayload_info; Loading @@ -978,9 +992,10 @@ static int synx_handle_deregister_user_payload( k_ioctl->size)) return -EFAULT; row = synx_from_handle(userpayload_info.synx_obj); synx_obj = userpayload_info.synx_obj; row = synx_from_handle(synx_obj); if (!row) { pr_err("invalid synx: 0x%x\n", userpayload_info.synx_obj); pr_err("invalid synx: 0x%x\n", synx_obj); return -EINVAL; } Loading Loading @@ -1028,7 +1043,7 @@ static int synx_handle_deregister_user_payload( SYNX_PAYLOAD_WORDS * sizeof(__u64)); user_payload_kernel->client = client; data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; data->status = SYNX_CALLBACK_RESULT_CANCELED; spin_lock_bh(&client->eventq_lock); Loading Loading @@ -1299,15 +1314,15 @@ static int synx_close(struct inode *inode, struct file *filep) * signal all ACTIVE objects as ERR, but we don't care * about the return status here apart from logging it. */ if (row->synx_obj && !is_merged_synx(row) && if (row->index && !is_merged_synx(row) && (synx_status(row) == SYNX_STATE_ACTIVE)) { pr_debug("synx 0x%x still active at shutdown\n", row->synx_obj); pr_debug("synx still active at shutdown at %d\n", row->index); rc = synx_signal_core(row, SYNX_STATE_SIGNALED_ERROR); if (rc < 0) pr_err("cleanup signal fail idx:0x%x\n", row->synx_obj); pr_err("cleanup signal fail at %d\n", row->index); } } Loading @@ -1325,11 +1340,11 @@ static int synx_close(struct inode *inode, struct file *filep) struct synx_table_row *row = synx_dev->synx_table + i; if (row->synx_obj) { rc = synx_release(row->synx_obj); if (row->index) { rc = synx_release_core(row); if (rc < 0) { pr_err("cleanup destroy fail idx:0x%x\n", row->synx_obj); pr_err("cleanup destroy fail at %d\n", row->index); } } } Loading
drivers/media/platform/msm/synx/synx_debugfs.c +11 −6 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ static ssize_t synx_table_read(struct file *file, struct error_node *err_node, *err_node_tmp; struct synx_table_row *row; char *dbuf, *cur, *end; struct synx_obj_node *obj_node; int i = 0; int state = SYNX_STATE_INVALID; Loading @@ -60,26 +61,23 @@ static ssize_t synx_table_read(struct file *file, end = cur + MAX_DBG_BUF_SIZE; if (columns & NAME_COLUMN) cur += scnprintf(cur, end - cur, "| Name |"); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "| ID |"); if (columns & BOUND_COLUMN) cur += scnprintf(cur, end - cur, "| Bound |"); if (columns & STATE_COLUMN) cur += scnprintf(cur, end - cur, "| Status |"); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "| ID |"); cur += scnprintf(cur, end - cur, "\n"); for (i = 0; i < SYNX_MAX_OBJS; i++) { row = &dev->synx_table[i]; if (!row || !row->synx_obj) if (!row->index) continue; spin_lock_bh(&dev->row_spinlocks[row->index]); if (columns & NAME_COLUMN) cur += scnprintf(cur, end - cur, "|%10s|", row->name); if (columns & ID_COLUMN) cur += scnprintf(cur, end - cur, "|%10d|", row->synx_obj); if (columns & BOUND_COLUMN) cur += scnprintf(cur, end - cur, "|%11d|", row->num_bound_synxs); Loading @@ -96,6 +94,13 @@ static ssize_t synx_table_read(struct file *file, cur, end); } if (columns & ID_COLUMN) { list_for_each_entry(obj_node, &row->synx_obj_list, list) { cur += scnprintf(cur, end - cur, "|0x%8x|", obj_node->synx_obj); } } spin_unlock_bh(&dev->row_spinlocks[row->index]); cur += scnprintf(cur, end - cur, "\n"); } Loading
drivers/media/platform/msm/synx/synx_private.h +14 −2 Original line number Diff line number Diff line Loading @@ -111,13 +111,25 @@ struct synx_cb_data { struct list_head list; }; /** * struct synx_obj_node - Single node of info for the synx handle * mapped to synx object metadata * * @synx_obj : Synx integer handle * @list : List member used to append to synx handle list */ struct synx_obj_node { s32 synx_obj; struct list_head list; }; /** * struct synx_table_row - Single row of information about a synx object, used * for internal book keeping in the synx driver * * @name : Optional string representation of the synx object * @fence : dma fence backing the synx object * @synx_obj : Integer id representing this synx object * @synx_obj_list : List of synx integer handles mapped * @index : Index of the spin lock table associated with synx obj * @num_bound_synxs : Number of external bound synx objects * @signaling_id : ID of the external sync object invoking the callback Loading @@ -129,7 +141,7 @@ struct synx_cb_data { struct synx_table_row { char name[SYNX_OBJ_NAME_LEN]; struct dma_fence *fence; s32 synx_obj; struct list_head synx_obj_list; s32 index; u32 num_bound_synxs; s32 signaling_id; Loading
drivers/media/platform/msm/synx/synx_util.c +81 −31 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ int synx_init_object(struct synx_table_row *table, { struct dma_fence *fence = NULL; struct synx_table_row *row = table + idx; struct synx_obj_node *obj_node; if (!table || idx <= 0 || idx >= SYNX_MAX_OBJS) return -EINVAL; Loading @@ -39,20 +40,28 @@ int synx_init_object(struct synx_table_row *table, if (!fence) return -ENOMEM; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) { kfree(fence); return -ENOMEM; } dma_fence_init(fence, ops, &synx_dev->row_spinlocks[idx], synx_dev->dma_context, 1); row->fence = fence; row->synx_obj = id; obj_node->synx_obj = id; row->index = idx; INIT_LIST_HEAD(&row->synx_obj_list); INIT_LIST_HEAD(&row->callback_list); INIT_LIST_HEAD(&row->user_payload_list); list_add(&obj_node->list, &row->synx_obj_list); if (name) strlcpy(row->name, name, sizeof(row->name)); pr_debug("synx obj init: id:0x%x state:%u fence: 0x%pK\n", row->synx_obj, synx_status_locked(row), fence); synx_status_locked(row), fence); return 0; } Loading @@ -65,20 +74,27 @@ int synx_init_group_object(struct synx_table_row *table, { struct synx_table_row *row = table + idx; struct dma_fence_array *array; struct synx_obj_node *obj_node; array = dma_fence_array_create(num_objs, fences, synx_dev->dma_context, 1, false); if (!array) return -EINVAL; obj_node = kzalloc(sizeof(*obj_node), GFP_KERNEL); if (!obj_node) return -ENOMEM; row->fence = &array->base; row->synx_obj = id; obj_node->synx_obj = id; row->index = idx; INIT_LIST_HEAD(&row->synx_obj_list); INIT_LIST_HEAD(&row->callback_list); INIT_LIST_HEAD(&row->user_payload_list); pr_debug("synx group obj init: id:0x%x state:%u fence: 0x%pK\n", row->synx_obj, synx_status_locked(row), row->fence); list_add(&obj_node->list, &row->synx_obj_list); pr_debug("synx group obj init: id:%d state:%u fence: 0x%pK\n", id, synx_status_locked(row), row->fence); return 0; } Loading Loading @@ -139,23 +155,31 @@ int synx_activate(struct synx_table_row *row) int synx_deinit_object(struct synx_table_row *row) { s32 synx_obj; s32 index; struct synx_client *client; struct synx_callback_info *synx_cb, *temp_cb; struct synx_cb_data *upayload_info, *temp_upayload; struct synx_obj_node *obj_node, *temp_obj_node; if (!row || !synx_dev) return -EINVAL; synx_obj = row->synx_obj; index = row->index; spin_lock_bh(&synx_dev->idr_lock); list_for_each_entry_safe(obj_node, temp_obj_node, &row->synx_obj_list, list) { if ((struct synx_table_row *)idr_remove(&synx_dev->synx_ids, row->synx_obj) != row) { obj_node->synx_obj) != row) { pr_err("removing data in idr table failed 0x%x\n", row->synx_obj); obj_node->synx_obj); spin_unlock_bh(&synx_dev->idr_lock); return -EINVAL; } pr_debug("removed synx obj at 0x%x successful\n", obj_node->synx_obj); list_del_init(&obj_node->list); kfree(obj_node); } spin_unlock_bh(&synx_dev->idr_lock); /* Loading @@ -163,27 +187,51 @@ int synx_deinit_object(struct synx_table_row *row) * dma fence array will release all the allocated mem * in its registered release function. */ if (!is_merged_synx(row)) if (!is_merged_synx(row)) { kfree(row->fence); /* * invoke remaining userspace and kernel callbacks on * synx obj destroyed, not signaled, with cancellation * event. */ list_for_each_entry_safe(upayload_info, temp_upayload, &row->user_payload_list, list) { pr_err("pending user callback payload\n"); list_del_init(&upayload_info->list); kfree(upayload_info); upayload_info->data.status = SYNX_CALLBACK_RESULT_CANCELED; memcpy(&upayload_info->data.payload_data[2], &upayload_info->data.payload_data[0], sizeof(u64)); client = upayload_info->client; if (!client) { pr_err("invalid client member in cb list\n"); continue; } spin_lock_bh(&client->eventq_lock); list_move_tail(&upayload_info->list, &client->eventq); spin_unlock_bh(&client->eventq_lock); /* * since cb can be registered by multiple clients, * wake the process right away */ wake_up_all(&client->wq); pr_debug("dispatched user cb\n"); } list_for_each_entry_safe(synx_cb, temp_cb, &row->callback_list, list) { pr_err("pending kernel callback payload\n"); synx_cb->status = SYNX_CALLBACK_RESULT_CANCELED; list_del_init(&synx_cb->list); kfree(synx_cb); queue_work(synx_dev->work_queue, &synx_cb->cb_dispatch_work); pr_debug("dispatched kernel cb\n"); } } clear_bit(row->index, synx_dev->bitmap); memset(row, 0, sizeof(*row)); pr_debug("destroying synx obj: 0x%x successful\n", synx_obj); pr_debug("destroying synx obj at %d successful\n", index); return 0; } Loading Loading @@ -570,8 +618,8 @@ struct synx_table_row *synx_from_fence(struct dma_fence *fence) for (idx = 0; idx < SYNX_MAX_OBJS; idx++) { if (table[idx].fence == fence) { row = table + idx; pr_debug("synx global data found for 0x%x\n", row->synx_obj); pr_debug("synx global data found at %d\n", row->index); break; } } Loading Loading @@ -602,6 +650,7 @@ struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key) } int synx_generate_import_key(struct synx_table_row *row, s32 synx_obj, u32 *key) { bool bit; Loading @@ -623,7 +672,7 @@ int synx_generate_import_key(struct synx_table_row *row, } while (!*key); data->key = *key; data->synx_obj = row->synx_obj; data->synx_obj = synx_obj; /* * Reason for separate metadata (for merged synx) * being dma fence array has separate release func Loading Loading @@ -657,6 +706,7 @@ int synx_generate_import_key(struct synx_table_row *row, /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; INIT_LIST_HEAD(&new_row->synx_obj_list); INIT_LIST_HEAD(&new_row->callback_list); INIT_LIST_HEAD(&new_row->user_payload_list); data->row = new_row; Loading @@ -665,7 +715,7 @@ int synx_generate_import_key(struct synx_table_row *row, } list_add(&data->list, &synx_dev->import_list); pr_debug("allocated import key for 0x%x\n", row->synx_obj); synx_obj); mutex_unlock(&synx_dev->table_lock); return 0; Loading
drivers/media/platform/msm/synx/synx_util.h +4 −2 Original line number Diff line number Diff line Loading @@ -234,11 +234,13 @@ int synx_generate_secure_key(struct synx_table_row *row); * verified during import. * * @param row : Pointer to the synx object row * @param synx_obj : Synx handle * @param key : Pointer to key (filled by the function) * * @return Status of operation. Negative in case of error. Zero otherwise. */ int synx_generate_import_key(struct synx_table_row *row, s32 synx_obj, u32 *key); /** Loading