xref: /linux/drivers/accel/amdxdna/aie2_message.c (revision c06b6cde2a1c3bcbb561bd57bb6f34eae9030921)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2023-2024, Advanced Micro Devices, Inc.
4  */
5 
6 #include <drm/amdxdna_accel.h>
7 #include <drm/drm_cache.h>
8 #include <drm/drm_device.h>
9 #include <drm/drm_gem.h>
10 #include <drm/drm_gem_shmem_helper.h>
11 #include <drm/drm_print.h>
12 #include <drm/gpu_scheduler.h>
13 #include <linux/bitfield.h>
14 #include <linux/errno.h>
15 #include <linux/pci.h>
16 #include <linux/types.h>
17 #include <linux/xarray.h>
18 
19 #include "aie.h"
20 #include "aie2_msg_priv.h"
21 #include "aie2_pci.h"
22 #include "amdxdna_ctx.h"
23 #include "amdxdna_gem.h"
24 #include "amdxdna_mailbox.h"
25 #include "amdxdna_mailbox_helper.h"
26 #include "amdxdna_pci_drv.h"
27 
28 #define EXEC_MSG_OPS(xdna)	((xdna)->dev_handle->exec_msg_ops)
29 
30 int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)
31 {
32 	DECLARE_AIE_MSG(suspend, MSG_OP_SUSPEND);
33 	int ret;
34 
35 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
36 	if (ret) {
37 		XDNA_ERR(ndev->aie.xdna, "Failed to suspend fw, ret %d", ret);
38 		return ret;
39 	}
40 
41 	return aie_psp_waitmode_poll(ndev->aie.psp_hdl);
42 }
43 
44 int aie2_resume_fw(struct amdxdna_dev_hdl *ndev)
45 {
46 	DECLARE_AIE_MSG(suspend, MSG_OP_RESUME);
47 
48 	return aie_send_mgmt_msg_wait(&ndev->aie, &msg);
49 }
50 
51 int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value)
52 {
53 	DECLARE_AIE_MSG(set_runtime_cfg, MSG_OP_SET_RUNTIME_CONFIG);
54 	int ret;
55 
56 	req.type = type;
57 	req.value = value;
58 
59 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
60 	if (ret) {
61 		XDNA_ERR(ndev->aie.xdna, "Failed to set runtime config, ret %d", ret);
62 		return ret;
63 	}
64 
65 	return 0;
66 }
67 
68 int aie2_get_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 *value)
69 {
70 	DECLARE_AIE_MSG(get_runtime_cfg, MSG_OP_GET_RUNTIME_CONFIG);
71 	int ret;
72 
73 	req.type = type;
74 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
75 	if (ret) {
76 		XDNA_ERR(ndev->aie.xdna, "Failed to get runtime config, ret %d", ret);
77 		return ret;
78 	}
79 
80 	*value = resp.value;
81 	return 0;
82 }
83 
84 int aie2_assign_mgmt_pasid(struct amdxdna_dev_hdl *ndev, u16 pasid)
85 {
86 	DECLARE_AIE_MSG(assign_mgmt_pasid, MSG_OP_ASSIGN_MGMT_PASID);
87 
88 	req.pasid = pasid;
89 
90 	return aie_send_mgmt_msg_wait(&ndev->aie, &msg);
91 }
92 
93 int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev,
94 			   struct amdxdna_drm_query_aie_version *version)
95 {
96 	DECLARE_AIE_MSG(aie_version_info, MSG_OP_QUERY_AIE_VERSION);
97 	struct amdxdna_dev *xdna = ndev->aie.xdna;
98 	int ret;
99 
100 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
101 	if (ret)
102 		return ret;
103 
104 	XDNA_DBG(xdna, "Query AIE version - major: %u minor: %u completed",
105 		 resp.major, resp.minor);
106 
107 	version->major = resp.major;
108 	version->minor = resp.minor;
109 
110 	return 0;
111 }
112 
113 int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev,
114 			    struct amdxdna_drm_query_aie_metadata *metadata)
115 {
116 	DECLARE_AIE_MSG(aie_tile_info, MSG_OP_QUERY_AIE_TILE_INFO);
117 	int ret;
118 
119 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
120 	if (ret)
121 		return ret;
122 
123 	metadata->col_size = resp.info.size;
124 	metadata->cols = resp.info.cols;
125 	metadata->rows = resp.info.rows;
126 
127 	metadata->version.major = resp.info.major;
128 	metadata->version.minor = resp.info.minor;
129 
130 	metadata->core.row_count = resp.info.core_rows;
131 	metadata->core.row_start = resp.info.core_row_start;
132 	metadata->core.dma_channel_count = resp.info.core_dma_channels;
133 	metadata->core.lock_count = resp.info.core_locks;
134 	metadata->core.event_reg_count = resp.info.core_events;
135 
136 	metadata->mem.row_count = resp.info.mem_rows;
137 	metadata->mem.row_start = resp.info.mem_row_start;
138 	metadata->mem.dma_channel_count = resp.info.mem_dma_channels;
139 	metadata->mem.lock_count = resp.info.mem_locks;
140 	metadata->mem.event_reg_count = resp.info.mem_events;
141 
142 	metadata->shim.row_count = resp.info.shim_rows;
143 	metadata->shim.row_start = resp.info.shim_row_start;
144 	metadata->shim.dma_channel_count = resp.info.shim_dma_channels;
145 	metadata->shim.lock_count = resp.info.shim_locks;
146 	metadata->shim.event_reg_count = resp.info.shim_events;
147 
148 	return 0;
149 }
150 
151 int aie2_query_firmware_version(struct amdxdna_dev_hdl *ndev,
152 				struct amdxdna_fw_ver *fw_ver)
153 {
154 	DECLARE_AIE_MSG(firmware_version, MSG_OP_GET_FIRMWARE_VERSION);
155 	int ret;
156 
157 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
158 	if (ret)
159 		return ret;
160 
161 	fw_ver->major = resp.major;
162 	fw_ver->minor = resp.minor;
163 	fw_ver->sub = resp.sub;
164 	fw_ver->build = resp.build;
165 
166 	return 0;
167 }
168 
169 static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id)
170 {
171 	DECLARE_AIE_MSG(destroy_ctx, MSG_OP_DESTROY_CONTEXT);
172 	struct amdxdna_dev *xdna = ndev->aie.xdna;
173 	int ret;
174 
175 	req.context_id = id;
176 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
177 	if (ret && ret != -ENODEV)
178 		XDNA_WARN(xdna, "Destroy context failed, ret %d", ret);
179 	else if (ret == -ENODEV)
180 		XDNA_DBG(xdna, "Destroy context: device already stopped");
181 
182 	return ret;
183 }
184 
185 static u32 aie2_get_context_priority(struct amdxdna_dev_hdl *ndev,
186 				     struct amdxdna_hwctx *hwctx)
187 {
188 	if (!AIE_FEATURE_ON(&ndev->aie, AIE2_PREEMPT))
189 		return PRIORITY_HIGH;
190 
191 	switch (hwctx->qos.priority) {
192 	case AMDXDNA_QOS_REALTIME_PRIORITY:
193 		return PRIORITY_REALTIME;
194 	case AMDXDNA_QOS_HIGH_PRIORITY:
195 		return PRIORITY_HIGH;
196 	case AMDXDNA_QOS_NORMAL_PRIORITY:
197 		return PRIORITY_NORMAL;
198 	case AMDXDNA_QOS_LOW_PRIORITY:
199 		return PRIORITY_LOW;
200 	default:
201 		return PRIORITY_HIGH;
202 	}
203 }
204 
205 int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx)
206 {
207 	DECLARE_AIE_MSG(create_ctx, MSG_OP_CREATE_CONTEXT);
208 	struct amdxdna_dev *xdna = ndev->aie.xdna;
209 	struct xdna_mailbox_chann_res x2i;
210 	struct xdna_mailbox_chann_res i2x;
211 	struct cq_pair *cq_pair;
212 	u32 intr_reg;
213 	int ret;
214 
215 	req.aie_type = 1;
216 	req.start_col = hwctx->start_col;
217 	req.num_col = hwctx->num_col;
218 	req.num_unused_col = hwctx->num_unused_col;
219 	req.num_cq_pairs_requested = 1;
220 	req.pasid = amdxdna_pasid_on(hwctx->client) ? hwctx->client->pasid : 0;
221 	req.context_priority = aie2_get_context_priority(ndev, hwctx);
222 
223 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
224 	if (ret)
225 		return ret;
226 
227 	hwctx->fw_ctx_id = resp.context_id;
228 	if (WARN_ON_ONCE(hwctx->fw_ctx_id == -1))
229 		return -EINVAL;
230 
231 	if (ndev->force_preempt_enabled) {
232 		ret = aie2_runtime_cfg(ndev, AIE2_RT_CFG_FORCE_PREEMPT, &hwctx->fw_ctx_id);
233 		if (ret) {
234 			XDNA_ERR(xdna, "failed to enable force preempt %d", ret);
235 			goto del_ctx_req;
236 		}
237 	}
238 
239 	cq_pair = &resp.cq_pair[0];
240 	x2i.mb_head_ptr_reg = AIE2_MBOX_OFF(ndev, cq_pair->x2i_q.head_addr);
241 	x2i.mb_tail_ptr_reg = AIE2_MBOX_OFF(ndev, cq_pair->x2i_q.tail_addr);
242 	x2i.rb_start_addr   = AIE2_SRAM_OFF(ndev, cq_pair->x2i_q.buf_addr);
243 	x2i.rb_size	    = cq_pair->x2i_q.buf_size;
244 
245 	i2x.mb_head_ptr_reg = AIE2_MBOX_OFF(ndev, cq_pair->i2x_q.head_addr);
246 	i2x.mb_tail_ptr_reg = AIE2_MBOX_OFF(ndev, cq_pair->i2x_q.tail_addr);
247 	i2x.rb_start_addr   = AIE2_SRAM_OFF(ndev, cq_pair->i2x_q.buf_addr);
248 	i2x.rb_size	    = cq_pair->i2x_q.buf_size;
249 
250 	ret = pci_irq_vector(to_pci_dev(xdna->ddev.dev), resp.msix_id);
251 	if (ret == -EINVAL) {
252 		XDNA_ERR(xdna, "Alloc IRQ failed %d", ret);
253 		goto del_ctx_req;
254 	}
255 
256 	intr_reg = i2x.mb_head_ptr_reg + 4;
257 	hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox);
258 	if (!hwctx->priv->mbox_chann) {
259 		XDNA_ERR(xdna, "Not able to create channel");
260 		ret = -EINVAL;
261 		goto del_ctx_req;
262 	}
263 
264 	ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, &i2x,
265 					 intr_reg, ret);
266 	if (ret) {
267 		XDNA_ERR(xdna, "Not able to create channel");
268 		ret = -EINVAL;
269 		goto free_channel;
270 	}
271 	ndev->hwctx_num++;
272 
273 	XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id);
274 	XDNA_DBG(xdna, "Created fw ctx %d pasid %d", hwctx->fw_ctx_id, hwctx->client->pasid);
275 
276 	return 0;
277 
278 free_channel:
279 	xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
280 del_ctx_req:
281 	aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
282 	return ret;
283 }
284 
285 int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx)
286 {
287 	struct amdxdna_dev *xdna = ndev->aie.xdna;
288 	int ret;
289 
290 	if (!hwctx->priv->mbox_chann)
291 		return 0;
292 
293 	xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
294 	ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
295 	xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
296 	XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id);
297 	hwctx->priv->mbox_chann = NULL;
298 	hwctx->fw_ctx_id = -1;
299 	ndev->hwctx_num--;
300 
301 	return ret;
302 }
303 
304 int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u64 size)
305 {
306 	DECLARE_AIE_MSG(map_host_buffer, MSG_OP_MAP_HOST_BUFFER);
307 	struct amdxdna_dev *xdna = ndev->aie.xdna;
308 	int ret;
309 
310 	req.context_id = context_id;
311 	req.buf_addr = addr;
312 	req.buf_size = size;
313 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
314 	if (ret)
315 		return ret;
316 
317 	XDNA_DBG(xdna, "fw ctx %d map host buf addr 0x%llx size 0x%llx",
318 		 context_id, addr, size);
319 
320 	return 0;
321 }
322 
323 static int amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx, void *arg)
324 {
325 	u32 *bitmap = arg;
326 
327 	*bitmap |= GENMASK(hwctx->start_col + hwctx->num_col - 1, hwctx->start_col);
328 
329 	return 0;
330 }
331 
332 int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
333 		      u32 size, u32 *cols_filled)
334 {
335 	DECLARE_AIE_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS);
336 	struct amdxdna_dev *xdna = ndev->aie.xdna;
337 	u32 buf_sz, aie_bitmap = 0;
338 	struct amdxdna_client *client;
339 	dma_addr_t dma_addr;
340 	u8 *buff_addr;
341 	int ret;
342 
343 	buf_sz = ndev->aie.metadata.cols * ndev->aie.metadata.col_size;
344 	buff_addr = amdxdna_alloc_msg_buffer(xdna, &buf_sz, &dma_addr);
345 	if (IS_ERR(buff_addr))
346 		return PTR_ERR(buff_addr);
347 
348 	/* Go through each hardware context and mark the AIE columns that are active */
349 	list_for_each_entry(client, &xdna->client_list, node)
350 		amdxdna_hwctx_walk(client, &aie_bitmap, amdxdna_hwctx_col_map);
351 
352 	*cols_filled = 0;
353 	req.dump_buff_addr = dma_addr;
354 	req.dump_buff_size = buf_sz;
355 	req.num_cols = hweight32(aie_bitmap);
356 	req.aie_bitmap = aie_bitmap;
357 
358 	drm_clflush_virt_range(buff_addr, req.dump_buff_size); /* device can access */
359 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
360 	if (ret) {
361 		XDNA_ERR(xdna, "Error during NPU query, status %d", ret);
362 		goto fail;
363 	}
364 
365 	XDNA_DBG(xdna, "Query NPU status completed");
366 
367 	if (buf_sz < resp.size) {
368 		ret = -EINVAL;
369 		XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u", buf_sz, resp.size);
370 		goto fail;
371 	}
372 
373 	size = min(size, resp.size);
374 	if (copy_to_user(buf, buff_addr, size)) {
375 		ret = -EFAULT;
376 		XDNA_ERR(xdna, "Failed to copy NPU status to user space");
377 		goto fail;
378 	}
379 
380 	*cols_filled = aie_bitmap;
381 
382 fail:
383 	amdxdna_free_msg_buffer(xdna, buf_sz, buff_addr, dma_addr);
384 	return ret;
385 }
386 
387 int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
388 			 char __user *buf, u32 size,
389 			 struct amdxdna_drm_query_telemetry_header *header)
390 {
391 	DECLARE_AIE_MSG(get_telemetry, MSG_OP_GET_TELEMETRY);
392 	struct amdxdna_dev *xdna = ndev->aie.xdna;
393 	dma_addr_t dma_addr;
394 	u32 buf_sz;
395 	u8 *addr;
396 	int ret;
397 
398 	if (header->type >= MAX_TELEMETRY_TYPE)
399 		return -EINVAL;
400 
401 	buf_sz = min(size, SZ_4M);
402 	addr = amdxdna_alloc_msg_buffer(xdna, &buf_sz, &dma_addr);
403 	if (IS_ERR(addr))
404 		return PTR_ERR(addr);
405 
406 	req.buf_addr = dma_addr;
407 	req.buf_size = buf_sz;
408 	req.type = header->type;
409 
410 	drm_clflush_virt_range(addr, req.buf_size); /* device can access */
411 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
412 	if (ret) {
413 		XDNA_ERR(xdna, "Query telemetry failed, status %d", ret);
414 		goto free_buf;
415 	}
416 
417 	if (buf_sz < resp.size) {
418 		ret = -EINVAL;
419 		XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u", buf_sz, resp.size);
420 		goto free_buf;
421 	}
422 
423 	size = min(size, resp.size);
424 	if (copy_to_user(buf, addr, size)) {
425 		ret = -EFAULT;
426 		XDNA_ERR(xdna, "Failed to copy telemetry to user space");
427 		goto free_buf;
428 	}
429 
430 	header->major = resp.major;
431 	header->minor = resp.minor;
432 
433 free_buf:
434 	amdxdna_free_msg_buffer(xdna, buf_sz, addr, dma_addr);
435 	return ret;
436 }
437 
438 int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size,
439 				 void *handle, int (*cb)(void*, void __iomem *, size_t))
440 {
441 	struct async_event_msg_req req = { 0 };
442 	struct xdna_mailbox_msg msg = {
443 		.send_data = (u8 *)&req,
444 		.send_size = sizeof(req),
445 		.handle = handle,
446 		.opcode = MSG_OP_REGISTER_ASYNC_EVENT_MSG,
447 		.notify_cb = cb,
448 	};
449 
450 	req.buf_addr = addr;
451 	req.buf_size = size;
452 
453 	XDNA_DBG(ndev->aie.xdna, "Register addr 0x%llx size 0x%x", addr, size);
454 	return xdna_mailbox_send_msg(ndev->aie.mgmt_chann, &msg, TX_TIMEOUT);
455 }
456 
457 int aie2_config_cu(struct amdxdna_hwctx *hwctx,
458 		   int (*notify_cb)(void *, void __iomem *, size_t))
459 {
460 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
461 	struct amdxdna_dev *xdna = hwctx->client->xdna;
462 	u32 shift = xdna->dev_info->dev_mem_buf_shift;
463 	struct config_cu_req req = { 0 };
464 	struct xdna_mailbox_msg msg;
465 	struct drm_gem_object *gobj;
466 	struct amdxdna_gem_obj *abo;
467 	int i;
468 
469 	if (!chann)
470 		return -ENODEV;
471 
472 	if (!hwctx->cus)
473 		return 0;
474 
475 	if (hwctx->cus->num_cus > MAX_NUM_CUS) {
476 		XDNA_DBG(xdna, "Exceed maximum CU %d", MAX_NUM_CUS);
477 		return -EINVAL;
478 	}
479 
480 	for (i = 0; i < hwctx->cus->num_cus; i++) {
481 		struct amdxdna_cu_config *cu = &hwctx->cus->cu_configs[i];
482 
483 		if (XDNA_MBZ_DBG(xdna, cu->pad, sizeof(cu->pad)))
484 			return -EINVAL;
485 
486 		gobj = drm_gem_object_lookup(hwctx->client->filp, cu->cu_bo);
487 		if (!gobj) {
488 			XDNA_ERR(xdna, "Lookup GEM object failed");
489 			return -EINVAL;
490 		}
491 		abo = to_xdna_obj(gobj);
492 
493 		if (abo->type != AMDXDNA_BO_DEV) {
494 			drm_gem_object_put(gobj);
495 			XDNA_ERR(xdna, "Invalid BO type");
496 			return -EINVAL;
497 		}
498 
499 		req.cfgs[i] = FIELD_PREP(AIE2_MSG_CFG_CU_PDI_ADDR,
500 					 amdxdna_gem_dev_addr(abo) >> shift);
501 		req.cfgs[i] |= FIELD_PREP(AIE2_MSG_CFG_CU_FUNC, cu->cu_func);
502 		XDNA_DBG(xdna, "CU %d full addr 0x%llx, cfg 0x%x", i,
503 			 amdxdna_gem_dev_addr(abo), req.cfgs[i]);
504 		drm_gem_object_put(gobj);
505 	}
506 	req.num_cus = hwctx->cus->num_cus;
507 
508 	msg.send_data = (u8 *)&req;
509 	msg.send_size = sizeof(req);
510 	msg.handle = hwctx;
511 	msg.opcode = MSG_OP_CONFIG_CU;
512 	msg.notify_cb = notify_cb;
513 	return xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
514 }
515 
516 static int aie2_init_exec_cu_req(struct amdxdna_gem_obj *cmd_bo, void *req,
517 				 size_t *size, u32 *msg_op)
518 {
519 	struct execute_buffer_req *cu_req = req;
520 	u32 cmd_len;
521 	void *cmd;
522 
523 	cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
524 	if (cmd_len > sizeof(cu_req->payload))
525 		return -EINVAL;
526 
527 	cu_req->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
528 	if (cu_req->cu_idx == INVALID_CU_IDX)
529 		return -EINVAL;
530 
531 	memcpy(cu_req->payload, cmd, cmd_len);
532 
533 	*size = sizeof(*cu_req);
534 	*msg_op = MSG_OP_EXECUTE_BUFFER_CF;
535 	return 0;
536 }
537 
538 static int aie2_init_exec_dpu_req(struct amdxdna_gem_obj *cmd_bo, void *req,
539 				  size_t *size, u32 *msg_op)
540 {
541 	struct exec_dpu_req *dpu_req = req;
542 	struct amdxdna_cmd_start_npu *sn;
543 	u32 cmd_len;
544 
545 	sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
546 	if (cmd_len - sizeof(*sn) > sizeof(dpu_req->payload))
547 		return -EINVAL;
548 
549 	dpu_req->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
550 	if (dpu_req->cu_idx == INVALID_CU_IDX)
551 		return -EINVAL;
552 
553 	dpu_req->inst_buf_addr = sn->buffer;
554 	dpu_req->inst_size = sn->buffer_size;
555 	dpu_req->inst_prop_cnt = sn->prop_count;
556 	memcpy(dpu_req->payload, sn->prop_args, cmd_len - sizeof(*sn));
557 
558 	*size = sizeof(*dpu_req);
559 	*msg_op = MSG_OP_EXEC_DPU;
560 	return 0;
561 }
562 
563 static void aie2_init_exec_chain_req(void *req, u64 slot_addr, size_t size, u32 cmd_cnt)
564 {
565 	struct cmd_chain_req *chain_req = req;
566 
567 	chain_req->buf_addr = slot_addr;
568 	chain_req->buf_size = size;
569 	chain_req->count = cmd_cnt;
570 }
571 
572 static void aie2_init_npu_chain_req(void *req, u64 slot_addr, size_t size, u32 cmd_cnt)
573 {
574 	struct cmd_chain_npu_req *npu_chain_req = req;
575 
576 	npu_chain_req->flags = 0;
577 	npu_chain_req->reserved = 0;
578 	npu_chain_req->buf_addr = slot_addr;
579 	npu_chain_req->buf_size = size;
580 	npu_chain_req->count = cmd_cnt;
581 }
582 
583 static int
584 aie2_cmdlist_fill_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
585 {
586 	struct cmd_chain_slot_execbuf_cf *cf_slot = slot;
587 	u32 cmd_len;
588 	void *cmd;
589 
590 	cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
591 	if (*size < sizeof(*cf_slot) + cmd_len)
592 		return -EINVAL;
593 
594 	cf_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
595 	if (cf_slot->cu_idx == INVALID_CU_IDX)
596 		return -EINVAL;
597 
598 	cf_slot->arg_cnt = cmd_len / sizeof(u32);
599 	memcpy(cf_slot->args, cmd, cmd_len);
600 	/* Accurate slot size to hint firmware to do necessary copy */
601 	*size = sizeof(*cf_slot) + cmd_len;
602 	return 0;
603 }
604 
605 static int
606 aie2_cmdlist_fill_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
607 {
608 	struct cmd_chain_slot_dpu *dpu_slot = slot;
609 	struct amdxdna_cmd_start_npu *sn;
610 	u32 cmd_len;
611 	u32 arg_sz;
612 
613 	sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
614 	arg_sz = cmd_len - sizeof(*sn);
615 	if (cmd_len < sizeof(*sn) || arg_sz > MAX_DPU_ARGS_SIZE)
616 		return -EINVAL;
617 
618 	if (*size < sizeof(*dpu_slot) + arg_sz)
619 		return -EINVAL;
620 
621 	dpu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
622 	if (dpu_slot->cu_idx == INVALID_CU_IDX)
623 		return -EINVAL;
624 
625 	dpu_slot->inst_buf_addr = sn->buffer;
626 	dpu_slot->inst_size = sn->buffer_size;
627 	dpu_slot->inst_prop_cnt = sn->prop_count;
628 	dpu_slot->arg_cnt = arg_sz / sizeof(u32);
629 	memcpy(dpu_slot->args, sn->prop_args, arg_sz);
630 
631 	/* Accurate slot size to hint firmware to do necessary copy */
632 	*size = sizeof(*dpu_slot) + arg_sz;
633 	return 0;
634 }
635 
636 static int aie2_cmdlist_unsupp(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
637 {
638 	return -EOPNOTSUPP;
639 }
640 
641 static u32 aie2_get_chain_msg_op(u32 cmd_op)
642 {
643 	switch (cmd_op) {
644 	case ERT_START_CU:
645 		return MSG_OP_CHAIN_EXEC_BUFFER_CF;
646 	case ERT_START_NPU:
647 		return MSG_OP_CHAIN_EXEC_DPU;
648 	default:
649 		break;
650 	}
651 
652 	return MSG_OP_MAX_OPCODE;
653 }
654 
655 static struct aie2_exec_msg_ops legacy_exec_message_ops = {
656 	.init_cu_req = aie2_init_exec_cu_req,
657 	.init_dpu_req = aie2_init_exec_dpu_req,
658 	.init_chain_req = aie2_init_exec_chain_req,
659 	.fill_cf_slot = aie2_cmdlist_fill_cf,
660 	.fill_dpu_slot = aie2_cmdlist_fill_dpu,
661 	.fill_preempt_slot = aie2_cmdlist_unsupp,
662 	.fill_elf_slot = aie2_cmdlist_unsupp,
663 	.get_chain_msg_op = aie2_get_chain_msg_op,
664 };
665 
666 static int
667 aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
668 {
669 	struct cmd_chain_slot_npu *npu_slot = slot;
670 	u32 cmd_len;
671 	void *cmd;
672 
673 	cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
674 	if (*size < sizeof(*npu_slot) + cmd_len)
675 		return -EINVAL;
676 
677 	memset(npu_slot, 0, sizeof(*npu_slot));
678 	npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
679 	if (npu_slot->cu_idx == INVALID_CU_IDX)
680 		return -EINVAL;
681 
682 	npu_slot->type = EXEC_NPU_TYPE_NON_ELF;
683 	npu_slot->arg_cnt = cmd_len / sizeof(u32);
684 	memcpy(npu_slot->args, cmd, cmd_len);
685 
686 	*size = sizeof(*npu_slot) + cmd_len;
687 	return 0;
688 }
689 
690 static int
691 aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
692 {
693 	struct cmd_chain_slot_npu *npu_slot = slot;
694 	struct amdxdna_cmd_start_npu *sn;
695 	u32 cmd_len;
696 	u32 arg_sz;
697 
698 	sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
699 	arg_sz = cmd_len - sizeof(*sn);
700 	if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
701 		return -EINVAL;
702 
703 	if (*size < sizeof(*npu_slot) + arg_sz)
704 		return -EINVAL;
705 
706 	memset(npu_slot, 0, sizeof(*npu_slot));
707 	npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
708 	if (npu_slot->cu_idx == INVALID_CU_IDX)
709 		return -EINVAL;
710 
711 	npu_slot->type = EXEC_NPU_TYPE_PARTIAL_ELF;
712 	npu_slot->inst_buf_addr = sn->buffer;
713 	npu_slot->inst_size = sn->buffer_size;
714 	npu_slot->inst_prop_cnt = sn->prop_count;
715 	npu_slot->arg_cnt = arg_sz / sizeof(u32);
716 	memcpy(npu_slot->args, sn->prop_args, arg_sz);
717 
718 	*size = sizeof(*npu_slot) + arg_sz;
719 	return 0;
720 }
721 
722 static int
723 aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
724 {
725 	struct cmd_chain_slot_npu *npu_slot = slot;
726 	struct amdxdna_cmd_preempt_data *pd;
727 	u32 cmd_len;
728 	u32 arg_sz;
729 
730 	pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
731 	arg_sz = cmd_len - sizeof(*pd);
732 	if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
733 		return -EINVAL;
734 
735 	if (*size < sizeof(*npu_slot) + arg_sz)
736 		return -EINVAL;
737 
738 	memset(npu_slot, 0, sizeof(*npu_slot));
739 	npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
740 	if (npu_slot->cu_idx == INVALID_CU_IDX)
741 		return -EINVAL;
742 
743 	npu_slot->type = EXEC_NPU_TYPE_PREEMPT;
744 	npu_slot->inst_buf_addr = pd->inst_buf;
745 	npu_slot->save_buf_addr = pd->save_buf;
746 	npu_slot->restore_buf_addr = pd->restore_buf;
747 	npu_slot->inst_size = pd->inst_size;
748 	npu_slot->save_size = pd->save_size;
749 	npu_slot->restore_size = pd->restore_size;
750 	npu_slot->inst_prop_cnt = pd->inst_prop_cnt;
751 	npu_slot->arg_cnt = arg_sz / sizeof(u32);
752 	memcpy(npu_slot->args, pd->prop_args, arg_sz);
753 
754 	*size = sizeof(*npu_slot) + arg_sz;
755 	return 0;
756 }
757 
758 static int
759 aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size)
760 {
761 	struct cmd_chain_slot_npu *npu_slot = slot;
762 	struct amdxdna_cmd_preempt_data *pd;
763 	u32 cmd_len;
764 	u32 arg_sz;
765 
766 	pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
767 	arg_sz = cmd_len - sizeof(*pd);
768 	if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
769 		return -EINVAL;
770 
771 	if (*size < sizeof(*npu_slot) + arg_sz)
772 		return -EINVAL;
773 
774 	memset(npu_slot, 0, sizeof(*npu_slot));
775 	npu_slot->type = EXEC_NPU_TYPE_ELF;
776 	npu_slot->inst_buf_addr = pd->inst_buf;
777 	npu_slot->save_buf_addr = pd->save_buf;
778 	npu_slot->restore_buf_addr = pd->restore_buf;
779 	npu_slot->inst_size = pd->inst_size;
780 	npu_slot->save_size = pd->save_size;
781 	npu_slot->restore_size = pd->restore_size;
782 	npu_slot->inst_prop_cnt = pd->inst_prop_cnt;
783 	npu_slot->arg_cnt = 1;
784 	npu_slot->args[0] = AIE2_EXEC_BUFFER_KERNEL_OP_TXN;
785 
786 	*size = struct_size(npu_slot, args, npu_slot->arg_cnt);
787 	return 0;
788 }
789 
790 static u32 aie2_get_npu_chain_msg_op(u32 cmd_op)
791 {
792 	return MSG_OP_CHAIN_EXEC_NPU;
793 }
794 
795 static struct aie2_exec_msg_ops npu_exec_message_ops = {
796 	.init_cu_req = aie2_init_exec_cu_req,
797 	.init_dpu_req = aie2_init_exec_dpu_req,
798 	.init_chain_req = aie2_init_npu_chain_req,
799 	.fill_cf_slot = aie2_cmdlist_fill_npu_cf,
800 	.fill_dpu_slot = aie2_cmdlist_fill_npu_dpu,
801 	.fill_preempt_slot = aie2_cmdlist_fill_npu_preempt,
802 	.fill_elf_slot = aie2_cmdlist_fill_npu_elf,
803 	.get_chain_msg_op = aie2_get_npu_chain_msg_op,
804 };
805 
806 static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
807 			      size_t *size, u32 *msg_op)
808 {
809 	struct amdxdna_dev *xdna = cmd_abo->client->xdna;
810 	int ret;
811 	u32 op;
812 
813 	op = amdxdna_cmd_get_op(cmd_abo);
814 	switch (op) {
815 	case ERT_START_CU:
816 		ret = EXEC_MSG_OPS(xdna)->init_cu_req(cmd_abo, req, size, msg_op);
817 		if (ret) {
818 			XDNA_DBG(xdna, "Init CU req failed ret %d", ret);
819 			return ret;
820 		}
821 		break;
822 	case ERT_START_NPU:
823 		ret = EXEC_MSG_OPS(xdna)->init_dpu_req(cmd_abo, req, size, msg_op);
824 		if (ret) {
825 			XDNA_DBG(xdna, "Init DPU req failed ret %d", ret);
826 			return ret;
827 		}
828 
829 		break;
830 	default:
831 		XDNA_ERR(xdna, "Unsupported op %d", op);
832 		ret = -EOPNOTSUPP;
833 		break;
834 	}
835 
836 	return ret;
837 }
838 
839 static int
840 aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
841 		       size_t *size, u32 *cmd_op)
842 {
843 	struct amdxdna_dev *xdna = cmd_abo->client->xdna;
844 	int ret;
845 	u32 op;
846 
847 	op = amdxdna_cmd_get_op(cmd_abo);
848 	if (*cmd_op == ERT_INVALID_CMD)
849 		*cmd_op = op;
850 	else if (op != *cmd_op)
851 		return -EINVAL;
852 
853 	switch (op) {
854 	case ERT_START_CU:
855 		ret = EXEC_MSG_OPS(xdna)->fill_cf_slot(cmd_abo, slot, size);
856 		break;
857 	case ERT_START_NPU:
858 		ret = EXEC_MSG_OPS(xdna)->fill_dpu_slot(cmd_abo, slot, size);
859 		break;
860 	case ERT_START_NPU_PREEMPT:
861 		if (!AIE_FEATURE_ON(&xdna->dev_handle->aie, AIE2_PREEMPT))
862 			return -EOPNOTSUPP;
863 		ret = EXEC_MSG_OPS(xdna)->fill_preempt_slot(cmd_abo, slot, size);
864 		break;
865 	case ERT_START_NPU_PREEMPT_ELF:
866 		if (!AIE_FEATURE_ON(&xdna->dev_handle->aie, AIE2_PREEMPT))
867 			return -EOPNOTSUPP;
868 		ret = EXEC_MSG_OPS(xdna)->fill_elf_slot(cmd_abo, slot, size);
869 		break;
870 	default:
871 		XDNA_INFO(xdna, "Unsupported op %d", op);
872 		ret = -EOPNOTSUPP;
873 		break;
874 	}
875 
876 	return ret;
877 }
878 
879 void aie2_msg_init(struct amdxdna_dev_hdl *ndev)
880 {
881 	if (AIE_FEATURE_ON(&ndev->aie, AIE2_NPU_COMMAND))
882 		ndev->exec_msg_ops = &npu_exec_message_ops;
883 	else
884 		ndev->exec_msg_ops = &legacy_exec_message_ops;
885 }
886 
887 static inline struct amdxdna_gem_obj *
888 aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job)
889 {
890 	int idx = get_job_idx(job->seq);
891 
892 	return job->hwctx->priv->cmd_buf[idx];
893 }
894 
895 int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
896 		 int (*notify_cb)(void *, void __iomem *, size_t))
897 {
898 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
899 	struct amdxdna_dev *xdna = hwctx->client->xdna;
900 	struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
901 	struct xdna_mailbox_msg msg;
902 	union exec_req req;
903 	int ret;
904 
905 	if (!chann)
906 		return -ENODEV;
907 
908 	ret = aie2_init_exec_req(&req, cmd_abo, &msg.send_size, &msg.opcode);
909 	if (ret)
910 		return ret;
911 
912 	msg.handle = job;
913 	msg.notify_cb = notify_cb;
914 	msg.send_data = (u8 *)&req;
915 	print_hex_dump_debug("cmd: ", DUMP_PREFIX_OFFSET, 16, 4, &req,
916 			     0x40, false);
917 
918 	ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
919 	if (ret) {
920 		XDNA_ERR(xdna, "Send message failed");
921 		return ret;
922 	}
923 
924 	return 0;
925 }
926 
927 int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
928 			       struct amdxdna_sched_job *job,
929 			       int (*notify_cb)(void *, void __iomem *, size_t))
930 {
931 	struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job);
932 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
933 	struct amdxdna_client *client = hwctx->client;
934 	struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
935 	void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
936 	struct amdxdna_dev *xdna = client->xdna;
937 	struct amdxdna_cmd_chain *payload;
938 	struct xdna_mailbox_msg msg;
939 	union exec_chain_req req;
940 	u32 payload_len, ccnt;
941 	u32 offset = 0;
942 	size_t size;
943 	int ret;
944 	u32 op;
945 	u32 i;
946 
947 	if (!cmd_buf)
948 		return -ENOMEM;
949 
950 	op = amdxdna_cmd_get_op(cmd_abo);
951 	payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
952 	if (op != ERT_CMD_CHAIN) {
953 		XDNA_DBG(xdna, "Invalid op code %d", op);
954 		return -EINVAL;
955 	}
956 
957 	if (!payload) {
958 		XDNA_DBG(xdna, "Failed to get command payload");
959 		return -EINVAL;
960 	}
961 
962 	ccnt = payload->command_count;
963 	if (payload_len < struct_size(payload, data, ccnt)) {
964 		XDNA_DBG(xdna, "Invalid command count %d", ccnt);
965 		return -EINVAL;
966 	}
967 
968 	op = ERT_INVALID_CMD;
969 	for (i = 0; i < ccnt; i++) {
970 		u32 boh = (u32)(payload->data[i]);
971 		struct amdxdna_gem_obj *abo;
972 
973 		abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_SHARE);
974 		if (!abo) {
975 			XDNA_ERR(xdna, "Failed to find cmd BO %d", boh);
976 			return -ENOENT;
977 		}
978 
979 		size = cmdbuf_abo->mem.size - offset;
980 		ret = aie2_cmdlist_fill_slot(cmd_buf + offset, abo, &size, &op);
981 		amdxdna_gem_put_obj(abo);
982 		if (ret)
983 			return ret;
984 
985 		offset += size;
986 	}
987 
988 	XDNA_DBG(xdna, "Total %d commands:", ccnt);
989 	print_hex_dump_debug("cmdbufs: ", DUMP_PREFIX_OFFSET, 16, 4,
990 			     cmd_buf, offset, false);
991 
992 	msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
993 	if (msg.opcode == MSG_OP_MAX_OPCODE)
994 		return -EOPNOTSUPP;
995 
996 	/* The offset is the accumulated total size of the cmd buffer */
997 	EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo),
998 					   offset, ccnt);
999 	drm_clflush_virt_range(cmd_buf, offset);
1000 
1001 	msg.handle = job;
1002 	msg.notify_cb = notify_cb;
1003 	msg.send_data = (u8 *)&req;
1004 	msg.send_size = sizeof(req);
1005 	print_hex_dump_debug("cmdlist msg: ", DUMP_PREFIX_OFFSET, 16, 4,
1006 			     &req, msg.send_size, false);
1007 	ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
1008 	if (ret) {
1009 		XDNA_ERR(xdna, "Send message failed");
1010 		return ret;
1011 	}
1012 
1013 	return 0;
1014 }
1015 
1016 int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx,
1017 				struct amdxdna_sched_job *job,
1018 				int (*notify_cb)(void *, void __iomem *, size_t))
1019 {
1020 	struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job);
1021 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
1022 	struct amdxdna_dev *xdna = hwctx->client->xdna;
1023 	struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
1024 	void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
1025 	struct xdna_mailbox_msg msg;
1026 	union exec_chain_req req;
1027 	u32 op = ERT_INVALID_CMD;
1028 	size_t size;
1029 	int ret;
1030 
1031 	if (!cmd_buf)
1032 		return -ENOMEM;
1033 
1034 	size = cmdbuf_abo->mem.size;
1035 	ret = aie2_cmdlist_fill_slot(cmd_buf, cmd_abo, &size, &op);
1036 	if (ret)
1037 		return ret;
1038 
1039 	print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4, cmd_buf, size, false);
1040 
1041 	msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
1042 	if (msg.opcode == MSG_OP_MAX_OPCODE)
1043 		return -EOPNOTSUPP;
1044 
1045 	EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo), size, 1);
1046 	drm_clflush_virt_range(cmd_buf, size);
1047 
1048 	msg.handle = job;
1049 	msg.notify_cb = notify_cb;
1050 	msg.send_data = (u8 *)&req;
1051 	msg.send_size = sizeof(req);
1052 	print_hex_dump_debug("cmdlist msg: ", DUMP_PREFIX_OFFSET, 16, 4,
1053 			     &req, msg.send_size, false);
1054 	ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
1055 	if (ret) {
1056 		XDNA_ERR(hwctx->client->xdna, "Send message failed");
1057 		return ret;
1058 	}
1059 
1060 	return 0;
1061 }
1062 
1063 int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
1064 		 int (*notify_cb)(void *, void __iomem *, size_t))
1065 {
1066 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
1067 	struct amdxdna_gem_obj *abo = to_xdna_obj(job->bos[0]);
1068 	struct amdxdna_dev *xdna = hwctx->client->xdna;
1069 	struct xdna_mailbox_msg msg;
1070 	struct sync_bo_req req;
1071 	int ret = 0;
1072 
1073 	req.src_addr = 0;
1074 	req.dst_addr = amdxdna_dev_bo_offset(abo);
1075 	req.size = abo->mem.size;
1076 
1077 	/* Device to Host */
1078 	req.type = FIELD_PREP(AIE2_MSG_SYNC_BO_SRC_TYPE, SYNC_BO_DEV_MEM) |
1079 		FIELD_PREP(AIE2_MSG_SYNC_BO_DST_TYPE, SYNC_BO_HOST_MEM);
1080 
1081 	XDNA_DBG(xdna, "sync %d bytes src(0x%llx) to dst(0x%llx) completed",
1082 		 req.size, req.src_addr, req.dst_addr);
1083 
1084 	msg.handle = job;
1085 	msg.notify_cb = notify_cb;
1086 	msg.send_data = (u8 *)&req;
1087 	msg.send_size = sizeof(req);
1088 	msg.opcode = MSG_OP_SYNC_BO;
1089 
1090 	ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
1091 	if (ret) {
1092 		XDNA_ERR(xdna, "Send message failed");
1093 		return ret;
1094 	}
1095 
1096 	return 0;
1097 }
1098 
1099 int aie2_config_debug_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
1100 			 int (*notify_cb)(void *, void __iomem *, size_t))
1101 {
1102 	struct mailbox_channel *chann = hwctx->priv->mbox_chann;
1103 	struct amdxdna_gem_obj *abo = to_xdna_obj(job->bos[0]);
1104 	struct amdxdna_dev *xdna = hwctx->client->xdna;
1105 	struct config_debug_bo_req req;
1106 	struct xdna_mailbox_msg msg;
1107 
1108 	if (job->drv_cmd->opcode == ATTACH_DEBUG_BO)
1109 		req.config = DEBUG_BO_REGISTER;
1110 	else
1111 		req.config = DEBUG_BO_UNREGISTER;
1112 
1113 	req.offset = amdxdna_dev_bo_offset(abo);
1114 	req.size = abo->mem.size;
1115 
1116 	XDNA_DBG(xdna, "offset 0x%llx size 0x%llx config %d",
1117 		 req.offset, req.size, req.config);
1118 
1119 	msg.handle = job;
1120 	msg.notify_cb = notify_cb;
1121 	msg.send_data = (u8 *)&req;
1122 	msg.send_size = sizeof(req);
1123 	msg.opcode = MSG_OP_CONFIG_DEBUG_BO;
1124 
1125 	return xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
1126 }
1127 
1128 int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
1129 			  struct app_health_report *report)
1130 {
1131 	DECLARE_AIE_MSG(get_app_health, MSG_OP_GET_APP_HEALTH);
1132 	struct amdxdna_dev *xdna = ndev->aie.xdna;
1133 	struct app_health_report *buf;
1134 	dma_addr_t dma_addr;
1135 	u32 buf_size;
1136 	int ret;
1137 
1138 	if (!AIE_FEATURE_ON(&ndev->aie, AIE2_APP_HEALTH)) {
1139 		XDNA_DBG(xdna, "App health feature not supported");
1140 		return -EOPNOTSUPP;
1141 	}
1142 
1143 	buf_size = sizeof(*report);
1144 	buf = amdxdna_alloc_msg_buffer(xdna, &buf_size, &dma_addr);
1145 	if (IS_ERR(buf)) {
1146 		XDNA_ERR(xdna, "Failed to allocate buffer for app health");
1147 		return PTR_ERR(buf);
1148 	}
1149 
1150 	req.buf_addr = dma_addr;
1151 	req.context_id = context_id;
1152 	req.buf_size = buf_size;
1153 
1154 	drm_clflush_virt_range(buf, req.buf_size);
1155 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
1156 	if (ret) {
1157 		XDNA_ERR(xdna, "Get app health failed, ret %d status 0x%x", ret, resp.status);
1158 		goto free_buf;
1159 	}
1160 
1161 	/* Copy the report to caller's buffer */
1162 	memcpy(report, buf, sizeof(*report));
1163 
1164 free_buf:
1165 	amdxdna_free_msg_buffer(xdna, buf_size, buf, dma_addr);
1166 	return ret;
1167 }
1168 
1169 static int
1170 aie2_runtime_update_ctx_prop(struct amdxdna_dev_hdl *ndev,
1171 			     struct amdxdna_hwctx *ctx, u32 type, u32 value)
1172 {
1173 	DECLARE_AIE_MSG(update_property, MSG_OP_UPDATE_PROPERTY);
1174 	struct amdxdna_dev *xdna = ndev->aie.xdna;
1175 	int ret;
1176 
1177 	if (!AIE_FEATURE_ON(&ndev->aie, AIE2_UPDATE_PROPERTY))
1178 		return -EOPNOTSUPP;
1179 
1180 	if (ctx)
1181 		req.context_id = ctx->fw_ctx_id;
1182 	else
1183 		req.context_id = AIE2_UPDATE_PROPERTY_ALL_CTX;
1184 
1185 	req.time_quota_us = value;
1186 	req.type = type;
1187 
1188 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
1189 	if (ret) {
1190 		XDNA_ERR(xdna, "%s update property failed, type %d ret %d",
1191 			 ctx ? ctx->name : "ctx.all", type, ret);
1192 		return ret;
1193 	}
1194 
1195 	return 0;
1196 }
1197 
1198 int aie2_update_prop_time_quota(struct amdxdna_dev_hdl *ndev, u32 us)
1199 {
1200 	struct amdxdna_dev *xdna = ndev->aie.xdna;
1201 	int ret;
1202 
1203 	ret = aie2_runtime_update_ctx_prop(ndev, NULL, UPDATE_PROPERTY_TIME_QUOTA, us);
1204 	if (ret == -EOPNOTSUPP) {
1205 		XDNA_DBG(xdna, "update time quota not support, skipped");
1206 		ret = 0;
1207 	} else if (!ret) {
1208 		XDNA_DBG(xdna, "Ctx exec time quantum updated to %u us", us);
1209 	}
1210 	return ret;
1211 }
1212 
1213 int aie2_get_dev_revision(struct amdxdna_dev_hdl *ndev, enum aie2_dev_revision *rev)
1214 {
1215 	DECLARE_AIE_MSG(get_dev_revision, MSG_OP_GET_DEV_REVISION);
1216 	struct amdxdna_dev *xdna = ndev->aie.xdna;
1217 	int ret;
1218 
1219 	if (!AIE_FEATURE_ON(&ndev->aie, AIE2_GET_DEV_REVISION))
1220 		return -EOPNOTSUPP;
1221 
1222 	ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
1223 	if (ret)
1224 		return ret;
1225 
1226 	*rev = resp.rev;
1227 
1228 	if (*rev < AIE2_DEV_REVISION_STXA || *rev >= AIE2_DEV_REVISION_UNKN) {
1229 		XDNA_ERR(xdna, "Unknown device revision: %d (raw fuse: 0x%x)",
1230 			 *rev, resp.raw_fuse_data);
1231 		return -EINVAL;
1232 	}
1233 
1234 	XDNA_DBG(xdna, "Device revision: %d (raw fuse: 0x%x)", *rev, resp.raw_fuse_data);
1235 	return 0;
1236 }
1237