1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2020-2021 Xilinx, Inc.
9 #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO
12 * Get function-local index of the associated VI from the
13 * virtqueue number queue 0 is reserved for MCDI
15 #define EFX_VIRTIO_GET_VI_INDEX(vq_num) (((vq_num) / 2) + 1)
17 __checkReturn efx_rc_t
19 __in efx_virtio_vq_t *evvp,
20 __in efx_virtio_vq_cfg_t *evvcp,
21 __in_opt efx_virtio_vq_dyncfg_t *evvdp)
24 efx_nic_t *enp = evvp->evv_enp;
27 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_INIT_QUEUE_REQ_LEN,
28 MC_CMD_VIRTIO_INIT_QUEUE_RESP_LEN);
31 EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_NET_RXQ ==
32 MC_CMD_VIRTIO_INIT_QUEUE_REQ_NET_RXQ);
33 EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_NET_TXQ ==
34 MC_CMD_VIRTIO_INIT_QUEUE_REQ_NET_TXQ);
35 EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_BLOCK ==
36 MC_CMD_VIRTIO_INIT_QUEUE_REQ_BLOCK);
38 if (evvcp->evvc_type >= EFX_VIRTIO_VQ_NTYPES) {
43 /* virtqueue size must be power of 2 */
44 if ((!ISP2(evvcp->evvc_vq_size)) ||
45 (evvcp->evvc_vq_size > EFX_VIRTIO_MAX_VQ_SIZE)) {
51 if ((evvdp->evvd_vq_cidx > evvcp->evvc_vq_size) ||
52 (evvdp->evvd_vq_pidx > evvcp->evvc_vq_size)) {
58 req.emr_cmd = MC_CMD_VIRTIO_INIT_QUEUE;
59 req.emr_in_buf = payload;
60 req.emr_in_length = MC_CMD_VIRTIO_INIT_QUEUE_REQ_LEN;
61 req.emr_out_buf = payload;
62 req.emr_out_length = MC_CMD_VIRTIO_INIT_QUEUE_RESP_LEN;
64 MCDI_IN_SET_BYTE(req, VIRTIO_INIT_QUEUE_REQ_QUEUE_TYPE,
66 MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_TARGET_VF,
67 evvcp->evvc_target_vf);
69 vi_index = EFX_VIRTIO_GET_VI_INDEX(evvcp->evvc_vq_num);
70 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INSTANCE, vi_index);
72 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_SIZE,
75 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_DESC_TBL_ADDR_LO,
76 evvcp->evvc_desc_tbl_addr & 0xFFFFFFFF);
77 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_DESC_TBL_ADDR_HI,
78 evvcp->evvc_desc_tbl_addr >> 32);
80 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_AVAIL_RING_ADDR_LO,
81 evvcp->evvc_avail_ring_addr & 0xFFFFFFFF);
82 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_AVAIL_RING_ADDR_HI,
83 evvcp->evvc_avail_ring_addr >> 32);
85 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_USED_RING_ADDR_LO,
86 evvcp->evvc_used_ring_addr & 0xFFFFFFFF);
87 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_USED_RING_ADDR_HI,
88 evvcp->evvc_used_ring_addr >> 32);
90 if (evvcp->evvc_use_pasid) {
91 MCDI_IN_POPULATE_DWORD_1(req, VIRTIO_INIT_QUEUE_REQ_FLAGS,
92 VIRTIO_INIT_QUEUE_REQ_USE_PASID, 1);
93 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_PASID,
97 MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_MSIX_VECTOR,
98 evvcp->evvc_msix_vector);
100 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_FEATURES_LO,
101 evvcp->evcc_features & 0xFFFFFFFF);
102 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_FEATURES_HI,
103 evvcp->evcc_features >> 32);
106 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INITIAL_PIDX,
107 evvdp->evvd_vq_pidx);
108 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INITIAL_CIDX,
109 evvdp->evvd_vq_cidx);
112 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_MPORT_SELECTOR,
113 MAE_MPORT_SELECTOR_ASSIGNED);
115 efx_mcdi_execute(enp, &req);
117 if (req.emr_rc != 0) {
122 evvp->evv_vi_index = vi_index;
133 EFSYS_PROBE1(fail1, efx_rc_t, rc);
138 __checkReturn efx_rc_t
140 __in efx_virtio_vq_t *evvp,
141 __out_opt efx_virtio_vq_dyncfg_t *evvdp)
144 efx_nic_t *enp = evvp->evv_enp;
145 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_FINI_QUEUE_REQ_LEN,
146 MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN);
149 req.emr_cmd = MC_CMD_VIRTIO_FINI_QUEUE;
150 req.emr_in_buf = payload;
151 req.emr_in_length = MC_CMD_VIRTIO_FINI_QUEUE_REQ_LEN;
152 req.emr_out_buf = payload;
153 req.emr_out_length = MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN;
155 MCDI_IN_SET_BYTE(req, VIRTIO_FINI_QUEUE_REQ_QUEUE_TYPE, evvp->evv_type);
156 MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_TARGET_VF,
157 evvp->evv_target_vf);
158 MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INSTANCE,
161 efx_mcdi_execute(enp, &req);
163 if (req.emr_rc != 0) {
168 if (req.emr_out_length_used < MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN) {
174 evvdp->evvd_vq_pidx =
175 MCDI_OUT_DWORD(req, VIRTIO_FINI_QUEUE_RESP_FINAL_PIDX);
176 evvdp->evvd_vq_cidx =
177 MCDI_OUT_DWORD(req, VIRTIO_FINI_QUEUE_RESP_FINAL_CIDX);
185 EFSYS_PROBE1(fail1, efx_rc_t, rc);
190 #endif /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO */