xref: /dpdk/drivers/common/sfc_efx/base/efx_virtio.c (revision b8a896ab97904ec1c3548d93561b488e62cd99be)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2020-2021 Xilinx, Inc.
4  */
5 
6 #include "efx.h"
7 #include "efx_impl.h"
8 
9 #if EFSYS_OPT_VIRTIO
10 
11 #if EFSYS_OPT_RIVERHEAD
12 static const efx_virtio_ops_t	__efx_virtio_rhead_ops = {
13 	rhead_virtio_qstart,			/* evo_virtio_qstart */
14 	rhead_virtio_qstop,			/* evo_virtio_qstop */
15 	rhead_virtio_get_doorbell_offset,	/* evo_get_doorbell_offset */
16 	rhead_virtio_get_features,		/* evo_get_features */
17 	rhead_virtio_verify_features,		/* evo_verify_features */
18 };
19 #endif /* EFSYS_OPT_RIVERHEAD */
20 
21 	__checkReturn	efx_rc_t
efx_virtio_init(__in efx_nic_t * enp)22 efx_virtio_init(
23 	__in		efx_nic_t *enp)
24 {
25 	const efx_virtio_ops_t *evop;
26 	efx_rc_t rc;
27 
28 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
29 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
30 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VIRTIO));
31 
32 	switch (enp->en_family) {
33 #if EFSYS_OPT_RIVERHEAD
34 	case EFX_FAMILY_RIVERHEAD:
35 		evop = &__efx_virtio_rhead_ops;
36 		break;
37 #endif /* EFSYS_OPT_RIVERHEAD */
38 
39 	default:
40 		EFSYS_ASSERT(0);
41 		rc = ENOTSUP;
42 		goto fail1;
43 	}
44 
45 	enp->en_evop = evop;
46 	enp->en_mod_flags |= EFX_MOD_VIRTIO;
47 
48 	return (0);
49 
50 fail1:
51 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
52 
53 	enp->en_evop = NULL;
54 	enp->en_mod_flags &= ~EFX_MOD_VIRTIO;
55 
56 	return (rc);
57 }
58 
59 	void
efx_virtio_fini(__in efx_nic_t * enp)60 efx_virtio_fini(
61 	__in		efx_nic_t *enp)
62 {
63 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
64 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
65 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
66 
67 	enp->en_evop = NULL;
68 	enp->en_mod_flags &= ~EFX_MOD_VIRTIO;
69 }
70 
71 	__checkReturn   efx_rc_t
efx_virtio_qcreate(__in efx_nic_t * enp,__deref_out efx_virtio_vq_t ** evvpp)72 efx_virtio_qcreate(
73 	__in		efx_nic_t *enp,
74 	__deref_out	efx_virtio_vq_t **evvpp)
75 {
76 	const efx_virtio_ops_t *evop = enp->en_evop;
77 	efx_virtio_vq_t *evvp;
78 	efx_rc_t rc;
79 
80 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
81 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
82 
83 	/* Allocate a virtqueue object */
84 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
85 	if (evvp == NULL) {
86 		rc = ENOMEM;
87 		goto fail1;
88 	}
89 
90 	evvp->evv_magic = EFX_VQ_MAGIC;
91 	evvp->evv_enp = enp;
92 	evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
93 
94 	*evvpp = evvp;
95 
96 	return (0);
97 
98 fail1:
99 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
100 
101 	return (rc);
102 }
103 
104 	__checkReturn   efx_rc_t
efx_virtio_qstart(__in efx_virtio_vq_t * evvp,__in efx_virtio_vq_cfg_t * evvcp,__in_opt efx_virtio_vq_dyncfg_t * evvdp)105 efx_virtio_qstart(
106 	__in		efx_virtio_vq_t *evvp,
107 	__in		efx_virtio_vq_cfg_t *evvcp,
108 	__in_opt	efx_virtio_vq_dyncfg_t *evvdp)
109 {
110 	const efx_virtio_ops_t *evop;
111 	efx_rc_t rc;
112 
113 	if ((evvcp == NULL) || (evvp == NULL)) {
114 		rc = EINVAL;
115 		goto fail1;
116 	}
117 
118 	if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_INITIALIZED) {
119 		rc = EINVAL;
120 		goto fail2;
121 	}
122 
123 	evop = evvp->evv_enp->en_evop;
124 	if (evop == NULL) {
125 		rc = ENOTSUP;
126 		goto fail3;
127 	}
128 
129 	if ((rc = evop->evo_virtio_qstart(evvp, evvcp, evvdp)) != 0)
130 		goto fail4;
131 
132 	evvp->evv_type = evvcp->evvc_type;
133 	evvp->evv_target_vf = evvcp->evvc_target_vf;
134 	evvp->evv_state = EFX_VIRTIO_VQ_STATE_STARTED;
135 
136 	return (0);
137 
138 fail4:
139 	EFSYS_PROBE(fail4);
140 fail3:
141 	EFSYS_PROBE(fail3);
142 fail2:
143 	EFSYS_PROBE(fail2);
144 fail1:
145 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
146 
147 	return (rc);
148 }
149 
150 	__checkReturn   efx_rc_t
efx_virtio_qstop(__in efx_virtio_vq_t * evvp,__out_opt efx_virtio_vq_dyncfg_t * evvdp)151 efx_virtio_qstop(
152 	__in		efx_virtio_vq_t *evvp,
153 	__out_opt	efx_virtio_vq_dyncfg_t *evvdp)
154 {
155 	efx_nic_t *enp;
156 	const efx_virtio_ops_t *evop;
157 	efx_rc_t rc;
158 
159 	if (evvp == NULL) {
160 		rc = EINVAL;
161 		goto fail1;
162 	}
163 
164 	enp = evvp->evv_enp;
165 	evop = enp->en_evop;
166 
167 	EFSYS_ASSERT3U(evvp->evv_magic, ==, EFX_VQ_MAGIC);
168 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
169 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
170 
171 	if (evop == NULL) {
172 		rc = ENOTSUP;
173 		goto fail2;
174 	}
175 
176 	if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_STARTED) {
177 		rc = EINVAL;
178 		goto fail3;
179 	}
180 
181 	if ((rc = evop->evo_virtio_qstop(evvp, evvdp)) != 0)
182 		goto fail4;
183 
184 	evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
185 
186 	return 0;
187 
188 fail4:
189 	EFSYS_PROBE(fail4);
190 fail3:
191 	EFSYS_PROBE(fail3);
192 fail2:
193 	EFSYS_PROBE(fail2);
194 fail1:
195 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
196 
197 	return (rc);
198 }
199 
200 	void
efx_virtio_qdestroy(__in efx_virtio_vq_t * evvp)201 efx_virtio_qdestroy(
202 	__in		efx_virtio_vq_t *evvp)
203 {
204 	efx_nic_t *enp;
205 
206 	if (evvp == NULL)
207 		return;
208 
209 	enp = evvp->evv_enp;
210 
211 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
212 
213 	if (evvp->evv_state == EFX_VIRTIO_VQ_STATE_INITIALIZED) {
214 		/* Free the virtqueue object */
215 		EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
216 	}
217 }
218 
219 	__checkReturn	efx_rc_t
efx_virtio_get_doorbell_offset(__in efx_virtio_vq_t * evvp,__out uint32_t * offsetp)220 efx_virtio_get_doorbell_offset(
221 	__in		efx_virtio_vq_t *evvp,
222 	__out		uint32_t *offsetp)
223 {
224 	efx_nic_t *enp;
225 	const efx_virtio_ops_t *evop;
226 	efx_rc_t rc;
227 
228 	if ((evvp == NULL) || (offsetp == NULL)) {
229 		rc = EINVAL;
230 		goto fail1;
231 	}
232 
233 	enp = evvp->evv_enp;
234 	evop = enp->en_evop;
235 
236 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
237 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
238 
239 	if (evop == NULL) {
240 		rc = ENOTSUP;
241 		goto fail2;
242 	}
243 
244 	if ((rc = evop->evo_get_doorbell_offset(evvp, offsetp)) != 0)
245 		goto fail3;
246 
247 	return (0);
248 
249 fail3:
250 	EFSYS_PROBE(fail3);
251 fail2:
252 	EFSYS_PROBE(fail2);
253 fail1:
254 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
255 
256 	return (rc);
257 }
258 
259 	__checkReturn	efx_rc_t
efx_virtio_get_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__out uint64_t * featuresp)260 efx_virtio_get_features(
261 	__in		efx_nic_t *enp,
262 	__in		efx_virtio_device_type_t type,
263 	__out		uint64_t *featuresp)
264 {
265 	const efx_virtio_ops_t *evop = enp->en_evop;
266 	efx_rc_t rc;
267 
268 	if (featuresp == NULL) {
269 		rc = EINVAL;
270 		goto fail1;
271 	}
272 
273 	if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
274 		rc = EINVAL;
275 		goto fail2;
276 	}
277 
278 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
279 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
280 
281 	if (evop == NULL) {
282 		rc = ENOTSUP;
283 		goto fail3;
284 	}
285 
286 	if ((rc = evop->evo_get_features(enp, type, featuresp)) != 0)
287 		goto fail4;
288 
289 	return (0);
290 
291 fail4:
292 	EFSYS_PROBE(fail4);
293 fail3:
294 	EFSYS_PROBE(fail3);
295 fail2:
296 	EFSYS_PROBE(fail2);
297 fail1:
298 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
299 
300 	return (rc);
301 }
302 
303 	__checkReturn	efx_rc_t
efx_virtio_verify_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__in uint64_t features)304 efx_virtio_verify_features(
305 	__in		efx_nic_t *enp,
306 	__in		efx_virtio_device_type_t type,
307 	__in		uint64_t features)
308 {
309 	const efx_virtio_ops_t *evop = enp->en_evop;
310 	efx_rc_t rc;
311 
312 	if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
313 		rc = EINVAL;
314 		goto fail1;
315 	}
316 
317 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
318 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
319 
320 	if (evop == NULL) {
321 		rc = ENOTSUP;
322 		goto fail2;
323 	}
324 
325 	if ((rc = evop->evo_verify_features(enp, type, features)) != 0)
326 		goto fail3;
327 
328 	return (0);
329 
330 fail3:
331 	EFSYS_PROBE(fail3);
332 fail2:
333 	EFSYS_PROBE(fail2);
334 fail1:
335 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
336 
337 	return (rc);
338 }
339 
340 #endif /* EFSYS_OPT_VIRTIO */
341