xref: /openbmc/linux/drivers/vdpa/pds/vdpa_dev.c (revision 1b0b4c4238c0bdcf1a8ffa4c5431ec1d3fb9a345)
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