xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c (revision 26d0dfbb16fcb17d128a79dc70f3020ea6992af0)
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 
169*50553ea7SCandice Li 	if (ta_bin_len > PSP_1_MEG)
170*50553ea7SCandice Li 		return -EINVAL;
171*50553ea7SCandice Li 
172e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
173e50d9ba0SCandice Li 
174e50d9ba0SCandice Li 	ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
175e50d9ba0SCandice Li 	if (!ta_bin)
176896b7addSCandice Li 		return -ENOMEM;
177a52ad5b6SDan Carpenter 	if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
178a52ad5b6SDan Carpenter 		ret = -EFAULT;
179e50d9ba0SCandice Li 		goto err_free_bin;
180a52ad5b6SDan Carpenter 	}
181e50d9ba0SCandice Li 
182896b7addSCandice Li 	/* Set TA context and functions */
183896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
184896b7addSCandice Li 
185896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
186896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to terminate TA\n");
187896b7addSCandice Li 		ret = -EOPNOTSUPP;
188e50d9ba0SCandice Li 		goto err_free_bin;
189e50d9ba0SCandice Li 	}
190e50d9ba0SCandice Li 
191896b7addSCandice Li 	/*
192896b7addSCandice Li 	 * Allocate TA shared buf in case shared buf was freed
193896b7addSCandice Li 	 * due to loading TA failed before.
194896b7addSCandice Li 	 */
195896b7addSCandice Li 	if (!context->mem_context.shared_buf) {
196896b7addSCandice Li 		ret = psp_ta_init_shared_buf(psp, &context->mem_context);
197896b7addSCandice Li 		if (ret) {
198896b7addSCandice Li 			ret = -ENOMEM;
199896b7addSCandice Li 			goto err_free_bin;
200896b7addSCandice Li 		}
201896b7addSCandice Li 	}
202e50d9ba0SCandice Li 
203896b7addSCandice Li 	ret = psp_fn_ta_terminate(psp);
204896b7addSCandice Li 	if (ret || context->resp_status) {
205896b7addSCandice Li 		dev_err(adev->dev,
206896b7addSCandice Li 			"Failed to unload embedded TA (%d) and status (0x%X)\n",
207896b7addSCandice Li 			ret, context->resp_status);
208a52ad5b6SDan Carpenter 		if (!ret)
209a52ad5b6SDan Carpenter 			ret = -EINVAL;
210896b7addSCandice Li 		goto err_free_ta_shared_buf;
211e50d9ba0SCandice Li 	}
212e50d9ba0SCandice Li 
213896b7addSCandice Li 	/* Prepare TA context for TA initialization */
214896b7addSCandice Li 	context->ta_type                     = ta_type;
215896b7addSCandice Li 	context->bin_desc.fw_version         = get_bin_version(ta_bin);
216896b7addSCandice Li 	context->bin_desc.size_bytes         = ta_bin_len;
217896b7addSCandice Li 	context->bin_desc.start_addr         = ta_bin;
218896b7addSCandice Li 
219896b7addSCandice Li 	if (!psp->ta_funcs->fn_ta_initialize) {
220896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to initialize TA\n");
221896b7addSCandice Li 		ret = -EOPNOTSUPP;
222896b7addSCandice Li 		goto err_free_ta_shared_buf;
223896b7addSCandice Li 	}
224896b7addSCandice Li 
225896b7addSCandice Li 	ret = psp_fn_ta_initialize(psp);
226896b7addSCandice Li 	if (ret || context->resp_status) {
227896b7addSCandice Li 		dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n",
228896b7addSCandice Li 			ret, context->resp_status);
229896b7addSCandice Li 		if (!ret)
230896b7addSCandice Li 			ret = -EINVAL;
231896b7addSCandice Li 		goto err_free_ta_shared_buf;
232896b7addSCandice Li 	}
233896b7addSCandice Li 
234896b7addSCandice Li 	if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t)))
235a52ad5b6SDan Carpenter 		ret = -EFAULT;
236e50d9ba0SCandice Li 
237896b7addSCandice Li err_free_ta_shared_buf:
238896b7addSCandice Li 	/* Only free TA shared buf when returns error code */
239896b7addSCandice Li 	if (ret && context->mem_context.shared_buf)
240896b7addSCandice Li 		psp_ta_free_shared_buf(&context->mem_context);
241e50d9ba0SCandice Li err_free_bin:
242e50d9ba0SCandice Li 	kfree(ta_bin);
243e50d9ba0SCandice Li 
244e50d9ba0SCandice Li 	return ret;
245e50d9ba0SCandice Li }
246e50d9ba0SCandice Li 
ta_if_unload_debugfs_write(struct file * fp,const char * buf,size_t len,loff_t * off)247e50d9ba0SCandice Li static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
248e50d9ba0SCandice Li {
249896b7addSCandice Li 	uint32_t ta_type    = 0;
250e50d9ba0SCandice Li 	uint32_t ta_id      = 0;
251896b7addSCandice Li 	uint32_t copy_pos   = 0;
252e50d9ba0SCandice Li 	int      ret        = 0;
253e50d9ba0SCandice Li 
254e50d9ba0SCandice Li 	struct amdgpu_device *adev    = (struct amdgpu_device *)file_inode(fp)->i_private;
255e50d9ba0SCandice Li 	struct psp_context   *psp     = &adev->psp;
256896b7addSCandice Li 	struct ta_context    *context = NULL;
257e50d9ba0SCandice Li 
258e50d9ba0SCandice Li 	if (!buf)
259e50d9ba0SCandice Li 		return -EINVAL;
260e50d9ba0SCandice Li 
261896b7addSCandice Li 	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
262896b7addSCandice Li 	if (ret || (!is_ta_type_valid(ta_type)))
263896b7addSCandice Li 		return -EFAULT;
264896b7addSCandice Li 
265896b7addSCandice Li 	copy_pos += sizeof(uint32_t);
266896b7addSCandice Li 
267896b7addSCandice Li 	ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
268e50d9ba0SCandice Li 	if (ret)
269896b7addSCandice Li 		return -EFAULT;
270e50d9ba0SCandice Li 
271896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
272896b7addSCandice Li 	context->session_id = ta_id;
273e50d9ba0SCandice Li 
274896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
275896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to terminate TA\n");
276896b7addSCandice Li 		return -EOPNOTSUPP;
277896b7addSCandice Li 	}
278896b7addSCandice Li 
279896b7addSCandice Li 	ret = psp_fn_ta_terminate(psp);
280896b7addSCandice Li 	if (ret || context->resp_status) {
281896b7addSCandice Li 		dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n",
282896b7addSCandice Li 			ret, context->resp_status);
283e50d9ba0SCandice Li 		if (!ret)
284896b7addSCandice Li 			ret = -EINVAL;
285896b7addSCandice Li 	}
286896b7addSCandice Li 
287896b7addSCandice Li 	if (context->mem_context.shared_buf)
288896b7addSCandice Li 		psp_ta_free_shared_buf(&context->mem_context);
289e50d9ba0SCandice Li 
290e50d9ba0SCandice Li 	return ret;
291e50d9ba0SCandice Li }
292e50d9ba0SCandice Li 
ta_if_invoke_debugfs_write(struct file * fp,const char * buf,size_t len,loff_t * off)293e50d9ba0SCandice Li static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
294e50d9ba0SCandice Li {
295896b7addSCandice Li 	uint32_t ta_type        = 0;
296e50d9ba0SCandice Li 	uint32_t ta_id          = 0;
297e50d9ba0SCandice Li 	uint32_t cmd_id         = 0;
298e50d9ba0SCandice Li 	uint32_t shared_buf_len = 0;
299e50d9ba0SCandice Li 	uint8_t *shared_buf     = NULL;
300e50d9ba0SCandice Li 	uint32_t copy_pos       = 0;
301e50d9ba0SCandice Li 	int      ret            = 0;
302e50d9ba0SCandice Li 
303e50d9ba0SCandice Li 	struct amdgpu_device *adev    = (struct amdgpu_device *)file_inode(fp)->i_private;
304e50d9ba0SCandice Li 	struct psp_context   *psp     = &adev->psp;
305896b7addSCandice Li 	struct ta_context    *context = NULL;
306e50d9ba0SCandice Li 
307e50d9ba0SCandice Li 	if (!buf)
308e50d9ba0SCandice Li 		return -EINVAL;
309e50d9ba0SCandice Li 
310896b7addSCandice Li 	ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
311896b7addSCandice Li 	if (ret)
312896b7addSCandice Li 		return -EFAULT;
313896b7addSCandice Li 	copy_pos += sizeof(uint32_t);
314896b7addSCandice Li 
315e50d9ba0SCandice Li 	ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
316e50d9ba0SCandice Li 	if (ret)
317896b7addSCandice Li 		return -EFAULT;
318e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
319e50d9ba0SCandice Li 
320e50d9ba0SCandice Li 	ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
321e50d9ba0SCandice Li 	if (ret)
322896b7addSCandice Li 		return -EFAULT;
323e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
324e50d9ba0SCandice Li 
325e50d9ba0SCandice Li 	ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
326e50d9ba0SCandice Li 	if (ret)
327896b7addSCandice Li 		return -EFAULT;
328e50d9ba0SCandice Li 	copy_pos += sizeof(uint32_t);
329e50d9ba0SCandice Li 
330e50d9ba0SCandice Li 	shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
331e50d9ba0SCandice Li 	if (!shared_buf)
3322f33a397SDan Carpenter 		return -ENOMEM;
333a52ad5b6SDan Carpenter 	if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) {
334a52ad5b6SDan Carpenter 		ret = -EFAULT;
335e50d9ba0SCandice Li 		goto err_free_shared_buf;
336a52ad5b6SDan Carpenter 	}
337e50d9ba0SCandice Li 
338896b7addSCandice Li 	set_ta_context_funcs(psp, ta_type, &context);
339e50d9ba0SCandice Li 
340641dac64SJesse Zhang 	if (!context || !context->initialized) {
341896b7addSCandice Li 		dev_err(adev->dev, "TA is not initialized\n");
342a52ad5b6SDan Carpenter 		ret = -EINVAL;
343896b7addSCandice Li 		goto err_free_shared_buf;
344e50d9ba0SCandice Li 	}
345e50d9ba0SCandice Li 
346896b7addSCandice Li 	if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
347896b7addSCandice Li 		dev_err(adev->dev, "Unsupported function to invoke TA\n");
348896b7addSCandice Li 		ret = -EOPNOTSUPP;
349896b7addSCandice Li 		goto err_free_shared_buf;
350896b7addSCandice Li 	}
351e50d9ba0SCandice Li 
352896b7addSCandice Li 	context->session_id = ta_id;
353896b7addSCandice Li 
354896b7addSCandice Li 	ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
355896b7addSCandice Li 	if (ret)
356896b7addSCandice Li 		goto err_free_shared_buf;
357896b7addSCandice Li 
358896b7addSCandice Li 	ret = psp_fn_ta_invoke(psp, cmd_id);
359896b7addSCandice Li 	if (ret || context->resp_status) {
360896b7addSCandice Li 		dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n",
361896b7addSCandice Li 			ret, context->resp_status);
362896b7addSCandice Li 		if (!ret) {
363896b7addSCandice Li 			ret = -EINVAL;
364896b7addSCandice Li 			goto err_free_shared_buf;
365896b7addSCandice Li 		}
366896b7addSCandice Li 	}
367896b7addSCandice Li 
368cb4541caSStanley.Yang 	if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
369896b7addSCandice Li 		ret = -EFAULT;
370e50d9ba0SCandice Li 
371e50d9ba0SCandice Li err_free_shared_buf:
372e50d9ba0SCandice Li 	kfree(shared_buf);
373e50d9ba0SCandice Li 
374e50d9ba0SCandice Li 	return ret;
375e50d9ba0SCandice Li }
376e50d9ba0SCandice Li 
amdgpu_ta_if_debugfs_init(struct amdgpu_device * adev)37786e18ac3SCandice Li void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
378e50d9ba0SCandice Li {
379e50d9ba0SCandice Li 	struct drm_minor *minor = adev_to_drm(adev)->primary;
380e50d9ba0SCandice Li 
38186e18ac3SCandice Li 	struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root);
382e50d9ba0SCandice Li 
38386e18ac3SCandice Li 	debugfs_create_file("ta_load", 0200, dir, adev,
384e50d9ba0SCandice Li 				     &ta_load_debugfs_fops);
385e50d9ba0SCandice Li 
38686e18ac3SCandice Li 	debugfs_create_file("ta_unload", 0200, dir,
387e50d9ba0SCandice Li 				     adev, &ta_unload_debugfs_fops);
388e50d9ba0SCandice Li 
38986e18ac3SCandice Li 	debugfs_create_file("ta_invoke", 0200, dir,
390e50d9ba0SCandice Li 				     adev, &ta_invoke_debugfs_fops);
391e50d9ba0SCandice Li }
392e50d9ba0SCandice Li 
39386e18ac3SCandice Li #else
amdgpu_ta_if_debugfs_init(struct amdgpu_device * adev)394e50d9ba0SCandice Li void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
395e50d9ba0SCandice Li {
396e50d9ba0SCandice Li 
397e50d9ba0SCandice Li }
39886e18ac3SCandice Li #endif
399