xref: /linux/drivers/accel/amdxdna/aie.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
15a55a5daSLizhi Hou // SPDX-License-Identifier: GPL-2.0
25a55a5daSLizhi Hou /*
35a55a5daSLizhi Hou  * Copyright (C) 2026, Advanced Micro Devices, Inc.
45a55a5daSLizhi Hou  */
55a55a5daSLizhi Hou 
65a55a5daSLizhi Hou #include <linux/errno.h>
75a55a5daSLizhi Hou 
85a55a5daSLizhi Hou #include "aie.h"
95a55a5daSLizhi Hou #include "amdxdna_mailbox_helper.h"
105a55a5daSLizhi Hou #include "amdxdna_mailbox.h"
115a55a5daSLizhi Hou #include "amdxdna_pci_drv.h"
125a55a5daSLizhi Hou 
135a55a5daSLizhi Hou void aie_dump_mgmt_chann_debug(struct aie_device *aie)
145a55a5daSLizhi Hou {
155a55a5daSLizhi Hou 	struct amdxdna_dev *xdna = aie->xdna;
165a55a5daSLizhi Hou 
175a55a5daSLizhi Hou 	XDNA_DBG(xdna, "i2x tail    0x%x", aie->mgmt_i2x.mb_tail_ptr_reg);
185a55a5daSLizhi Hou 	XDNA_DBG(xdna, "i2x head    0x%x", aie->mgmt_i2x.mb_head_ptr_reg);
195a55a5daSLizhi Hou 	XDNA_DBG(xdna, "i2x ringbuf 0x%x", aie->mgmt_i2x.rb_start_addr);
205a55a5daSLizhi Hou 	XDNA_DBG(xdna, "i2x rsize   0x%x", aie->mgmt_i2x.rb_size);
215a55a5daSLizhi Hou 	XDNA_DBG(xdna, "x2i tail    0x%x", aie->mgmt_x2i.mb_tail_ptr_reg);
225a55a5daSLizhi Hou 	XDNA_DBG(xdna, "x2i head    0x%x", aie->mgmt_x2i.mb_head_ptr_reg);
235a55a5daSLizhi Hou 	XDNA_DBG(xdna, "x2i ringbuf 0x%x", aie->mgmt_x2i.rb_start_addr);
245a55a5daSLizhi Hou 	XDNA_DBG(xdna, "x2i rsize   0x%x", aie->mgmt_x2i.rb_size);
255a55a5daSLizhi Hou 	XDNA_DBG(xdna, "x2i chann index 0x%x", aie->mgmt_chan_idx);
265a55a5daSLizhi Hou 	XDNA_DBG(xdna, "mailbox protocol major 0x%x", aie->mgmt_prot_major);
275a55a5daSLizhi Hou 	XDNA_DBG(xdna, "mailbox protocol minor 0x%x", aie->mgmt_prot_minor);
285a55a5daSLizhi Hou }
295a55a5daSLizhi Hou 
305a55a5daSLizhi Hou void aie_destroy_chann(struct aie_device *aie, struct mailbox_channel **chann)
315a55a5daSLizhi Hou {
325a55a5daSLizhi Hou 	struct amdxdna_dev *xdna = aie->xdna;
335a55a5daSLizhi Hou 
345a55a5daSLizhi Hou 	drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
355a55a5daSLizhi Hou 
365a55a5daSLizhi Hou 	if (!*chann)
375a55a5daSLizhi Hou 		return;
385a55a5daSLizhi Hou 
395a55a5daSLizhi Hou 	xdna_mailbox_stop_channel(*chann);
405a55a5daSLizhi Hou 	xdna_mailbox_free_channel(*chann);
415a55a5daSLizhi Hou 	*chann = NULL;
425a55a5daSLizhi Hou }
435a55a5daSLizhi Hou 
445a55a5daSLizhi Hou int aie_send_mgmt_msg_wait(struct aie_device *aie, struct xdna_mailbox_msg *msg)
455a55a5daSLizhi Hou {
465a55a5daSLizhi Hou 	struct amdxdna_dev *xdna = aie->xdna;
475a55a5daSLizhi Hou 	struct xdna_notify *hdl = msg->handle;
485a55a5daSLizhi Hou 	int ret;
495a55a5daSLizhi Hou 
505a55a5daSLizhi Hou 	drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
515a55a5daSLizhi Hou 
525a55a5daSLizhi Hou 	if (!aie->mgmt_chann)
535a55a5daSLizhi Hou 		return -ENODEV;
545a55a5daSLizhi Hou 
555a55a5daSLizhi Hou 	ret = xdna_send_msg_wait(xdna, aie->mgmt_chann, msg);
565a55a5daSLizhi Hou 	if (ret == -ETIME)
575a55a5daSLizhi Hou 		aie_destroy_chann(aie, &aie->mgmt_chann);
585a55a5daSLizhi Hou 
595a55a5daSLizhi Hou 	if (!ret && *hdl->status) {
605a55a5daSLizhi Hou 		XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x",
615a55a5daSLizhi Hou 			 msg->opcode, *hdl->data);
625a55a5daSLizhi Hou 		ret = -EINVAL;
635a55a5daSLizhi Hou 	}
645a55a5daSLizhi Hou 
655a55a5daSLizhi Hou 	return ret;
665a55a5daSLizhi Hou }
675a55a5daSLizhi Hou 
685a55a5daSLizhi Hou int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor)
695a55a5daSLizhi Hou {
705a55a5daSLizhi Hou 	const struct amdxdna_fw_feature_tbl *feature;
715a55a5daSLizhi Hou 	bool found = false;
725a55a5daSLizhi Hou 
735a55a5daSLizhi Hou 	for (feature = aie->xdna->dev_info->fw_feature_tbl;
745a55a5daSLizhi Hou 	     feature->major; feature++) {
755a55a5daSLizhi Hou 		if (feature->major != fw_major)
765a55a5daSLizhi Hou 			continue;
775a55a5daSLizhi Hou 		if (fw_minor < feature->min_minor)
785a55a5daSLizhi Hou 			continue;
795a55a5daSLizhi Hou 		if (feature->max_minor > 0 && fw_minor > feature->max_minor)
805a55a5daSLizhi Hou 			continue;
815a55a5daSLizhi Hou 
825a55a5daSLizhi Hou 		aie->feature_mask |= feature->features;
835a55a5daSLizhi Hou 
845a55a5daSLizhi Hou 		/* firmware version matches one of the driver support entry */
855a55a5daSLizhi Hou 		found = true;
865a55a5daSLizhi Hou 	}
875a55a5daSLizhi Hou 
885a55a5daSLizhi Hou 	return found ? 0 : -EOPNOTSUPP;
895a55a5daSLizhi Hou }
90d8c33b9cSMax Zhen 
91d8c33b9cSMax Zhen static void amdxdna_update_vbnv(struct amdxdna_dev *xdna,
92d8c33b9cSMax Zhen 				const struct amdxdna_rev_vbnv *tbl,
93d8c33b9cSMax Zhen 				u32 rev)
94d8c33b9cSMax Zhen {
95d8c33b9cSMax Zhen 	int i;
96d8c33b9cSMax Zhen 
97d8c33b9cSMax Zhen 	for (i = 0; tbl[i].vbnv; i++) {
98d8c33b9cSMax Zhen 		if (tbl[i].revision == rev) {
99d8c33b9cSMax Zhen 			xdna->vbnv = tbl[i].vbnv;
100d8c33b9cSMax Zhen 			break;
101d8c33b9cSMax Zhen 		}
102d8c33b9cSMax Zhen 	}
103d8c33b9cSMax Zhen }
104d8c33b9cSMax Zhen 
105d8c33b9cSMax Zhen void amdxdna_vbnv_init(struct amdxdna_dev *xdna)
106d8c33b9cSMax Zhen {
107d8c33b9cSMax Zhen 	const struct amdxdna_dev_info *info = xdna->dev_info;
108d8c33b9cSMax Zhen 	u32 rev;
109d8c33b9cSMax Zhen 
110d8c33b9cSMax Zhen 	xdna->vbnv = info->default_vbnv;
111d8c33b9cSMax Zhen 
112d8c33b9cSMax Zhen 	if (!info->ops->get_dev_revision || !info->rev_vbnv_tbl)
113d8c33b9cSMax Zhen 		return;
114d8c33b9cSMax Zhen 
115d8c33b9cSMax Zhen 	if (info->ops->get_dev_revision(xdna, &rev))
116d8c33b9cSMax Zhen 		return;
117d8c33b9cSMax Zhen 
118d8c33b9cSMax Zhen 	amdxdna_update_vbnv(xdna, info->rev_vbnv_tbl, rev);
119d8c33b9cSMax Zhen }
1200b087e06SDavid Zhang 
1210b087e06SDavid Zhang int amdxdna_get_metadata(struct aie_device *aie,
1220b087e06SDavid Zhang 			 struct amdxdna_client *client,
1230b087e06SDavid Zhang 			 struct amdxdna_drm_get_info *args)
1240b087e06SDavid Zhang {
1250b087e06SDavid Zhang 	int ret = 0;
1260b087e06SDavid Zhang 	u32 buf_sz;
1270b087e06SDavid Zhang 
1280b087e06SDavid Zhang 	buf_sz = min(args->buffer_size, sizeof(aie->metadata));
1290b087e06SDavid Zhang 	if (copy_to_user(u64_to_user_ptr(args->buffer), &aie->metadata, buf_sz))
1300b087e06SDavid Zhang 		ret = -EFAULT;
1310b087e06SDavid Zhang 
1320b087e06SDavid Zhang 	return ret;
1330b087e06SDavid Zhang }
134*c0069781SNishad Saraf 
135*c0069781SNishad Saraf void *amdxdna_alloc_msg_buffer(struct amdxdna_dev *xdna, u32 *size,
136*c0069781SNishad Saraf 			       dma_addr_t *dma_addr)
137*c0069781SNishad Saraf {
138*c0069781SNishad Saraf 	void *vaddr;
139*c0069781SNishad Saraf 	int order;
140*c0069781SNishad Saraf 
141*c0069781SNishad Saraf 	*size = max_t(u32, *size, SZ_8K);
142*c0069781SNishad Saraf 	order = get_order(*size);
143*c0069781SNishad Saraf 	if (order > MAX_PAGE_ORDER)
144*c0069781SNishad Saraf 		return ERR_PTR(-EINVAL);
145*c0069781SNishad Saraf 	*size = PAGE_SIZE << order;
146*c0069781SNishad Saraf 
147*c0069781SNishad Saraf 	if (amdxdna_iova_on(xdna))
148*c0069781SNishad Saraf 		return amdxdna_iommu_alloc(xdna, *size, dma_addr);
149*c0069781SNishad Saraf 
150*c0069781SNishad Saraf 	vaddr = dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr,
151*c0069781SNishad Saraf 				      DMA_FROM_DEVICE, GFP_KERNEL);
152*c0069781SNishad Saraf 	if (!vaddr)
153*c0069781SNishad Saraf 		return ERR_PTR(-ENOMEM);
154*c0069781SNishad Saraf 
155*c0069781SNishad Saraf 	return vaddr;
156*c0069781SNishad Saraf }
157*c0069781SNishad Saraf 
158*c0069781SNishad Saraf void amdxdna_free_msg_buffer(struct amdxdna_dev *xdna, size_t size,
159*c0069781SNishad Saraf 			     void *cpu_addr, dma_addr_t dma_addr)
160*c0069781SNishad Saraf {
161*c0069781SNishad Saraf 	if (amdxdna_iova_on(xdna)) {
162*c0069781SNishad Saraf 		amdxdna_iommu_free(xdna, size, cpu_addr, dma_addr);
163*c0069781SNishad Saraf 		return;
164*c0069781SNishad Saraf 	}
165*c0069781SNishad Saraf 
166*c0069781SNishad Saraf 	dma_free_noncoherent(xdna->ddev.dev, size, cpu_addr, dma_addr, DMA_FROM_DEVICE);
167*c0069781SNishad Saraf }
168