1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2026, Advanced Micro Devices, Inc. 4 */ 5 6 #include <linux/errno.h> 7 8 #include "aie.h" 9 #include "amdxdna_mailbox_helper.h" 10 #include "amdxdna_mailbox.h" 11 #include "amdxdna_pci_drv.h" 12 13 void aie_dump_mgmt_chann_debug(struct aie_device *aie) 14 { 15 struct amdxdna_dev *xdna = aie->xdna; 16 17 XDNA_DBG(xdna, "i2x tail 0x%x", aie->mgmt_i2x.mb_tail_ptr_reg); 18 XDNA_DBG(xdna, "i2x head 0x%x", aie->mgmt_i2x.mb_head_ptr_reg); 19 XDNA_DBG(xdna, "i2x ringbuf 0x%x", aie->mgmt_i2x.rb_start_addr); 20 XDNA_DBG(xdna, "i2x rsize 0x%x", aie->mgmt_i2x.rb_size); 21 XDNA_DBG(xdna, "x2i tail 0x%x", aie->mgmt_x2i.mb_tail_ptr_reg); 22 XDNA_DBG(xdna, "x2i head 0x%x", aie->mgmt_x2i.mb_head_ptr_reg); 23 XDNA_DBG(xdna, "x2i ringbuf 0x%x", aie->mgmt_x2i.rb_start_addr); 24 XDNA_DBG(xdna, "x2i rsize 0x%x", aie->mgmt_x2i.rb_size); 25 XDNA_DBG(xdna, "x2i chann index 0x%x", aie->mgmt_chan_idx); 26 XDNA_DBG(xdna, "mailbox protocol major 0x%x", aie->mgmt_prot_major); 27 XDNA_DBG(xdna, "mailbox protocol minor 0x%x", aie->mgmt_prot_minor); 28 } 29 30 void aie_destroy_chann(struct aie_device *aie, struct mailbox_channel **chann) 31 { 32 struct amdxdna_dev *xdna = aie->xdna; 33 34 drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 35 36 if (!*chann) 37 return; 38 39 xdna_mailbox_stop_channel(*chann); 40 xdna_mailbox_free_channel(*chann); 41 *chann = NULL; 42 } 43 44 int aie_send_mgmt_msg_wait(struct aie_device *aie, struct xdna_mailbox_msg *msg) 45 { 46 struct amdxdna_dev *xdna = aie->xdna; 47 struct xdna_notify *hdl = msg->handle; 48 int ret; 49 50 drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 51 52 if (!aie->mgmt_chann) 53 return -ENODEV; 54 55 ret = xdna_send_msg_wait(xdna, aie->mgmt_chann, msg); 56 if (ret == -ETIME) 57 aie_destroy_chann(aie, &aie->mgmt_chann); 58 59 if (!ret && *hdl->status) { 60 XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x", 61 msg->opcode, *hdl->data); 62 ret = -EINVAL; 63 } 64 65 return ret; 66 } 67 68 int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor) 69 { 70 const struct amdxdna_fw_feature_tbl *feature; 71 bool found = false; 72 73 for (feature = aie->xdna->dev_info->fw_feature_tbl; 74 feature->major; feature++) { 75 if (feature->major != fw_major) 76 continue; 77 if (fw_minor < feature->min_minor) 78 continue; 79 if (feature->max_minor > 0 && fw_minor > feature->max_minor) 80 continue; 81 82 aie->feature_mask |= feature->features; 83 84 /* firmware version matches one of the driver support entry */ 85 found = true; 86 } 87 88 return found ? 0 : -EOPNOTSUPP; 89 } 90 91 static void amdxdna_update_vbnv(struct amdxdna_dev *xdna, 92 const struct amdxdna_rev_vbnv *tbl, 93 u32 rev) 94 { 95 int i; 96 97 for (i = 0; tbl[i].vbnv; i++) { 98 if (tbl[i].revision == rev) { 99 xdna->vbnv = tbl[i].vbnv; 100 break; 101 } 102 } 103 } 104 105 void amdxdna_vbnv_init(struct amdxdna_dev *xdna) 106 { 107 const struct amdxdna_dev_info *info = xdna->dev_info; 108 u32 rev; 109 110 xdna->vbnv = info->default_vbnv; 111 112 if (!info->ops->get_dev_revision || !info->rev_vbnv_tbl) 113 return; 114 115 if (info->ops->get_dev_revision(xdna, &rev)) 116 return; 117 118 amdxdna_update_vbnv(xdna, info->rev_vbnv_tbl, rev); 119 } 120 121 int amdxdna_get_metadata(struct aie_device *aie, 122 struct amdxdna_client *client, 123 struct amdxdna_drm_get_info *args) 124 { 125 int ret = 0; 126 u32 buf_sz; 127 128 buf_sz = min(args->buffer_size, sizeof(aie->metadata)); 129 if (copy_to_user(u64_to_user_ptr(args->buffer), &aie->metadata, buf_sz)) 130 ret = -EFAULT; 131 132 return ret; 133 } 134 135 void *amdxdna_alloc_msg_buffer(struct amdxdna_dev *xdna, u32 *size, 136 dma_addr_t *dma_addr) 137 { 138 void *vaddr; 139 int order; 140 141 *size = max_t(u32, *size, SZ_8K); 142 order = get_order(*size); 143 if (order > MAX_PAGE_ORDER) 144 return ERR_PTR(-EINVAL); 145 *size = PAGE_SIZE << order; 146 147 if (amdxdna_iova_on(xdna)) 148 return amdxdna_iommu_alloc(xdna, *size, dma_addr); 149 150 vaddr = dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr, 151 DMA_FROM_DEVICE, GFP_KERNEL); 152 if (!vaddr) 153 return ERR_PTR(-ENOMEM); 154 155 return vaddr; 156 } 157 158 void amdxdna_free_msg_buffer(struct amdxdna_dev *xdna, size_t size, 159 void *cpu_addr, dma_addr_t dma_addr) 160 { 161 if (amdxdna_iova_on(xdna)) { 162 amdxdna_iommu_free(xdna, size, cpu_addr, dma_addr); 163 return; 164 } 165 166 dma_free_noncoherent(xdna->ddev.dev, size, cpu_addr, dma_addr, DMA_FROM_DEVICE); 167 } 168