Loading drivers/soc/qcom/smcinvoke.c +68 −47 Original line number Diff line number Diff line Loading @@ -125,6 +125,10 @@ #define FILE_IS_REMOTE_OBJ(f) ((f)->f_op && (f)->f_op == &g_smcinvoke_fops) static DEFINE_MUTEX(g_smcinvoke_lock); #define NO_LOCK 0 #define TAKE_LOCK 1 #define MUTEX_LOCK(x) { if (x) mutex_lock(&g_smcinvoke_lock); } #define MUTEX_UNLOCK(x) { if (x) mutex_unlock(&g_smcinvoke_lock); } static DEFINE_HASHTABLE(g_cb_servers, 8); static LIST_HEAD(g_mem_objs); static uint16_t g_last_cb_server_id = CBOBJ_SERVER_ID_START; Loading @@ -134,6 +138,7 @@ static size_t g_max_cb_buf_size = SMCINVOKE_TZ_MIN_BUF_SIZE; static long smcinvoke_ioctl(struct file *, unsigned int, unsigned long); static int smcinvoke_open(struct inode *, struct file *); static int smcinvoke_release(struct inode *, struct file *); static int destroy_cb_server(uint16_t); static const struct file_operations g_smcinvoke_fops = { .owner = THIS_MODULE, Loading Loading @@ -195,6 +200,7 @@ struct smcinvoke_cb_txn { size_t cb_req_bytes; struct file **filp_to_release; struct hlist_node hash; struct kref ref_cnt; }; struct smcinvoke_server_info { Loading Loading @@ -272,10 +278,8 @@ static struct smcinvoke_mem_obj *find_mem_obj_locked(uint16_t mem_obj_id, { struct smcinvoke_mem_obj *mem_obj = NULL; if (list_empty(&g_mem_objs)) { pr_err("%s: mem obj %d not found\n", __func__, mem_obj_id); if (list_empty(&g_mem_objs)) return NULL; } list_for_each_entry(mem_obj, &g_mem_objs, list) { if ((is_mem_rgn_obj && Loading Loading @@ -373,9 +377,11 @@ static void free_pending_cbobj_locked(struct kref *kref) server = obj->server; kfree(obj); if ((server->state == SMCINVOKE_SERVER_STATE_DEFUNCT) && list_empty(&server->pending_cbobjs)) list_empty(&server->pending_cbobjs)) { hash_del(&server->hash); kfree(server); } } static int get_pending_cbobj_locked(uint16_t srvr_id, int16_t obj_id) { Loading Loading @@ -445,6 +451,15 @@ static void release_tzhandles(const int32_t *tzhandles, size_t len) mutex_unlock(&g_smcinvoke_lock); } static void delete_cb_txn(struct kref *kref) { struct smcinvoke_cb_txn *cb_txn = container_of(kref, struct smcinvoke_cb_txn, ref_cnt); kfree(cb_txn->cb_req); kfree(cb_txn); } static struct smcinvoke_cb_txn *find_cbtxn_locked( struct smcinvoke_server_info *server, uint32_t txn_id, int32_t state) Loading @@ -459,6 +474,7 @@ static struct smcinvoke_cb_txn *find_cbtxn_locked( if (state == SMCINVOKE_REQ_PLACED) { /* pick up 1st req */ hash_for_each(server->reqs_table, i, cb_txn, hash) { kref_get(&cb_txn->ref_cnt); hash_del(&cb_txn->hash); return cb_txn; } Loading @@ -466,6 +482,7 @@ static struct smcinvoke_cb_txn *find_cbtxn_locked( hash_for_each_possible( server->responses_table, cb_txn, hash, txn_id) { if (cb_txn->txn_id == txn_id) { kref_get(&cb_txn->ref_cnt); hash_del(&cb_txn->hash); return cb_txn; } Loading Loading @@ -612,14 +629,10 @@ static int get_tzhandle_from_uhandle(int32_t uhandle, int32_t server_fd, } } out: if (ret && *filp) { fput(*filp); *filp = NULL; } return ret; } static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd) static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int32_t *fd) { int unused_fd = -1, ret = -EINVAL; struct file *f = NULL; Loading Loading @@ -663,7 +676,7 @@ static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd) } static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, int64_t *uhandle) int32_t *uhandle, bool lock) { int ret = -1; Loading @@ -674,14 +687,14 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, if (srvr_id != TZHANDLE_GET_SERVER(tzhandle)) goto out; *uhandle = UHANDLE_MAKE_CB_OBJ(TZHANDLE_GET_OBJID(tzhandle)); mutex_lock(&g_smcinvoke_lock); ret = get_pending_cbobj_locked(srvr_id, MUTEX_LOCK(lock) ret = get_pending_cbobj_locked(TZHANDLE_GET_SERVER(tzhandle), TZHANDLE_GET_OBJID(tzhandle)); mutex_unlock(&g_smcinvoke_lock); MUTEX_UNLOCK(lock) } else if (TZHANDLE_IS_MEM_RGN_OBJ(tzhandle)) { struct smcinvoke_mem_obj *mem_obj = NULL; mutex_lock(&g_smcinvoke_lock); MUTEX_LOCK(lock) mem_obj = find_mem_obj_locked(TZHANDLE_GET_OBJID(tzhandle), SMCINVOKE_MEM_RGN_OBJ); Loading @@ -699,7 +712,7 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, ret = 0; } exit_lock: mutex_unlock(&g_smcinvoke_lock); MUTEX_UNLOCK(lock) } else if (TZHANDLE_IS_REMOTE(tzhandle)) { /* if execution comes here => tzhandle is an unsigned int */ ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_TZ_OBJ, Loading Loading @@ -826,7 +839,12 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) if (buf_len < sizeof(struct smcinvoke_tzcb_req)) return; cb_req = buf; cb_req = kmemdup(buf, buf_len, GFP_KERNEL); if (!cb_req) { ret = OBJECT_ERROR_KMEM; goto out; } /* check whether it is to be served by kernel or userspace */ if (TZHANDLE_IS_KERNEL_OBJ(cb_req->hdr.tzhandle)) { return process_kernel_obj(buf, buf_len); Loading @@ -847,6 +865,7 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) cb_txn->cb_req = cb_req; cb_txn->cb_req_bytes = buf_len; cb_txn->filp_to_release = arr_filp; kref_init(&cb_txn->ref_cnt); mutex_lock(&g_smcinvoke_lock); srvr_info = find_cb_server_locked( Loading @@ -860,9 +879,11 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) hash_add(srvr_info->reqs_table, &cb_txn->hash, cb_txn->txn_id); mutex_unlock(&g_smcinvoke_lock); wake_up_interruptible(&srvr_info->req_wait_q); wait_event(srvr_info->rsp_wait_q, ret = wait_event_interruptible(srvr_info->rsp_wait_q, (cb_txn->state == SMCINVOKE_REQ_PROCESSED) || (srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT)); if (ret) pr_err("%s wait_event interrupted: ret = %d\n", __func__, ret); out: /* * If we are here, either req is processed or not Loading @@ -870,19 +891,19 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) * if not processed, we should set result with ret which should have * correct value that TZ/TA can understand */ mutex_lock(&g_smcinvoke_lock); if (!cb_txn || (cb_txn->state != SMCINVOKE_REQ_PROCESSED)) { cb_req->result = ret; if (srvr_info && srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT && OBJECT_OP_METHODID(cb_req->hdr.op) == OBJECT_OP_RELEASE) { mutex_lock(&g_smcinvoke_lock); put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_req->hdr.tzhandle)); mutex_unlock(&g_smcinvoke_lock); release_tzhandle_locked(cb_req->hdr.tzhandle); } } kfree(cb_txn); hash_del(&cb_txn->hash); memcpy(buf, cb_req, buf_len); kref_put(&cb_txn->ref_cnt, delete_cb_txn); mutex_unlock(&g_smcinvoke_lock); } static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size, Loading Loading @@ -931,7 +952,8 @@ static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size, * to server who serves it and that info comes from USpace. */ ret = get_uhandle_from_tzhandle(tz_args->handle, args_buf[i].o.cb_server_fd, &(args_buf[i].o.fd)); TZHANDLE_GET_SERVER(tz_args->handle), (int32_t *)&(args_buf[i].o.fd), NO_LOCK); if (ret) goto out; tz_args++; Loading Loading @@ -1146,7 +1168,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn, user_req->txn_id = cb_txn->txn_id; if (get_uhandle_from_tzhandle(tzcb_req->hdr.tzhandle, srvr_id, (int64_t *)&user_req->cbobj_id)) { &user_req->cbobj_id, TAKE_LOCK)) { ret = -EINVAL; goto out; } Loading Loading @@ -1208,7 +1230,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn, * context */ ret = get_uhandle_from_tzhandle(tz_args[i].handle, srvr_id, &(tmp_arg.o.fd)); (int32_t *)&(tmp_arg.o.fd), TAKE_LOCK); if (ret) { ret = -EINVAL; goto out; Loading @@ -1232,10 +1254,8 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req, int32_t tzhandles_to_release[OBJECT_COUNTS_MAX_OO] = {0}; struct smcinvoke_tzcb_req *tzcb_req = cb_txn->cb_req; union smcinvoke_tz_args *tz_args = tzcb_req->args; put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle)); release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1); tzcb_req->result = user_req->result; FOR_ARGS(i, tzcb_req->hdr.counts, BO) { union smcinvoke_arg tmp_arg; Loading Loading @@ -1265,18 +1285,16 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req, ret = -EFAULT; goto out; } ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, 0, &arr_filp[i], ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, tmp_arg.o.cb_server_fd, &arr_filp[i], &(tz_args[i].handle)); if (ret) goto out; tzhandles_to_release[i] = tz_args[i].handle; } FOR_ARGS(i, tzcb_req->hdr.counts, OI) { if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle)) { put_pending_cbobj_locked( TZHANDLE_GET_SERVER(tz_args[i].handle), TZHANDLE_GET_OBJID(tz_args[i].handle)); } if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle)) release_tzhandles(&tz_args[i].handle, 1); } ret = 0; out: Loading Loading @@ -1334,7 +1352,7 @@ static long process_server_req(struct file *filp, unsigned int cmd, unsigned long arg) { int ret = -1; int64_t server_fd = -1; int32_t server_fd = -1; struct smcinvoke_server server_req = {0}; struct smcinvoke_server_info *server_info = NULL; Loading Loading @@ -1369,12 +1387,9 @@ static long process_server_req(struct file *filp, unsigned int cmd, ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_SERVER, server_info->server_id, &server_fd); if (ret) { mutex_lock(&g_smcinvoke_lock); hash_del(&server_info->hash); mutex_unlock(&g_smcinvoke_lock); kfree(server_info); } if (ret) destroy_cb_server(server_info->server_id); return server_fd; } Loading Loading @@ -1429,11 +1444,10 @@ static long process_accept_req(struct file *filp, unsigned int cmd, cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; if (OBJECT_OP_METHODID(user_args.op) == OBJECT_OP_RELEASE) put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle)); release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1); cb_txn->state = SMCINVOKE_REQ_PROCESSED; kref_put(&cb_txn->ref_cnt, delete_cb_txn); wake_up(&server_info->rsp_wait_q); /* * if marshal_out fails, we should let userspace release Loading @@ -1449,8 +1463,11 @@ static long process_accept_req(struct file *filp, unsigned int cmd, do { ret = wait_event_interruptible(server_info->req_wait_q, !hash_empty(server_info->reqs_table)); if (ret) if (ret) { pr_err("%s wait_event interrupted: ret = %d\n", __func__, ret); goto out; } mutex_lock(&g_smcinvoke_lock); cb_txn = find_cbtxn_locked(server_info, Loading @@ -1464,12 +1481,14 @@ static long process_accept_req(struct file *filp, unsigned int cmd, if (ret) { cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; cb_txn->state = SMCINVOKE_REQ_PROCESSED; kref_put(&cb_txn->ref_cnt, delete_cb_txn); wake_up_interruptible(&server_info->rsp_wait_q); continue; } mutex_lock(&g_smcinvoke_lock); hash_add(server_info->responses_table, &cb_txn->hash, cb_txn->txn_id); kref_put(&cb_txn->ref_cnt, delete_cb_txn); mutex_unlock(&g_smcinvoke_lock); ret = copy_to_user((void __user *)arg, &user_args, sizeof(struct smcinvoke_accept)); Loading Loading @@ -1697,6 +1716,8 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp) goto out; } memset(in_buf, 0, PAGE_SIZE); memset(out_buf, 0, PAGE_SIZE); hdr.tzhandle = tzhandle; hdr.op = OBJECT_OP_RELEASE; hdr.counts = 0; Loading Loading
drivers/soc/qcom/smcinvoke.c +68 −47 Original line number Diff line number Diff line Loading @@ -125,6 +125,10 @@ #define FILE_IS_REMOTE_OBJ(f) ((f)->f_op && (f)->f_op == &g_smcinvoke_fops) static DEFINE_MUTEX(g_smcinvoke_lock); #define NO_LOCK 0 #define TAKE_LOCK 1 #define MUTEX_LOCK(x) { if (x) mutex_lock(&g_smcinvoke_lock); } #define MUTEX_UNLOCK(x) { if (x) mutex_unlock(&g_smcinvoke_lock); } static DEFINE_HASHTABLE(g_cb_servers, 8); static LIST_HEAD(g_mem_objs); static uint16_t g_last_cb_server_id = CBOBJ_SERVER_ID_START; Loading @@ -134,6 +138,7 @@ static size_t g_max_cb_buf_size = SMCINVOKE_TZ_MIN_BUF_SIZE; static long smcinvoke_ioctl(struct file *, unsigned int, unsigned long); static int smcinvoke_open(struct inode *, struct file *); static int smcinvoke_release(struct inode *, struct file *); static int destroy_cb_server(uint16_t); static const struct file_operations g_smcinvoke_fops = { .owner = THIS_MODULE, Loading Loading @@ -195,6 +200,7 @@ struct smcinvoke_cb_txn { size_t cb_req_bytes; struct file **filp_to_release; struct hlist_node hash; struct kref ref_cnt; }; struct smcinvoke_server_info { Loading Loading @@ -272,10 +278,8 @@ static struct smcinvoke_mem_obj *find_mem_obj_locked(uint16_t mem_obj_id, { struct smcinvoke_mem_obj *mem_obj = NULL; if (list_empty(&g_mem_objs)) { pr_err("%s: mem obj %d not found\n", __func__, mem_obj_id); if (list_empty(&g_mem_objs)) return NULL; } list_for_each_entry(mem_obj, &g_mem_objs, list) { if ((is_mem_rgn_obj && Loading Loading @@ -373,9 +377,11 @@ static void free_pending_cbobj_locked(struct kref *kref) server = obj->server; kfree(obj); if ((server->state == SMCINVOKE_SERVER_STATE_DEFUNCT) && list_empty(&server->pending_cbobjs)) list_empty(&server->pending_cbobjs)) { hash_del(&server->hash); kfree(server); } } static int get_pending_cbobj_locked(uint16_t srvr_id, int16_t obj_id) { Loading Loading @@ -445,6 +451,15 @@ static void release_tzhandles(const int32_t *tzhandles, size_t len) mutex_unlock(&g_smcinvoke_lock); } static void delete_cb_txn(struct kref *kref) { struct smcinvoke_cb_txn *cb_txn = container_of(kref, struct smcinvoke_cb_txn, ref_cnt); kfree(cb_txn->cb_req); kfree(cb_txn); } static struct smcinvoke_cb_txn *find_cbtxn_locked( struct smcinvoke_server_info *server, uint32_t txn_id, int32_t state) Loading @@ -459,6 +474,7 @@ static struct smcinvoke_cb_txn *find_cbtxn_locked( if (state == SMCINVOKE_REQ_PLACED) { /* pick up 1st req */ hash_for_each(server->reqs_table, i, cb_txn, hash) { kref_get(&cb_txn->ref_cnt); hash_del(&cb_txn->hash); return cb_txn; } Loading @@ -466,6 +482,7 @@ static struct smcinvoke_cb_txn *find_cbtxn_locked( hash_for_each_possible( server->responses_table, cb_txn, hash, txn_id) { if (cb_txn->txn_id == txn_id) { kref_get(&cb_txn->ref_cnt); hash_del(&cb_txn->hash); return cb_txn; } Loading Loading @@ -612,14 +629,10 @@ static int get_tzhandle_from_uhandle(int32_t uhandle, int32_t server_fd, } } out: if (ret && *filp) { fput(*filp); *filp = NULL; } return ret; } static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd) static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int32_t *fd) { int unused_fd = -1, ret = -EINVAL; struct file *f = NULL; Loading Loading @@ -663,7 +676,7 @@ static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd) } static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, int64_t *uhandle) int32_t *uhandle, bool lock) { int ret = -1; Loading @@ -674,14 +687,14 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, if (srvr_id != TZHANDLE_GET_SERVER(tzhandle)) goto out; *uhandle = UHANDLE_MAKE_CB_OBJ(TZHANDLE_GET_OBJID(tzhandle)); mutex_lock(&g_smcinvoke_lock); ret = get_pending_cbobj_locked(srvr_id, MUTEX_LOCK(lock) ret = get_pending_cbobj_locked(TZHANDLE_GET_SERVER(tzhandle), TZHANDLE_GET_OBJID(tzhandle)); mutex_unlock(&g_smcinvoke_lock); MUTEX_UNLOCK(lock) } else if (TZHANDLE_IS_MEM_RGN_OBJ(tzhandle)) { struct smcinvoke_mem_obj *mem_obj = NULL; mutex_lock(&g_smcinvoke_lock); MUTEX_LOCK(lock) mem_obj = find_mem_obj_locked(TZHANDLE_GET_OBJID(tzhandle), SMCINVOKE_MEM_RGN_OBJ); Loading @@ -699,7 +712,7 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, ret = 0; } exit_lock: mutex_unlock(&g_smcinvoke_lock); MUTEX_UNLOCK(lock) } else if (TZHANDLE_IS_REMOTE(tzhandle)) { /* if execution comes here => tzhandle is an unsigned int */ ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_TZ_OBJ, Loading Loading @@ -826,7 +839,12 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) if (buf_len < sizeof(struct smcinvoke_tzcb_req)) return; cb_req = buf; cb_req = kmemdup(buf, buf_len, GFP_KERNEL); if (!cb_req) { ret = OBJECT_ERROR_KMEM; goto out; } /* check whether it is to be served by kernel or userspace */ if (TZHANDLE_IS_KERNEL_OBJ(cb_req->hdr.tzhandle)) { return process_kernel_obj(buf, buf_len); Loading @@ -847,6 +865,7 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) cb_txn->cb_req = cb_req; cb_txn->cb_req_bytes = buf_len; cb_txn->filp_to_release = arr_filp; kref_init(&cb_txn->ref_cnt); mutex_lock(&g_smcinvoke_lock); srvr_info = find_cb_server_locked( Loading @@ -860,9 +879,11 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) hash_add(srvr_info->reqs_table, &cb_txn->hash, cb_txn->txn_id); mutex_unlock(&g_smcinvoke_lock); wake_up_interruptible(&srvr_info->req_wait_q); wait_event(srvr_info->rsp_wait_q, ret = wait_event_interruptible(srvr_info->rsp_wait_q, (cb_txn->state == SMCINVOKE_REQ_PROCESSED) || (srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT)); if (ret) pr_err("%s wait_event interrupted: ret = %d\n", __func__, ret); out: /* * If we are here, either req is processed or not Loading @@ -870,19 +891,19 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) * if not processed, we should set result with ret which should have * correct value that TZ/TA can understand */ mutex_lock(&g_smcinvoke_lock); if (!cb_txn || (cb_txn->state != SMCINVOKE_REQ_PROCESSED)) { cb_req->result = ret; if (srvr_info && srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT && OBJECT_OP_METHODID(cb_req->hdr.op) == OBJECT_OP_RELEASE) { mutex_lock(&g_smcinvoke_lock); put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_req->hdr.tzhandle)); mutex_unlock(&g_smcinvoke_lock); release_tzhandle_locked(cb_req->hdr.tzhandle); } } kfree(cb_txn); hash_del(&cb_txn->hash); memcpy(buf, cb_req, buf_len); kref_put(&cb_txn->ref_cnt, delete_cb_txn); mutex_unlock(&g_smcinvoke_lock); } static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size, Loading Loading @@ -931,7 +952,8 @@ static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size, * to server who serves it and that info comes from USpace. */ ret = get_uhandle_from_tzhandle(tz_args->handle, args_buf[i].o.cb_server_fd, &(args_buf[i].o.fd)); TZHANDLE_GET_SERVER(tz_args->handle), (int32_t *)&(args_buf[i].o.fd), NO_LOCK); if (ret) goto out; tz_args++; Loading Loading @@ -1146,7 +1168,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn, user_req->txn_id = cb_txn->txn_id; if (get_uhandle_from_tzhandle(tzcb_req->hdr.tzhandle, srvr_id, (int64_t *)&user_req->cbobj_id)) { &user_req->cbobj_id, TAKE_LOCK)) { ret = -EINVAL; goto out; } Loading Loading @@ -1208,7 +1230,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn, * context */ ret = get_uhandle_from_tzhandle(tz_args[i].handle, srvr_id, &(tmp_arg.o.fd)); (int32_t *)&(tmp_arg.o.fd), TAKE_LOCK); if (ret) { ret = -EINVAL; goto out; Loading @@ -1232,10 +1254,8 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req, int32_t tzhandles_to_release[OBJECT_COUNTS_MAX_OO] = {0}; struct smcinvoke_tzcb_req *tzcb_req = cb_txn->cb_req; union smcinvoke_tz_args *tz_args = tzcb_req->args; put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle)); release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1); tzcb_req->result = user_req->result; FOR_ARGS(i, tzcb_req->hdr.counts, BO) { union smcinvoke_arg tmp_arg; Loading Loading @@ -1265,18 +1285,16 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req, ret = -EFAULT; goto out; } ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, 0, &arr_filp[i], ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, tmp_arg.o.cb_server_fd, &arr_filp[i], &(tz_args[i].handle)); if (ret) goto out; tzhandles_to_release[i] = tz_args[i].handle; } FOR_ARGS(i, tzcb_req->hdr.counts, OI) { if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle)) { put_pending_cbobj_locked( TZHANDLE_GET_SERVER(tz_args[i].handle), TZHANDLE_GET_OBJID(tz_args[i].handle)); } if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle)) release_tzhandles(&tz_args[i].handle, 1); } ret = 0; out: Loading Loading @@ -1334,7 +1352,7 @@ static long process_server_req(struct file *filp, unsigned int cmd, unsigned long arg) { int ret = -1; int64_t server_fd = -1; int32_t server_fd = -1; struct smcinvoke_server server_req = {0}; struct smcinvoke_server_info *server_info = NULL; Loading Loading @@ -1369,12 +1387,9 @@ static long process_server_req(struct file *filp, unsigned int cmd, ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_SERVER, server_info->server_id, &server_fd); if (ret) { mutex_lock(&g_smcinvoke_lock); hash_del(&server_info->hash); mutex_unlock(&g_smcinvoke_lock); kfree(server_info); } if (ret) destroy_cb_server(server_info->server_id); return server_fd; } Loading Loading @@ -1429,11 +1444,10 @@ static long process_accept_req(struct file *filp, unsigned int cmd, cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; if (OBJECT_OP_METHODID(user_args.op) == OBJECT_OP_RELEASE) put_pending_cbobj_locked( TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle), TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle)); release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1); cb_txn->state = SMCINVOKE_REQ_PROCESSED; kref_put(&cb_txn->ref_cnt, delete_cb_txn); wake_up(&server_info->rsp_wait_q); /* * if marshal_out fails, we should let userspace release Loading @@ -1449,8 +1463,11 @@ static long process_accept_req(struct file *filp, unsigned int cmd, do { ret = wait_event_interruptible(server_info->req_wait_q, !hash_empty(server_info->reqs_table)); if (ret) if (ret) { pr_err("%s wait_event interrupted: ret = %d\n", __func__, ret); goto out; } mutex_lock(&g_smcinvoke_lock); cb_txn = find_cbtxn_locked(server_info, Loading @@ -1464,12 +1481,14 @@ static long process_accept_req(struct file *filp, unsigned int cmd, if (ret) { cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; cb_txn->state = SMCINVOKE_REQ_PROCESSED; kref_put(&cb_txn->ref_cnt, delete_cb_txn); wake_up_interruptible(&server_info->rsp_wait_q); continue; } mutex_lock(&g_smcinvoke_lock); hash_add(server_info->responses_table, &cb_txn->hash, cb_txn->txn_id); kref_put(&cb_txn->ref_cnt, delete_cb_txn); mutex_unlock(&g_smcinvoke_lock); ret = copy_to_user((void __user *)arg, &user_args, sizeof(struct smcinvoke_accept)); Loading Loading @@ -1697,6 +1716,8 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp) goto out; } memset(in_buf, 0, PAGE_SIZE); memset(out_buf, 0, PAGE_SIZE); hdr.tzhandle = tzhandle; hdr.op = OBJECT_OP_RELEASE; hdr.counts = 0; Loading