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