Loading drivers/media/platform/msm/synx/synx.c +25 −40 Original line number Diff line number Diff line Loading @@ -633,74 +633,57 @@ int synx_addrefcount(s32 synx_obj, s32 count) return 0; } int synx_import(s32 synx_obj, u32 secure_key, s32 *new_synx_obj) int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) { bool bit; s32 id; long idx = 0; struct dma_fence *fence; struct synx_table_row *row = NULL; struct synx_table_row *new_row = NULL; pr_debug("Enter %s\n", __func__); if (!new_synx_obj) return -EINVAL; row = synx_from_key(synx_obj, secure_key); row = synx_from_import_key(synx_obj, import_key); if (!row) return -EINVAL; /* * Reason for separate metadata (for merged synx) being * dma fence array has separate release func registed with * dma fence ops, which doesn't invoke release func registered * by the framework to clear metadata when all refs are released. * Hence we need to clear the metadata for merged synx obj * upon synx_release itself. But this creates a problem if * the synx obj is exported. Thus we need separate metadata * structures even though they represent same synx obj. * Note, only the metadata is released, and the fence reference * count is decremented still. */ if (is_merged_synx(row)) { do { idx = find_first_zero_bit(synx_dev->bitmap, SYNX_MAX_OBJS); if (idx >= SYNX_MAX_OBJS) return -ENOMEM; bit = test_and_set_bit(idx, synx_dev->bitmap); } while (bit); new_row = synx_dev->synx_table + idx; /* new global synx id */ id = synx_create_handle(new_row); /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; new_row->synx_obj = id; } else { /* new global synx id. Imported synx points to same metadata */ id = synx_create_handle(row); if (id < 0) { fence = row->fence; if (is_merged_synx(row)) { clear_bit(row->index, synx_dev->bitmap); memset(row, 0, sizeof(*row)); } /* release the reference obtained during export */ dma_fence_put(fence); return -EINVAL; } row->synx_obj = id; *new_synx_obj = id; pr_debug("Exit %s\n", __func__); return 0; } int synx_export(s32 synx_obj, u32 *key) int synx_export(s32 synx_obj, u32 *import_key) { int rc; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) return -EINVAL; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); *key = synx_generate_secure_key(row); rc = synx_generate_import_key(row, import_key); if (rc < 0) return rc; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); /* * to make sure the synx is not lost if the process dies or * synx is released before any other process gets a chance to Loading @@ -710,6 +693,7 @@ int synx_export(s32 synx_obj, u32 *key) */ dma_fence_get(row->fence); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_debug("Exit %s\n", __func__); return 0; } Loading Loading @@ -1489,6 +1473,7 @@ static int __init synx_init(void) } INIT_LIST_HEAD(&synx_dev->client_list); INIT_LIST_HEAD(&synx_dev->import_list); synx_dev->dma_context = dma_fence_context_alloc(1); synx_dev->debugfs_root = init_synx_debug_dir(synx_dev); Loading drivers/media/platform/msm/synx/synx_private.h +18 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,22 @@ struct synx_registered_ops { u32 type; }; /** * struct synx_import_data - Import metadata for sharing synx handles * with processes * * @key : Import key for sharing synx handle * @synx_obj : Synx handle being exported * @row : Pointer to synx object * @list : List member used to append the node to import list */ struct synx_import_data { u32 key; s32 synx_obj; struct synx_table_row *row; struct list_head list; }; /** * struct synx_device - Internal struct to book keep synx driver details * Loading @@ -175,6 +191,7 @@ struct synx_registered_ops { * debugfs_root : Root directory for debugfs * synx_node_head : list head for synx nodes * synx_node_list_lock : Spinlock for synx nodes * import_list : List to validate synx import requests */ struct synx_device { struct cdev cdev; Loading @@ -194,6 +211,7 @@ struct synx_device { struct dentry *debugfs_root; struct list_head synx_debug_head; spinlock_t synx_node_list_lock; struct list_head import_list; }; /** Loading drivers/media/platform/msm/synx/synx_util.c +92 −0 Original line number Diff line number Diff line Loading @@ -579,6 +579,98 @@ struct synx_table_row *synx_from_fence(struct dma_fence *fence) return row; } struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key) { struct synx_import_data *data, *tmp_data; struct synx_table_row *row = NULL; mutex_lock(&synx_dev->table_lock); list_for_each_entry_safe(data, tmp_data, &synx_dev->import_list, list) { if (data->key == key && data->synx_obj == synx_obj) { pr_debug("found synx handle, importing 0x%x\n", synx_obj); row = data->row; list_del_init(&data->list); kfree(data); break; } } mutex_unlock(&synx_dev->table_lock); return row; } int synx_generate_import_key(struct synx_table_row *row, u32 *key) { bool bit; long idx = 0; struct synx_import_data *data; struct synx_table_row *new_row; if (!row) return -EINVAL; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; mutex_lock(&synx_dev->table_lock); do { /* obtain a random non-zero key */ get_random_bytes(key, sizeof(*key)); } while (!*key); data->key = *key; data->synx_obj = row->synx_obj; /* * Reason for separate metadata (for merged synx) * being dma fence array has separate release func * registed with dma fence ops, which doesn't invoke * release func registered by the framework to clear * metadata when all refs are released. * Hence we need to clear the metadata for merged synx * obj upon synx_release itself. But this creates a * problem if synx obj is exported. Thus need separate * metadata structures even though they represent same * synx obj. * Note, only the metadata is released, and the fence * reference count is decremented still. */ if (is_merged_synx(row)) { do { idx = find_first_zero_bit( synx_dev->bitmap, SYNX_MAX_OBJS); if (idx >= SYNX_MAX_OBJS) { kfree(data); mutex_unlock( &synx_dev->table_lock); return -ENOMEM; } bit = test_and_set_bit(idx, synx_dev->bitmap); } while (bit); new_row = synx_dev->synx_table + idx; /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; INIT_LIST_HEAD(&new_row->callback_list); INIT_LIST_HEAD(&new_row->user_payload_list); data->row = new_row; } else { data->row = row; } list_add(&data->list, &synx_dev->import_list); pr_debug("allocated import key for 0x%x\n", row->synx_obj); mutex_unlock(&synx_dev->table_lock); return 0; } void *synx_from_key(s32 id, u32 secure_key) { struct synx_table_row *row = NULL; Loading drivers/media/platform/msm/synx/synx_util.h +25 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,31 @@ struct bind_operations *synx_get_bind_ops(u32 type); */ int synx_generate_secure_key(struct synx_table_row *row); /** * @brief: Function to generate a key for authenticating requests * Generated key for synx object being exported is * verified during import. * * @param row : Pointer to the synx object row * @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, u32 *key); /** * @brief: Function to authenticate requests for importing synx handle * Used to verify the requests generated on synx object * being imported. * * @param synx_obj : Synx handle being imported * @param key : Key to authenticate import request * * @return Pointer to the synx object row for valid request. NULL otherwise. */ struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key); /** * @brief: Function to handle adding an error * code to a synx Loading Loading
drivers/media/platform/msm/synx/synx.c +25 −40 Original line number Diff line number Diff line Loading @@ -633,74 +633,57 @@ int synx_addrefcount(s32 synx_obj, s32 count) return 0; } int synx_import(s32 synx_obj, u32 secure_key, s32 *new_synx_obj) int synx_import(s32 synx_obj, u32 import_key, s32 *new_synx_obj) { bool bit; s32 id; long idx = 0; struct dma_fence *fence; struct synx_table_row *row = NULL; struct synx_table_row *new_row = NULL; pr_debug("Enter %s\n", __func__); if (!new_synx_obj) return -EINVAL; row = synx_from_key(synx_obj, secure_key); row = synx_from_import_key(synx_obj, import_key); if (!row) return -EINVAL; /* * Reason for separate metadata (for merged synx) being * dma fence array has separate release func registed with * dma fence ops, which doesn't invoke release func registered * by the framework to clear metadata when all refs are released. * Hence we need to clear the metadata for merged synx obj * upon synx_release itself. But this creates a problem if * the synx obj is exported. Thus we need separate metadata * structures even though they represent same synx obj. * Note, only the metadata is released, and the fence reference * count is decremented still. */ if (is_merged_synx(row)) { do { idx = find_first_zero_bit(synx_dev->bitmap, SYNX_MAX_OBJS); if (idx >= SYNX_MAX_OBJS) return -ENOMEM; bit = test_and_set_bit(idx, synx_dev->bitmap); } while (bit); new_row = synx_dev->synx_table + idx; /* new global synx id */ id = synx_create_handle(new_row); /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; new_row->synx_obj = id; } else { /* new global synx id. Imported synx points to same metadata */ id = synx_create_handle(row); if (id < 0) { fence = row->fence; if (is_merged_synx(row)) { clear_bit(row->index, synx_dev->bitmap); memset(row, 0, sizeof(*row)); } /* release the reference obtained during export */ dma_fence_put(fence); return -EINVAL; } row->synx_obj = id; *new_synx_obj = id; pr_debug("Exit %s\n", __func__); return 0; } int synx_export(s32 synx_obj, u32 *key) int synx_export(s32 synx_obj, u32 *import_key) { int rc; struct synx_table_row *row = NULL; pr_debug("Enter %s\n", __func__); row = synx_from_handle(synx_obj); if (!row) return -EINVAL; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); *key = synx_generate_secure_key(row); rc = synx_generate_import_key(row, import_key); if (rc < 0) return rc; spin_lock_bh(&synx_dev->row_spinlocks[row->index]); /* * to make sure the synx is not lost if the process dies or * synx is released before any other process gets a chance to Loading @@ -710,6 +693,7 @@ int synx_export(s32 synx_obj, u32 *key) */ dma_fence_get(row->fence); spin_unlock_bh(&synx_dev->row_spinlocks[row->index]); pr_debug("Exit %s\n", __func__); return 0; } Loading Loading @@ -1489,6 +1473,7 @@ static int __init synx_init(void) } INIT_LIST_HEAD(&synx_dev->client_list); INIT_LIST_HEAD(&synx_dev->import_list); synx_dev->dma_context = dma_fence_context_alloc(1); synx_dev->debugfs_root = init_synx_debug_dir(synx_dev); Loading
drivers/media/platform/msm/synx/synx_private.h +18 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,22 @@ struct synx_registered_ops { u32 type; }; /** * struct synx_import_data - Import metadata for sharing synx handles * with processes * * @key : Import key for sharing synx handle * @synx_obj : Synx handle being exported * @row : Pointer to synx object * @list : List member used to append the node to import list */ struct synx_import_data { u32 key; s32 synx_obj; struct synx_table_row *row; struct list_head list; }; /** * struct synx_device - Internal struct to book keep synx driver details * Loading @@ -175,6 +191,7 @@ struct synx_registered_ops { * debugfs_root : Root directory for debugfs * synx_node_head : list head for synx nodes * synx_node_list_lock : Spinlock for synx nodes * import_list : List to validate synx import requests */ struct synx_device { struct cdev cdev; Loading @@ -194,6 +211,7 @@ struct synx_device { struct dentry *debugfs_root; struct list_head synx_debug_head; spinlock_t synx_node_list_lock; struct list_head import_list; }; /** Loading
drivers/media/platform/msm/synx/synx_util.c +92 −0 Original line number Diff line number Diff line Loading @@ -579,6 +579,98 @@ struct synx_table_row *synx_from_fence(struct dma_fence *fence) return row; } struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key) { struct synx_import_data *data, *tmp_data; struct synx_table_row *row = NULL; mutex_lock(&synx_dev->table_lock); list_for_each_entry_safe(data, tmp_data, &synx_dev->import_list, list) { if (data->key == key && data->synx_obj == synx_obj) { pr_debug("found synx handle, importing 0x%x\n", synx_obj); row = data->row; list_del_init(&data->list); kfree(data); break; } } mutex_unlock(&synx_dev->table_lock); return row; } int synx_generate_import_key(struct synx_table_row *row, u32 *key) { bool bit; long idx = 0; struct synx_import_data *data; struct synx_table_row *new_row; if (!row) return -EINVAL; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; mutex_lock(&synx_dev->table_lock); do { /* obtain a random non-zero key */ get_random_bytes(key, sizeof(*key)); } while (!*key); data->key = *key; data->synx_obj = row->synx_obj; /* * Reason for separate metadata (for merged synx) * being dma fence array has separate release func * registed with dma fence ops, which doesn't invoke * release func registered by the framework to clear * metadata when all refs are released. * Hence we need to clear the metadata for merged synx * obj upon synx_release itself. But this creates a * problem if synx obj is exported. Thus need separate * metadata structures even though they represent same * synx obj. * Note, only the metadata is released, and the fence * reference count is decremented still. */ if (is_merged_synx(row)) { do { idx = find_first_zero_bit( synx_dev->bitmap, SYNX_MAX_OBJS); if (idx >= SYNX_MAX_OBJS) { kfree(data); mutex_unlock( &synx_dev->table_lock); return -ENOMEM; } bit = test_and_set_bit(idx, synx_dev->bitmap); } while (bit); new_row = synx_dev->synx_table + idx; /* both metadata points to same dma fence */ new_row->fence = row->fence; new_row->index = idx; INIT_LIST_HEAD(&new_row->callback_list); INIT_LIST_HEAD(&new_row->user_payload_list); data->row = new_row; } else { data->row = row; } list_add(&data->list, &synx_dev->import_list); pr_debug("allocated import key for 0x%x\n", row->synx_obj); mutex_unlock(&synx_dev->table_lock); return 0; } void *synx_from_key(s32 id, u32 secure_key) { struct synx_table_row *row = NULL; Loading
drivers/media/platform/msm/synx/synx_util.h +25 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,31 @@ struct bind_operations *synx_get_bind_ops(u32 type); */ int synx_generate_secure_key(struct synx_table_row *row); /** * @brief: Function to generate a key for authenticating requests * Generated key for synx object being exported is * verified during import. * * @param row : Pointer to the synx object row * @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, u32 *key); /** * @brief: Function to authenticate requests for importing synx handle * Used to verify the requests generated on synx object * being imported. * * @param synx_obj : Synx handle being imported * @param key : Key to authenticate import request * * @return Pointer to the synx object row for valid request. NULL otherwise. */ struct synx_table_row *synx_from_import_key(s32 synx_obj, u32 key); /** * @brief: Function to handle adding an error * code to a synx Loading