1e50d9ba0SCandice Li /*
2e50d9ba0SCandice Li  * Copyright 2022 Advanced Micro Devices, Inc.
3e50d9ba0SCandice Li  *
4e50d9ba0SCandice Li  * Permission is hereby granted, free of charge, to any person obtaining a
5e50d9ba0SCandice Li  * copy of this software and associated documentation files (the "Software"),
6e50d9ba0SCandice Li  * to deal in the Software without restriction, including without limitation
7e50d9ba0SCandice Li  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e50d9ba0SCandice Li  * and/or sell copies of the Software, and to permit persons to whom the
9e50d9ba0SCandice Li  * Software is furnished to do so, subject to the following conditions:
10e50d9ba0SCandice Li  *
11e50d9ba0SCandice Li  * The above copyright notice and this permission notice shall be included in
12e50d9ba0SCandice Li  * all copies or substantial portions of the Software.
13e50d9ba0SCandice Li  *
14e50d9ba0SCandice Li  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e50d9ba0SCandice Li  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e50d9ba0SCandice Li  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17e50d9ba0SCandice Li  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18e50d9ba0SCandice Li  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19e50d9ba0SCandice Li  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20e50d9ba0SCandice Li  * OTHER DEALINGS IN THE SOFTWARE.
21e50d9ba0SCandice Li  *
22e50d9ba0SCandice Li  */
23e50d9ba0SCandice Li 
24e50d9ba0SCandice Li #include "amdgpu.h"
25e50d9ba0SCandice Li #include "amdgpu_psp_ta.h"
26e50d9ba0SCandice Li 
2786e18ac3SCandice Li #if defined(CONFIG_DEBUG_FS)
28e50d9ba0SCandice Li 
29e50d9ba0SCandice Li static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf,
30e50d9ba0SCandice Li 					    size_t len, loff_t *off);
31e50d9ba0SCandice Li static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf,
32e50d9ba0SCandice Li 					    size_t len, loff_t *off);
33e50d9ba0SCandice Li static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf,
34e50d9ba0SCandice Li 					    size_t len, loff_t *off);
35e50d9ba0SCandice Li 
get_bin_version(const uint8_t * bin)36e50d9ba0SCandice Li static uint32_t get_bin_version(const uint8_t *bin)
37e50d9ba0SCandice Li {
38e50d9ba0SCandice Li 	const struct common_firmware_header *hdr =
39e50d9ba0SCandice Li 			     (const struct common_firmware_header *)bin;
40e50d9ba0SCandice Li 
41e50d9ba0SCandice Li 	return hdr->ucode_version;
42e50d9ba0SCandice Li }
43e50d9ba0SCandice Li 
prep_ta_mem_context(struct ta_mem_context * mem_context,uint8_t * shared_buf,uint32_t shared_buf_len)44896b7addSCandice Li static int prep_ta_mem_context(struct ta_mem_context *mem_context,
45e50d9ba0SCandice Li 					     uint8_t *shared_buf,
46e50d9ba0SCandice Li 					     uint32_t shared_buf_len)
47e50d9ba0SCandice Li {
48896b7addSCandice Li 	if (mem_context->shared_mem_size < shared_buf_len)
49896b7addSCandice Li 		return -EINVAL;
50896b7addSCandice Li 	memset(mem_context->shared_buf, 0, mem_context->shared_mem_size);
51896b7addSCandice Li 	memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len);
52e50d9ba0SCandice Li 
53896b7addSCandice Li 	return 0;
54e50d9ba0SCandice Li }
55e50d9ba0SCandice Li 
is_ta_type_valid(enum ta_type_id ta_type)56e50d9ba0SCandice Li static bool is_ta_type_valid(enum ta_type_id ta_type)
57e50d9ba0SCandice Li {
58e50d9ba0SCandice Li 	switch (ta_type) {
59e50d9ba0SCandice Li 	case TA_TYPE_RAS:
60896b7addSCandice Li 		return true;
61896b7addSCandice Li 	default:
62896b7addSCandice Li 		return false;
63896b7addSCandice Li 	}
64896b7addSCandice Li }
65896b7addSCandice Li 
66896b7addSCandice Li static const struct ta_funcs ras_ta_funcs = {
67896b7addSCandice Li 	.fn_ta_initialize = psp_ras_initialize,
68896b7addSCandice Li 	.fn_ta_invoke    = psp_ras_invoke,
69896b7addSCandice Li 	.fn_ta_terminate = psp_ras_terminate
70896b7addSCandice Li };
71896b7addSCandice Li 
set_ta_context_funcs(struct psp_context * psp,enum ta_type_id ta_type,struct ta_context ** pcontext)72896b7addSCandice Li static void set_ta_context_funcs(struct psp_context *psp,
73896b7addSCandice Li 						      enum ta_type_id ta_type,
74896b7addSCandice Li 						      struct ta_context **pcontext)
75896b7addSCandice Li {
76896b7addSCandice Li 	switch (ta_type) {
77896b7addSCandice Li 	case TA_TYPE_RAS:
78896b7addSCandice Li 		*pcontext = &psp->ras_context.context;
79896b7addSCandice Li 		psp->ta_funcs = &ras_ta_funcs;
80e50d9ba0SCandice Li 		break;
81e50d9ba0SCandice Li 	default:
82e50d9ba0SCandice Li 		break;
83e50d9ba0SCandice Li 	}
84e50d9ba0SCandice Li }
85e50d9ba0SCandice Li 
86e50d9ba0SCandice Li static const struct file_operations ta_load_debugfs_fops = {
87e50d9ba0SCandice Li 	.write  = ta_if_load_debugfs_write,
88e50d9ba0SCandice Li 	.llseek = default_llseek,
89e50d9ba0SCandice Li 	.owner  = THIS_MODULE
90e50d9ba0SCandice Li };
91e50d9ba0SCandice Li 
92e50d9ba0SCandice Li static const struct file_operations ta_unload_debugfs_fops = {
93e50d9ba0SCandice Li 	.write  = ta_if_unload_debugfs_write,
94e50d9ba0SCandice Li 	.llseek = default_llseek,
95e50d9ba0SCandice Li 	.owner  = THIS_MODULE
96e50d9ba0SCandice Li };
97e50d9ba0SCandice Li 
98e50d9ba0SCandice Li static const struct file_operations ta_invoke_debugfs_fops = {
99e50d9ba0SCandice Li 	.write  = ta_if_invoke_debugfs_write,
100e50d9ba0SCandice Li 	.llseek = default_llseek,
101e50d9ba0SCandice Li 	.owner  = THIS_MODULE
102e50d9ba0SCandice Li };
103e50d9ba0SCandice Li 
104896b7addSCandice Li /*
105e50d9ba0SCandice Li  * DOC: AMDGPU TA debugfs interfaces
106e50d9ba0SCandice Li  *
107e50d9ba0SCandice Li  * Three debugfs interfaces can be opened by a program to
108e50d9ba0SCandice Li  * load/invoke/unload TA,
109e50d9ba0SCandice Li  *
110e50d9ba0SCandice Li  * - /sys/kernel/debug/dri/<N>/ta_if/ta_load
111e50d9ba0SCandice Li  * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke
112e50d9ba0SCandice Li  * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload
113e50d9ba0SCandice Li  *
114e50d9ba0SCandice Li  * How to use the interfaces in a program?
115e50d9ba0SCandice Li  *
116e50d9ba0SCandice Li  * A program needs to provide transmit buffer to the interfaces
117e50d9ba0SCandice Li  * and will receive buffer from the interfaces below,
118e50d9ba0SCandice Li  *
119e50d9ba0SCandice Li  * - For TA load debugfs interface:
120e50d9ba0SCandice Li  *   Transmit buffer:
121e50d9ba0SCandice Li  *    - TA type (4bytes)
122e50d9ba0SCandice Li  *    - TA bin length (4bytes)
123e50d9ba0SCandice Li  *    - TA bin
124e50d9ba0SCandice Li  *   Receive buffer:
125e50d9ba0SCandice Li  *    - TA ID (4bytes)
126e50d9ba0SCandice Li  *
127e50d9ba0SCandice Li  * - For TA invoke debugfs interface:
128e50d9ba0SCandice Li  *   Transmit buffer:
129896b7addSCandice Li  *    - TA type (4bytes)
130e50d9ba0SCandice Li  *    - TA ID (4bytes)
131e50d9ba0SCandice Li  *    - TA CMD ID (4bytes)
132896b7addSCandice Li  *    - TA shard buf length
133896b7addSCandice Li  *      (4bytes, value not beyond TA shared memory size)
134e50d9ba0SCandice Li  *    - TA shared buf
135e50d9ba0SCandice Li  *   Receive buffer:
136e50d9ba0SCandice Li  *    - TA shared buf
137e50d9ba0SCandice Li  *
138e50d9ba0SCandice Li  * - For TA unload debugfs interface:
139e50d9ba0SCandice Li  *   Transmit buffer:
140896b7addSCandice Li  *    - TA type (4bytes)
141e50d9ba0SCandice Li  *    - TA ID (4bytes)
142e50d9ba0SCandice Li  */
143e50d9ba0SCandice Li 
ta_if_load_debugfs_write(struct file * fp,const char * buf,size_t len,loff_t * off)144e50d9ba0SCandice Li static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
145e50d9ba0SCandice Li {
146e50d9ba0SCandice Li 	uint32_t ta_type    = 0;
147e50d9ba0SCandice Li 	uint32_t ta_bin_len = 0;
148e50d9ba0SCandice Li 	uint8_t  *ta_bin    = NULL;
149e50d9ba0SCandice Li 	uint32_t copy_pos   = 0;
150e50d9ba0SCandice Li 	int      ret        = 0;
151e50d9ba0SCandice Li 
152e50d9ba0SCandice Li 	struct amdgpu_device *adev    = (struct amdgpu_device *)file_inode(fp)->i_private;
153e50d9ba0SCandice Li 	struct psp_context   *psp     = &adev->psp;
154896b7addSCandice Li 	struct ta_context    *context = NULL;
155e50d9ba0SCandice Li 
156e50d9ba0SCandice Li 	if (!buf)
157e50d9ba0SCandice Li 		return -EINVAL;
158e50d9ba0SCandice Li 
159e50d9ba0SCandice Li 	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
160e50d9ba0SCandice Li 	if (ret || (!is_ta_type_valid(ta_type)))
161896b7addSCandice Li 		return -EFAULT;
162e50d9ba0SCandice Li 
163e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
164e50d9ba0SCandice Li 
165e50d9ba0SCandice Li 	ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
166e50d9ba0SCandice Li 	if (ret)
167896b7addSCandice Li 		return -EFAULT;
168e50d9ba0SCandice Li 
169e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
170e50d9ba0SCandice Li 
171e50d9ba0SCandice Li 	ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
172e50d9ba0SCandice Li 	if (!ta_bin)
173896b7addSCandice Li 		return -ENOMEM;
174a52ad5b6SDan Carpenter 	if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
175a52ad5b6SDan Carpenter 		ret = -EFAULT;
176e50d9ba0SCandice Li 		goto err_free_bin;
177a52ad5b6SDan Carpenter 	}
178e50d9ba0SCandice Li 
179896b7addSCandice Li 	/* Set TA context and functions */
180896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
181896b7addSCandice Li 
182896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
183896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to terminate TA\n");
184896b7addSCandice Li 		ret = -EOPNOTSUPP;
185e50d9ba0SCandice Li 		goto err_free_bin;
186e50d9ba0SCandice Li 	}
187e50d9ba0SCandice Li 
188896b7addSCandice Li 	/*
189896b7addSCandice Li 	 * Allocate TA shared buf in case shared buf was freed
190896b7addSCandice Li 	 * due to loading TA failed before.
191896b7addSCandice Li 	 */
192896b7addSCandice Li 	if (!context->mem_context.shared_buf) {
193896b7addSCandice Li 		ret = psp_ta_init_shared_buf(psp, &context->mem_context);
194896b7addSCandice Li 		if (ret) {
195896b7addSCandice Li 			ret = -ENOMEM;
196896b7addSCandice Li 			goto err_free_bin;
197896b7addSCandice Li 		}
198896b7addSCandice Li 	}
199e50d9ba0SCandice Li 
200896b7addSCandice Li 	ret = psp_fn_ta_terminate(psp);
201896b7addSCandice Li 	if (ret || context->resp_status) {
202896b7addSCandice Li 		dev_err(adev->dev,
203896b7addSCandice Li 			"Failed to unload embedded TA (%d) and status (0x%X)\n",
204896b7addSCandice Li 			ret, context->resp_status);
205a52ad5b6SDan Carpenter 		if (!ret)
206a52ad5b6SDan Carpenter 			ret = -EINVAL;
207896b7addSCandice Li 		goto err_free_ta_shared_buf;
208e50d9ba0SCandice Li 	}
209e50d9ba0SCandice Li 
210896b7addSCandice Li 	/* Prepare TA context for TA initialization */
211896b7addSCandice Li 	context->ta_type                     = ta_type;
212896b7addSCandice Li 	context->bin_desc.fw_version         = get_bin_version(ta_bin);
213896b7addSCandice Li 	context->bin_desc.size_bytes         = ta_bin_len;
214896b7addSCandice Li 	context->bin_desc.start_addr         = ta_bin;
215896b7addSCandice Li 
216896b7addSCandice Li 	if (!psp->ta_funcs->fn_ta_initialize) {
217896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to initialize TA\n");
218896b7addSCandice Li 		ret = -EOPNOTSUPP;
219896b7addSCandice Li 		goto err_free_ta_shared_buf;
220896b7addSCandice Li 	}
221896b7addSCandice Li 
222896b7addSCandice Li 	ret = psp_fn_ta_initialize(psp);
223896b7addSCandice Li 	if (ret || context->resp_status) {
224896b7addSCandice Li 		dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n",
225896b7addSCandice Li 			ret, context->resp_status);
226896b7addSCandice Li 		if (!ret)
227896b7addSCandice Li 			ret = -EINVAL;
228896b7addSCandice Li 		goto err_free_ta_shared_buf;
229896b7addSCandice Li 	}
230896b7addSCandice Li 
231896b7addSCandice Li 	if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t)))
232a52ad5b6SDan Carpenter 		ret = -EFAULT;
233e50d9ba0SCandice Li 
234896b7addSCandice Li err_free_ta_shared_buf:
235896b7addSCandice Li 	/* Only free TA shared buf when returns error code */
236896b7addSCandice Li 	if (ret && context->mem_context.shared_buf)
237896b7addSCandice Li 		psp_ta_free_shared_buf(&context->mem_context);
238e50d9ba0SCandice Li err_free_bin:
239e50d9ba0SCandice Li 	kfree(ta_bin);
240e50d9ba0SCandice Li 
241e50d9ba0SCandice Li 	return ret;
242e50d9ba0SCandice Li }
243e50d9ba0SCandice Li 
ta_if_unload_debugfs_write(struct file * fp,const char * buf,size_t len,loff_t * off)244e50d9ba0SCandice Li static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
245e50d9ba0SCandice Li {
246896b7addSCandice Li 	uint32_t ta_type    = 0;
247e50d9ba0SCandice Li 	uint32_t ta_id      = 0;
248896b7addSCandice Li 	uint32_t copy_pos   = 0;
249e50d9ba0SCandice Li 	int      ret        = 0;
250e50d9ba0SCandice Li 
251e50d9ba0SCandice Li 	struct amdgpu_device *adev    = (struct amdgpu_device *)file_inode(fp)->i_private;
252e50d9ba0SCandice Li 	struct psp_context   *psp     = &adev->psp;
253896b7addSCandice Li 	struct ta_context    *context = NULL;
254e50d9ba0SCandice Li 
255e50d9ba0SCandice Li 	if (!buf)
256e50d9ba0SCandice Li 		return -EINVAL;
257e50d9ba0SCandice Li 
258896b7addSCandice Li 	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
259896b7addSCandice Li 	if (ret || (!is_ta_type_valid(ta_type)))
260896b7addSCandice Li 		return -EFAULT;
261896b7addSCandice Li 
262896b7addSCandice Li 	copy_pos += sizeof(uint32_t);
263896b7addSCandice Li 
264896b7addSCandice Li 	ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
265e50d9ba0SCandice Li 	if (ret)
266896b7addSCandice Li 		return -EFAULT;
267e50d9ba0SCandice Li 
268896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
269896b7addSCandice Li 	context->session_id = ta_id;
270e50d9ba0SCandice Li 
271896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
272896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to terminate TA\n");
273896b7addSCandice Li 		return -EOPNOTSUPP;
274896b7addSCandice Li 	}
275896b7addSCandice Li 
276896b7addSCandice Li 	ret = psp_fn_ta_terminate(psp);
277896b7addSCandice Li 	if (ret || context->resp_status) {
278896b7addSCandice Li 		dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n",
279896b7addSCandice Li 			ret, context->resp_status);
280e50d9ba0SCandice Li 		if (!ret)
281896b7addSCandice Li 			ret = -EINVAL;
282896b7addSCandice Li 	}
283896b7addSCandice Li 
284896b7addSCandice Li 	if (context->mem_context.shared_buf)
285896b7addSCandice Li 		psp_ta_free_shared_buf(&context->mem_context);
286e50d9ba0SCandice Li 
287e50d9ba0SCandice Li 	return ret;
288e50d9ba0SCandice Li }
289e50d9ba0SCandice Li 
ta_if_invoke_debugfs_write(struct file * fp,const char * buf,size_t len,loff_t * off)290e50d9ba0SCandice Li static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
291e50d9ba0SCandice Li {
292896b7addSCandice Li 	uint32_t ta_type        = 0;
293e50d9ba0SCandice Li 	uint32_t ta_id          = 0;
294e50d9ba0SCandice Li 	uint32_t cmd_id         = 0;
295e50d9ba0SCandice Li 	uint32_t shared_buf_len = 0;
296e50d9ba0SCandice Li 	uint8_t *shared_buf     = NULL;
297e50d9ba0SCandice Li 	uint32_t copy_pos       = 0;
298e50d9ba0SCandice Li 	int      ret            = 0;
299e50d9ba0SCandice Li 
300e50d9ba0SCandice Li 	struct amdgpu_device *adev    = (struct amdgpu_device *)file_inode(fp)->i_private;
301e50d9ba0SCandice Li 	struct psp_context   *psp     = &adev->psp;
302896b7addSCandice Li 	struct ta_context    *context = NULL;
303e50d9ba0SCandice Li 
304e50d9ba0SCandice Li 	if (!buf)
305e50d9ba0SCandice Li 		return -EINVAL;
306e50d9ba0SCandice Li 
307896b7addSCandice Li 	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
308896b7addSCandice Li 	if (ret)
309896b7addSCandice Li 		return -EFAULT;
310896b7addSCandice Li 	copy_pos += sizeof(uint32_t);
311896b7addSCandice Li 
312e50d9ba0SCandice Li 	ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
313e50d9ba0SCandice Li 	if (ret)
314896b7addSCandice Li 		return -EFAULT;
315e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
316e50d9ba0SCandice Li 
317e50d9ba0SCandice Li 	ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
318e50d9ba0SCandice Li 	if (ret)
319896b7addSCandice Li 		return -EFAULT;
320e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
321e50d9ba0SCandice Li 
322e50d9ba0SCandice Li 	ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
323e50d9ba0SCandice Li 	if (ret)
324896b7addSCandice Li 		return -EFAULT;
325e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
326e50d9ba0SCandice Li 
327e50d9ba0SCandice Li 	shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
328e50d9ba0SCandice Li 	if (!shared_buf)
3292f33a397SDan Carpenter 		return -ENOMEM;
330a52ad5b6SDan Carpenter 	if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) {
331a52ad5b6SDan Carpenter 		ret = -EFAULT;
332e50d9ba0SCandice Li 		goto err_free_shared_buf;
333a52ad5b6SDan Carpenter 	}
334e50d9ba0SCandice Li 
335896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
336e50d9ba0SCandice Li 
337896b7addSCandice Li 	if (!context->initialized) {
338896b7addSCandice Li 		dev_err(adev->dev, "TA is not initialized\n");
339a52ad5b6SDan Carpenter 		ret = -EINVAL;
340896b7addSCandice Li 		goto err_free_shared_buf;
341e50d9ba0SCandice Li 	}
342e50d9ba0SCandice Li 
343896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
344896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to invoke TA\n");
345896b7addSCandice Li 		ret = -EOPNOTSUPP;
346896b7addSCandice Li 		goto err_free_shared_buf;
347896b7addSCandice Li 	}
348e50d9ba0SCandice Li 
349896b7addSCandice Li 	context->session_id = ta_id;
350896b7addSCandice Li 
351896b7addSCandice Li 	ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
352896b7addSCandice Li 	if (ret)
353896b7addSCandice Li 		goto err_free_shared_buf;
354896b7addSCandice Li 
355896b7addSCandice Li 	ret = psp_fn_ta_invoke(psp, cmd_id);
356896b7addSCandice Li 	if (ret || context->resp_status) {
357896b7addSCandice Li 		dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n",
358896b7addSCandice Li 			ret, context->resp_status);
359896b7addSCandice Li 		if (!ret) {
360896b7addSCandice Li 			ret = -EINVAL;
361896b7addSCandice Li 			goto err_free_shared_buf;
362896b7addSCandice Li 		}
363896b7addSCandice Li 	}
364896b7addSCandice Li 
365*cb4541caSStanley.Yang 	if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
366896b7addSCandice Li 		ret = -EFAULT;
367e50d9ba0SCandice Li 
368e50d9ba0SCandice Li err_free_shared_buf:
369e50d9ba0SCandice Li 	kfree(shared_buf);
370e50d9ba0SCandice Li 
371e50d9ba0SCandice Li 	return ret;
372e50d9ba0SCandice Li }
373e50d9ba0SCandice Li 
amdgpu_ta_if_debugfs_init(struct amdgpu_device * adev)37486e18ac3SCandice Li void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
375e50d9ba0SCandice Li {
376e50d9ba0SCandice Li 	struct drm_minor *minor = adev_to_drm(adev)->primary;
377e50d9ba0SCandice Li 
37886e18ac3SCandice Li 	struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root);
379e50d9ba0SCandice Li 
38086e18ac3SCandice Li 	debugfs_create_file("ta_load", 0200, dir, adev,
381e50d9ba0SCandice Li 				     &ta_load_debugfs_fops);
382e50d9ba0SCandice Li 
38386e18ac3SCandice Li 	debugfs_create_file("ta_unload", 0200, dir,
384e50d9ba0SCandice Li 				     adev, &ta_unload_debugfs_fops);
385e50d9ba0SCandice Li 
38686e18ac3SCandice Li 	debugfs_create_file("ta_invoke", 0200, dir,
387e50d9ba0SCandice Li 				     adev, &ta_invoke_debugfs_fops);
388e50d9ba0SCandice Li }
389e50d9ba0SCandice Li 
39086e18ac3SCandice Li #else
amdgpu_ta_if_debugfs_init(struct amdgpu_device * adev)391e50d9ba0SCandice Li void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
392e50d9ba0SCandice Li {
393e50d9ba0SCandice Li 
394e50d9ba0SCandice Li }
39586e18ac3SCandice Li #endif
396