14dda72dbSVijay Srivastava /* SPDX-License-Identifier: BSD-3-Clause
24dda72dbSVijay Srivastava *
34dda72dbSVijay Srivastava * Copyright(c) 2020-2021 Xilinx, Inc.
44dda72dbSVijay Srivastava */
54dda72dbSVijay Srivastava
64dda72dbSVijay Srivastava #include "efx.h"
74dda72dbSVijay Srivastava #include "efx_impl.h"
84dda72dbSVijay Srivastava
94dda72dbSVijay Srivastava #if EFSYS_OPT_VIRTIO
104dda72dbSVijay Srivastava
114dda72dbSVijay Srivastava #if EFSYS_OPT_RIVERHEAD
124dda72dbSVijay Srivastava static const efx_virtio_ops_t __efx_virtio_rhead_ops = {
134dda72dbSVijay Srivastava rhead_virtio_qstart, /* evo_virtio_qstart */
144dda72dbSVijay Srivastava rhead_virtio_qstop, /* evo_virtio_qstop */
15ec03ce69SVijay Srivastava rhead_virtio_get_doorbell_offset, /* evo_get_doorbell_offset */
1646d2b38bSVijay Kumar Srivastava rhead_virtio_get_features, /* evo_get_features */
17*b8a896abSVijay Kumar Srivastava rhead_virtio_verify_features, /* evo_verify_features */
184dda72dbSVijay Srivastava };
194dda72dbSVijay Srivastava #endif /* EFSYS_OPT_RIVERHEAD */
204dda72dbSVijay Srivastava
214dda72dbSVijay Srivastava __checkReturn efx_rc_t
efx_virtio_init(__in efx_nic_t * enp)224dda72dbSVijay Srivastava efx_virtio_init(
234dda72dbSVijay Srivastava __in efx_nic_t *enp)
244dda72dbSVijay Srivastava {
254dda72dbSVijay Srivastava const efx_virtio_ops_t *evop;
264dda72dbSVijay Srivastava efx_rc_t rc;
274dda72dbSVijay Srivastava
284dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
294dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
304dda72dbSVijay Srivastava EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VIRTIO));
314dda72dbSVijay Srivastava
324dda72dbSVijay Srivastava switch (enp->en_family) {
334dda72dbSVijay Srivastava #if EFSYS_OPT_RIVERHEAD
344dda72dbSVijay Srivastava case EFX_FAMILY_RIVERHEAD:
354dda72dbSVijay Srivastava evop = &__efx_virtio_rhead_ops;
364dda72dbSVijay Srivastava break;
374dda72dbSVijay Srivastava #endif /* EFSYS_OPT_RIVERHEAD */
384dda72dbSVijay Srivastava
394dda72dbSVijay Srivastava default:
404dda72dbSVijay Srivastava EFSYS_ASSERT(0);
414dda72dbSVijay Srivastava rc = ENOTSUP;
424dda72dbSVijay Srivastava goto fail1;
434dda72dbSVijay Srivastava }
444dda72dbSVijay Srivastava
454dda72dbSVijay Srivastava enp->en_evop = evop;
464dda72dbSVijay Srivastava enp->en_mod_flags |= EFX_MOD_VIRTIO;
474dda72dbSVijay Srivastava
484dda72dbSVijay Srivastava return (0);
494dda72dbSVijay Srivastava
504dda72dbSVijay Srivastava fail1:
514dda72dbSVijay Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
524dda72dbSVijay Srivastava
534dda72dbSVijay Srivastava enp->en_evop = NULL;
544dda72dbSVijay Srivastava enp->en_mod_flags &= ~EFX_MOD_VIRTIO;
554dda72dbSVijay Srivastava
564dda72dbSVijay Srivastava return (rc);
574dda72dbSVijay Srivastava }
584dda72dbSVijay Srivastava
594dda72dbSVijay Srivastava void
efx_virtio_fini(__in efx_nic_t * enp)604dda72dbSVijay Srivastava efx_virtio_fini(
614dda72dbSVijay Srivastava __in efx_nic_t *enp)
624dda72dbSVijay Srivastava {
634dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
644dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
654dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
664dda72dbSVijay Srivastava
674dda72dbSVijay Srivastava enp->en_evop = NULL;
684dda72dbSVijay Srivastava enp->en_mod_flags &= ~EFX_MOD_VIRTIO;
694dda72dbSVijay Srivastava }
704dda72dbSVijay Srivastava
714dda72dbSVijay Srivastava __checkReturn efx_rc_t
efx_virtio_qcreate(__in efx_nic_t * enp,__deref_out efx_virtio_vq_t ** evvpp)724dda72dbSVijay Srivastava efx_virtio_qcreate(
734dda72dbSVijay Srivastava __in efx_nic_t *enp,
744dda72dbSVijay Srivastava __deref_out efx_virtio_vq_t **evvpp)
754dda72dbSVijay Srivastava {
764dda72dbSVijay Srivastava const efx_virtio_ops_t *evop = enp->en_evop;
774dda72dbSVijay Srivastava efx_virtio_vq_t *evvp;
784dda72dbSVijay Srivastava efx_rc_t rc;
794dda72dbSVijay Srivastava
804dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
814dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
824dda72dbSVijay Srivastava
834dda72dbSVijay Srivastava /* Allocate a virtqueue object */
844dda72dbSVijay Srivastava EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
854dda72dbSVijay Srivastava if (evvp == NULL) {
864dda72dbSVijay Srivastava rc = ENOMEM;
874dda72dbSVijay Srivastava goto fail1;
884dda72dbSVijay Srivastava }
894dda72dbSVijay Srivastava
904dda72dbSVijay Srivastava evvp->evv_magic = EFX_VQ_MAGIC;
914dda72dbSVijay Srivastava evvp->evv_enp = enp;
924dda72dbSVijay Srivastava evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
934dda72dbSVijay Srivastava
944dda72dbSVijay Srivastava *evvpp = evvp;
954dda72dbSVijay Srivastava
964dda72dbSVijay Srivastava return (0);
974dda72dbSVijay Srivastava
984dda72dbSVijay Srivastava fail1:
994dda72dbSVijay Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
1004dda72dbSVijay Srivastava
1014dda72dbSVijay Srivastava return (rc);
1024dda72dbSVijay Srivastava }
1034dda72dbSVijay Srivastava
1044dda72dbSVijay Srivastava __checkReturn efx_rc_t
efx_virtio_qstart(__in efx_virtio_vq_t * evvp,__in efx_virtio_vq_cfg_t * evvcp,__in_opt efx_virtio_vq_dyncfg_t * evvdp)1054dda72dbSVijay Srivastava efx_virtio_qstart(
1064dda72dbSVijay Srivastava __in efx_virtio_vq_t *evvp,
1074dda72dbSVijay Srivastava __in efx_virtio_vq_cfg_t *evvcp,
1084dda72dbSVijay Srivastava __in_opt efx_virtio_vq_dyncfg_t *evvdp)
1094dda72dbSVijay Srivastava {
1104dda72dbSVijay Srivastava const efx_virtio_ops_t *evop;
1114dda72dbSVijay Srivastava efx_rc_t rc;
1124dda72dbSVijay Srivastava
1134dda72dbSVijay Srivastava if ((evvcp == NULL) || (evvp == NULL)) {
1144dda72dbSVijay Srivastava rc = EINVAL;
1154dda72dbSVijay Srivastava goto fail1;
1164dda72dbSVijay Srivastava }
1174dda72dbSVijay Srivastava
1184dda72dbSVijay Srivastava if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_INITIALIZED) {
1194dda72dbSVijay Srivastava rc = EINVAL;
1204dda72dbSVijay Srivastava goto fail2;
1214dda72dbSVijay Srivastava }
1224dda72dbSVijay Srivastava
1234dda72dbSVijay Srivastava evop = evvp->evv_enp->en_evop;
1244dda72dbSVijay Srivastava if (evop == NULL) {
1254dda72dbSVijay Srivastava rc = ENOTSUP;
1264dda72dbSVijay Srivastava goto fail3;
1274dda72dbSVijay Srivastava }
1284dda72dbSVijay Srivastava
1294dda72dbSVijay Srivastava if ((rc = evop->evo_virtio_qstart(evvp, evvcp, evvdp)) != 0)
1304dda72dbSVijay Srivastava goto fail4;
1314dda72dbSVijay Srivastava
1324dda72dbSVijay Srivastava evvp->evv_type = evvcp->evvc_type;
1334dda72dbSVijay Srivastava evvp->evv_target_vf = evvcp->evvc_target_vf;
1344dda72dbSVijay Srivastava evvp->evv_state = EFX_VIRTIO_VQ_STATE_STARTED;
1354dda72dbSVijay Srivastava
1364dda72dbSVijay Srivastava return (0);
1374dda72dbSVijay Srivastava
1384dda72dbSVijay Srivastava fail4:
1394dda72dbSVijay Srivastava EFSYS_PROBE(fail4);
1404dda72dbSVijay Srivastava fail3:
1414dda72dbSVijay Srivastava EFSYS_PROBE(fail3);
1424dda72dbSVijay Srivastava fail2:
1434dda72dbSVijay Srivastava EFSYS_PROBE(fail2);
1444dda72dbSVijay Srivastava fail1:
1454dda72dbSVijay Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
1464dda72dbSVijay Srivastava
1474dda72dbSVijay Srivastava return (rc);
1484dda72dbSVijay Srivastava }
1494dda72dbSVijay Srivastava
1504dda72dbSVijay Srivastava __checkReturn efx_rc_t
efx_virtio_qstop(__in efx_virtio_vq_t * evvp,__out_opt efx_virtio_vq_dyncfg_t * evvdp)1514dda72dbSVijay Srivastava efx_virtio_qstop(
1524dda72dbSVijay Srivastava __in efx_virtio_vq_t *evvp,
1534dda72dbSVijay Srivastava __out_opt efx_virtio_vq_dyncfg_t *evvdp)
1544dda72dbSVijay Srivastava {
1554dda72dbSVijay Srivastava efx_nic_t *enp;
1564dda72dbSVijay Srivastava const efx_virtio_ops_t *evop;
1574dda72dbSVijay Srivastava efx_rc_t rc;
1584dda72dbSVijay Srivastava
1594dda72dbSVijay Srivastava if (evvp == NULL) {
1604dda72dbSVijay Srivastava rc = EINVAL;
1614dda72dbSVijay Srivastava goto fail1;
1624dda72dbSVijay Srivastava }
1634dda72dbSVijay Srivastava
1644dda72dbSVijay Srivastava enp = evvp->evv_enp;
1654dda72dbSVijay Srivastava evop = enp->en_evop;
1664dda72dbSVijay Srivastava
1674dda72dbSVijay Srivastava EFSYS_ASSERT3U(evvp->evv_magic, ==, EFX_VQ_MAGIC);
1684dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1694dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
1704dda72dbSVijay Srivastava
1714dda72dbSVijay Srivastava if (evop == NULL) {
1724dda72dbSVijay Srivastava rc = ENOTSUP;
1734dda72dbSVijay Srivastava goto fail2;
1744dda72dbSVijay Srivastava }
1754dda72dbSVijay Srivastava
1764dda72dbSVijay Srivastava if (evvp->evv_state != EFX_VIRTIO_VQ_STATE_STARTED) {
1774dda72dbSVijay Srivastava rc = EINVAL;
1784dda72dbSVijay Srivastava goto fail3;
1794dda72dbSVijay Srivastava }
1804dda72dbSVijay Srivastava
1814dda72dbSVijay Srivastava if ((rc = evop->evo_virtio_qstop(evvp, evvdp)) != 0)
1824dda72dbSVijay Srivastava goto fail4;
1834dda72dbSVijay Srivastava
1844dda72dbSVijay Srivastava evvp->evv_state = EFX_VIRTIO_VQ_STATE_INITIALIZED;
1854dda72dbSVijay Srivastava
1864dda72dbSVijay Srivastava return 0;
1874dda72dbSVijay Srivastava
1884dda72dbSVijay Srivastava fail4:
1894dda72dbSVijay Srivastava EFSYS_PROBE(fail4);
1904dda72dbSVijay Srivastava fail3:
1914dda72dbSVijay Srivastava EFSYS_PROBE(fail3);
1924dda72dbSVijay Srivastava fail2:
1934dda72dbSVijay Srivastava EFSYS_PROBE(fail2);
1944dda72dbSVijay Srivastava fail1:
1954dda72dbSVijay Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
1964dda72dbSVijay Srivastava
1974dda72dbSVijay Srivastava return (rc);
1984dda72dbSVijay Srivastava }
1994dda72dbSVijay Srivastava
2004dda72dbSVijay Srivastava void
efx_virtio_qdestroy(__in efx_virtio_vq_t * evvp)2014dda72dbSVijay Srivastava efx_virtio_qdestroy(
2024dda72dbSVijay Srivastava __in efx_virtio_vq_t *evvp)
2034dda72dbSVijay Srivastava {
2044dda72dbSVijay Srivastava efx_nic_t *enp;
2054dda72dbSVijay Srivastava
2064dda72dbSVijay Srivastava if (evvp == NULL)
2074dda72dbSVijay Srivastava return;
2084dda72dbSVijay Srivastava
2094dda72dbSVijay Srivastava enp = evvp->evv_enp;
2104dda72dbSVijay Srivastava
2114dda72dbSVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2124dda72dbSVijay Srivastava
2134dda72dbSVijay Srivastava if (evvp->evv_state == EFX_VIRTIO_VQ_STATE_INITIALIZED) {
2144dda72dbSVijay Srivastava /* Free the virtqueue object */
2154dda72dbSVijay Srivastava EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_virtio_vq_t), evvp);
2164dda72dbSVijay Srivastava }
2174dda72dbSVijay Srivastava }
2184dda72dbSVijay Srivastava
219ec03ce69SVijay Srivastava __checkReturn efx_rc_t
efx_virtio_get_doorbell_offset(__in efx_virtio_vq_t * evvp,__out uint32_t * offsetp)220ec03ce69SVijay Srivastava efx_virtio_get_doorbell_offset(
221ec03ce69SVijay Srivastava __in efx_virtio_vq_t *evvp,
222ec03ce69SVijay Srivastava __out uint32_t *offsetp)
223ec03ce69SVijay Srivastava {
224ec03ce69SVijay Srivastava efx_nic_t *enp;
225ec03ce69SVijay Srivastava const efx_virtio_ops_t *evop;
226ec03ce69SVijay Srivastava efx_rc_t rc;
227ec03ce69SVijay Srivastava
228ec03ce69SVijay Srivastava if ((evvp == NULL) || (offsetp == NULL)) {
229ec03ce69SVijay Srivastava rc = EINVAL;
230ec03ce69SVijay Srivastava goto fail1;
231ec03ce69SVijay Srivastava }
232ec03ce69SVijay Srivastava
233ec03ce69SVijay Srivastava enp = evvp->evv_enp;
234ec03ce69SVijay Srivastava evop = enp->en_evop;
235ec03ce69SVijay Srivastava
236ec03ce69SVijay Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
237ec03ce69SVijay Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
238ec03ce69SVijay Srivastava
239ec03ce69SVijay Srivastava if (evop == NULL) {
240ec03ce69SVijay Srivastava rc = ENOTSUP;
241ec03ce69SVijay Srivastava goto fail2;
242ec03ce69SVijay Srivastava }
243ec03ce69SVijay Srivastava
244ec03ce69SVijay Srivastava if ((rc = evop->evo_get_doorbell_offset(evvp, offsetp)) != 0)
245ec03ce69SVijay Srivastava goto fail3;
246ec03ce69SVijay Srivastava
247ec03ce69SVijay Srivastava return (0);
248ec03ce69SVijay Srivastava
249ec03ce69SVijay Srivastava fail3:
250ec03ce69SVijay Srivastava EFSYS_PROBE(fail3);
251ec03ce69SVijay Srivastava fail2:
252ec03ce69SVijay Srivastava EFSYS_PROBE(fail2);
253ec03ce69SVijay Srivastava fail1:
254ec03ce69SVijay Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
255ec03ce69SVijay Srivastava
256ec03ce69SVijay Srivastava return (rc);
257ec03ce69SVijay Srivastava }
258ec03ce69SVijay Srivastava
25946d2b38bSVijay Kumar Srivastava __checkReturn efx_rc_t
efx_virtio_get_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__out uint64_t * featuresp)26046d2b38bSVijay Kumar Srivastava efx_virtio_get_features(
26146d2b38bSVijay Kumar Srivastava __in efx_nic_t *enp,
26246d2b38bSVijay Kumar Srivastava __in efx_virtio_device_type_t type,
26346d2b38bSVijay Kumar Srivastava __out uint64_t *featuresp)
26446d2b38bSVijay Kumar Srivastava {
26546d2b38bSVijay Kumar Srivastava const efx_virtio_ops_t *evop = enp->en_evop;
26646d2b38bSVijay Kumar Srivastava efx_rc_t rc;
26746d2b38bSVijay Kumar Srivastava
26846d2b38bSVijay Kumar Srivastava if (featuresp == NULL) {
26946d2b38bSVijay Kumar Srivastava rc = EINVAL;
27046d2b38bSVijay Kumar Srivastava goto fail1;
27146d2b38bSVijay Kumar Srivastava }
27246d2b38bSVijay Kumar Srivastava
27346d2b38bSVijay Kumar Srivastava if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
27446d2b38bSVijay Kumar Srivastava rc = EINVAL;
27546d2b38bSVijay Kumar Srivastava goto fail2;
27646d2b38bSVijay Kumar Srivastava }
27746d2b38bSVijay Kumar Srivastava
27846d2b38bSVijay Kumar Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
27946d2b38bSVijay Kumar Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
28046d2b38bSVijay Kumar Srivastava
28146d2b38bSVijay Kumar Srivastava if (evop == NULL) {
28246d2b38bSVijay Kumar Srivastava rc = ENOTSUP;
28346d2b38bSVijay Kumar Srivastava goto fail3;
28446d2b38bSVijay Kumar Srivastava }
28546d2b38bSVijay Kumar Srivastava
28646d2b38bSVijay Kumar Srivastava if ((rc = evop->evo_get_features(enp, type, featuresp)) != 0)
28746d2b38bSVijay Kumar Srivastava goto fail4;
28846d2b38bSVijay Kumar Srivastava
28946d2b38bSVijay Kumar Srivastava return (0);
29046d2b38bSVijay Kumar Srivastava
29146d2b38bSVijay Kumar Srivastava fail4:
29246d2b38bSVijay Kumar Srivastava EFSYS_PROBE(fail4);
29346d2b38bSVijay Kumar Srivastava fail3:
29446d2b38bSVijay Kumar Srivastava EFSYS_PROBE(fail3);
29546d2b38bSVijay Kumar Srivastava fail2:
29646d2b38bSVijay Kumar Srivastava EFSYS_PROBE(fail2);
29746d2b38bSVijay Kumar Srivastava fail1:
29846d2b38bSVijay Kumar Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
29946d2b38bSVijay Kumar Srivastava
30046d2b38bSVijay Kumar Srivastava return (rc);
30146d2b38bSVijay Kumar Srivastava }
30246d2b38bSVijay Kumar Srivastava
303*b8a896abSVijay Kumar Srivastava __checkReturn efx_rc_t
efx_virtio_verify_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__in uint64_t features)304*b8a896abSVijay Kumar Srivastava efx_virtio_verify_features(
305*b8a896abSVijay Kumar Srivastava __in efx_nic_t *enp,
306*b8a896abSVijay Kumar Srivastava __in efx_virtio_device_type_t type,
307*b8a896abSVijay Kumar Srivastava __in uint64_t features)
308*b8a896abSVijay Kumar Srivastava {
309*b8a896abSVijay Kumar Srivastava const efx_virtio_ops_t *evop = enp->en_evop;
310*b8a896abSVijay Kumar Srivastava efx_rc_t rc;
311*b8a896abSVijay Kumar Srivastava
312*b8a896abSVijay Kumar Srivastava if (type >= EFX_VIRTIO_DEVICE_NTYPES) {
313*b8a896abSVijay Kumar Srivastava rc = EINVAL;
314*b8a896abSVijay Kumar Srivastava goto fail1;
315*b8a896abSVijay Kumar Srivastava }
316*b8a896abSVijay Kumar Srivastava
317*b8a896abSVijay Kumar Srivastava EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
318*b8a896abSVijay Kumar Srivastava EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO);
319*b8a896abSVijay Kumar Srivastava
320*b8a896abSVijay Kumar Srivastava if (evop == NULL) {
321*b8a896abSVijay Kumar Srivastava rc = ENOTSUP;
322*b8a896abSVijay Kumar Srivastava goto fail2;
323*b8a896abSVijay Kumar Srivastava }
324*b8a896abSVijay Kumar Srivastava
325*b8a896abSVijay Kumar Srivastava if ((rc = evop->evo_verify_features(enp, type, features)) != 0)
326*b8a896abSVijay Kumar Srivastava goto fail3;
327*b8a896abSVijay Kumar Srivastava
328*b8a896abSVijay Kumar Srivastava return (0);
329*b8a896abSVijay Kumar Srivastava
330*b8a896abSVijay Kumar Srivastava fail3:
331*b8a896abSVijay Kumar Srivastava EFSYS_PROBE(fail3);
332*b8a896abSVijay Kumar Srivastava fail2:
333*b8a896abSVijay Kumar Srivastava EFSYS_PROBE(fail2);
334*b8a896abSVijay Kumar Srivastava fail1:
335*b8a896abSVijay Kumar Srivastava EFSYS_PROBE1(fail1, efx_rc_t, rc);
336*b8a896abSVijay Kumar Srivastava
337*b8a896abSVijay Kumar Srivastava return (rc);
338*b8a896abSVijay Kumar Srivastava }
339*b8a896abSVijay Kumar Srivastava
3404dda72dbSVijay Srivastava #endif /* EFSYS_OPT_VIRTIO */
341