Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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}