1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */ 3 4 #include <linux/vdpa.h> 5 #include <linux/virtio_pci_modern.h> 6 7 #include <linux/pds/pds_common.h> 8 #include <linux/pds/pds_core_if.h> 9 #include <linux/pds/pds_adminq.h> 10 #include <linux/pds/pds_auxbus.h> 11 12 #include "vdpa_dev.h" 13 #include "aux_drv.h" 14 #include "cmds.h" 15 16 int pds_vdpa_init_hw(struct pds_vdpa_device *pdsv) 17 { 18 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 19 struct device *dev = &padev->aux_dev.dev; 20 union pds_core_adminq_cmd cmd = { 21 .vdpa_init.opcode = PDS_VDPA_CMD_INIT, 22 .vdpa_init.vdpa_index = pdsv->vdpa_index, 23 .vdpa_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 24 }; 25 union pds_core_adminq_comp comp = {}; 26 int err; 27 28 /* Initialize the vdpa/virtio device */ 29 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_init), 30 &comp, 0); 31 if (err) 32 dev_dbg(dev, "Failed to init hw, status %d: %pe\n", 33 comp.status, ERR_PTR(err)); 34 35 return err; 36 } 37 38 int pds_vdpa_cmd_reset(struct pds_vdpa_device *pdsv) 39 { 40 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 41 struct device *dev = &padev->aux_dev.dev; 42 union pds_core_adminq_cmd cmd = { 43 .vdpa.opcode = PDS_VDPA_CMD_RESET, 44 .vdpa.vdpa_index = pdsv->vdpa_index, 45 .vdpa.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 46 }; 47 union pds_core_adminq_comp comp = {}; 48 int err; 49 50 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa), &comp, 0); 51 if (err) 52 dev_dbg(dev, "Failed to reset hw, status %d: %pe\n", 53 comp.status, ERR_PTR(err)); 54 55 return err; 56 } 57 58 int pds_vdpa_cmd_set_status(struct pds_vdpa_device *pdsv, u8 status) 59 { 60 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 61 struct device *dev = &padev->aux_dev.dev; 62 union pds_core_adminq_cmd cmd = { 63 .vdpa_status.opcode = PDS_VDPA_CMD_STATUS_UPDATE, 64 .vdpa_status.vdpa_index = pdsv->vdpa_index, 65 .vdpa_status.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 66 .vdpa_status.status = status, 67 }; 68 union pds_core_adminq_comp comp = {}; 69 int err; 70 71 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_status), &comp, 0); 72 if (err) 73 dev_dbg(dev, "Failed to set status to %#x, error status %d: %pe\n", 74 status, comp.status, ERR_PTR(err)); 75 76 return err; 77 } 78 79 int pds_vdpa_cmd_set_mac(struct pds_vdpa_device *pdsv, u8 *mac) 80 { 81 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 82 struct device *dev = &padev->aux_dev.dev; 83 union pds_core_adminq_cmd cmd = { 84 .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR, 85 .vdpa_setattr.vdpa_index = pdsv->vdpa_index, 86 .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 87 .vdpa_setattr.attr = PDS_VDPA_ATTR_MAC, 88 }; 89 union pds_core_adminq_comp comp = {}; 90 int err; 91 92 ether_addr_copy(cmd.vdpa_setattr.mac, mac); 93 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr), 94 &comp, 0); 95 if (err) 96 dev_dbg(dev, "Failed to set mac address %pM, status %d: %pe\n", 97 mac, comp.status, ERR_PTR(err)); 98 99 return err; 100 } 101 102 int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device *pdsv, u16 max_vqp) 103 { 104 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 105 struct device *dev = &padev->aux_dev.dev; 106 union pds_core_adminq_cmd cmd = { 107 .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR, 108 .vdpa_setattr.vdpa_index = pdsv->vdpa_index, 109 .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 110 .vdpa_setattr.attr = PDS_VDPA_ATTR_MAX_VQ_PAIRS, 111 .vdpa_setattr.max_vq_pairs = cpu_to_le16(max_vqp), 112 }; 113 union pds_core_adminq_comp comp = {}; 114 int err; 115 116 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr), 117 &comp, 0); 118 if (err) 119 dev_dbg(dev, "Failed to set max vq pairs %u, status %d: %pe\n", 120 max_vqp, comp.status, ERR_PTR(err)); 121 122 return err; 123 } 124 125 int pds_vdpa_cmd_init_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, 126 struct pds_vdpa_vq_info *vq_info) 127 { 128 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 129 struct device *dev = &padev->aux_dev.dev; 130 union pds_core_adminq_cmd cmd = { 131 .vdpa_vq_init.opcode = PDS_VDPA_CMD_VQ_INIT, 132 .vdpa_vq_init.vdpa_index = pdsv->vdpa_index, 133 .vdpa_vq_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 134 .vdpa_vq_init.qid = cpu_to_le16(qid), 135 .vdpa_vq_init.len = cpu_to_le16(ilog2(vq_info->q_len)), 136 .vdpa_vq_init.desc_addr = cpu_to_le64(vq_info->desc_addr), 137 .vdpa_vq_init.avail_addr = cpu_to_le64(vq_info->avail_addr), 138 .vdpa_vq_init.used_addr = cpu_to_le64(vq_info->used_addr), 139 .vdpa_vq_init.intr_index = cpu_to_le16(qid), 140 .vdpa_vq_init.avail_index = cpu_to_le16(vq_info->avail_idx ^ invert_idx), 141 .vdpa_vq_init.used_index = cpu_to_le16(vq_info->used_idx ^ invert_idx), 142 }; 143 union pds_core_adminq_comp comp = {}; 144 int err; 145 146 dev_dbg(dev, "%s: qid %d len %d desc_addr %#llx avail_addr %#llx used_addr %#llx\n", 147 __func__, qid, ilog2(vq_info->q_len), 148 vq_info->desc_addr, vq_info->avail_addr, vq_info->used_addr); 149 150 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_init), 151 &comp, 0); 152 if (err) 153 dev_dbg(dev, "Failed to init vq %d, status %d: %pe\n", 154 qid, comp.status, ERR_PTR(err)); 155 156 return err; 157 } 158 159 int pds_vdpa_cmd_reset_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, 160 struct pds_vdpa_vq_info *vq_info) 161 { 162 struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; 163 struct device *dev = &padev->aux_dev.dev; 164 union pds_core_adminq_cmd cmd = { 165 .vdpa_vq_reset.opcode = PDS_VDPA_CMD_VQ_RESET, 166 .vdpa_vq_reset.vdpa_index = pdsv->vdpa_index, 167 .vdpa_vq_reset.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), 168 .vdpa_vq_reset.qid = cpu_to_le16(qid), 169 }; 170 union pds_core_adminq_comp comp = {}; 171 int err; 172 173 err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_reset), 174 &comp, 0); 175 if (err) { 176 dev_dbg(dev, "Failed to reset vq %d, status %d: %pe\n", 177 qid, comp.status, ERR_PTR(err)); 178 return err; 179 } 180 181 vq_info->avail_idx = le16_to_cpu(comp.vdpa_vq_reset.avail_index) ^ invert_idx; 182 vq_info->used_idx = le16_to_cpu(comp.vdpa_vq_reset.used_index) ^ invert_idx; 183 184 return 0; 185 } 186