1/*
2 * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd.
3 * Description: dynamic Ion memory allocation and free.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "dynamic_ion_mem.h"
16#include <linux/version.h>
17#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
18#include <stdarg.h>
19#else
20#include <linux/stdarg.h>
21#endif
22#include <linux/workqueue.h>
23#include <linux/kthread.h>
24#include <linux/list.h>
25#include <linux/sched.h>
26#include <linux/delay.h>
27#include <linux/mutex.h>
28#include <linux/timer.h>
29#include <linux/kernel.h>
30#include <linux/uaccess.h>
31#include <linux/debugfs.h>
32#include <linux/module.h>
33#include <linux/version.h>
34#ifndef CONFIG_DMABUF_MM
35#include <linux/ion.h>
36#endif
37#include <linux/mm.h>
38#include <linux/cma.h>
39#include <asm/tlbflush.h>
40#include <asm/cacheflush.h>
41#if ((defined CONFIG_ION_MM) || (defined CONFIG_ION_MM_SECSG))
42#include <linux/ion/mm_ion.h>
43#endif
44#ifdef CONFIG_DMABUF_MM
45#include <linux/dmabuf/mm_dma_heap.h>
46#endif
47#include "tc_ns_log.h"
48#include "tc_ns_client.h"
49#include "smc_smp.h"
50#include "gp_ops.h"
51#include "teek_client_constants.h"
52#include "mailbox_mempool.h"
53#include "dynamic_ion_uuid.h"
54
55static DEFINE_MUTEX(dynamic_mem_lock);
56struct dynamic_mem_list {
57	struct list_head list;
58};
59
60static const struct dynamic_mem_config g_dyn_mem_config[] = {
61	#ifdef DEF_ENG
62	{TEE_SERVICE_UT, SEC_EID},
63	{TEE_SERVICE_TEST_DYNION, SEC_AI_ION},
64	#endif
65	{TEE_SECIDENTIFICATION1, SEC_EID},
66	{TEE_SECIDENTIFICATION3, SEC_EID},
67	{TEE_SERVICE_AI, SEC_AI_ION},
68	{TEE_SERVICE_AI_TINY, SEC_AI_ION},
69	{TEE_SERVICE_VCODEC, SEC_DRM_TEE},
70};
71
72static struct dynamic_mem_list g_dynamic_mem_list;
73static const uint32_t g_dyn_mem_config_num = ARRAY_SIZE(g_dyn_mem_config);
74
75static int release_ion_srv(const struct tc_uuid *uuid)
76{
77	struct tc_ns_smc_cmd smc_cmd = {{0}, 0};
78
79	smc_cmd.err_origin = TEEC_ORIGIN_COMMS;
80	smc_cmd.cmd_type = CMD_TYPE_GLOBAL;
81	smc_cmd.cmd_id = GLOBAL_CMD_ID_RELEASE_ION_SRV;
82	if (memcpy_s(&smc_cmd.uuid, sizeof(smc_cmd.uuid), uuid, sizeof(*uuid))) {
83		tloge("copy uuid failed\n");
84		return -ENOMEM;
85	}
86
87	if (tc_ns_smc(&smc_cmd)) {
88		tloge("send release ion srv cmd failed\n");
89		return -EPERM;
90	}
91	return 0;
92}
93
94
95static int get_ion_sglist(struct dynamic_mem_item *mem_item)
96{
97	struct sglist *tmp_sglist = NULL;
98	struct scatterlist *sg = NULL;
99	struct page *page = NULL;
100	uint32_t sglist_size;
101	uint32_t i = 0;
102	struct sg_table *ion_sg_table = mem_item->memory.dyn_sg_table;
103
104	if (!ion_sg_table)
105		return -EINVAL;
106
107	if (ion_sg_table->nents <= 0 || ion_sg_table->nents > MAX_ION_NENTS)
108		return -EINVAL;
109
110	for_each_sg(ion_sg_table->sgl, sg, ion_sg_table->nents, i) {
111		if (!sg) {
112			tloge("an error sg when get ion sglist\n");
113			return -EINVAL;
114		}
115	}
116
117	sglist_size = sizeof(struct ion_page_info) * ion_sg_table->nents + sizeof(*tmp_sglist);
118	tmp_sglist = (struct sglist *)mailbox_alloc(sglist_size, MB_FLAG_ZERO);
119	if (!tmp_sglist) {
120		tloge("mailbox alloc failed\n");
121		return -ENOMEM;
122	}
123
124	tmp_sglist->sglist_size = (uint64_t)sglist_size;
125	tmp_sglist->ion_size = (uint64_t)mem_item->size;
126	tmp_sglist->info_length = (uint64_t)ion_sg_table->nents;
127	for_each_sg(ion_sg_table->sgl, sg, ion_sg_table->nents, i) {
128		page = sg_page(sg);
129		tmp_sglist->page_info[i].phys_addr = page_to_phys(page);
130		tmp_sglist->page_info[i].npages = sg->length / PAGE_SIZE;
131	}
132	mem_item->memory.ion_phys_addr = mailbox_virt_to_phys((uintptr_t)(void *)tmp_sglist);
133	mem_item->memory.len = sglist_size;
134	return 0;
135}
136
137static int send_dyn_ion_cmd(struct dynamic_mem_item *mem_item, unsigned int cmd_id, int32_t *ret_origin)
138{
139	struct tc_ns_smc_cmd smc_cmd = {{0}, 0};
140	int ret;
141	struct mb_cmd_pack *mb_pack = NULL;
142
143	if (!mem_item) {
144		tloge("mem_item is null\n");
145		return -EINVAL;
146	}
147
148	ret = get_ion_sglist(mem_item);
149	if (ret != 0)
150		return ret;
151
152	mb_pack = mailbox_alloc_cmd_pack();
153	if (!mb_pack) {
154		mailbox_free(phys_to_virt(mem_item->memory.ion_phys_addr));
155		tloge("alloc cmd pack failed\n");
156		return -ENOMEM;
157	}
158	smc_cmd.cmd_type = CMD_TYPE_GLOBAL;
159	smc_cmd.cmd_id = cmd_id;
160	smc_cmd.err_origin = TEEC_ORIGIN_COMMS;
161	mb_pack->operation.paramtypes = teec_param_types(
162		TEE_PARAM_TYPE_ION_SGLIST_INPUT,
163		TEE_PARAM_TYPE_VALUE_INPUT,
164		TEE_PARAM_TYPE_VALUE_INPUT,
165		TEE_PARAM_TYPE_NONE);
166
167	mb_pack->operation.params[0].memref.size = (uint32_t)mem_item->memory.len;
168	mb_pack->operation.params[0].memref.buffer =
169	(uint32_t)(mem_item->memory.ion_phys_addr & 0xFFFFFFFF);
170	mb_pack->operation.buffer_h_addr[0] =
171	(uint64_t)(mem_item->memory.ion_phys_addr) >> ADDR_TRANS_NUM;
172	mb_pack->operation.params[1].value.a = (uint32_t)mem_item->size;
173	mb_pack->operation.params[2].value.a = mem_item->configid;
174	smc_cmd.operation_phys = (unsigned int)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation);
175	smc_cmd.operation_h_phys = (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM;
176
177	if (tc_ns_smc(&smc_cmd)) {
178		if (ret_origin)
179			*ret_origin = smc_cmd.err_origin;
180		ret = -EPERM;
181		tlogd("send loadapp ion failed\n");
182	}
183	mailbox_free(phys_to_virt(mem_item->memory.ion_phys_addr));
184	mailbox_free(mb_pack);
185	return ret;
186}
187
188static struct dynamic_mem_item *find_memitem_by_configid_locked(uint32_t configid)
189{
190	struct dynamic_mem_item *item = NULL;
191	list_for_each_entry(item, &g_dynamic_mem_list.list, head) {
192		if (item->configid == configid)
193			return item;
194	}
195	return NULL;
196}
197
198static struct dynamic_mem_item *find_memitem_by_uuid_locked(const struct tc_uuid *uuid)
199{
200	struct dynamic_mem_item *item = NULL;
201	list_for_each_entry(item, &g_dynamic_mem_list.list, head) {
202		if (!memcmp(&item->uuid, uuid, sizeof(*uuid)))
203			return item;
204	}
205	return NULL;
206}
207
208#define BLOCK_64KB_SIZE (64 * 1024) /* 64 */
209#define BLOCK_64KB_MASK 0xFFFFFFFFFFFF0000
210/* size should be aligned with 64KB */
211#define BLOCK_64KB_SIZE_MASK (BLOCK_64KB_SIZE -1)
212static int proc_alloc_dyn_mem(struct dynamic_mem_item *mem_item)
213{
214	struct sg_table *ion_sg_table = NULL;
215
216	if (mem_item->size + BLOCK_64KB_SIZE_MASK < mem_item->size) {
217		tloge("ion size is error, size = %x\n", mem_item->size);
218		return -EINVAL;
219	}
220	mem_item->memory.len = (mem_item ->size + BLOCK_64KB_SIZE_MASK) & BLOCK_64KB_MASK;
221
222	ion_sg_table = mm_secmem_alloc(mem_item->addr_sec_region,
223		mem_item->memory.len);
224	if (!ion_sg_table) {
225		tloge("failed to get ion page, configid = %d\n",
226			mem_item->configid);
227		return -ENOMEM;
228	}
229	mem_item->memory.dyn_sg_table = ion_sg_table;
230	return 0;
231}
232
233static void proc_free_dyn_mem(struct dynamic_mem_item *mem_item)
234{
235	if (!mem_item->memory.dyn_sg_table) {
236		tloge("ion_phys_addr is NULL\n");
237		return;
238	}
239	mm_secmem_free(mem_item->ddr_sec_region,
240		mem_item->memory.dyn_sg_table);
241	mem_item->memory.dyn_sg_table = NULL;
242	return;
243}
244
245int init_dynamic_mem(void)
246{
247	INIT_LIST_HEAD(&(g_dynamic_mem_list.list));
248	return 0;
249}
250
251static int32_t find_ddr_sec_region_by_uuid(const struct tc_uuid *uuid,
252	uint32_t *ddr_sec_region)
253{
254	uint32_t i;
255	for (i = 0; i < g_dyn_mem_config_num; i++) {
256		if (!memcmp(&(g_dyn_mem_config[i].uuid), uuid,
257			sizeof(*uuid))) {
258			*ddr_sec_region = g_dyn_mem_config[i].ddr_sec_region;
259		return 0;
260		}
261	}
262	return -EINVAL;
263}
264
265static struct dynamic_mem_item *alloc_dyn_mem_item(uint32_t configid,
266	uint32_t cafd, const struct tc_uuid *uuid, uint32_t size)
267{
268	uint32_t ddr_sec_region;
269	struct dynamic_mem_item *mem_item = NULL;
270	int32_t result;
271
272	result = find_ddr_sec_region_by_uuid(uuid, &ddr_sec_region);
273	if (result != 0) {
274		tloge("find ddr sec region failed\n");
275		return NULL;
276	}
277
278	mem_item = kzalloc(sizeof(*mem_item), GFP_KERNEL);
279	if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)mem_item)) {
280		tloge("alloc mem item failed\n");
281		return NULL;
282	}
283
284	mem_item->ddr_sec_region = ddr_sec_region;
285	mem_item->configid = configid;
286	mem_item->size = size;
287	mem_item->cafd = cafd;
288	result = memcpy_s(&mem_item->uuid, sizeof(mem_item->uuid), uuid,
289		sizeof(*uuid));
290	if(result != EOK) {
291		tloge("memcpy uuid failed\n");
292		kfree(mem_item);
293		return NULL;
294	}
295	return mem_item;
296}
297
298
299static int trans_configid2memid(uint32_t configid, uint32_t cafd,
300	const struct tc_uuid *uuid, uint32_t size, int32_t *ret_origin)
301{
302	int result;
303
304	if (!uuid)
305		return -EINVAL;
306	mutex_lock(&dynamic_mem_lock);
307	do {
308		struct dynamic_mem_item *mem_item =
309		find_memitem_by_configid_locked(configid);
310		if (mem_item) {
311			result = -EINVAL;
312			break;
313		}
314
315		mem_item = alloc_dyn_mem_item(configid, cafd, uuid, size);
316		if (!mem_item) {
317			tloge("alloc dyn mem item failed\n");
318			result = -ENOMEM;
319			break;
320		}
321
322		result = proc_alloc_dyn_mem(mem_item);
323		if (result != 0) {
324			tloge("alloc dyn mem failed , ret = %d\n", result);
325			kfree(mem_item);
326			break;
327		}
328		/* register to tee */
329		result = send_dyn_ion_cmd(mem_item, GLOBAL_CMD_ID_ADD_DYNAMIC_ION, ret_origin);
330		if (result != 0) {
331			tloge("register to tee failed, result = %d\n", result);
332			proc_free_dyn_mem(mem_item);
333			kfree(mem_item);
334			break;
335		}
336		list_add_tail(&mem_item->head, &g_dynamic_mem_list.list);
337		tloge("log import:alloc ion configid=%d\n",
338			mem_item->configid);
339	} while (0);
340
341	mutex_unlock(&dynamic_mem_lock);
342	return result;
343}
344
345static void release_configid_mem_locked(uint32_t configid)
346{
347	int result;
348	/* if config id is memid map, and can reuse */
349	do {
350		struct dynamic_mem_item *mem_item =
351		find_memitem_by_configid_locked(configid);
352		if (!mem_item) {
353			tloge("fail to find memitem by configid\n");
354			break;
355		}
356
357		result = send_dyn_ion_cmd(mem_item, GLOBAL_CMD_ID_DEL_DYNAMIC_ION, NULL);
358		if (result != 0) {
359			tloge("unregister_from_tee configid=%d, result =%d\n",
360				mem_item->configid, result);
361			break;
362		}
363		proc_free_dyn_mem(mem_item);
364		list_del(&mem_item->head);
365		kfree(mem_item);
366		tloge("log import: free ion\n");
367	} while (0);
368
369	return;
370}
371
372
373int load_app_use_configid(uint32_t configid, uint32_t cafd,
374	const struct tc_uuid *uuid, uint32_t size, int32_t *ret_origin)
375{
376	int result;
377
378	if (!uuid)
379		return -EINVAL;
380
381	result = trans_configid2memid(configid, cafd, uuid, size, ret_origin);
382	if (result != 0) {
383		tloge("trans_configid2memid failed ret = %d\n", result);
384		if (release_ion_srv(uuid) != 0)
385			tloge("release ion srv failed\n");
386	}
387	return result;
388}
389
390
391void kill_ion_by_uuid(const struct tc_uuid *uuid)
392{
393	if (!uuid) {
394		tloge("uuid is null\n");
395		return;
396	}
397	mutex_lock(&dynamic_mem_lock);
398	do {
399		struct dynamic_mem_item *mem_item =
400		find_memitem_by_uuid_locked(uuid);
401		if (!mem_item)
402			break;
403		tlogd("kill ION by UUID\n");
404		release_configid_mem_locked(mem_item->configid);
405	} while (0);
406	mutex_unlock(&dynamic_mem_lock);
407}
408
409void kill_ion_by_cafd(unsigned int cafd)
410{
411	struct dynamic_mem_item *item = NULL;
412	struct dynamic_mem_item *temp = NULL;
413	tlogd("kill_ion_by_cafd:\n");
414	mutex_lock(&dynamic_mem_lock);
415	list_for_each_entry_safe(item, temp, &g_dynamic_mem_list.list, head) {
416		if (item->cafd == cafd)
417			release_configid_mem_locked(item->configid);
418	}
419	mutex_unlock(&dynamic_mem_lock);
420}
421
422int load_image_for_ion(const struct load_img_params *params, int32_t *ret_origin)
423{
424	int ret = 0;
425
426	if (!params)
427		return -EFAULT;
428	/* check need to add ionmem */
429	uint32_t configid = params->mb_pack->operation.params[1].value.a;
430	uint32_t ion_size = params->mb_pack->operation.params[1].value.b;
431	int32_t check_result = (configid != 0 && ion_size != 0);
432
433	tloge("check load result=%d, cfgid=%d, ion_size=%d, uuid=%x\n",
434		check_result, configid, ion_size, params->uuid_return->time_low);
435	if (check_result) {
436		ret = load_app_use_configid(configid, params->dev_file->dev_file_id,
437			params->uuid_return, ion_sizeret_origin);
438		if (ret != 0) {
439			tloge("load app use configid failed ret=%d\n", ret);
440			return -EFAULT;
441		}
442	}
443	return ret;
444}
445
446bool is_ion_param(uint32_t param_type)
447{
448	if (param_type == TEEC_ION_INPUT ||
449		param_type == TEEC_ION_SGLIST_INPUT)
450		return true;
451	return false;
452}
453
454static void fill_sg_list(struct sg_table *ion_table,
455	uint32_t ion_list_num, struct sglist *tmp_sglist)
456{
457	uint32_t i;
458	struct page *page = NULL;
459	struct scatterlist *sg = NULL;
460
461	for_each_sg(ion_table->sgl, sg, ion_list_num, i) {
462		page = sg_page(sg);
463		tmp_sglist->page_info[i].phys_addr = page_to_phys(page);
464		tmp_sglist->page_info[i].npages = sg->length / PAGE_SIZE;
465	}
466}
467
468static int check_sg_list(const struct sg_table *ion_table, uint32_t ion_list_num)
469{
470	struct scatterlist *sg = NULL;
471	uint32_t i;
472	for_each_sg(ion_table->sgl, sg, ion_list_num, i) {
473		if (!sg) {
474			tloge("an error sg when get ion sglist \n");
475			return -EFAULT;
476		}
477	}
478	return 0;
479}
480
481static int get_ion_sg_list_from_fd(uint32_t ion_shared_fd,
482	uint32_t ion_alloc_size, phys_addr_t *sglist_table,
483	size_t *ion_sglist_size)
484{
485	struct sg_table *ion_table = NULL;
486	struct sglist *tmp_sglist = NULL;
487	uint64_t ion_id = 0;
488	enum SEC_SVC ion_type = 0;
489	uint32_t ion_list_num = 0;
490	uint32_t sglist_size;
491#ifdef CONFIG_DMABUF_MM
492	if (mm_dma_heap_secmem_get_buffer(ion_shared_fd, &ion_table, &ion_id, &ion_type)) {
493#else
494	if (secmem_get_buffer(ion_shared_fd, &ion_table, &ion_id, &ion_type)) {
495#endif
496		tloge("get ion table failed. \n");
497		return -EFAULT;
498	}
499
500	if (ion_type != SEC_DRM_TEE) {
501		if (ion_table->nents <= 0 || ion_table->nents > MAX_ION_NENTS)
502			return -EFAULT;
503		ion_list_num = (uint32_t)(ion_table->nents & INT_MAX);
504		if (check_sg_list(ion_table, ion_list_num) != 0)
505			return -EFAULT;
506	}
507	/* ion_list_num is less than 1024, so sglist_size won't flow */
508	sglist_size = sizeof(struct ion_page_info) * ion_list_num + sizeof(*tmp_sglist);
509	tmp_sglist = (struct sglist *)mailbox_alloc(sglist_size, MB_FLAG_ZERO);
510	if (!tmp_sglist) {
511		tloge("sglist mem alloc failed\n");
512		return -ENOMEM;
513	}
514	tmp_sglist->sglist_size = (uint64_t)sglist_size;
515	tmp_sglist->ion_size = (uint64_t)ion_alloc_size;
516	tmp_sglist->info_length = (uint64_t)ion_list_num;
517	if (ion_type != SEC_DRM_TEE)
518		fill_sg_list(ion_table, ion_list_num, tmp_sglist);
519	else
520		tmp_sglist->ion_id = ion_id;
521
522	*sglist_table = mailbox_virt_to_phys((uintptr_t)tmp_sglist);
523	*ion_sglist_size = sglist_size;
524	return 0;
525}
526
527int alloc_for_ion_sglist(const struct tc_call_params *call_params,
528	struct tc_op_params *op_params, uint8_t kernel_params,
529	uint32_t param_type, unsigned int index)
530{
531	struct tc_ns_operation *operation = NULL;
532	size_t ion_sglist_size = 0;
533	phys_addr_t ion_sglist_addr = 0x0;
534	union tc_ns_client_param *client_param = NULL;
535	unsigned int ion_shared_fd = 0;
536	unsigned int ion_alloc_size;
537	uint64_t a_addr, b_addr;
538
539	/* this never happens */
540	if (index >= TEE_PARAM_NUM || !call_params || !op_params)
541		return -EINVAL;
542
543	operation = &op_params->mb_pack->operation;
544	client_param = &(call_params->context->params[index]);
545	a_addr = client_param->value.a_addr |
546	((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM);
547	b_addr = client_param->value.b_addr |
548	((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM);
549
550	if (read_from_client(&operation->params[index].value.a,
551		sizeof(operation->params[index].value.a),
552		(void *)(uintptr_t)a_addr,
553		sizeof(operation->params[index].value.a), kernel_params)) {
554		tloge("valuea copy failed\n");
555		return -EFAULT;
556	}
557	if (read_from_client(&operation->params[index].value.b,
558		sizeof(operation->params[index].value.b),
559		(void *)(uintptr_t)b_addr,
560		sizeof(operation->params[index].value.b), kernel_params)) {
561		tloge("valueb copy failed\n");
562		return -EFAULT;
563	}
564	ion_shared_fd = operation->params[index].value.a;
565	ion_alloc_size = operation->params[index].value.b;
566
567	if(get_ion_sg_list_from_fd(ion_shared_fd, ion_alloc_size,
568		&ion_sglist_addr, &ion_sglist_size)) {
569		tloge("get ion sglist failed, fd=%u\n", ion_shared_fd);
570		return -EFAULT;
571	}
572	op_params->local_tmpbuf[index].temp_buffer = phys_to_virt(ion_sglist_addr);
573	op_params->local_tmpbuf[index].size = ion_sglist_size;
574
575	operation->params[index].memref.buffer = (unsigned int)ion_sglist_addr;
576	operation->buffer_h_addr[index] =
577	(uint64_t)ion_sglist_addr >> ADDR_TRANS_NUM;
578	operation->params[index].memref.size = (unsigned int)ion_sglist_size;
579	op_params->trans_paramtype[index] = param_type;
580
581	return 0;
582}
583
584static int transfer_ion_params(struct tc_ns_operation *operation,
585	union tc_ns_client_param *client_param, uint8_t kernel_params,
586	unsigned int index)
587{
588	uint64_t a_addr = client_param->value.a_addr |
589	((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM);
590	uint64_t b_addr = client_param->value.b_addr |
591	((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM);
592
593	if (read_from_client(&operation->params[index].value.a,
594		sizeof(operation->params[index].value.a),
595		(void *)(uintptr_t)a_addr,
596		sizeof(operation->params[index].value.a), kernel_params)) {
597		tloge("value.a_addr copy failed\n");
598		return -EFAULT;
599	}
600
601	if (read_from_client(&operation->params[index].value.b,
602		sizeof(operation->params[index].value.b),
603		(void *)(uintptr_t)b_addr,
604		sizeof(operation->params[index].value.b), kernel_params)) {
605		tloge("value.b_addr copy failed\n");
606		return -EFAULT;
607	}
608
609	return 0;
610}
611
612int alloc_for_ion(const struct tc_call_params *call_params,
613	struct tc_op_params *op_params, uint8_t kernel_params,
614	uint32_t param_type, unsigned int index)
615{
616	struct tc_ns_operation *operation = NULL;
617	size_t drm_ion_size = 0;
618	phys_addr_t drm_ion_phys = 0x0;
619	struct dma_buf *drm_dma_buf = NULL;
620	union tc_ns_client_param *client_param = NULL;
621	unsigned int ion_shared_fd = 0;
622	int ret = 0;
623
624	/* this never happens */
625	if (index >= TEE_PARAM_NUM || !call_params || !op_params)
626		return -EINVAL;
627
628	operation = &op_params->mb_pack->operation;
629	client_param = &(call_params->context->params[index]);
630	if (transfer_ion_params(operation, client_param, kernel_params, index))
631		return -EFAULT;
632
633	ion_shared_fd = operation->params[index].value.a;
634	drm_dma_buf = dma_buf_get(ion_shared_fd);
635	if (IS_ERR_OR_NULL(drm_dma_buf)) {
636		tloge("drm dma buf is err, ret = %d fd = %u\n", ret, ion_shared_fd);
637		return -EFAULT;
638	}
639#ifdef CONFIG_DMABUF_MM
640	ret = mm_dma_heap_secmem_get_phys(drm_dma_buf, &drm_ion_phys, &drm_ion_size);
641#else
642	ret = ion_secmem_get_phys(drm_dma_buf, &drm_ion_phys, &drm_ion_size);
643#endif
644	if (ret != 0) {
645		tloge("in %s err:ret=%d fd=%u\n", __func__, ret, ion_shared_fd);
646		dma_buf_put(drm_dma_buf);
647		return -EFAULT;
648	}
649
650	if (drm_ion_size > operation->params[index].value.b)
651		drm_ion_size = operation->params[index].value.b;
652	operation->params[index].value.a = (unsigned int)drm_ion_phys;
653	operation->params[index].value.b = (unsigned int)drm_ion_size;
654	op_params->trans_paramtype[index] = param_type;
655	dma_buf_put(drm_dma_buf);
656
657	return ret;
658}