File Index
Files and directories
Sign in
FILE

aie2_message.c

File preview with syntax highlighting.

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