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
pds_vdpa_init_hw(struct pds_vdpa_device * pdsv)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
pds_vdpa_cmd_reset(struct pds_vdpa_device * pdsv)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
pds_vdpa_cmd_set_status(struct pds_vdpa_device * pdsv,u8 status)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
pds_vdpa_cmd_set_mac(struct pds_vdpa_device * pdsv,u8 * mac)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
pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device * pdsv,u16 max_vqp)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
pds_vdpa_cmd_init_vq(struct pds_vdpa_device * pdsv,u16 qid,u16 invert_idx,struct pds_vdpa_vq_info * vq_info)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
pds_vdpa_cmd_reset_vq(struct pds_vdpa_device * pdsv,u16 qid,u16 invert_idx,struct pds_vdpa_vq_info * vq_info)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