Branch data Line data Source code
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
22 : 0 : efx_virtio_init(
23 : : __in efx_nic_t *enp)
24 : : {
25 : : const efx_virtio_ops_t *evop;
26 : : efx_rc_t rc;
27 : :
28 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
29 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
30 [ # # ]: 0 : EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VIRTIO));
31 : :
32 [ # # ]: 0 : switch (enp->en_family) {
33 : : #if EFSYS_OPT_RIVERHEAD
34 : 0 : case EFX_FAMILY_RIVERHEAD:
35 : : evop = &__efx_virtio_rhead_ops;
36 : : break;
37 : : #endif /* EFSYS_OPT_RIVERHEAD */
38 : :
39 : : default:
40 : 0 : EFSYS_ASSERT(0);
41 : : rc = ENOTSUP;
42 : : goto fail1;
43 : : }
44 : :
45 : 0 : enp->en_evop = evop;
46 : 0 : 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
60 : 0 : efx_virtio_fini(
61 : : __in efx_nic_t *enp)
62 : : {
63 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
64 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
65 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
66 : :
67 : 0 : enp->en_evop = NULL;
68 : 0 : enp->en_mod_flags &= ~EFX_MOD_VIRTIO;
69 : 0 : }
70 : :
71 : : __checkReturn efx_rc_t
72 : 0 : 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 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
81 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
82 : :
83 : : /* Allocate a virtqueue object */
84 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
85 [ # # ]: 0 : if (evvp == NULL) {
86 : : rc = ENOMEM;
87 : 0 : goto fail1;
88 : : }
89 : :
90 : 0 : evvp->evv_magic = EFX_VQ_MAGIC;
91 : 0 : evvp->evv_enp = enp;
92 : 0 : evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
93 : :
94 : 0 : *evvpp = evvp;
95 : :
96 : 0 : return (0);
97 : :
98 : : fail1:
99 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
100 : :
101 : 0 : return (rc);
102 : : }
103 : :
104 : : __checkReturn efx_rc_t
105 : 0 : 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 [ # # ]: 0 : if ((evvcp == NULL) || (evvp == NULL)) {
114 : : rc = EINVAL;
115 : 0 : goto fail1;
116 : : }
117 : :
118 [ # # ]: 0 : if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_INITIALIZED) {
119 : : rc = EINVAL;
120 : 0 : goto fail2;
121 : : }
122 : :
123 : 0 : evop = evvp->evv_enp->en_evop;
124 [ # # ]: 0 : if (evop == NULL) {
125 : : rc = ENOTSUP;
126 : 0 : goto fail3;
127 : : }
128 : :
129 [ # # ]: 0 : if ((rc = evop->evo_virtio_qstart(evvp, evvcp, evvdp)) != 0)
130 : 0 : goto fail4;
131 : :
132 : 0 : evvp->evv_type = evvcp->evvc_type;
133 : 0 : evvp->evv_target_vf = evvcp->evvc_target_vf;
134 : 0 : evvp->evv_state = EFX_VIRTIO_VQ_STATE_STARTED;
135 : :
136 : 0 : 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
151 : 0 : 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 [ # # ]: 0 : if (evvp == NULL) {
160 : : rc = EINVAL;
161 : 0 : goto fail1;
162 : : }
163 : :
164 : 0 : enp = evvp->evv_enp;
165 : 0 : evop = enp->en_evop;
166 : :
167 [ # # ]: 0 : EFSYS_ASSERT3U(evvp->evv_magic, ==, EFX_VQ_MAGIC);
168 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
169 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
170 : :
171 [ # # ]: 0 : if (evop == NULL) {
172 : : rc = ENOTSUP;
173 : 0 : goto fail2;
174 : : }
175 : :
176 [ # # ]: 0 : if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_STARTED) {
177 : : rc = EINVAL;
178 : 0 : goto fail3;
179 : : }
180 : :
181 [ # # ]: 0 : if ((rc = evop->evo_virtio_qstop(evvp, evvdp)) != 0)
182 : 0 : goto fail4;
183 : :
184 : 0 : evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
185 : :
186 : 0 : 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
201 : 0 : efx_virtio_qdestroy(
202 : : __in efx_virtio_vq_t *evvp)
203 : : {
204 : : efx_nic_t *enp;
205 : :
206 [ # # ]: 0 : if (evvp == NULL)
207 : : return;
208 : :
209 : 0 : enp = evvp->evv_enp;
210 : :
211 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
212 : :
213 [ # # ]: 0 : if (evvp->evv_state == EFX_VIRTIO_VQ_STATE_INITIALIZED) {
214 : : /* Free the virtqueue object */
215 : 0 : EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
216 : : }
217 : : }
218 : :
219 : : __checkReturn efx_rc_t
220 : 0 : 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 [ # # ]: 0 : if ((evvp == NULL) || (offsetp == NULL)) {
229 : : rc = EINVAL;
230 : 0 : goto fail1;
231 : : }
232 : :
233 : 0 : enp = evvp->evv_enp;
234 : 0 : evop = enp->en_evop;
235 : :
236 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
237 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
238 : :
239 [ # # ]: 0 : if (evop == NULL) {
240 : : rc = ENOTSUP;
241 : 0 : goto fail2;
242 : : }
243 : :
244 [ # # ]: 0 : if ((rc = evop->evo_get_doorbell_offset(evvp, offsetp)) != 0)
245 : 0 : 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
260 : 0 : 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 : 0 : const efx_virtio_ops_t *evop = enp->en_evop;
266 : : efx_rc_t rc;
267 : :
268 [ # # ]: 0 : if (featuresp == NULL) {
269 : : rc = EINVAL;
270 : 0 : goto fail1;
271 : : }
272 : :
273 [ # # ]: 0 : if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
274 : : rc = EINVAL;
275 : 0 : goto fail2;
276 : : }
277 : :
278 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
279 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
280 : :
281 [ # # ]: 0 : if (evop == NULL) {
282 : : rc = ENOTSUP;
283 : 0 : goto fail3;
284 : : }
285 : :
286 [ # # ]: 0 : if ((rc = evop->evo_get_features(enp, type, featuresp)) != 0)
287 : 0 : 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
304 : 0 : 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 : 0 : const efx_virtio_ops_t *evop = enp->en_evop;
310 : : efx_rc_t rc;
311 : :
312 [ # # ]: 0 : if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
313 : : rc = EINVAL;
314 : 0 : goto fail1;
315 : : }
316 : :
317 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
318 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
319 : :
320 [ # # ]: 0 : if (evop == NULL) {
321 : : rc = ENOTSUP;
322 : 0 : goto fail2;
323 : : }
324 : :
325 [ # # ]: 0 : if ((rc = evop->evo_verify_features(enp, type, features)) != 0)
326 : 0 : 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 */
|