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 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 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 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 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 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 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 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 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 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