1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
4 #include <linux/vdpa.h>
5 #include <linux/virtio_pci_modern.h>
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>
16 int pds_vdpa_init_hw(struct pds_vdpa_device
*pdsv
)
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
),
25 union pds_core_adminq_comp comp
= {};
28 /* Initialize the vdpa/virtio device */
29 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_init
),
32 dev_dbg(dev
, "Failed to init hw, status %d: %pe\n",
33 comp
.status
, ERR_PTR(err
));
38 int pds_vdpa_cmd_reset(struct pds_vdpa_device
*pdsv
)
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
),
47 union pds_core_adminq_comp comp
= {};
50 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa
), &comp
, 0);
52 dev_dbg(dev
, "Failed to reset hw, status %d: %pe\n",
53 comp
.status
, ERR_PTR(err
));
58 int pds_vdpa_cmd_set_status(struct pds_vdpa_device
*pdsv
, u8 status
)
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
,
68 union pds_core_adminq_comp comp
= {};
71 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_status
), &comp
, 0);
73 dev_dbg(dev
, "Failed to set status to %#x, error status %d: %pe\n",
74 status
, comp
.status
, ERR_PTR(err
));
79 int pds_vdpa_cmd_set_mac(struct pds_vdpa_device
*pdsv
, u8
*mac
)
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
,
89 union pds_core_adminq_comp comp
= {};
92 ether_addr_copy(cmd
.vdpa_setattr
.mac
, mac
);
93 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_setattr
),
96 dev_dbg(dev
, "Failed to set mac address %pM, status %d: %pe\n",
97 mac
, comp
.status
, ERR_PTR(err
));
102 int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device
*pdsv
, u16 max_vqp
)
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
),
113 union pds_core_adminq_comp comp
= {};
116 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_setattr
),
119 dev_dbg(dev
, "Failed to set max vq pairs %u, status %d: %pe\n",
120 max_vqp
, comp
.status
, ERR_PTR(err
));
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
)
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
),
143 union pds_core_adminq_comp comp
= {};
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
);
150 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_vq_init
),
153 dev_dbg(dev
, "Failed to init vq %d, status %d: %pe\n",
154 qid
, comp
.status
, ERR_PTR(err
));
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
)
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
),
170 union pds_core_adminq_comp comp
= {};
173 err
= pds_client_adminq_cmd(padev
, &cmd
, sizeof(cmd
.vdpa_vq_reset
),
176 dev_dbg(dev
, "Failed to reset vq %d, status %d: %pe\n",
177 qid
, comp
.status
, ERR_PTR(err
));
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
;