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