xref: /kernel/linux/linux-6.6/drivers/vdpa/pds/cmds.c (revision 62306a36)
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
16int 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
38int 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
58int 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
79int 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
102int 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
125int 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
159int 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