xref: /linux/drivers/vdpa/pds/cmds.c (revision a06c3fad49a50d5d5eb078f93e70f4d3eca5d5a5)
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