xref: /dpdk/drivers/vdpa/sfc/sfc_vdpa_ops.c (revision a7ba40b2b1bf7ab11fda4050a585d2ca3b159f19)
16dad9a73SVijay Kumar Srivastava /* SPDX-License-Identifier: BSD-3-Clause
26dad9a73SVijay Kumar Srivastava  * Copyright(c) 2020-2021 Xilinx, Inc.
36dad9a73SVijay Kumar Srivastava  */
46dad9a73SVijay Kumar Srivastava 
5630be406SVijay Kumar Srivastava #include <pthread.h>
6630be406SVijay Kumar Srivastava #include <unistd.h>
7b1196136SVijay Kumar Srivastava #include <sys/ioctl.h>
8b1196136SVijay Kumar Srivastava 
9f66a66e6SVijay Kumar Srivastava #include <rte_errno.h>
106dad9a73SVijay Kumar Srivastava #include <rte_malloc.h>
116dad9a73SVijay Kumar Srivastava #include <rte_vdpa.h>
12b1196136SVijay Kumar Srivastava #include <rte_vfio.h>
136dad9a73SVijay Kumar Srivastava #include <rte_vhost.h>
146dad9a73SVijay Kumar Srivastava 
156dad9a73SVijay Kumar Srivastava #include <vdpa_driver.h>
166dad9a73SVijay Kumar Srivastava 
17f66a66e6SVijay Kumar Srivastava #include "efx.h"
186dad9a73SVijay Kumar Srivastava #include "sfc_vdpa_ops.h"
196dad9a73SVijay Kumar Srivastava #include "sfc_vdpa.h"
206dad9a73SVijay Kumar Srivastava 
21f66a66e6SVijay Kumar Srivastava /* These protocol features are needed to enable notifier ctrl */
22f66a66e6SVijay Kumar Srivastava #define SFC_VDPA_PROTOCOL_FEATURES \
23f66a66e6SVijay Kumar Srivastava 		((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
24f1eb477eSNobuhiro Miki 		 (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_REQ) | \
25f1eb477eSNobuhiro Miki 		 (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD) | \
26f66a66e6SVijay Kumar Srivastava 		 (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
27f2c0e634SAbhimanyu Saini 		 (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \
28f2c0e634SAbhimanyu Saini 		 (1ULL << VHOST_USER_PROTOCOL_F_MQ))
29f66a66e6SVijay Kumar Srivastava 
30f66a66e6SVijay Kumar Srivastava /*
31f66a66e6SVijay Kumar Srivastava  * Set of features which are enabled by default.
32f66a66e6SVijay Kumar Srivastava  * Protocol feature bit is needed to enable notification notifier ctrl.
336dad9a73SVijay Kumar Srivastava  */
34f66a66e6SVijay Kumar Srivastava #define SFC_VDPA_DEFAULT_FEATURES \
35f2c0e634SAbhimanyu Saini 		((1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
36f2c0e634SAbhimanyu Saini 		 (1ULL << VIRTIO_NET_F_MQ))
37f66a66e6SVijay Kumar Srivastava 
38b1196136SVijay Kumar Srivastava #define SFC_VDPA_MSIX_IRQ_SET_BUF_LEN \
39b1196136SVijay Kumar Srivastava 		(sizeof(struct vfio_irq_set) + \
40b1196136SVijay Kumar Srivastava 		sizeof(int) * (SFC_VDPA_MAX_QUEUE_PAIRS * 2 + 1))
416dad9a73SVijay Kumar Srivastava 
42b1196136SVijay Kumar Srivastava /* It will be used for target VF when calling function is not PF */
43b1196136SVijay Kumar Srivastava #define SFC_VDPA_VF_NULL		0xFFFF
446dad9a73SVijay Kumar Srivastava 
456dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_get_device_features(struct sfc_vdpa_ops_data * ops_data)46f66a66e6SVijay Kumar Srivastava sfc_vdpa_get_device_features(struct sfc_vdpa_ops_data *ops_data)
47f66a66e6SVijay Kumar Srivastava {
48f66a66e6SVijay Kumar Srivastava 	int rc;
49f66a66e6SVijay Kumar Srivastava 	uint64_t dev_features;
50f66a66e6SVijay Kumar Srivastava 	efx_nic_t *nic;
51f66a66e6SVijay Kumar Srivastava 
52f66a66e6SVijay Kumar Srivastava 	nic = sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle)->nic;
53f66a66e6SVijay Kumar Srivastava 
54f66a66e6SVijay Kumar Srivastava 	rc = efx_virtio_get_features(nic, EFX_VIRTIO_DEVICE_TYPE_NET,
55f66a66e6SVijay Kumar Srivastava 				     &dev_features);
56f66a66e6SVijay Kumar Srivastava 	if (rc != 0) {
57f66a66e6SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
58f66a66e6SVijay Kumar Srivastava 			     "could not read device feature: %s",
59f66a66e6SVijay Kumar Srivastava 			     rte_strerror(rc));
60f66a66e6SVijay Kumar Srivastava 		return rc;
61f66a66e6SVijay Kumar Srivastava 	}
62f66a66e6SVijay Kumar Srivastava 
63f66a66e6SVijay Kumar Srivastava 	ops_data->dev_features = dev_features;
64f66a66e6SVijay Kumar Srivastava 
65f66a66e6SVijay Kumar Srivastava 	sfc_vdpa_info(ops_data->dev_handle,
66f66a66e6SVijay Kumar Srivastava 		      "device supported virtio features : 0x%" PRIx64,
67f66a66e6SVijay Kumar Srivastava 		      ops_data->dev_features);
68f66a66e6SVijay Kumar Srivastava 
69f66a66e6SVijay Kumar Srivastava 	return 0;
70f66a66e6SVijay Kumar Srivastava }
71f66a66e6SVijay Kumar Srivastava 
72b1196136SVijay Kumar Srivastava static uint64_t
hva_to_gpa(int vid,uint64_t hva)73b1196136SVijay Kumar Srivastava hva_to_gpa(int vid, uint64_t hva)
74b1196136SVijay Kumar Srivastava {
75b1196136SVijay Kumar Srivastava 	struct rte_vhost_memory *vhost_mem = NULL;
76b1196136SVijay Kumar Srivastava 	struct rte_vhost_mem_region *mem_reg = NULL;
77b1196136SVijay Kumar Srivastava 	uint32_t i;
78b1196136SVijay Kumar Srivastava 	uint64_t gpa = 0;
79b1196136SVijay Kumar Srivastava 
80b1196136SVijay Kumar Srivastava 	if (rte_vhost_get_mem_table(vid, &vhost_mem) < 0)
81b1196136SVijay Kumar Srivastava 		goto error;
82b1196136SVijay Kumar Srivastava 
83b1196136SVijay Kumar Srivastava 	for (i = 0; i < vhost_mem->nregions; i++) {
84b1196136SVijay Kumar Srivastava 		mem_reg = &vhost_mem->regions[i];
85b1196136SVijay Kumar Srivastava 
86b1196136SVijay Kumar Srivastava 		if (hva >= mem_reg->host_user_addr &&
87b1196136SVijay Kumar Srivastava 				hva < mem_reg->host_user_addr + mem_reg->size) {
88b1196136SVijay Kumar Srivastava 			gpa = (hva - mem_reg->host_user_addr) +
89b1196136SVijay Kumar Srivastava 				mem_reg->guest_phys_addr;
90b1196136SVijay Kumar Srivastava 			break;
91b1196136SVijay Kumar Srivastava 		}
92b1196136SVijay Kumar Srivastava 	}
93b1196136SVijay Kumar Srivastava 
94b1196136SVijay Kumar Srivastava error:
95b1196136SVijay Kumar Srivastava 	free(vhost_mem);
96b1196136SVijay Kumar Srivastava 	return gpa;
97b1196136SVijay Kumar Srivastava }
98b1196136SVijay Kumar Srivastava 
99b1196136SVijay Kumar Srivastava static int
sfc_vdpa_enable_vfio_intr(struct sfc_vdpa_ops_data * ops_data)100b1196136SVijay Kumar Srivastava sfc_vdpa_enable_vfio_intr(struct sfc_vdpa_ops_data *ops_data)
101b1196136SVijay Kumar Srivastava {
102b1196136SVijay Kumar Srivastava 	int rc;
103b1196136SVijay Kumar Srivastava 	int *irq_fd_ptr;
104b1196136SVijay Kumar Srivastava 	int vfio_dev_fd;
105b1196136SVijay Kumar Srivastava 	uint32_t i, num_vring;
106b1196136SVijay Kumar Srivastava 	struct rte_vhost_vring vring;
107b1196136SVijay Kumar Srivastava 	struct vfio_irq_set *irq_set;
108b1196136SVijay Kumar Srivastava 	struct rte_pci_device *pci_dev;
109b1196136SVijay Kumar Srivastava 	char irq_set_buf[SFC_VDPA_MSIX_IRQ_SET_BUF_LEN];
110b1196136SVijay Kumar Srivastava 	void *dev;
111b1196136SVijay Kumar Srivastava 
112b1196136SVijay Kumar Srivastava 	num_vring = rte_vhost_get_vring_num(ops_data->vid);
113b1196136SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
114b1196136SVijay Kumar Srivastava 	vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
115b1196136SVijay Kumar Srivastava 	pci_dev = sfc_vdpa_adapter_by_dev_handle(dev)->pdev;
116b1196136SVijay Kumar Srivastava 
117b1196136SVijay Kumar Srivastava 	irq_set = (struct vfio_irq_set *)irq_set_buf;
118b1196136SVijay Kumar Srivastava 	irq_set->argsz = sizeof(irq_set_buf);
119b1196136SVijay Kumar Srivastava 	irq_set->count = num_vring + 1;
120b1196136SVijay Kumar Srivastava 	irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
121b1196136SVijay Kumar Srivastava 			 VFIO_IRQ_SET_ACTION_TRIGGER;
122b1196136SVijay Kumar Srivastava 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
123b1196136SVijay Kumar Srivastava 	irq_set->start = 0;
124b1196136SVijay Kumar Srivastava 	irq_fd_ptr = (int *)&irq_set->data;
125b1196136SVijay Kumar Srivastava 	irq_fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] =
126b1196136SVijay Kumar Srivastava 		rte_intr_fd_get(pci_dev->intr_handle);
127b1196136SVijay Kumar Srivastava 
128b1196136SVijay Kumar Srivastava 	for (i = 0; i < num_vring; i++) {
129b1196136SVijay Kumar Srivastava 		rc = rte_vhost_get_vhost_vring(ops_data->vid, i, &vring);
130b1196136SVijay Kumar Srivastava 		if (rc)
131b1196136SVijay Kumar Srivastava 			return -1;
132b1196136SVijay Kumar Srivastava 
133b1196136SVijay Kumar Srivastava 		irq_fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i] = vring.callfd;
134b1196136SVijay Kumar Srivastava 	}
135b1196136SVijay Kumar Srivastava 
136b1196136SVijay Kumar Srivastava 	rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
137b1196136SVijay Kumar Srivastava 	if (rc) {
138b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
139b1196136SVijay Kumar Srivastava 			     "error enabling MSI-X interrupts: %s",
140b1196136SVijay Kumar Srivastava 			     strerror(errno));
141b1196136SVijay Kumar Srivastava 		return -1;
142b1196136SVijay Kumar Srivastava 	}
143b1196136SVijay Kumar Srivastava 
144b1196136SVijay Kumar Srivastava 	return 0;
145b1196136SVijay Kumar Srivastava }
146b1196136SVijay Kumar Srivastava 
147b1196136SVijay Kumar Srivastava static int
sfc_vdpa_disable_vfio_intr(struct sfc_vdpa_ops_data * ops_data)148b1196136SVijay Kumar Srivastava sfc_vdpa_disable_vfio_intr(struct sfc_vdpa_ops_data *ops_data)
149b1196136SVijay Kumar Srivastava {
150b1196136SVijay Kumar Srivastava 	int rc;
151b1196136SVijay Kumar Srivastava 	int vfio_dev_fd;
152b1196136SVijay Kumar Srivastava 	struct vfio_irq_set irq_set;
153b1196136SVijay Kumar Srivastava 	void *dev;
154b1196136SVijay Kumar Srivastava 
155b1196136SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
156b1196136SVijay Kumar Srivastava 	vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
157b1196136SVijay Kumar Srivastava 
158b1196136SVijay Kumar Srivastava 	irq_set.argsz = sizeof(irq_set);
159b1196136SVijay Kumar Srivastava 	irq_set.count = 0;
160b1196136SVijay Kumar Srivastava 	irq_set.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
161b1196136SVijay Kumar Srivastava 	irq_set.index = VFIO_PCI_MSIX_IRQ_INDEX;
162b1196136SVijay Kumar Srivastava 	irq_set.start = 0;
163b1196136SVijay Kumar Srivastava 
164b1196136SVijay Kumar Srivastava 	rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, &irq_set);
165b1196136SVijay Kumar Srivastava 	if (rc) {
166b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
167b1196136SVijay Kumar Srivastava 			     "error disabling MSI-X interrupts: %s",
168b1196136SVijay Kumar Srivastava 			     strerror(errno));
169b1196136SVijay Kumar Srivastava 		return -1;
170b1196136SVijay Kumar Srivastava 	}
171b1196136SVijay Kumar Srivastava 
172b1196136SVijay Kumar Srivastava 	return 0;
173b1196136SVijay Kumar Srivastava }
174b1196136SVijay Kumar Srivastava 
175b1196136SVijay Kumar Srivastava static int
sfc_vdpa_get_vring_info(struct sfc_vdpa_ops_data * ops_data,int vq_num,struct sfc_vdpa_vring_info * vring)176b1196136SVijay Kumar Srivastava sfc_vdpa_get_vring_info(struct sfc_vdpa_ops_data *ops_data,
177b1196136SVijay Kumar Srivastava 			int vq_num, struct sfc_vdpa_vring_info *vring)
178b1196136SVijay Kumar Srivastava {
179b1196136SVijay Kumar Srivastava 	int rc;
180b1196136SVijay Kumar Srivastava 	uint64_t gpa;
181b1196136SVijay Kumar Srivastava 	struct rte_vhost_vring vq;
182b1196136SVijay Kumar Srivastava 
183b1196136SVijay Kumar Srivastava 	rc = rte_vhost_get_vhost_vring(ops_data->vid, vq_num, &vq);
184b1196136SVijay Kumar Srivastava 	if (rc < 0) {
185b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
186b1196136SVijay Kumar Srivastava 			     "get vhost vring failed: %s", rte_strerror(rc));
187b1196136SVijay Kumar Srivastava 		return rc;
188b1196136SVijay Kumar Srivastava 	}
189b1196136SVijay Kumar Srivastava 
190b1196136SVijay Kumar Srivastava 	gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.desc);
191b1196136SVijay Kumar Srivastava 	if (gpa == 0) {
192b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
193b1196136SVijay Kumar Srivastava 			     "fail to get GPA for descriptor ring.");
194b1196136SVijay Kumar Srivastava 		return -1;
195b1196136SVijay Kumar Srivastava 	}
196b1196136SVijay Kumar Srivastava 	vring->desc = gpa;
197b1196136SVijay Kumar Srivastava 
198b1196136SVijay Kumar Srivastava 	gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.avail);
199b1196136SVijay Kumar Srivastava 	if (gpa == 0) {
200b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
201b1196136SVijay Kumar Srivastava 			     "fail to get GPA for available ring.");
202b1196136SVijay Kumar Srivastava 		return -1;
203b1196136SVijay Kumar Srivastava 	}
204b1196136SVijay Kumar Srivastava 	vring->avail = gpa;
205b1196136SVijay Kumar Srivastava 
206b1196136SVijay Kumar Srivastava 	gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.used);
207b1196136SVijay Kumar Srivastava 	if (gpa == 0) {
208b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
209b1196136SVijay Kumar Srivastava 			     "fail to get GPA for used ring.");
210b1196136SVijay Kumar Srivastava 		return -1;
211b1196136SVijay Kumar Srivastava 	}
212b1196136SVijay Kumar Srivastava 	vring->used = gpa;
213b1196136SVijay Kumar Srivastava 
214b1196136SVijay Kumar Srivastava 	vring->size = vq.size;
215b1196136SVijay Kumar Srivastava 
216b1196136SVijay Kumar Srivastava 	rc = rte_vhost_get_vring_base(ops_data->vid, vq_num,
217b1196136SVijay Kumar Srivastava 				      &vring->last_avail_idx,
218b1196136SVijay Kumar Srivastava 				      &vring->last_used_idx);
219b1196136SVijay Kumar Srivastava 
220b1196136SVijay Kumar Srivastava 	return rc;
221b1196136SVijay Kumar Srivastava }
222b1196136SVijay Kumar Srivastava 
223b1196136SVijay Kumar Srivastava static int
sfc_vdpa_virtq_start(struct sfc_vdpa_ops_data * ops_data,int vq_num)224b1196136SVijay Kumar Srivastava sfc_vdpa_virtq_start(struct sfc_vdpa_ops_data *ops_data, int vq_num)
225b1196136SVijay Kumar Srivastava {
226b1196136SVijay Kumar Srivastava 	int rc;
227d9a1ef20SAbhimanyu Saini 	uint32_t doorbell;
228b1196136SVijay Kumar Srivastava 	efx_virtio_vq_t *vq;
229b1196136SVijay Kumar Srivastava 	struct sfc_vdpa_vring_info vring;
230b1196136SVijay Kumar Srivastava 	efx_virtio_vq_cfg_t vq_cfg;
231b1196136SVijay Kumar Srivastava 	efx_virtio_vq_dyncfg_t vq_dyncfg;
232b1196136SVijay Kumar Srivastava 
233b1196136SVijay Kumar Srivastava 	vq = ops_data->vq_cxt[vq_num].vq;
234b1196136SVijay Kumar Srivastava 	if (vq == NULL)
235b1196136SVijay Kumar Srivastava 		return -1;
236b1196136SVijay Kumar Srivastava 
237b1196136SVijay Kumar Srivastava 	rc = sfc_vdpa_get_vring_info(ops_data, vq_num, &vring);
238b1196136SVijay Kumar Srivastava 	if (rc < 0) {
239b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
240b1196136SVijay Kumar Srivastava 			     "get vring info failed: %s", rte_strerror(rc));
241b1196136SVijay Kumar Srivastava 		goto fail_vring_info;
242b1196136SVijay Kumar Srivastava 	}
243b1196136SVijay Kumar Srivastava 
244b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_target_vf = SFC_VDPA_VF_NULL;
245b1196136SVijay Kumar Srivastava 
246b1196136SVijay Kumar Srivastava 	/* even virtqueue for RX and odd for TX */
247b1196136SVijay Kumar Srivastava 	if (vq_num % 2) {
248b1196136SVijay Kumar Srivastava 		vq_cfg.evvc_type = EFX_VIRTIO_VQ_TYPE_NET_TXQ;
249b1196136SVijay Kumar Srivastava 		sfc_vdpa_info(ops_data->dev_handle,
250b1196136SVijay Kumar Srivastava 			      "configure virtqueue # %d (TXQ)", vq_num);
251b1196136SVijay Kumar Srivastava 	} else {
252b1196136SVijay Kumar Srivastava 		vq_cfg.evvc_type = EFX_VIRTIO_VQ_TYPE_NET_RXQ;
253b1196136SVijay Kumar Srivastava 		sfc_vdpa_info(ops_data->dev_handle,
254b1196136SVijay Kumar Srivastava 			      "configure virtqueue # %d (RXQ)", vq_num);
255b1196136SVijay Kumar Srivastava 	}
256b1196136SVijay Kumar Srivastava 
257b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_vq_num = vq_num;
258b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_desc_tbl_addr   = vring.desc;
259b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_avail_ring_addr = vring.avail;
260b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_used_ring_addr  = vring.used;
261b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_vq_size = vring.size;
262b1196136SVijay Kumar Srivastava 
26305308e34SAbhimanyu Saini 	vq_dyncfg.evvd_vq_used_idx  = vring.last_used_idx;
26405308e34SAbhimanyu Saini 	vq_dyncfg.evvd_vq_avail_idx = vring.last_avail_idx;
265b1196136SVijay Kumar Srivastava 
266b1196136SVijay Kumar Srivastava 	/* MSI-X vector is function-relative */
267b1196136SVijay Kumar Srivastava 	vq_cfg.evvc_msix_vector = RTE_INTR_VEC_RXTX_OFFSET + vq_num;
268b1196136SVijay Kumar Srivastava 	if (ops_data->vdpa_context == SFC_VDPA_AS_VF)
269b1196136SVijay Kumar Srivastava 		vq_cfg.evvc_pas_id = 0;
270b1196136SVijay Kumar Srivastava 	vq_cfg.evcc_features = ops_data->dev_features &
271b1196136SVijay Kumar Srivastava 			       ops_data->req_features;
272b1196136SVijay Kumar Srivastava 
273b1196136SVijay Kumar Srivastava 	/* Start virtqueue */
274b1196136SVijay Kumar Srivastava 	rc = efx_virtio_qstart(vq, &vq_cfg, &vq_dyncfg);
275b1196136SVijay Kumar Srivastava 	if (rc != 0) {
276b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
277b1196136SVijay Kumar Srivastava 			     "virtqueue start failed: %s",
278b1196136SVijay Kumar Srivastava 			     rte_strerror(rc));
279b1196136SVijay Kumar Srivastava 		goto fail_virtio_qstart;
280b1196136SVijay Kumar Srivastava 	}
281b1196136SVijay Kumar Srivastava 
282b1196136SVijay Kumar Srivastava 	sfc_vdpa_info(ops_data->dev_handle,
283b1196136SVijay Kumar Srivastava 		      "virtqueue started successfully for vq_num %d", vq_num);
284b1196136SVijay Kumar Srivastava 
285d9a1ef20SAbhimanyu Saini 	rc = efx_virtio_get_doorbell_offset(vq,	&doorbell);
286d9a1ef20SAbhimanyu Saini 	if (rc != 0) {
287d9a1ef20SAbhimanyu Saini 		sfc_vdpa_err(ops_data->dev_handle,
288d9a1ef20SAbhimanyu Saini 			     "failed to get doorbell offset: %s",
289d9a1ef20SAbhimanyu Saini 			     rte_strerror(rc));
290d9a1ef20SAbhimanyu Saini 		goto fail_doorbell;
291d9a1ef20SAbhimanyu Saini 	}
292d9a1ef20SAbhimanyu Saini 
293d9a1ef20SAbhimanyu Saini 	/*
294d9a1ef20SAbhimanyu Saini 	 * Cache the bar_offset here for each VQ here, it will come
295d9a1ef20SAbhimanyu Saini 	 * in handy when sfc_vdpa_get_notify_area() is invoked.
296d9a1ef20SAbhimanyu Saini 	 */
297d9a1ef20SAbhimanyu Saini 	ops_data->vq_cxt[vq_num].doorbell = (void *)(uintptr_t)doorbell;
298b1196136SVijay Kumar Srivastava 	ops_data->vq_cxt[vq_num].enable = B_TRUE;
299b1196136SVijay Kumar Srivastava 
300b1196136SVijay Kumar Srivastava 	return rc;
301b1196136SVijay Kumar Srivastava 
302d9a1ef20SAbhimanyu Saini fail_doorbell:
303b1196136SVijay Kumar Srivastava fail_virtio_qstart:
304d9a1ef20SAbhimanyu Saini 	efx_virtio_qdestroy(vq);
305b1196136SVijay Kumar Srivastava fail_vring_info:
306b1196136SVijay Kumar Srivastava 	return rc;
307b1196136SVijay Kumar Srivastava }
308b1196136SVijay Kumar Srivastava 
309b1196136SVijay Kumar Srivastava static int
sfc_vdpa_virtq_stop(struct sfc_vdpa_ops_data * ops_data,int vq_num)310b1196136SVijay Kumar Srivastava sfc_vdpa_virtq_stop(struct sfc_vdpa_ops_data *ops_data, int vq_num)
311b1196136SVijay Kumar Srivastava {
312b1196136SVijay Kumar Srivastava 	int rc;
313b1196136SVijay Kumar Srivastava 	efx_virtio_vq_dyncfg_t vq_idx;
314b1196136SVijay Kumar Srivastava 	efx_virtio_vq_t *vq;
315b1196136SVijay Kumar Srivastava 
316b1196136SVijay Kumar Srivastava 	if (ops_data->vq_cxt[vq_num].enable != B_TRUE)
317b1196136SVijay Kumar Srivastava 		return -1;
318b1196136SVijay Kumar Srivastava 
319b1196136SVijay Kumar Srivastava 	vq = ops_data->vq_cxt[vq_num].vq;
320b1196136SVijay Kumar Srivastava 	if (vq == NULL)
321b1196136SVijay Kumar Srivastava 		return -1;
322b1196136SVijay Kumar Srivastava 
323b1196136SVijay Kumar Srivastava 	/* stop the vq */
324b1196136SVijay Kumar Srivastava 	rc = efx_virtio_qstop(vq, &vq_idx);
325b1196136SVijay Kumar Srivastava 	if (rc == 0) {
32605308e34SAbhimanyu Saini 		ops_data->vq_cxt[vq_num].cidx = vq_idx.evvd_vq_used_idx;
32705308e34SAbhimanyu Saini 		ops_data->vq_cxt[vq_num].pidx = vq_idx.evvd_vq_avail_idx;
328b1196136SVijay Kumar Srivastava 	}
329b1196136SVijay Kumar Srivastava 	ops_data->vq_cxt[vq_num].enable = B_FALSE;
330b1196136SVijay Kumar Srivastava 
331b1196136SVijay Kumar Srivastava 	return rc;
332b1196136SVijay Kumar Srivastava }
333b1196136SVijay Kumar Srivastava 
334b1196136SVijay Kumar Srivastava static int
sfc_vdpa_configure(struct sfc_vdpa_ops_data * ops_data)335b1196136SVijay Kumar Srivastava sfc_vdpa_configure(struct sfc_vdpa_ops_data *ops_data)
336b1196136SVijay Kumar Srivastava {
337b1196136SVijay Kumar Srivastava 	int rc, i;
338b1196136SVijay Kumar Srivastava 	int nr_vring;
339b1196136SVijay Kumar Srivastava 	int max_vring_cnt;
340b1196136SVijay Kumar Srivastava 	efx_virtio_vq_t *vq;
341b1196136SVijay Kumar Srivastava 	efx_nic_t *nic;
342b1196136SVijay Kumar Srivastava 	void *dev;
343b1196136SVijay Kumar Srivastava 
344b1196136SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
345b1196136SVijay Kumar Srivastava 	nic = sfc_vdpa_adapter_by_dev_handle(dev)->nic;
346b1196136SVijay Kumar Srivastava 
347b1196136SVijay Kumar Srivastava 	SFC_EFX_ASSERT(ops_data->state == SFC_VDPA_STATE_INITIALIZED);
348b1196136SVijay Kumar Srivastava 
349b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_CONFIGURING;
350b1196136SVijay Kumar Srivastava 
351b1196136SVijay Kumar Srivastava 	nr_vring = rte_vhost_get_vring_num(ops_data->vid);
352b1196136SVijay Kumar Srivastava 	max_vring_cnt =
353b1196136SVijay Kumar Srivastava 		(sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
354b1196136SVijay Kumar Srivastava 
355b1196136SVijay Kumar Srivastava 	/* number of vring should not be more than supported max vq count */
356b1196136SVijay Kumar Srivastava 	if (nr_vring > max_vring_cnt) {
357b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(dev,
358b1196136SVijay Kumar Srivastava 			     "nr_vring (%d) is > max vring count (%d)",
359b1196136SVijay Kumar Srivastava 			     nr_vring, max_vring_cnt);
360b1196136SVijay Kumar Srivastava 		goto fail_vring_num;
361b1196136SVijay Kumar Srivastava 	}
362b1196136SVijay Kumar Srivastava 
363b1196136SVijay Kumar Srivastava 	rc = sfc_vdpa_dma_map(ops_data, true);
364b1196136SVijay Kumar Srivastava 	if (rc) {
365b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(dev,
366b1196136SVijay Kumar Srivastava 			     "DMA map failed: %s", rte_strerror(rc));
367b1196136SVijay Kumar Srivastava 		goto fail_dma_map;
368b1196136SVijay Kumar Srivastava 	}
369b1196136SVijay Kumar Srivastava 
370b1196136SVijay Kumar Srivastava 	for (i = 0; i < nr_vring; i++) {
371b1196136SVijay Kumar Srivastava 		rc = efx_virtio_qcreate(nic, &vq);
372b1196136SVijay Kumar Srivastava 		if ((rc != 0) || (vq == NULL)) {
373b1196136SVijay Kumar Srivastava 			sfc_vdpa_err(dev,
374b1196136SVijay Kumar Srivastava 				     "virtqueue create failed: %s",
375b1196136SVijay Kumar Srivastava 				     rte_strerror(rc));
376b1196136SVijay Kumar Srivastava 			goto fail_vq_create;
377b1196136SVijay Kumar Srivastava 		}
378b1196136SVijay Kumar Srivastava 
379b1196136SVijay Kumar Srivastava 		/* store created virtqueue context */
380b1196136SVijay Kumar Srivastava 		ops_data->vq_cxt[i].vq = vq;
381b1196136SVijay Kumar Srivastava 	}
382b1196136SVijay Kumar Srivastava 
383b1196136SVijay Kumar Srivastava 	ops_data->vq_count = i;
384b1196136SVijay Kumar Srivastava 
385b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_CONFIGURED;
386b1196136SVijay Kumar Srivastava 
387b1196136SVijay Kumar Srivastava 	return 0;
388b1196136SVijay Kumar Srivastava 
389b1196136SVijay Kumar Srivastava fail_vq_create:
390b1196136SVijay Kumar Srivastava 	sfc_vdpa_dma_map(ops_data, false);
391b1196136SVijay Kumar Srivastava 
392b1196136SVijay Kumar Srivastava fail_dma_map:
393b1196136SVijay Kumar Srivastava fail_vring_num:
394b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_INITIALIZED;
395b1196136SVijay Kumar Srivastava 
396b1196136SVijay Kumar Srivastava 	return -1;
397b1196136SVijay Kumar Srivastava }
398b1196136SVijay Kumar Srivastava 
399b1196136SVijay Kumar Srivastava static void
sfc_vdpa_close(struct sfc_vdpa_ops_data * ops_data)400b1196136SVijay Kumar Srivastava sfc_vdpa_close(struct sfc_vdpa_ops_data *ops_data)
401b1196136SVijay Kumar Srivastava {
402b1196136SVijay Kumar Srivastava 	int i;
403b1196136SVijay Kumar Srivastava 
404b1196136SVijay Kumar Srivastava 	if (ops_data->state != SFC_VDPA_STATE_CONFIGURED)
405b1196136SVijay Kumar Srivastava 		return;
406b1196136SVijay Kumar Srivastava 
407b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_CLOSING;
408b1196136SVijay Kumar Srivastava 
409b1196136SVijay Kumar Srivastava 	for (i = 0; i < ops_data->vq_count; i++) {
410b1196136SVijay Kumar Srivastava 		if (ops_data->vq_cxt[i].vq == NULL)
411b1196136SVijay Kumar Srivastava 			continue;
412b1196136SVijay Kumar Srivastava 
413b1196136SVijay Kumar Srivastava 		efx_virtio_qdestroy(ops_data->vq_cxt[i].vq);
414b1196136SVijay Kumar Srivastava 	}
415b1196136SVijay Kumar Srivastava 
416b1196136SVijay Kumar Srivastava 	sfc_vdpa_dma_map(ops_data, false);
417b1196136SVijay Kumar Srivastava 
418b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_INITIALIZED;
419b1196136SVijay Kumar Srivastava }
420b1196136SVijay Kumar Srivastava 
421b1196136SVijay Kumar Srivastava static void
sfc_vdpa_stop(struct sfc_vdpa_ops_data * ops_data)422b1196136SVijay Kumar Srivastava sfc_vdpa_stop(struct sfc_vdpa_ops_data *ops_data)
423b1196136SVijay Kumar Srivastava {
424b1196136SVijay Kumar Srivastava 	int i;
425b1196136SVijay Kumar Srivastava 	int rc;
426b1196136SVijay Kumar Srivastava 
427b1196136SVijay Kumar Srivastava 	if (ops_data->state != SFC_VDPA_STATE_STARTED)
428b1196136SVijay Kumar Srivastava 		return;
429b1196136SVijay Kumar Srivastava 
430b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_STOPPING;
431b1196136SVijay Kumar Srivastava 
432b1196136SVijay Kumar Srivastava 	for (i = 0; i < ops_data->vq_count; i++) {
433b1196136SVijay Kumar Srivastava 		rc = sfc_vdpa_virtq_stop(ops_data, i);
434b1196136SVijay Kumar Srivastava 		if (rc != 0)
435b1196136SVijay Kumar Srivastava 			continue;
436b1196136SVijay Kumar Srivastava 	}
437b1196136SVijay Kumar Srivastava 
438b1196136SVijay Kumar Srivastava 	sfc_vdpa_disable_vfio_intr(ops_data);
439b1196136SVijay Kumar Srivastava 
440cfeed08aSVijay Kumar Srivastava 	sfc_vdpa_filter_remove(ops_data);
441cfeed08aSVijay Kumar Srivastava 
442b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_CONFIGURED;
443b1196136SVijay Kumar Srivastava }
444b1196136SVijay Kumar Srivastava 
445b1196136SVijay Kumar Srivastava static int
sfc_vdpa_start(struct sfc_vdpa_ops_data * ops_data)446b1196136SVijay Kumar Srivastava sfc_vdpa_start(struct sfc_vdpa_ops_data *ops_data)
447b1196136SVijay Kumar Srivastava {
448b1196136SVijay Kumar Srivastava 	int i, j;
449b1196136SVijay Kumar Srivastava 	int rc;
450b1196136SVijay Kumar Srivastava 
451b1196136SVijay Kumar Srivastava 	SFC_EFX_ASSERT(ops_data->state == SFC_VDPA_STATE_CONFIGURED);
452b1196136SVijay Kumar Srivastava 
453b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "entry");
454b1196136SVijay Kumar Srivastava 
455b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_STARTING;
456b1196136SVijay Kumar Srivastava 
457b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "enable interrupts");
458b1196136SVijay Kumar Srivastava 	rc = sfc_vdpa_enable_vfio_intr(ops_data);
459b1196136SVijay Kumar Srivastava 	if (rc < 0) {
460b1196136SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
461b1196136SVijay Kumar Srivastava 			     "vfio intr allocation failed: %s",
462b1196136SVijay Kumar Srivastava 			     rte_strerror(rc));
463b1196136SVijay Kumar Srivastava 		goto fail_enable_vfio_intr;
464b1196136SVijay Kumar Srivastava 	}
465b1196136SVijay Kumar Srivastava 
466b1196136SVijay Kumar Srivastava 	rte_vhost_get_negotiated_features(ops_data->vid,
467b1196136SVijay Kumar Srivastava 					  &ops_data->req_features);
468b1196136SVijay Kumar Srivastava 
469b1196136SVijay Kumar Srivastava 	sfc_vdpa_info(ops_data->dev_handle,
470b1196136SVijay Kumar Srivastava 		      "negotiated feature : 0x%" PRIx64,
471b1196136SVijay Kumar Srivastava 		      ops_data->req_features);
472b1196136SVijay Kumar Srivastava 
473b1196136SVijay Kumar Srivastava 	for (i = 0; i < ops_data->vq_count; i++) {
474b1196136SVijay Kumar Srivastava 		sfc_vdpa_log_init(ops_data->dev_handle,
475b1196136SVijay Kumar Srivastava 				  "starting vq# %d", i);
476b1196136SVijay Kumar Srivastava 		rc = sfc_vdpa_virtq_start(ops_data, i);
477b1196136SVijay Kumar Srivastava 		if (rc != 0)
478b1196136SVijay Kumar Srivastava 			goto fail_vq_start;
479b1196136SVijay Kumar Srivastava 	}
480b1196136SVijay Kumar Srivastava 
481cfeed08aSVijay Kumar Srivastava 	ops_data->vq_count = i;
482cfeed08aSVijay Kumar Srivastava 
483cfeed08aSVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle,
484cfeed08aSVijay Kumar Srivastava 			  "configure MAC filters");
485cfeed08aSVijay Kumar Srivastava 	rc = sfc_vdpa_filter_config(ops_data);
486cfeed08aSVijay Kumar Srivastava 	if (rc != 0) {
487cfeed08aSVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
488cfeed08aSVijay Kumar Srivastava 			     "MAC filter config failed: %s",
489cfeed08aSVijay Kumar Srivastava 			     rte_strerror(rc));
490cfeed08aSVijay Kumar Srivastava 		goto fail_filter_cfg;
491cfeed08aSVijay Kumar Srivastava 	}
492cfeed08aSVijay Kumar Srivastava 
493b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_STARTED;
494b1196136SVijay Kumar Srivastava 
495b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "done");
496b1196136SVijay Kumar Srivastava 
497b1196136SVijay Kumar Srivastava 	return 0;
498b1196136SVijay Kumar Srivastava 
499cfeed08aSVijay Kumar Srivastava fail_filter_cfg:
500cfeed08aSVijay Kumar Srivastava 	/* remove already created filters */
501cfeed08aSVijay Kumar Srivastava 	sfc_vdpa_filter_remove(ops_data);
502b1196136SVijay Kumar Srivastava fail_vq_start:
503b1196136SVijay Kumar Srivastava 	/* stop already started virtqueues */
504b1196136SVijay Kumar Srivastava 	for (j = 0; j < i; j++)
505b1196136SVijay Kumar Srivastava 		sfc_vdpa_virtq_stop(ops_data, j);
506b1196136SVijay Kumar Srivastava 	sfc_vdpa_disable_vfio_intr(ops_data);
507b1196136SVijay Kumar Srivastava 
508b1196136SVijay Kumar Srivastava fail_enable_vfio_intr:
509b1196136SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_CONFIGURED;
510b1196136SVijay Kumar Srivastava 
511b1196136SVijay Kumar Srivastava 	return rc;
512b1196136SVijay Kumar Srivastava }
513b1196136SVijay Kumar Srivastava 
514b1196136SVijay Kumar Srivastava static int
sfc_vdpa_get_queue_num(struct rte_vdpa_device * vdpa_dev,uint32_t * queue_num)515b1196136SVijay Kumar Srivastava sfc_vdpa_get_queue_num(struct rte_vdpa_device *vdpa_dev, uint32_t *queue_num)
516b1196136SVijay Kumar Srivastava {
517b1196136SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
518b1196136SVijay Kumar Srivastava 	void *dev;
519b1196136SVijay Kumar Srivastava 
520b1196136SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
521b1196136SVijay Kumar Srivastava 	if (ops_data == NULL)
522b1196136SVijay Kumar Srivastava 		return -1;
523b1196136SVijay Kumar Srivastava 
524b1196136SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
525b1196136SVijay Kumar Srivastava 	*queue_num = sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count;
526b1196136SVijay Kumar Srivastava 
527b1196136SVijay Kumar Srivastava 	sfc_vdpa_info(dev, "vDPA ops get_queue_num :: supported queue num : %u",
528b1196136SVijay Kumar Srivastava 		      *queue_num);
529b1196136SVijay Kumar Srivastava 
530b1196136SVijay Kumar Srivastava 	return 0;
531b1196136SVijay Kumar Srivastava }
532b1196136SVijay Kumar Srivastava 
533f66a66e6SVijay Kumar Srivastava static int
sfc_vdpa_get_features(struct rte_vdpa_device * vdpa_dev,uint64_t * features)5346dad9a73SVijay Kumar Srivastava sfc_vdpa_get_features(struct rte_vdpa_device *vdpa_dev, uint64_t *features)
5356dad9a73SVijay Kumar Srivastava {
536f66a66e6SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
5376dad9a73SVijay Kumar Srivastava 
538f66a66e6SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
539f66a66e6SVijay Kumar Srivastava 	if (ops_data == NULL)
5406dad9a73SVijay Kumar Srivastava 		return -1;
541f66a66e6SVijay Kumar Srivastava 
542f66a66e6SVijay Kumar Srivastava 	*features = ops_data->drv_features;
543f66a66e6SVijay Kumar Srivastava 
544f66a66e6SVijay Kumar Srivastava 	sfc_vdpa_info(ops_data->dev_handle,
545f66a66e6SVijay Kumar Srivastava 		      "vDPA ops get_feature :: features : 0x%" PRIx64,
546f66a66e6SVijay Kumar Srivastava 		      *features);
547f66a66e6SVijay Kumar Srivastava 
548f66a66e6SVijay Kumar Srivastava 	return 0;
5496dad9a73SVijay Kumar Srivastava }
5506dad9a73SVijay Kumar Srivastava 
5516dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_get_protocol_features(struct rte_vdpa_device * vdpa_dev,uint64_t * features)5526dad9a73SVijay Kumar Srivastava sfc_vdpa_get_protocol_features(struct rte_vdpa_device *vdpa_dev,
5536dad9a73SVijay Kumar Srivastava 			       uint64_t *features)
5546dad9a73SVijay Kumar Srivastava {
555f66a66e6SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
5566dad9a73SVijay Kumar Srivastava 
557f66a66e6SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
558f66a66e6SVijay Kumar Srivastava 	if (ops_data == NULL)
5596dad9a73SVijay Kumar Srivastava 		return -1;
560f66a66e6SVijay Kumar Srivastava 
561f66a66e6SVijay Kumar Srivastava 	*features = SFC_VDPA_PROTOCOL_FEATURES;
562f66a66e6SVijay Kumar Srivastava 
563f66a66e6SVijay Kumar Srivastava 	sfc_vdpa_info(ops_data->dev_handle,
564f66a66e6SVijay Kumar Srivastava 		      "vDPA ops get_protocol_feature :: features : 0x%" PRIx64,
565f66a66e6SVijay Kumar Srivastava 		      *features);
566f66a66e6SVijay Kumar Srivastava 
567f66a66e6SVijay Kumar Srivastava 	return 0;
5686dad9a73SVijay Kumar Srivastava }
5696dad9a73SVijay Kumar Srivastava 
570*a7ba40b2SThomas Monjalon static uint32_t
sfc_vdpa_notify_ctrl(void * arg)571630be406SVijay Kumar Srivastava sfc_vdpa_notify_ctrl(void *arg)
572630be406SVijay Kumar Srivastava {
573630be406SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
574630be406SVijay Kumar Srivastava 	int vid;
575630be406SVijay Kumar Srivastava 
576630be406SVijay Kumar Srivastava 	ops_data = arg;
577630be406SVijay Kumar Srivastava 	if (ops_data == NULL)
578*a7ba40b2SThomas Monjalon 		return 0;
579630be406SVijay Kumar Srivastava 
580a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
581630be406SVijay Kumar Srivastava 
582630be406SVijay Kumar Srivastava 	vid = ops_data->vid;
583630be406SVijay Kumar Srivastava 
584630be406SVijay Kumar Srivastava 	if (rte_vhost_host_notifier_ctrl(vid, RTE_VHOST_QUEUE_ALL, true) != 0)
585630be406SVijay Kumar Srivastava 		sfc_vdpa_info(ops_data->dev_handle,
586630be406SVijay Kumar Srivastava 			      "vDPA (%s): Notifier could not get configured",
587630be406SVijay Kumar Srivastava 			      ops_data->vdpa_dev->device->name);
588630be406SVijay Kumar Srivastava 
589a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
590630be406SVijay Kumar Srivastava 
591*a7ba40b2SThomas Monjalon 	return 0;
592630be406SVijay Kumar Srivastava }
593630be406SVijay Kumar Srivastava 
594630be406SVijay Kumar Srivastava static int
sfc_vdpa_setup_notify_ctrl(struct sfc_vdpa_ops_data * ops_data)595630be406SVijay Kumar Srivastava sfc_vdpa_setup_notify_ctrl(struct sfc_vdpa_ops_data *ops_data)
596630be406SVijay Kumar Srivastava {
597630be406SVijay Kumar Srivastava 	int ret;
598630be406SVijay Kumar Srivastava 
599630be406SVijay Kumar Srivastava 	ops_data->is_notify_thread_started = false;
600630be406SVijay Kumar Srivastava 
601630be406SVijay Kumar Srivastava 	/*
602630be406SVijay Kumar Srivastava 	 * Use rte_vhost_host_notifier_ctrl in a thread to avoid
603630be406SVijay Kumar Srivastava 	 * dead lock scenario when multiple VFs are used in single vdpa
604630be406SVijay Kumar Srivastava 	 * application and multiple VFs are passed to a single VM.
605630be406SVijay Kumar Srivastava 	 */
606*a7ba40b2SThomas Monjalon 	ret = rte_thread_create_internal_control(&ops_data->notify_tid,
607*a7ba40b2SThomas Monjalon 			     "sfc-vdpa", sfc_vdpa_notify_ctrl, ops_data);
608630be406SVijay Kumar Srivastava 	if (ret != 0) {
609630be406SVijay Kumar Srivastava 		sfc_vdpa_err(ops_data->dev_handle,
610630be406SVijay Kumar Srivastava 			     "failed to create notify_ctrl thread: %s",
611630be406SVijay Kumar Srivastava 			     rte_strerror(ret));
612630be406SVijay Kumar Srivastava 		return -1;
613630be406SVijay Kumar Srivastava 	}
614630be406SVijay Kumar Srivastava 	ops_data->is_notify_thread_started = true;
615630be406SVijay Kumar Srivastava 
616630be406SVijay Kumar Srivastava 	return 0;
617630be406SVijay Kumar Srivastava }
618630be406SVijay Kumar Srivastava 
6196dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_dev_config(int vid)6206dad9a73SVijay Kumar Srivastava sfc_vdpa_dev_config(int vid)
6216dad9a73SVijay Kumar Srivastava {
622b1196136SVijay Kumar Srivastava 	struct rte_vdpa_device *vdpa_dev;
623b1196136SVijay Kumar Srivastava 	int rc;
624b1196136SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
625b1196136SVijay Kumar Srivastava 
626b1196136SVijay Kumar Srivastava 	vdpa_dev = rte_vhost_get_vdpa_device(vid);
627b1196136SVijay Kumar Srivastava 
628b1196136SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
629b1196136SVijay Kumar Srivastava 	if (ops_data == NULL) {
630d8875804SWeiguo Li 		SFC_VDPA_GENERIC_LOG(ERR,
631b1196136SVijay Kumar Srivastava 			     "invalid vDPA device : %p, vid : %d",
632b1196136SVijay Kumar Srivastava 			     vdpa_dev, vid);
633b1196136SVijay Kumar Srivastava 		return -1;
634b1196136SVijay Kumar Srivastava 	}
635b1196136SVijay Kumar Srivastava 
636b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "entry");
637b1196136SVijay Kumar Srivastava 
638b1196136SVijay Kumar Srivastava 	ops_data->vid = vid;
639b1196136SVijay Kumar Srivastava 
640a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
641b1196136SVijay Kumar Srivastava 
642b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "configuring");
643b1196136SVijay Kumar Srivastava 	rc = sfc_vdpa_configure(ops_data);
644b1196136SVijay Kumar Srivastava 	if (rc != 0)
645b1196136SVijay Kumar Srivastava 		goto fail_vdpa_config;
646b1196136SVijay Kumar Srivastava 
647b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "starting");
648b1196136SVijay Kumar Srivastava 	rc = sfc_vdpa_start(ops_data);
649b1196136SVijay Kumar Srivastava 	if (rc != 0)
650b1196136SVijay Kumar Srivastava 		goto fail_vdpa_start;
651b1196136SVijay Kumar Srivastava 
652630be406SVijay Kumar Srivastava 	rc = sfc_vdpa_setup_notify_ctrl(ops_data);
653630be406SVijay Kumar Srivastava 	if (rc != 0)
654630be406SVijay Kumar Srivastava 		goto fail_vdpa_notify;
655b1196136SVijay Kumar Srivastava 
656a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
657b1196136SVijay Kumar Srivastava 
658b1196136SVijay Kumar Srivastava 	sfc_vdpa_log_init(ops_data->dev_handle, "done");
659b1196136SVijay Kumar Srivastava 
660b1196136SVijay Kumar Srivastava 	return 0;
661b1196136SVijay Kumar Srivastava 
662630be406SVijay Kumar Srivastava fail_vdpa_notify:
663630be406SVijay Kumar Srivastava 	sfc_vdpa_stop(ops_data);
664630be406SVijay Kumar Srivastava 
665b1196136SVijay Kumar Srivastava fail_vdpa_start:
666b1196136SVijay Kumar Srivastava 	sfc_vdpa_close(ops_data);
667b1196136SVijay Kumar Srivastava 
668b1196136SVijay Kumar Srivastava fail_vdpa_config:
669a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
6706dad9a73SVijay Kumar Srivastava 
6716dad9a73SVijay Kumar Srivastava 	return -1;
6726dad9a73SVijay Kumar Srivastava }
6736dad9a73SVijay Kumar Srivastava 
6746dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_dev_close(int vid)6756dad9a73SVijay Kumar Srivastava sfc_vdpa_dev_close(int vid)
6766dad9a73SVijay Kumar Srivastava {
677630be406SVijay Kumar Srivastava 	int ret;
678b1196136SVijay Kumar Srivastava 	struct rte_vdpa_device *vdpa_dev;
679b1196136SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
6806dad9a73SVijay Kumar Srivastava 
681b1196136SVijay Kumar Srivastava 	vdpa_dev = rte_vhost_get_vdpa_device(vid);
682b1196136SVijay Kumar Srivastava 
683b1196136SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
684b1196136SVijay Kumar Srivastava 	if (ops_data == NULL) {
685d8875804SWeiguo Li 		SFC_VDPA_GENERIC_LOG(ERR,
686b1196136SVijay Kumar Srivastava 			     "invalid vDPA device : %p, vid : %d",
687b1196136SVijay Kumar Srivastava 			     vdpa_dev, vid);
6886dad9a73SVijay Kumar Srivastava 		return -1;
6896dad9a73SVijay Kumar Srivastava 	}
6906dad9a73SVijay Kumar Srivastava 
691a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
692630be406SVijay Kumar Srivastava 	if (ops_data->is_notify_thread_started == true) {
693*a7ba40b2SThomas Monjalon 		ret = pthread_cancel((pthread_t)ops_data->notify_tid.opaque_id);
694630be406SVijay Kumar Srivastava 		if (ret != 0) {
695630be406SVijay Kumar Srivastava 			sfc_vdpa_err(ops_data->dev_handle,
696630be406SVijay Kumar Srivastava 				     "failed to cancel notify_ctrl thread: %s",
697630be406SVijay Kumar Srivastava 				     rte_strerror(ret));
698630be406SVijay Kumar Srivastava 		}
699630be406SVijay Kumar Srivastava 
700*a7ba40b2SThomas Monjalon 		ret = rte_thread_join(ops_data->notify_tid, NULL);
701630be406SVijay Kumar Srivastava 		if (ret != 0) {
702630be406SVijay Kumar Srivastava 			sfc_vdpa_err(ops_data->dev_handle,
703630be406SVijay Kumar Srivastava 				     "failed to join terminated notify_ctrl thread: %s",
704630be406SVijay Kumar Srivastava 				     rte_strerror(ret));
705630be406SVijay Kumar Srivastava 		}
706630be406SVijay Kumar Srivastava 	}
707630be406SVijay Kumar Srivastava 	ops_data->is_notify_thread_started = false;
708b1196136SVijay Kumar Srivastava 
709b1196136SVijay Kumar Srivastava 	sfc_vdpa_stop(ops_data);
710b1196136SVijay Kumar Srivastava 	sfc_vdpa_close(ops_data);
711b1196136SVijay Kumar Srivastava 
712a3f35d4aSDavid Marchand 	sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
713b1196136SVijay Kumar Srivastava 
714b1196136SVijay Kumar Srivastava 	return 0;
715b1196136SVijay Kumar Srivastava }
716b1196136SVijay Kumar Srivastava 
7176dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_set_vring_state(int vid,int vring,int state)7186dad9a73SVijay Kumar Srivastava sfc_vdpa_set_vring_state(int vid, int vring, int state)
7196dad9a73SVijay Kumar Srivastava {
720b3fc3504SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
721b3fc3504SVijay Kumar Srivastava 	struct rte_vdpa_device *vdpa_dev;
722b3fc3504SVijay Kumar Srivastava 	efx_rc_t rc;
723b3fc3504SVijay Kumar Srivastava 	int vring_max;
724b3fc3504SVijay Kumar Srivastava 	void *dev;
7256dad9a73SVijay Kumar Srivastava 
726b3fc3504SVijay Kumar Srivastava 	vdpa_dev = rte_vhost_get_vdpa_device(vid);
727b3fc3504SVijay Kumar Srivastava 
728b3fc3504SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
729b3fc3504SVijay Kumar Srivastava 	if (ops_data == NULL)
7306dad9a73SVijay Kumar Srivastava 		return -1;
731b3fc3504SVijay Kumar Srivastava 
732b3fc3504SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
733b3fc3504SVijay Kumar Srivastava 
734b3fc3504SVijay Kumar Srivastava 	sfc_vdpa_info(dev,
735b3fc3504SVijay Kumar Srivastava 		      "vDPA ops set_vring_state: vid: %d, vring: %d, state:%d",
736b3fc3504SVijay Kumar Srivastava 		      vid, vring, state);
737b3fc3504SVijay Kumar Srivastava 
738b3fc3504SVijay Kumar Srivastava 	vring_max = (sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
739b3fc3504SVijay Kumar Srivastava 
740b3fc3504SVijay Kumar Srivastava 	if (vring < 0 || vring > vring_max) {
741b3fc3504SVijay Kumar Srivastava 		sfc_vdpa_err(dev, "received invalid vring id : %d to set state",
742b3fc3504SVijay Kumar Srivastava 			     vring);
743b3fc3504SVijay Kumar Srivastava 		return -1;
744b3fc3504SVijay Kumar Srivastava 	}
745b3fc3504SVijay Kumar Srivastava 
746b3fc3504SVijay Kumar Srivastava 	/*
747b3fc3504SVijay Kumar Srivastava 	 * Skip if device is not yet started. virtqueues state can be
748b3fc3504SVijay Kumar Srivastava 	 * changed once it is created and other configurations are done.
749b3fc3504SVijay Kumar Srivastava 	 */
750b3fc3504SVijay Kumar Srivastava 	if (ops_data->state != SFC_VDPA_STATE_STARTED)
751b3fc3504SVijay Kumar Srivastava 		return 0;
752b3fc3504SVijay Kumar Srivastava 
753b3fc3504SVijay Kumar Srivastava 	if (ops_data->vq_cxt[vring].enable == state)
754b3fc3504SVijay Kumar Srivastava 		return 0;
755b3fc3504SVijay Kumar Srivastava 
756b3fc3504SVijay Kumar Srivastava 	if (state == 0) {
757b3fc3504SVijay Kumar Srivastava 		rc = sfc_vdpa_virtq_stop(ops_data, vring);
758b3fc3504SVijay Kumar Srivastava 		if (rc != 0) {
759b3fc3504SVijay Kumar Srivastava 			sfc_vdpa_err(dev, "virtqueue stop failed: %s",
760b3fc3504SVijay Kumar Srivastava 				     rte_strerror(rc));
761b3fc3504SVijay Kumar Srivastava 		}
762b3fc3504SVijay Kumar Srivastava 	} else {
763b3fc3504SVijay Kumar Srivastava 		rc = sfc_vdpa_virtq_start(ops_data, vring);
764b3fc3504SVijay Kumar Srivastava 		if (rc != 0) {
765b3fc3504SVijay Kumar Srivastava 			sfc_vdpa_err(dev, "virtqueue start failed: %s",
766b3fc3504SVijay Kumar Srivastava 				     rte_strerror(rc));
767b3fc3504SVijay Kumar Srivastava 		}
768b3fc3504SVijay Kumar Srivastava 	}
769b3fc3504SVijay Kumar Srivastava 
770b3fc3504SVijay Kumar Srivastava 	return rc;
7716dad9a73SVijay Kumar Srivastava }
7726dad9a73SVijay Kumar Srivastava 
7736dad9a73SVijay Kumar Srivastava static int
sfc_vdpa_set_features(int vid)7746dad9a73SVijay Kumar Srivastava sfc_vdpa_set_features(int vid)
7756dad9a73SVijay Kumar Srivastava {
7766dad9a73SVijay Kumar Srivastava 	RTE_SET_USED(vid);
7776dad9a73SVijay Kumar Srivastava 
7786dad9a73SVijay Kumar Srivastava 	return -1;
7796dad9a73SVijay Kumar Srivastava }
7806dad9a73SVijay Kumar Srivastava 
781340c4bd0SVijay Kumar Srivastava static int
sfc_vdpa_get_vfio_device_fd(int vid)782340c4bd0SVijay Kumar Srivastava sfc_vdpa_get_vfio_device_fd(int vid)
783340c4bd0SVijay Kumar Srivastava {
784340c4bd0SVijay Kumar Srivastava 	struct rte_vdpa_device *vdpa_dev;
785340c4bd0SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
786340c4bd0SVijay Kumar Srivastava 	int vfio_dev_fd;
787340c4bd0SVijay Kumar Srivastava 	void *dev;
788340c4bd0SVijay Kumar Srivastava 
789340c4bd0SVijay Kumar Srivastava 	vdpa_dev = rte_vhost_get_vdpa_device(vid);
790340c4bd0SVijay Kumar Srivastava 
791340c4bd0SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
792340c4bd0SVijay Kumar Srivastava 	if (ops_data == NULL)
793340c4bd0SVijay Kumar Srivastava 		return -1;
794340c4bd0SVijay Kumar Srivastava 
795340c4bd0SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
796340c4bd0SVijay Kumar Srivastava 	vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
797340c4bd0SVijay Kumar Srivastava 
798340c4bd0SVijay Kumar Srivastava 	sfc_vdpa_info(dev, "vDPA ops get_vfio_device_fd :: vfio fd : %d",
799340c4bd0SVijay Kumar Srivastava 		      vfio_dev_fd);
800340c4bd0SVijay Kumar Srivastava 
801340c4bd0SVijay Kumar Srivastava 	return vfio_dev_fd;
802340c4bd0SVijay Kumar Srivastava }
803340c4bd0SVijay Kumar Srivastava 
804630be406SVijay Kumar Srivastava static int
sfc_vdpa_get_notify_area(int vid,int qid,uint64_t * offset,uint64_t * size)805630be406SVijay Kumar Srivastava sfc_vdpa_get_notify_area(int vid, int qid, uint64_t *offset, uint64_t *size)
806630be406SVijay Kumar Srivastava {
807630be406SVijay Kumar Srivastava 	int ret;
808630be406SVijay Kumar Srivastava 	efx_nic_t *nic;
809630be406SVijay Kumar Srivastava 	int vfio_dev_fd;
8102eb13ddeSAbhimanyu Saini 	volatile void *doorbell;
8112eb13ddeSAbhimanyu Saini 	struct rte_pci_device *pci_dev;
812630be406SVijay Kumar Srivastava 	struct rte_vdpa_device *vdpa_dev;
813630be406SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
814630be406SVijay Kumar Srivastava 	struct vfio_region_info reg = { .argsz = sizeof(reg) };
815630be406SVijay Kumar Srivastava 	const efx_nic_cfg_t *encp;
816630be406SVijay Kumar Srivastava 	int max_vring_cnt;
817630be406SVijay Kumar Srivastava 	int64_t len;
818630be406SVijay Kumar Srivastava 	void *dev;
819630be406SVijay Kumar Srivastava 
820630be406SVijay Kumar Srivastava 	vdpa_dev = rte_vhost_get_vdpa_device(vid);
821630be406SVijay Kumar Srivastava 
822630be406SVijay Kumar Srivastava 	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
823630be406SVijay Kumar Srivastava 	if (ops_data == NULL)
824630be406SVijay Kumar Srivastava 		return -1;
825630be406SVijay Kumar Srivastava 
826630be406SVijay Kumar Srivastava 	dev = ops_data->dev_handle;
827630be406SVijay Kumar Srivastava 
828630be406SVijay Kumar Srivastava 	vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
829630be406SVijay Kumar Srivastava 	max_vring_cnt =
830630be406SVijay Kumar Srivastava 		(sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
831630be406SVijay Kumar Srivastava 
832630be406SVijay Kumar Srivastava 	nic = sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle)->nic;
833630be406SVijay Kumar Srivastava 	encp = efx_nic_cfg_get(nic);
834630be406SVijay Kumar Srivastava 
835630be406SVijay Kumar Srivastava 	if (qid >= max_vring_cnt) {
836630be406SVijay Kumar Srivastava 		sfc_vdpa_err(dev, "invalid qid : %d", qid);
837630be406SVijay Kumar Srivastava 		return -1;
838630be406SVijay Kumar Srivastava 	}
839630be406SVijay Kumar Srivastava 
840630be406SVijay Kumar Srivastava 	reg.index = sfc_vdpa_adapter_by_dev_handle(dev)->mem_bar.esb_rid;
841630be406SVijay Kumar Srivastava 	ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg);
842630be406SVijay Kumar Srivastava 	if (ret != 0) {
843630be406SVijay Kumar Srivastava 		sfc_vdpa_err(dev, "could not get device region info: %s",
844630be406SVijay Kumar Srivastava 			     strerror(errno));
845630be406SVijay Kumar Srivastava 		return ret;
846630be406SVijay Kumar Srivastava 	}
847630be406SVijay Kumar Srivastava 
848d9a1ef20SAbhimanyu Saini 	/* Use bar_offset that was cached during sfc_vdpa_virtq_start() */
849d9a1ef20SAbhimanyu Saini 	*offset = reg.offset + (uint64_t)ops_data->vq_cxt[qid].doorbell;
850630be406SVijay Kumar Srivastava 
851630be406SVijay Kumar Srivastava 	len = (1U << encp->enc_vi_window_shift) / 2;
852630be406SVijay Kumar Srivastava 	if (len >= sysconf(_SC_PAGESIZE)) {
853630be406SVijay Kumar Srivastava 		*size = sysconf(_SC_PAGESIZE);
854630be406SVijay Kumar Srivastava 	} else {
855630be406SVijay Kumar Srivastava 		sfc_vdpa_err(dev, "invalid VI window size : 0x%" PRIx64, len);
856630be406SVijay Kumar Srivastava 		return -1;
857630be406SVijay Kumar Srivastava 	}
858630be406SVijay Kumar Srivastava 
859630be406SVijay Kumar Srivastava 	sfc_vdpa_info(dev, "vDPA ops get_notify_area :: offset : 0x%" PRIx64,
860630be406SVijay Kumar Srivastava 		      *offset);
861630be406SVijay Kumar Srivastava 
8622eb13ddeSAbhimanyu Saini 	pci_dev = sfc_vdpa_adapter_by_dev_handle(dev)->pdev;
8632eb13ddeSAbhimanyu Saini 	doorbell = (uint8_t *)pci_dev->mem_resource[reg.index].addr + *offset;
8642eb13ddeSAbhimanyu Saini 
8652eb13ddeSAbhimanyu Saini 	/*
8662eb13ddeSAbhimanyu Saini 	 * virtio-net driver in VM sends queue notifications before
8672eb13ddeSAbhimanyu Saini 	 * vDPA has a chance to setup the queues and notification area,
8682eb13ddeSAbhimanyu Saini 	 * and hence the HW misses these doorbell notifications.
8692eb13ddeSAbhimanyu Saini 	 * Since, it is safe to send duplicate doorbell, send another
8702eb13ddeSAbhimanyu Saini 	 * doorbell from vDPA driver as workaround for this timing issue.
8712eb13ddeSAbhimanyu Saini 	 */
8722eb13ddeSAbhimanyu Saini 	rte_write16(qid, doorbell);
8732eb13ddeSAbhimanyu Saini 
874630be406SVijay Kumar Srivastava 	return 0;
875630be406SVijay Kumar Srivastava }
876630be406SVijay Kumar Srivastava 
8776dad9a73SVijay Kumar Srivastava static struct rte_vdpa_dev_ops sfc_vdpa_ops = {
8786dad9a73SVijay Kumar Srivastava 	.get_queue_num = sfc_vdpa_get_queue_num,
8796dad9a73SVijay Kumar Srivastava 	.get_features = sfc_vdpa_get_features,
8806dad9a73SVijay Kumar Srivastava 	.get_protocol_features = sfc_vdpa_get_protocol_features,
8816dad9a73SVijay Kumar Srivastava 	.dev_conf = sfc_vdpa_dev_config,
8826dad9a73SVijay Kumar Srivastava 	.dev_close = sfc_vdpa_dev_close,
8836dad9a73SVijay Kumar Srivastava 	.set_vring_state = sfc_vdpa_set_vring_state,
8846dad9a73SVijay Kumar Srivastava 	.set_features = sfc_vdpa_set_features,
885340c4bd0SVijay Kumar Srivastava 	.get_vfio_device_fd = sfc_vdpa_get_vfio_device_fd,
886630be406SVijay Kumar Srivastava 	.get_notify_area = sfc_vdpa_get_notify_area,
8876dad9a73SVijay Kumar Srivastava };
8886dad9a73SVijay Kumar Srivastava 
8896dad9a73SVijay Kumar Srivastava struct sfc_vdpa_ops_data *
sfc_vdpa_device_init(void * dev_handle,enum sfc_vdpa_context context)8906dad9a73SVijay Kumar Srivastava sfc_vdpa_device_init(void *dev_handle, enum sfc_vdpa_context context)
8916dad9a73SVijay Kumar Srivastava {
8926dad9a73SVijay Kumar Srivastava 	struct sfc_vdpa_ops_data *ops_data;
8936dad9a73SVijay Kumar Srivastava 	struct rte_pci_device *pci_dev;
894f66a66e6SVijay Kumar Srivastava 	int rc;
8956dad9a73SVijay Kumar Srivastava 
8966dad9a73SVijay Kumar Srivastava 	/* Create vDPA ops context */
8976dad9a73SVijay Kumar Srivastava 	ops_data = rte_zmalloc("vdpa", sizeof(struct sfc_vdpa_ops_data), 0);
8986dad9a73SVijay Kumar Srivastava 	if (ops_data == NULL)
8996dad9a73SVijay Kumar Srivastava 		return NULL;
9006dad9a73SVijay Kumar Srivastava 
9016dad9a73SVijay Kumar Srivastava 	ops_data->vdpa_context = context;
9026dad9a73SVijay Kumar Srivastava 	ops_data->dev_handle = dev_handle;
9036dad9a73SVijay Kumar Srivastava 
9046dad9a73SVijay Kumar Srivastava 	pci_dev = sfc_vdpa_adapter_by_dev_handle(dev_handle)->pdev;
9056dad9a73SVijay Kumar Srivastava 
9066dad9a73SVijay Kumar Srivastava 	/* Register vDPA Device */
9076dad9a73SVijay Kumar Srivastava 	sfc_vdpa_log_init(dev_handle, "register vDPA device");
9086dad9a73SVijay Kumar Srivastava 	ops_data->vdpa_dev =
9096dad9a73SVijay Kumar Srivastava 		rte_vdpa_register_device(&pci_dev->device, &sfc_vdpa_ops);
9106dad9a73SVijay Kumar Srivastava 	if (ops_data->vdpa_dev == NULL) {
9116dad9a73SVijay Kumar Srivastava 		sfc_vdpa_err(dev_handle, "vDPA device registration failed");
9126dad9a73SVijay Kumar Srivastava 		goto fail_register_device;
9136dad9a73SVijay Kumar Srivastava 	}
9146dad9a73SVijay Kumar Srivastava 
915f66a66e6SVijay Kumar Srivastava 	/* Read supported device features */
916f66a66e6SVijay Kumar Srivastava 	sfc_vdpa_log_init(dev_handle, "get device feature");
917f66a66e6SVijay Kumar Srivastava 	rc = sfc_vdpa_get_device_features(ops_data);
918f66a66e6SVijay Kumar Srivastava 	if (rc != 0)
919f66a66e6SVijay Kumar Srivastava 		goto fail_get_dev_feature;
920f66a66e6SVijay Kumar Srivastava 
921f66a66e6SVijay Kumar Srivastava 	/* Driver features are superset of device supported feature
922f66a66e6SVijay Kumar Srivastava 	 * and any additional features supported by the driver.
923f66a66e6SVijay Kumar Srivastava 	 */
924f66a66e6SVijay Kumar Srivastava 	ops_data->drv_features =
925f66a66e6SVijay Kumar Srivastava 		ops_data->dev_features | SFC_VDPA_DEFAULT_FEATURES;
926f66a66e6SVijay Kumar Srivastava 
9276dad9a73SVijay Kumar Srivastava 	ops_data->state = SFC_VDPA_STATE_INITIALIZED;
9286dad9a73SVijay Kumar Srivastava 
9296dad9a73SVijay Kumar Srivastava 	return ops_data;
9306dad9a73SVijay Kumar Srivastava 
931f66a66e6SVijay Kumar Srivastava fail_get_dev_feature:
932f66a66e6SVijay Kumar Srivastava 	rte_vdpa_unregister_device(ops_data->vdpa_dev);
933f66a66e6SVijay Kumar Srivastava 
9346dad9a73SVijay Kumar Srivastava fail_register_device:
9356dad9a73SVijay Kumar Srivastava 	rte_free(ops_data);
9366dad9a73SVijay Kumar Srivastava 	return NULL;
9376dad9a73SVijay Kumar Srivastava }
9386dad9a73SVijay Kumar Srivastava 
9396dad9a73SVijay Kumar Srivastava void
sfc_vdpa_device_fini(struct sfc_vdpa_ops_data * ops_data)9406dad9a73SVijay Kumar Srivastava sfc_vdpa_device_fini(struct sfc_vdpa_ops_data *ops_data)
9416dad9a73SVijay Kumar Srivastava {
9426dad9a73SVijay Kumar Srivastava 	rte_vdpa_unregister_device(ops_data->vdpa_dev);
9436dad9a73SVijay Kumar Srivastava 
9446dad9a73SVijay Kumar Srivastava 	rte_free(ops_data);
9456dad9a73SVijay Kumar Srivastava }
946