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