125d1270bSShannon Nelson // SPDX-License-Identifier: GPL-2.0-only
225d1270bSShannon Nelson /* Copyright(c) 2023 Advanced Micro Devices, Inc */
325d1270bSShannon Nelson
425d1270bSShannon Nelson #include <linux/pci.h>
525d1270bSShannon Nelson #include <linux/vdpa.h>
625d1270bSShannon Nelson #include <uapi/linux/vdpa.h>
7151cc834SShannon Nelson #include <linux/virtio_pci_modern.h>
825d1270bSShannon Nelson
925d1270bSShannon Nelson #include <linux/pds/pds_common.h>
1025d1270bSShannon Nelson #include <linux/pds/pds_core_if.h>
1125d1270bSShannon Nelson #include <linux/pds/pds_adminq.h>
1225d1270bSShannon Nelson #include <linux/pds/pds_auxbus.h>
1325d1270bSShannon Nelson
1425d1270bSShannon Nelson #include "vdpa_dev.h"
1525d1270bSShannon Nelson #include "aux_drv.h"
16151cc834SShannon Nelson #include "cmds.h"
17151cc834SShannon Nelson #include "debugfs.h"
1825d1270bSShannon Nelson
19151cc834SShannon Nelson static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev);
20151cc834SShannon Nelson
vdpa_to_pdsv(struct vdpa_device * vdpa_dev)21151cc834SShannon Nelson static struct pds_vdpa_device *vdpa_to_pdsv(struct vdpa_device *vdpa_dev)
22151cc834SShannon Nelson {
23151cc834SShannon Nelson return container_of(vdpa_dev, struct pds_vdpa_device, vdpa_dev);
24151cc834SShannon Nelson }
25151cc834SShannon Nelson
pds_vdpa_notify_handler(struct notifier_block * nb,unsigned long ecode,void * data)2667f27b8bSShannon Nelson static int pds_vdpa_notify_handler(struct notifier_block *nb,
2767f27b8bSShannon Nelson unsigned long ecode,
2867f27b8bSShannon Nelson void *data)
2967f27b8bSShannon Nelson {
3067f27b8bSShannon Nelson struct pds_vdpa_device *pdsv = container_of(nb, struct pds_vdpa_device, nb);
3167f27b8bSShannon Nelson struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
3267f27b8bSShannon Nelson
3367f27b8bSShannon Nelson dev_dbg(dev, "%s: event code %lu\n", __func__, ecode);
3467f27b8bSShannon Nelson
3567f27b8bSShannon Nelson if (ecode == PDS_EVENT_RESET || ecode == PDS_EVENT_LINK_CHANGE) {
3667f27b8bSShannon Nelson if (pdsv->config_cb.callback)
3767f27b8bSShannon Nelson pdsv->config_cb.callback(pdsv->config_cb.private);
3867f27b8bSShannon Nelson }
3967f27b8bSShannon Nelson
4067f27b8bSShannon Nelson return 0;
4167f27b8bSShannon Nelson }
4267f27b8bSShannon Nelson
pds_vdpa_register_event_handler(struct pds_vdpa_device * pdsv)4367f27b8bSShannon Nelson static int pds_vdpa_register_event_handler(struct pds_vdpa_device *pdsv)
4467f27b8bSShannon Nelson {
4567f27b8bSShannon Nelson struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
4667f27b8bSShannon Nelson struct notifier_block *nb = &pdsv->nb;
4767f27b8bSShannon Nelson int err;
4867f27b8bSShannon Nelson
4967f27b8bSShannon Nelson if (!nb->notifier_call) {
5067f27b8bSShannon Nelson nb->notifier_call = pds_vdpa_notify_handler;
5167f27b8bSShannon Nelson err = pdsc_register_notify(nb);
5267f27b8bSShannon Nelson if (err) {
5367f27b8bSShannon Nelson nb->notifier_call = NULL;
5467f27b8bSShannon Nelson dev_err(dev, "failed to register pds event handler: %ps\n",
5567f27b8bSShannon Nelson ERR_PTR(err));
5667f27b8bSShannon Nelson return -EINVAL;
5767f27b8bSShannon Nelson }
5867f27b8bSShannon Nelson dev_dbg(dev, "pds event handler registered\n");
5967f27b8bSShannon Nelson }
6067f27b8bSShannon Nelson
6167f27b8bSShannon Nelson return 0;
6267f27b8bSShannon Nelson }
6367f27b8bSShannon Nelson
pds_vdpa_unregister_event_handler(struct pds_vdpa_device * pdsv)6467f27b8bSShannon Nelson static void pds_vdpa_unregister_event_handler(struct pds_vdpa_device *pdsv)
6567f27b8bSShannon Nelson {
6667f27b8bSShannon Nelson if (pdsv->nb.notifier_call) {
6767f27b8bSShannon Nelson pdsc_unregister_notify(&pdsv->nb);
6867f27b8bSShannon Nelson pdsv->nb.notifier_call = NULL;
6967f27b8bSShannon Nelson }
7067f27b8bSShannon Nelson }
7167f27b8bSShannon Nelson
pds_vdpa_set_vq_address(struct vdpa_device * vdpa_dev,u16 qid,u64 desc_addr,u64 driver_addr,u64 device_addr)72151cc834SShannon Nelson static int pds_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid,
73151cc834SShannon Nelson u64 desc_addr, u64 driver_addr, u64 device_addr)
74151cc834SShannon Nelson {
75151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
76151cc834SShannon Nelson
77151cc834SShannon Nelson pdsv->vqs[qid].desc_addr = desc_addr;
78151cc834SShannon Nelson pdsv->vqs[qid].avail_addr = driver_addr;
79151cc834SShannon Nelson pdsv->vqs[qid].used_addr = device_addr;
80151cc834SShannon Nelson
81151cc834SShannon Nelson return 0;
82151cc834SShannon Nelson }
83151cc834SShannon Nelson
pds_vdpa_set_vq_num(struct vdpa_device * vdpa_dev,u16 qid,u32 num)84151cc834SShannon Nelson static void pds_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, u32 num)
85151cc834SShannon Nelson {
86151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
87151cc834SShannon Nelson
88151cc834SShannon Nelson pdsv->vqs[qid].q_len = num;
89151cc834SShannon Nelson }
90151cc834SShannon Nelson
pds_vdpa_kick_vq(struct vdpa_device * vdpa_dev,u16 qid)91151cc834SShannon Nelson static void pds_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid)
92151cc834SShannon Nelson {
93151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
94151cc834SShannon Nelson
95151cc834SShannon Nelson iowrite16(qid, pdsv->vqs[qid].notify);
96151cc834SShannon Nelson }
97151cc834SShannon Nelson
pds_vdpa_set_vq_cb(struct vdpa_device * vdpa_dev,u16 qid,struct vdpa_callback * cb)98151cc834SShannon Nelson static void pds_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid,
99151cc834SShannon Nelson struct vdpa_callback *cb)
100151cc834SShannon Nelson {
101151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
102151cc834SShannon Nelson
103151cc834SShannon Nelson pdsv->vqs[qid].event_cb = *cb;
104151cc834SShannon Nelson }
105151cc834SShannon Nelson
pds_vdpa_isr(int irq,void * data)106151cc834SShannon Nelson static irqreturn_t pds_vdpa_isr(int irq, void *data)
107151cc834SShannon Nelson {
108151cc834SShannon Nelson struct pds_vdpa_vq_info *vq;
109151cc834SShannon Nelson
110151cc834SShannon Nelson vq = data;
111151cc834SShannon Nelson if (vq->event_cb.callback)
112151cc834SShannon Nelson vq->event_cb.callback(vq->event_cb.private);
113151cc834SShannon Nelson
114151cc834SShannon Nelson return IRQ_HANDLED;
115151cc834SShannon Nelson }
116151cc834SShannon Nelson
pds_vdpa_release_irq(struct pds_vdpa_device * pdsv,int qid)117151cc834SShannon Nelson static void pds_vdpa_release_irq(struct pds_vdpa_device *pdsv, int qid)
118151cc834SShannon Nelson {
119151cc834SShannon Nelson if (pdsv->vqs[qid].irq == VIRTIO_MSI_NO_VECTOR)
120151cc834SShannon Nelson return;
121151cc834SShannon Nelson
122151cc834SShannon Nelson free_irq(pdsv->vqs[qid].irq, &pdsv->vqs[qid]);
123151cc834SShannon Nelson pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR;
124151cc834SShannon Nelson }
125151cc834SShannon Nelson
pds_vdpa_set_vq_ready(struct vdpa_device * vdpa_dev,u16 qid,bool ready)126151cc834SShannon Nelson static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready)
127151cc834SShannon Nelson {
128151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
129151cc834SShannon Nelson struct device *dev = &pdsv->vdpa_dev.dev;
130151cc834SShannon Nelson u64 driver_features;
131151cc834SShannon Nelson u16 invert_idx = 0;
132151cc834SShannon Nelson int err;
133151cc834SShannon Nelson
134151cc834SShannon Nelson dev_dbg(dev, "%s: qid %d ready %d => %d\n",
135151cc834SShannon Nelson __func__, qid, pdsv->vqs[qid].ready, ready);
136151cc834SShannon Nelson if (ready == pdsv->vqs[qid].ready)
137151cc834SShannon Nelson return;
138151cc834SShannon Nelson
139151cc834SShannon Nelson driver_features = pds_vdpa_get_driver_features(vdpa_dev);
140151cc834SShannon Nelson if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED))
141151cc834SShannon Nelson invert_idx = PDS_VDPA_PACKED_INVERT_IDX;
142151cc834SShannon Nelson
143151cc834SShannon Nelson if (ready) {
144151cc834SShannon Nelson /* Pass vq setup info to DSC using adminq to gather up and
145151cc834SShannon Nelson * send all info at once so FW can do its full set up in
146151cc834SShannon Nelson * one easy operation
147151cc834SShannon Nelson */
148151cc834SShannon Nelson err = pds_vdpa_cmd_init_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]);
149151cc834SShannon Nelson if (err) {
150151cc834SShannon Nelson dev_err(dev, "Failed to init vq %d: %pe\n",
151151cc834SShannon Nelson qid, ERR_PTR(err));
152151cc834SShannon Nelson ready = false;
153151cc834SShannon Nelson }
154151cc834SShannon Nelson } else {
155151cc834SShannon Nelson err = pds_vdpa_cmd_reset_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]);
156151cc834SShannon Nelson if (err)
157151cc834SShannon Nelson dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
158151cc834SShannon Nelson __func__, qid, ERR_PTR(err));
159151cc834SShannon Nelson }
160151cc834SShannon Nelson
161151cc834SShannon Nelson pdsv->vqs[qid].ready = ready;
162151cc834SShannon Nelson }
163151cc834SShannon Nelson
pds_vdpa_get_vq_ready(struct vdpa_device * vdpa_dev,u16 qid)164151cc834SShannon Nelson static bool pds_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid)
165151cc834SShannon Nelson {
166151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
167151cc834SShannon Nelson
168151cc834SShannon Nelson return pdsv->vqs[qid].ready;
169151cc834SShannon Nelson }
170151cc834SShannon Nelson
pds_vdpa_set_vq_state(struct vdpa_device * vdpa_dev,u16 qid,const struct vdpa_vq_state * state)171151cc834SShannon Nelson static int pds_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
172151cc834SShannon Nelson const struct vdpa_vq_state *state)
173151cc834SShannon Nelson {
174151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
175151cc834SShannon Nelson struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
176151cc834SShannon Nelson struct device *dev = &padev->aux_dev.dev;
177151cc834SShannon Nelson u64 driver_features;
178151cc834SShannon Nelson u16 avail;
179151cc834SShannon Nelson u16 used;
180151cc834SShannon Nelson
181151cc834SShannon Nelson if (pdsv->vqs[qid].ready) {
182151cc834SShannon Nelson dev_err(dev, "Setting device position is denied while vq is enabled\n");
183151cc834SShannon Nelson return -EINVAL;
184151cc834SShannon Nelson }
185151cc834SShannon Nelson
186151cc834SShannon Nelson driver_features = pds_vdpa_get_driver_features(vdpa_dev);
187151cc834SShannon Nelson if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) {
188151cc834SShannon Nelson avail = state->packed.last_avail_idx |
189151cc834SShannon Nelson (state->packed.last_avail_counter << 15);
190151cc834SShannon Nelson used = state->packed.last_used_idx |
191151cc834SShannon Nelson (state->packed.last_used_counter << 15);
192151cc834SShannon Nelson
193151cc834SShannon Nelson /* The avail and used index are stored with the packed wrap
194151cc834SShannon Nelson * counter bit inverted. This way, in case set_vq_state is
195151cc834SShannon Nelson * not called, the initial value can be set to zero prior to
196151cc834SShannon Nelson * feature negotiation, and it is good for both packed and
197151cc834SShannon Nelson * split vq.
198151cc834SShannon Nelson */
199151cc834SShannon Nelson avail ^= PDS_VDPA_PACKED_INVERT_IDX;
200151cc834SShannon Nelson used ^= PDS_VDPA_PACKED_INVERT_IDX;
201151cc834SShannon Nelson } else {
202151cc834SShannon Nelson avail = state->split.avail_index;
203151cc834SShannon Nelson /* state->split does not provide a used_index:
204151cc834SShannon Nelson * the vq will be set to "empty" here, and the vq will read
205151cc834SShannon Nelson * the current used index the next time the vq is kicked.
206151cc834SShannon Nelson */
207151cc834SShannon Nelson used = avail;
208151cc834SShannon Nelson }
209151cc834SShannon Nelson
210151cc834SShannon Nelson if (used != avail) {
211151cc834SShannon Nelson dev_dbg(dev, "Setting used equal to avail, for interoperability\n");
212151cc834SShannon Nelson used = avail;
213151cc834SShannon Nelson }
214151cc834SShannon Nelson
215151cc834SShannon Nelson pdsv->vqs[qid].avail_idx = avail;
216151cc834SShannon Nelson pdsv->vqs[qid].used_idx = used;
217151cc834SShannon Nelson
218151cc834SShannon Nelson return 0;
219151cc834SShannon Nelson }
220151cc834SShannon Nelson
pds_vdpa_get_vq_state(struct vdpa_device * vdpa_dev,u16 qid,struct vdpa_vq_state * state)221151cc834SShannon Nelson static int pds_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
222151cc834SShannon Nelson struct vdpa_vq_state *state)
223151cc834SShannon Nelson {
224151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
225151cc834SShannon Nelson struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
226151cc834SShannon Nelson struct device *dev = &padev->aux_dev.dev;
227151cc834SShannon Nelson u64 driver_features;
228151cc834SShannon Nelson u16 avail;
229151cc834SShannon Nelson u16 used;
230151cc834SShannon Nelson
231151cc834SShannon Nelson if (pdsv->vqs[qid].ready) {
232151cc834SShannon Nelson dev_err(dev, "Getting device position is denied while vq is enabled\n");
233151cc834SShannon Nelson return -EINVAL;
234151cc834SShannon Nelson }
235151cc834SShannon Nelson
236151cc834SShannon Nelson avail = pdsv->vqs[qid].avail_idx;
237151cc834SShannon Nelson used = pdsv->vqs[qid].used_idx;
238151cc834SShannon Nelson
239151cc834SShannon Nelson driver_features = pds_vdpa_get_driver_features(vdpa_dev);
240151cc834SShannon Nelson if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) {
241151cc834SShannon Nelson avail ^= PDS_VDPA_PACKED_INVERT_IDX;
242151cc834SShannon Nelson used ^= PDS_VDPA_PACKED_INVERT_IDX;
243151cc834SShannon Nelson
244151cc834SShannon Nelson state->packed.last_avail_idx = avail & 0x7fff;
245151cc834SShannon Nelson state->packed.last_avail_counter = avail >> 15;
246151cc834SShannon Nelson state->packed.last_used_idx = used & 0x7fff;
247151cc834SShannon Nelson state->packed.last_used_counter = used >> 15;
248151cc834SShannon Nelson } else {
249151cc834SShannon Nelson state->split.avail_index = avail;
250151cc834SShannon Nelson /* state->split does not provide a used_index. */
251151cc834SShannon Nelson }
252151cc834SShannon Nelson
253151cc834SShannon Nelson return 0;
254151cc834SShannon Nelson }
255151cc834SShannon Nelson
256151cc834SShannon Nelson static struct vdpa_notification_area
pds_vdpa_get_vq_notification(struct vdpa_device * vdpa_dev,u16 qid)257151cc834SShannon Nelson pds_vdpa_get_vq_notification(struct vdpa_device *vdpa_dev, u16 qid)
258151cc834SShannon Nelson {
259151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
260151cc834SShannon Nelson struct virtio_pci_modern_device *vd_mdev;
261151cc834SShannon Nelson struct vdpa_notification_area area;
262151cc834SShannon Nelson
263151cc834SShannon Nelson area.addr = pdsv->vqs[qid].notify_pa;
264151cc834SShannon Nelson
265151cc834SShannon Nelson vd_mdev = &pdsv->vdpa_aux->vd_mdev;
266151cc834SShannon Nelson if (!vd_mdev->notify_offset_multiplier)
267151cc834SShannon Nelson area.size = PDS_PAGE_SIZE;
268151cc834SShannon Nelson else
269151cc834SShannon Nelson area.size = vd_mdev->notify_offset_multiplier;
270151cc834SShannon Nelson
271151cc834SShannon Nelson return area;
272151cc834SShannon Nelson }
273151cc834SShannon Nelson
pds_vdpa_get_vq_irq(struct vdpa_device * vdpa_dev,u16 qid)274151cc834SShannon Nelson static int pds_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, u16 qid)
275151cc834SShannon Nelson {
276151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
277151cc834SShannon Nelson
278151cc834SShannon Nelson return pdsv->vqs[qid].irq;
279151cc834SShannon Nelson }
280151cc834SShannon Nelson
pds_vdpa_get_vq_align(struct vdpa_device * vdpa_dev)281151cc834SShannon Nelson static u32 pds_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
282151cc834SShannon Nelson {
283151cc834SShannon Nelson return PDS_PAGE_SIZE;
284151cc834SShannon Nelson }
285151cc834SShannon Nelson
pds_vdpa_get_vq_group(struct vdpa_device * vdpa_dev,u16 idx)286151cc834SShannon Nelson static u32 pds_vdpa_get_vq_group(struct vdpa_device *vdpa_dev, u16 idx)
287151cc834SShannon Nelson {
288151cc834SShannon Nelson return 0;
289151cc834SShannon Nelson }
290151cc834SShannon Nelson
pds_vdpa_get_device_features(struct vdpa_device * vdpa_dev)291151cc834SShannon Nelson static u64 pds_vdpa_get_device_features(struct vdpa_device *vdpa_dev)
292151cc834SShannon Nelson {
293151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
294151cc834SShannon Nelson
295151cc834SShannon Nelson return pdsv->supported_features;
296151cc834SShannon Nelson }
297151cc834SShannon Nelson
pds_vdpa_set_driver_features(struct vdpa_device * vdpa_dev,u64 features)298151cc834SShannon Nelson static int pds_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 features)
299151cc834SShannon Nelson {
300151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
301151cc834SShannon Nelson struct device *dev = &pdsv->vdpa_dev.dev;
302151cc834SShannon Nelson u64 driver_features;
303151cc834SShannon Nelson u64 nego_features;
304abdf31bdSShannon Nelson u64 hw_features;
305151cc834SShannon Nelson u64 missing;
306151cc834SShannon Nelson
307151cc834SShannon Nelson if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) {
308151cc834SShannon Nelson dev_err(dev, "VIRTIO_F_ACCESS_PLATFORM is not negotiated\n");
309151cc834SShannon Nelson return -EOPNOTSUPP;
310151cc834SShannon Nelson }
311151cc834SShannon Nelson
312151cc834SShannon Nelson /* Check for valid feature bits */
313abdf31bdSShannon Nelson nego_features = features & pdsv->supported_features;
314abdf31bdSShannon Nelson missing = features & ~nego_features;
315151cc834SShannon Nelson if (missing) {
316151cc834SShannon Nelson dev_err(dev, "Can't support all requested features in %#llx, missing %#llx features\n",
317abdf31bdSShannon Nelson features, missing);
318151cc834SShannon Nelson return -EOPNOTSUPP;
319151cc834SShannon Nelson }
320151cc834SShannon Nelson
321151cc834SShannon Nelson driver_features = pds_vdpa_get_driver_features(vdpa_dev);
322*06cb2064SShannon Nelson pdsv->negotiated_features = nego_features;
323151cc834SShannon Nelson dev_dbg(dev, "%s: %#llx => %#llx\n",
324151cc834SShannon Nelson __func__, driver_features, nego_features);
325151cc834SShannon Nelson
326abdf31bdSShannon Nelson /* if we're faking the F_MAC, strip it before writing to device */
327abdf31bdSShannon Nelson hw_features = le64_to_cpu(pdsv->vdpa_aux->ident.hw_features);
328abdf31bdSShannon Nelson if (!(hw_features & BIT_ULL(VIRTIO_NET_F_MAC)))
329abdf31bdSShannon Nelson nego_features &= ~BIT_ULL(VIRTIO_NET_F_MAC);
330abdf31bdSShannon Nelson
331151cc834SShannon Nelson if (driver_features == nego_features)
332151cc834SShannon Nelson return 0;
333151cc834SShannon Nelson
334151cc834SShannon Nelson vp_modern_set_features(&pdsv->vdpa_aux->vd_mdev, nego_features);
335151cc834SShannon Nelson
336151cc834SShannon Nelson return 0;
337151cc834SShannon Nelson }
338151cc834SShannon Nelson
pds_vdpa_get_driver_features(struct vdpa_device * vdpa_dev)339151cc834SShannon Nelson static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev)
340151cc834SShannon Nelson {
341151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
342151cc834SShannon Nelson
343abdf31bdSShannon Nelson return pdsv->negotiated_features;
344151cc834SShannon Nelson }
345151cc834SShannon Nelson
pds_vdpa_set_config_cb(struct vdpa_device * vdpa_dev,struct vdpa_callback * cb)346151cc834SShannon Nelson static void pds_vdpa_set_config_cb(struct vdpa_device *vdpa_dev,
347151cc834SShannon Nelson struct vdpa_callback *cb)
348151cc834SShannon Nelson {
349151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
350151cc834SShannon Nelson
351151cc834SShannon Nelson pdsv->config_cb.callback = cb->callback;
352151cc834SShannon Nelson pdsv->config_cb.private = cb->private;
353151cc834SShannon Nelson }
354151cc834SShannon Nelson
pds_vdpa_get_vq_num_max(struct vdpa_device * vdpa_dev)355151cc834SShannon Nelson static u16 pds_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev)
356151cc834SShannon Nelson {
357151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
358151cc834SShannon Nelson
359151cc834SShannon Nelson /* qemu has assert() that vq_num_max <= VIRTQUEUE_MAX_SIZE (1024) */
360151cc834SShannon Nelson return min_t(u16, 1024, BIT(le16_to_cpu(pdsv->vdpa_aux->ident.max_qlen)));
361151cc834SShannon Nelson }
362151cc834SShannon Nelson
pds_vdpa_get_device_id(struct vdpa_device * vdpa_dev)363151cc834SShannon Nelson static u32 pds_vdpa_get_device_id(struct vdpa_device *vdpa_dev)
364151cc834SShannon Nelson {
365151cc834SShannon Nelson return VIRTIO_ID_NET;
366151cc834SShannon Nelson }
367151cc834SShannon Nelson
pds_vdpa_get_vendor_id(struct vdpa_device * vdpa_dev)368151cc834SShannon Nelson static u32 pds_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev)
369151cc834SShannon Nelson {
370151cc834SShannon Nelson return PCI_VENDOR_ID_PENSANDO;
371151cc834SShannon Nelson }
372151cc834SShannon Nelson
pds_vdpa_get_status(struct vdpa_device * vdpa_dev)373151cc834SShannon Nelson static u8 pds_vdpa_get_status(struct vdpa_device *vdpa_dev)
374151cc834SShannon Nelson {
375151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
376151cc834SShannon Nelson
377151cc834SShannon Nelson return vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
378151cc834SShannon Nelson }
379151cc834SShannon Nelson
pds_vdpa_request_irqs(struct pds_vdpa_device * pdsv)380c0a6c5cbSAllen Hubbe static int pds_vdpa_request_irqs(struct pds_vdpa_device *pdsv)
381c0a6c5cbSAllen Hubbe {
382c0a6c5cbSAllen Hubbe struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
383c0a6c5cbSAllen Hubbe struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
384c0a6c5cbSAllen Hubbe struct device *dev = &pdsv->vdpa_dev.dev;
385c0a6c5cbSAllen Hubbe int max_vq, nintrs, qid, err;
386c0a6c5cbSAllen Hubbe
387c0a6c5cbSAllen Hubbe max_vq = vdpa_aux->vdpa_mdev.max_supported_vqs;
388c0a6c5cbSAllen Hubbe
389c0a6c5cbSAllen Hubbe nintrs = pci_alloc_irq_vectors(pdev, max_vq, max_vq, PCI_IRQ_MSIX);
390c0a6c5cbSAllen Hubbe if (nintrs < 0) {
391c0a6c5cbSAllen Hubbe dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
392c0a6c5cbSAllen Hubbe max_vq, ERR_PTR(nintrs));
393c0a6c5cbSAllen Hubbe return nintrs;
394c0a6c5cbSAllen Hubbe }
395c0a6c5cbSAllen Hubbe
396c0a6c5cbSAllen Hubbe for (qid = 0; qid < pdsv->num_vqs; ++qid) {
397c0a6c5cbSAllen Hubbe int irq = pci_irq_vector(pdev, qid);
398c0a6c5cbSAllen Hubbe
399c0a6c5cbSAllen Hubbe snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
400c0a6c5cbSAllen Hubbe "vdpa-%s-%d", dev_name(dev), qid);
401c0a6c5cbSAllen Hubbe
402c0a6c5cbSAllen Hubbe err = request_irq(irq, pds_vdpa_isr, 0,
403c0a6c5cbSAllen Hubbe pdsv->vqs[qid].irq_name,
404c0a6c5cbSAllen Hubbe &pdsv->vqs[qid]);
405c0a6c5cbSAllen Hubbe if (err) {
406c0a6c5cbSAllen Hubbe dev_err(dev, "%s: no irq for qid %d: %pe\n",
407c0a6c5cbSAllen Hubbe __func__, qid, ERR_PTR(err));
408c0a6c5cbSAllen Hubbe goto err_release;
409c0a6c5cbSAllen Hubbe }
410c0a6c5cbSAllen Hubbe
411c0a6c5cbSAllen Hubbe pdsv->vqs[qid].irq = irq;
412c0a6c5cbSAllen Hubbe }
413c0a6c5cbSAllen Hubbe
414c0a6c5cbSAllen Hubbe vdpa_aux->nintrs = nintrs;
415c0a6c5cbSAllen Hubbe
416c0a6c5cbSAllen Hubbe return 0;
417c0a6c5cbSAllen Hubbe
418c0a6c5cbSAllen Hubbe err_release:
419c0a6c5cbSAllen Hubbe while (qid--)
420c0a6c5cbSAllen Hubbe pds_vdpa_release_irq(pdsv, qid);
421c0a6c5cbSAllen Hubbe
422c0a6c5cbSAllen Hubbe pci_free_irq_vectors(pdev);
423c0a6c5cbSAllen Hubbe
424c0a6c5cbSAllen Hubbe vdpa_aux->nintrs = 0;
425c0a6c5cbSAllen Hubbe
426c0a6c5cbSAllen Hubbe return err;
427c0a6c5cbSAllen Hubbe }
428c0a6c5cbSAllen Hubbe
pds_vdpa_release_irqs(struct pds_vdpa_device * pdsv)429c0a6c5cbSAllen Hubbe static void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
430c0a6c5cbSAllen Hubbe {
431c0a6c5cbSAllen Hubbe struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
432c0a6c5cbSAllen Hubbe struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
433c0a6c5cbSAllen Hubbe int qid;
434c0a6c5cbSAllen Hubbe
435c0a6c5cbSAllen Hubbe if (!vdpa_aux->nintrs)
436c0a6c5cbSAllen Hubbe return;
437c0a6c5cbSAllen Hubbe
438c0a6c5cbSAllen Hubbe for (qid = 0; qid < pdsv->num_vqs; qid++)
439c0a6c5cbSAllen Hubbe pds_vdpa_release_irq(pdsv, qid);
440c0a6c5cbSAllen Hubbe
441c0a6c5cbSAllen Hubbe pci_free_irq_vectors(pdev);
442c0a6c5cbSAllen Hubbe
443c0a6c5cbSAllen Hubbe vdpa_aux->nintrs = 0;
444c0a6c5cbSAllen Hubbe }
445c0a6c5cbSAllen Hubbe
pds_vdpa_set_status(struct vdpa_device * vdpa_dev,u8 status)446151cc834SShannon Nelson static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
447151cc834SShannon Nelson {
448151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
449151cc834SShannon Nelson struct device *dev = &pdsv->vdpa_dev.dev;
450151cc834SShannon Nelson u8 old_status;
451151cc834SShannon Nelson int i;
452151cc834SShannon Nelson
453151cc834SShannon Nelson old_status = pds_vdpa_get_status(vdpa_dev);
454151cc834SShannon Nelson dev_dbg(dev, "%s: old %#x new %#x\n", __func__, old_status, status);
455151cc834SShannon Nelson
456c0a6c5cbSAllen Hubbe if (status & ~old_status & VIRTIO_CONFIG_S_DRIVER_OK) {
457c0a6c5cbSAllen Hubbe if (pds_vdpa_request_irqs(pdsv))
458c0a6c5cbSAllen Hubbe status = old_status | VIRTIO_CONFIG_S_FAILED;
459c0a6c5cbSAllen Hubbe }
460c0a6c5cbSAllen Hubbe
461151cc834SShannon Nelson pds_vdpa_cmd_set_status(pdsv, status);
462151cc834SShannon Nelson
463151cc834SShannon Nelson if (status == 0) {
464d3bb92beSShannon Nelson struct vdpa_callback null_cb = { };
465d3bb92beSShannon Nelson
466d3bb92beSShannon Nelson pds_vdpa_set_config_cb(vdpa_dev, &null_cb);
467151cc834SShannon Nelson pds_vdpa_cmd_reset(pdsv);
468151cc834SShannon Nelson
469151cc834SShannon Nelson for (i = 0; i < pdsv->num_vqs; i++) {
470151cc834SShannon Nelson pdsv->vqs[i].avail_idx = 0;
471151cc834SShannon Nelson pdsv->vqs[i].used_idx = 0;
472151cc834SShannon Nelson }
4730cd2c13bSAllen Hubbe
4740cd2c13bSAllen Hubbe pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
475151cc834SShannon Nelson }
476151cc834SShannon Nelson
477151cc834SShannon Nelson if (status & ~old_status & VIRTIO_CONFIG_S_FEATURES_OK) {
478151cc834SShannon Nelson for (i = 0; i < pdsv->num_vqs; i++) {
479151cc834SShannon Nelson pdsv->vqs[i].notify =
480151cc834SShannon Nelson vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
481151cc834SShannon Nelson i, &pdsv->vqs[i].notify_pa);
482151cc834SShannon Nelson }
483151cc834SShannon Nelson }
484c0a6c5cbSAllen Hubbe
485c0a6c5cbSAllen Hubbe if (old_status & ~status & VIRTIO_CONFIG_S_DRIVER_OK)
486c0a6c5cbSAllen Hubbe pds_vdpa_release_irqs(pdsv);
487151cc834SShannon Nelson }
488151cc834SShannon Nelson
pds_vdpa_init_vqs_entry(struct pds_vdpa_device * pdsv,int qid,void __iomem * notify)489ed888630SShannon Nelson static void pds_vdpa_init_vqs_entry(struct pds_vdpa_device *pdsv, int qid,
490ed888630SShannon Nelson void __iomem *notify)
491ed888630SShannon Nelson {
492ed888630SShannon Nelson memset(&pdsv->vqs[qid], 0, sizeof(pdsv->vqs[0]));
493ed888630SShannon Nelson pdsv->vqs[qid].qid = qid;
494ed888630SShannon Nelson pdsv->vqs[qid].pdsv = pdsv;
495ed888630SShannon Nelson pdsv->vqs[qid].ready = false;
496ed888630SShannon Nelson pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR;
497ed888630SShannon Nelson pdsv->vqs[qid].notify = notify;
498ed888630SShannon Nelson }
499ed888630SShannon Nelson
pds_vdpa_reset(struct vdpa_device * vdpa_dev)500151cc834SShannon Nelson static int pds_vdpa_reset(struct vdpa_device *vdpa_dev)
501151cc834SShannon Nelson {
502151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
503151cc834SShannon Nelson struct device *dev;
504151cc834SShannon Nelson int err = 0;
505151cc834SShannon Nelson u8 status;
506151cc834SShannon Nelson int i;
507151cc834SShannon Nelson
508151cc834SShannon Nelson dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
509151cc834SShannon Nelson status = pds_vdpa_get_status(vdpa_dev);
510151cc834SShannon Nelson
511151cc834SShannon Nelson if (status == 0)
512151cc834SShannon Nelson return 0;
513151cc834SShannon Nelson
514151cc834SShannon Nelson if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
515151cc834SShannon Nelson /* Reset the vqs */
516151cc834SShannon Nelson for (i = 0; i < pdsv->num_vqs && !err; i++) {
517151cc834SShannon Nelson err = pds_vdpa_cmd_reset_vq(pdsv, i, 0, &pdsv->vqs[i]);
518151cc834SShannon Nelson if (err)
519151cc834SShannon Nelson dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
520151cc834SShannon Nelson __func__, i, ERR_PTR(err));
521151cc834SShannon Nelson }
522151cc834SShannon Nelson }
523151cc834SShannon Nelson
524151cc834SShannon Nelson pds_vdpa_set_status(vdpa_dev, 0);
525151cc834SShannon Nelson
526c0a6c5cbSAllen Hubbe if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
527c0a6c5cbSAllen Hubbe /* Reset the vq info */
528c0a6c5cbSAllen Hubbe for (i = 0; i < pdsv->num_vqs && !err; i++)
529c0a6c5cbSAllen Hubbe pds_vdpa_init_vqs_entry(pdsv, i, pdsv->vqs[i].notify);
530c0a6c5cbSAllen Hubbe }
531c0a6c5cbSAllen Hubbe
532151cc834SShannon Nelson return 0;
533151cc834SShannon Nelson }
534151cc834SShannon Nelson
pds_vdpa_get_config_size(struct vdpa_device * vdpa_dev)535151cc834SShannon Nelson static size_t pds_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
536151cc834SShannon Nelson {
537151cc834SShannon Nelson return sizeof(struct virtio_net_config);
538151cc834SShannon Nelson }
539151cc834SShannon Nelson
pds_vdpa_get_config(struct vdpa_device * vdpa_dev,unsigned int offset,void * buf,unsigned int len)540151cc834SShannon Nelson static void pds_vdpa_get_config(struct vdpa_device *vdpa_dev,
541151cc834SShannon Nelson unsigned int offset,
542151cc834SShannon Nelson void *buf, unsigned int len)
543151cc834SShannon Nelson {
544151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
545151cc834SShannon Nelson void __iomem *device;
546151cc834SShannon Nelson
547151cc834SShannon Nelson if (offset + len > sizeof(struct virtio_net_config)) {
548151cc834SShannon Nelson WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len);
549151cc834SShannon Nelson return;
550151cc834SShannon Nelson }
551151cc834SShannon Nelson
552151cc834SShannon Nelson device = pdsv->vdpa_aux->vd_mdev.device;
553151cc834SShannon Nelson memcpy_fromio(buf, device + offset, len);
554151cc834SShannon Nelson }
555151cc834SShannon Nelson
pds_vdpa_set_config(struct vdpa_device * vdpa_dev,unsigned int offset,const void * buf,unsigned int len)556151cc834SShannon Nelson static void pds_vdpa_set_config(struct vdpa_device *vdpa_dev,
557151cc834SShannon Nelson unsigned int offset, const void *buf,
558151cc834SShannon Nelson unsigned int len)
559151cc834SShannon Nelson {
560151cc834SShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
561151cc834SShannon Nelson void __iomem *device;
562151cc834SShannon Nelson
563151cc834SShannon Nelson if (offset + len > sizeof(struct virtio_net_config)) {
564151cc834SShannon Nelson WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len);
565151cc834SShannon Nelson return;
566151cc834SShannon Nelson }
567151cc834SShannon Nelson
568151cc834SShannon Nelson device = pdsv->vdpa_aux->vd_mdev.device;
569151cc834SShannon Nelson memcpy_toio(device + offset, buf, len);
570151cc834SShannon Nelson }
571151cc834SShannon Nelson
572151cc834SShannon Nelson static const struct vdpa_config_ops pds_vdpa_ops = {
573151cc834SShannon Nelson .set_vq_address = pds_vdpa_set_vq_address,
574151cc834SShannon Nelson .set_vq_num = pds_vdpa_set_vq_num,
575151cc834SShannon Nelson .kick_vq = pds_vdpa_kick_vq,
576151cc834SShannon Nelson .set_vq_cb = pds_vdpa_set_vq_cb,
577151cc834SShannon Nelson .set_vq_ready = pds_vdpa_set_vq_ready,
578151cc834SShannon Nelson .get_vq_ready = pds_vdpa_get_vq_ready,
579151cc834SShannon Nelson .set_vq_state = pds_vdpa_set_vq_state,
580151cc834SShannon Nelson .get_vq_state = pds_vdpa_get_vq_state,
581151cc834SShannon Nelson .get_vq_notification = pds_vdpa_get_vq_notification,
582151cc834SShannon Nelson .get_vq_irq = pds_vdpa_get_vq_irq,
583151cc834SShannon Nelson .get_vq_align = pds_vdpa_get_vq_align,
584151cc834SShannon Nelson .get_vq_group = pds_vdpa_get_vq_group,
585151cc834SShannon Nelson
586151cc834SShannon Nelson .get_device_features = pds_vdpa_get_device_features,
587151cc834SShannon Nelson .set_driver_features = pds_vdpa_set_driver_features,
588151cc834SShannon Nelson .get_driver_features = pds_vdpa_get_driver_features,
589151cc834SShannon Nelson .set_config_cb = pds_vdpa_set_config_cb,
590151cc834SShannon Nelson .get_vq_num_max = pds_vdpa_get_vq_num_max,
591151cc834SShannon Nelson .get_device_id = pds_vdpa_get_device_id,
592151cc834SShannon Nelson .get_vendor_id = pds_vdpa_get_vendor_id,
593151cc834SShannon Nelson .get_status = pds_vdpa_get_status,
594151cc834SShannon Nelson .set_status = pds_vdpa_set_status,
595151cc834SShannon Nelson .reset = pds_vdpa_reset,
596151cc834SShannon Nelson .get_config_size = pds_vdpa_get_config_size,
597151cc834SShannon Nelson .get_config = pds_vdpa_get_config,
598151cc834SShannon Nelson .set_config = pds_vdpa_set_config,
599151cc834SShannon Nelson };
60025d1270bSShannon Nelson static struct virtio_device_id pds_vdpa_id_table[] = {
60125d1270bSShannon Nelson {VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID},
60225d1270bSShannon Nelson {0},
60325d1270bSShannon Nelson };
60425d1270bSShannon Nelson
pds_vdpa_dev_add(struct vdpa_mgmt_dev * mdev,const char * name,const struct vdpa_dev_set_config * add_config)60525d1270bSShannon Nelson static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
60625d1270bSShannon Nelson const struct vdpa_dev_set_config *add_config)
60725d1270bSShannon Nelson {
608151cc834SShannon Nelson struct pds_vdpa_aux *vdpa_aux;
609151cc834SShannon Nelson struct pds_vdpa_device *pdsv;
610151cc834SShannon Nelson struct vdpa_mgmt_dev *mgmt;
611151cc834SShannon Nelson u16 fw_max_vqs, vq_pairs;
612151cc834SShannon Nelson struct device *dma_dev;
613151cc834SShannon Nelson struct pci_dev *pdev;
614151cc834SShannon Nelson struct device *dev;
615151cc834SShannon Nelson int err;
616151cc834SShannon Nelson int i;
617151cc834SShannon Nelson
618151cc834SShannon Nelson vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev);
619151cc834SShannon Nelson dev = &vdpa_aux->padev->aux_dev.dev;
620151cc834SShannon Nelson mgmt = &vdpa_aux->vdpa_mdev;
621151cc834SShannon Nelson
622151cc834SShannon Nelson if (vdpa_aux->pdsv) {
623151cc834SShannon Nelson dev_warn(dev, "Multiple vDPA devices on a VF is not supported.\n");
62425d1270bSShannon Nelson return -EOPNOTSUPP;
62525d1270bSShannon Nelson }
62625d1270bSShannon Nelson
627151cc834SShannon Nelson pdsv = vdpa_alloc_device(struct pds_vdpa_device, vdpa_dev,
628151cc834SShannon Nelson dev, &pds_vdpa_ops, 1, 1, name, false);
629151cc834SShannon Nelson if (IS_ERR(pdsv)) {
630151cc834SShannon Nelson dev_err(dev, "Failed to allocate vDPA structure: %pe\n", pdsv);
631151cc834SShannon Nelson return PTR_ERR(pdsv);
632151cc834SShannon Nelson }
633151cc834SShannon Nelson
634151cc834SShannon Nelson vdpa_aux->pdsv = pdsv;
635151cc834SShannon Nelson pdsv->vdpa_aux = vdpa_aux;
636151cc834SShannon Nelson
637151cc834SShannon Nelson pdev = vdpa_aux->padev->vf_pdev;
638151cc834SShannon Nelson dma_dev = &pdev->dev;
639151cc834SShannon Nelson pdsv->vdpa_dev.dma_dev = dma_dev;
640151cc834SShannon Nelson
641151cc834SShannon Nelson pdsv->supported_features = mgmt->supported_features;
642151cc834SShannon Nelson
643151cc834SShannon Nelson if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) {
644151cc834SShannon Nelson u64 unsupp_features =
645abdf31bdSShannon Nelson add_config->device_features & ~pdsv->supported_features;
646151cc834SShannon Nelson
647151cc834SShannon Nelson if (unsupp_features) {
648151cc834SShannon Nelson dev_err(dev, "Unsupported features: %#llx\n", unsupp_features);
649151cc834SShannon Nelson err = -EOPNOTSUPP;
650151cc834SShannon Nelson goto err_unmap;
651151cc834SShannon Nelson }
652151cc834SShannon Nelson
653151cc834SShannon Nelson pdsv->supported_features = add_config->device_features;
654151cc834SShannon Nelson }
655151cc834SShannon Nelson
656151cc834SShannon Nelson err = pds_vdpa_cmd_reset(pdsv);
657151cc834SShannon Nelson if (err) {
658151cc834SShannon Nelson dev_err(dev, "Failed to reset hw: %pe\n", ERR_PTR(err));
659151cc834SShannon Nelson goto err_unmap;
660151cc834SShannon Nelson }
661151cc834SShannon Nelson
662151cc834SShannon Nelson err = pds_vdpa_init_hw(pdsv);
663151cc834SShannon Nelson if (err) {
664151cc834SShannon Nelson dev_err(dev, "Failed to init hw: %pe\n", ERR_PTR(err));
665151cc834SShannon Nelson goto err_unmap;
666151cc834SShannon Nelson }
667151cc834SShannon Nelson
668151cc834SShannon Nelson fw_max_vqs = le16_to_cpu(pdsv->vdpa_aux->ident.max_vqs);
669151cc834SShannon Nelson vq_pairs = fw_max_vqs / 2;
670151cc834SShannon Nelson
671151cc834SShannon Nelson /* Make sure we have the queues being requested */
672151cc834SShannon Nelson if (add_config->mask & (1 << VDPA_ATTR_DEV_NET_CFG_MAX_VQP))
673151cc834SShannon Nelson vq_pairs = add_config->net.max_vq_pairs;
674151cc834SShannon Nelson
675151cc834SShannon Nelson pdsv->num_vqs = 2 * vq_pairs;
676151cc834SShannon Nelson if (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
677151cc834SShannon Nelson pdsv->num_vqs++;
678151cc834SShannon Nelson
679151cc834SShannon Nelson if (pdsv->num_vqs > fw_max_vqs) {
680151cc834SShannon Nelson dev_err(dev, "%s: queue count requested %u greater than max %u\n",
681151cc834SShannon Nelson __func__, pdsv->num_vqs, fw_max_vqs);
682151cc834SShannon Nelson err = -ENOSPC;
683151cc834SShannon Nelson goto err_unmap;
684151cc834SShannon Nelson }
685151cc834SShannon Nelson
686151cc834SShannon Nelson if (pdsv->num_vqs != fw_max_vqs) {
687151cc834SShannon Nelson err = pds_vdpa_cmd_set_max_vq_pairs(pdsv, vq_pairs);
688151cc834SShannon Nelson if (err) {
689151cc834SShannon Nelson dev_err(dev, "Failed to set max_vq_pairs: %pe\n",
690151cc834SShannon Nelson ERR_PTR(err));
691151cc834SShannon Nelson goto err_unmap;
692151cc834SShannon Nelson }
693151cc834SShannon Nelson }
694151cc834SShannon Nelson
695151cc834SShannon Nelson /* Set a mac, either from the user config if provided
696abdf31bdSShannon Nelson * or use the device's mac if not 00:..:00
697abdf31bdSShannon Nelson * or set a random mac
698151cc834SShannon Nelson */
699151cc834SShannon Nelson if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) {
7000cd2c13bSAllen Hubbe ether_addr_copy(pdsv->mac, add_config->net.mac);
701151cc834SShannon Nelson } else {
702151cc834SShannon Nelson struct virtio_net_config __iomem *vc;
703151cc834SShannon Nelson
704151cc834SShannon Nelson vc = pdsv->vdpa_aux->vd_mdev.device;
7050cd2c13bSAllen Hubbe memcpy_fromio(pdsv->mac, vc->mac, sizeof(pdsv->mac));
706abdf31bdSShannon Nelson if (is_zero_ether_addr(pdsv->mac) &&
707abdf31bdSShannon Nelson (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_MAC))) {
7080cd2c13bSAllen Hubbe eth_random_addr(pdsv->mac);
7090cd2c13bSAllen Hubbe dev_info(dev, "setting random mac %pM\n", pdsv->mac);
710151cc834SShannon Nelson }
711151cc834SShannon Nelson }
7120cd2c13bSAllen Hubbe pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
713151cc834SShannon Nelson
714151cc834SShannon Nelson for (i = 0; i < pdsv->num_vqs; i++) {
715ed888630SShannon Nelson void __iomem *notify;
716ed888630SShannon Nelson
717ed888630SShannon Nelson notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
718151cc834SShannon Nelson i, &pdsv->vqs[i].notify_pa);
719ed888630SShannon Nelson pds_vdpa_init_vqs_entry(pdsv, i, notify);
720151cc834SShannon Nelson }
721151cc834SShannon Nelson
722151cc834SShannon Nelson pdsv->vdpa_dev.mdev = &vdpa_aux->vdpa_mdev;
723151cc834SShannon Nelson
72467f27b8bSShannon Nelson err = pds_vdpa_register_event_handler(pdsv);
72567f27b8bSShannon Nelson if (err) {
72667f27b8bSShannon Nelson dev_err(dev, "Failed to register for PDS events: %pe\n", ERR_PTR(err));
72767f27b8bSShannon Nelson goto err_unmap;
72867f27b8bSShannon Nelson }
72967f27b8bSShannon Nelson
730151cc834SShannon Nelson /* We use the _vdpa_register_device() call rather than the
731151cc834SShannon Nelson * vdpa_register_device() to avoid a deadlock because our
732151cc834SShannon Nelson * dev_add() is called with the vdpa_dev_lock already set
733151cc834SShannon Nelson * by vdpa_nl_cmd_dev_add_set_doit()
734151cc834SShannon Nelson */
735151cc834SShannon Nelson err = _vdpa_register_device(&pdsv->vdpa_dev, pdsv->num_vqs);
736151cc834SShannon Nelson if (err) {
737151cc834SShannon Nelson dev_err(dev, "Failed to register to vDPA bus: %pe\n", ERR_PTR(err));
73867f27b8bSShannon Nelson goto err_unevent;
739151cc834SShannon Nelson }
740151cc834SShannon Nelson
741151cc834SShannon Nelson pds_vdpa_debugfs_add_vdpadev(vdpa_aux);
742151cc834SShannon Nelson
743151cc834SShannon Nelson return 0;
744151cc834SShannon Nelson
74567f27b8bSShannon Nelson err_unevent:
74667f27b8bSShannon Nelson pds_vdpa_unregister_event_handler(pdsv);
747151cc834SShannon Nelson err_unmap:
748151cc834SShannon Nelson put_device(&pdsv->vdpa_dev.dev);
749151cc834SShannon Nelson vdpa_aux->pdsv = NULL;
750151cc834SShannon Nelson return err;
751151cc834SShannon Nelson }
752151cc834SShannon Nelson
pds_vdpa_dev_del(struct vdpa_mgmt_dev * mdev,struct vdpa_device * vdpa_dev)75325d1270bSShannon Nelson static void pds_vdpa_dev_del(struct vdpa_mgmt_dev *mdev,
75425d1270bSShannon Nelson struct vdpa_device *vdpa_dev)
75525d1270bSShannon Nelson {
75667f27b8bSShannon Nelson struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
757151cc834SShannon Nelson struct pds_vdpa_aux *vdpa_aux;
758151cc834SShannon Nelson
75967f27b8bSShannon Nelson pds_vdpa_unregister_event_handler(pdsv);
76067f27b8bSShannon Nelson
761151cc834SShannon Nelson vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev);
762151cc834SShannon Nelson _vdpa_unregister_device(vdpa_dev);
763151cc834SShannon Nelson
764151cc834SShannon Nelson pds_vdpa_cmd_reset(vdpa_aux->pdsv);
765151cc834SShannon Nelson pds_vdpa_debugfs_reset_vdpadev(vdpa_aux);
766151cc834SShannon Nelson
767151cc834SShannon Nelson vdpa_aux->pdsv = NULL;
768151cc834SShannon Nelson
769151cc834SShannon Nelson dev_info(&vdpa_aux->padev->aux_dev.dev, "Removed vdpa device\n");
77025d1270bSShannon Nelson }
77125d1270bSShannon Nelson
77225d1270bSShannon Nelson static const struct vdpa_mgmtdev_ops pds_vdpa_mgmt_dev_ops = {
77325d1270bSShannon Nelson .dev_add = pds_vdpa_dev_add,
77425d1270bSShannon Nelson .dev_del = pds_vdpa_dev_del
77525d1270bSShannon Nelson };
77625d1270bSShannon Nelson
pds_vdpa_get_mgmt_info(struct pds_vdpa_aux * vdpa_aux)77725d1270bSShannon Nelson int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
77825d1270bSShannon Nelson {
77925d1270bSShannon Nelson union pds_core_adminq_cmd cmd = {
78025d1270bSShannon Nelson .vdpa_ident.opcode = PDS_VDPA_CMD_IDENT,
78125d1270bSShannon Nelson .vdpa_ident.vf_id = cpu_to_le16(vdpa_aux->vf_id),
78225d1270bSShannon Nelson };
78325d1270bSShannon Nelson union pds_core_adminq_comp comp = {};
78425d1270bSShannon Nelson struct vdpa_mgmt_dev *mgmt;
78525d1270bSShannon Nelson struct pci_dev *pf_pdev;
78625d1270bSShannon Nelson struct device *pf_dev;
78725d1270bSShannon Nelson struct pci_dev *pdev;
78825d1270bSShannon Nelson dma_addr_t ident_pa;
78925d1270bSShannon Nelson struct device *dev;
79025d1270bSShannon Nelson u16 dev_intrs;
79125d1270bSShannon Nelson u16 max_vqs;
79225d1270bSShannon Nelson int err;
79325d1270bSShannon Nelson
79425d1270bSShannon Nelson dev = &vdpa_aux->padev->aux_dev.dev;
79525d1270bSShannon Nelson pdev = vdpa_aux->padev->vf_pdev;
79625d1270bSShannon Nelson mgmt = &vdpa_aux->vdpa_mdev;
79725d1270bSShannon Nelson
79825d1270bSShannon Nelson /* Get resource info through the PF's adminq. It is a block of info,
79925d1270bSShannon Nelson * so we need to map some memory for PF to make available to the
80025d1270bSShannon Nelson * firmware for writing the data.
80125d1270bSShannon Nelson */
80225d1270bSShannon Nelson pf_pdev = pci_physfn(vdpa_aux->padev->vf_pdev);
80325d1270bSShannon Nelson pf_dev = &pf_pdev->dev;
80425d1270bSShannon Nelson ident_pa = dma_map_single(pf_dev, &vdpa_aux->ident,
80525d1270bSShannon Nelson sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
80625d1270bSShannon Nelson if (dma_mapping_error(pf_dev, ident_pa)) {
80725d1270bSShannon Nelson dev_err(dev, "Failed to map ident space\n");
80825d1270bSShannon Nelson return -ENOMEM;
80925d1270bSShannon Nelson }
81025d1270bSShannon Nelson
81125d1270bSShannon Nelson cmd.vdpa_ident.ident_pa = cpu_to_le64(ident_pa);
81225d1270bSShannon Nelson cmd.vdpa_ident.len = cpu_to_le32(sizeof(vdpa_aux->ident));
81325d1270bSShannon Nelson err = pds_client_adminq_cmd(vdpa_aux->padev, &cmd,
81425d1270bSShannon Nelson sizeof(cmd.vdpa_ident), &comp, 0);
81525d1270bSShannon Nelson dma_unmap_single(pf_dev, ident_pa,
81625d1270bSShannon Nelson sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
81725d1270bSShannon Nelson if (err) {
81825d1270bSShannon Nelson dev_err(dev, "Failed to ident hw, status %d: %pe\n",
81925d1270bSShannon Nelson comp.status, ERR_PTR(err));
82025d1270bSShannon Nelson return err;
82125d1270bSShannon Nelson }
82225d1270bSShannon Nelson
82325d1270bSShannon Nelson max_vqs = le16_to_cpu(vdpa_aux->ident.max_vqs);
82425d1270bSShannon Nelson dev_intrs = pci_msix_vec_count(pdev);
82525d1270bSShannon Nelson dev_dbg(dev, "ident.max_vqs %d dev_intrs %d\n", max_vqs, dev_intrs);
82625d1270bSShannon Nelson
82725d1270bSShannon Nelson max_vqs = min_t(u16, dev_intrs, max_vqs);
82825d1270bSShannon Nelson mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs);
829c0a6c5cbSAllen Hubbe vdpa_aux->nintrs = 0;
83025d1270bSShannon Nelson
83125d1270bSShannon Nelson mgmt->ops = &pds_vdpa_mgmt_dev_ops;
83225d1270bSShannon Nelson mgmt->id_table = pds_vdpa_id_table;
83325d1270bSShannon Nelson mgmt->device = dev;
83425d1270bSShannon Nelson mgmt->supported_features = le64_to_cpu(vdpa_aux->ident.hw_features);
835abdf31bdSShannon Nelson
836abdf31bdSShannon Nelson /* advertise F_MAC even if the device doesn't */
837abdf31bdSShannon Nelson mgmt->supported_features |= BIT_ULL(VIRTIO_NET_F_MAC);
838abdf31bdSShannon Nelson
83925d1270bSShannon Nelson mgmt->config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR);
84025d1270bSShannon Nelson mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
841151cc834SShannon Nelson mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_FEATURES);
84225d1270bSShannon Nelson
84325d1270bSShannon Nelson return 0;
84425d1270bSShannon Nelson }
845