common/sfc_efx/base: add base virtio support for vDPA
[dpdk.git] / drivers / common / sfc_efx / base / rhead_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_RIVERHEAD && EFSYS_OPT_VIRTIO
10
11 /*
12  * Get function-local index of the associated VI from the
13  * virtqueue number queue 0 is reserved for MCDI
14  */
15 #define EFX_VIRTIO_GET_VI_INDEX(vq_num) (((vq_num) / 2) + 1)
16
17         __checkReturn   efx_rc_t
18 rhead_virtio_qstart(
19         __in            efx_virtio_vq_t *evvp,
20         __in            efx_virtio_vq_cfg_t *evvcp,
21         __in_opt        efx_virtio_vq_dyncfg_t *evvdp)
22
23 {
24         efx_nic_t *enp = evvp->evv_enp;
25         efx_mcdi_req_t req;
26         uint32_t vi_index;
27         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_INIT_QUEUE_REQ_LEN,
28                 MC_CMD_VIRTIO_INIT_QUEUE_RESP_LEN);
29         efx_rc_t rc;
30
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);
37
38         if (evvcp->evvc_type >= EFX_VIRTIO_VQ_NTYPES) {
39                 rc = EINVAL;
40                 goto fail1;
41         }
42
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)) {
46                 rc = EINVAL;
47                 goto fail2;
48         }
49
50         if (evvdp != NULL) {
51                 if ((evvdp->evvd_vq_cidx > evvcp->evvc_vq_size) ||
52                     (evvdp->evvd_vq_pidx > evvcp->evvc_vq_size)) {
53                         rc = EINVAL;
54                         goto fail3;
55                 }
56         }
57
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;
63
64         MCDI_IN_SET_BYTE(req, VIRTIO_INIT_QUEUE_REQ_QUEUE_TYPE,
65                 evvcp->evvc_type);
66         MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_TARGET_VF,
67                 evvcp->evvc_target_vf);
68
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);
71
72         MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_SIZE,
73                 evvcp->evvc_vq_size);
74
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);
79
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);
84
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);
89
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,
94                         evvcp->evvc_pas_id);
95         }
96
97         MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_MSIX_VECTOR,
98                 evvcp->evvc_msix_vector);
99
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);
104
105         if (evvdp != NULL) {
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);
110         }
111
112         MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_MPORT_SELECTOR,
113                 MAE_MPORT_SELECTOR_ASSIGNED);
114
115         efx_mcdi_execute(enp, &req);
116
117         if (req.emr_rc != 0) {
118                 rc = req.emr_rc;
119                 goto fail4;
120         }
121
122         evvp->evv_vi_index = vi_index;
123
124         return (0);
125
126 fail4:
127         EFSYS_PROBE(fail4);
128 fail3:
129         EFSYS_PROBE(fail3);
130 fail2:
131         EFSYS_PROBE(fail2);
132 fail1:
133         EFSYS_PROBE1(fail1, efx_rc_t, rc);
134
135         return (rc);
136 }
137
138         __checkReturn   efx_rc_t
139 rhead_virtio_qstop(
140         __in            efx_virtio_vq_t *evvp,
141         __out_opt       efx_virtio_vq_dyncfg_t *evvdp)
142 {
143         efx_mcdi_req_t req;
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);
147         efx_rc_t rc;
148
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;
154
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,
159                 evvp->evv_vi_index);
160
161         efx_mcdi_execute(enp, &req);
162
163         if (req.emr_rc != 0) {
164                 rc = req.emr_rc;
165                 goto fail1;
166         }
167
168         if (req.emr_out_length_used < MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN) {
169                 rc = EMSGSIZE;
170                 goto fail2;
171         }
172
173         if (evvdp != NULL) {
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);
178         }
179
180         return (0);
181
182 fail2:
183         EFSYS_PROBE(fail2);
184 fail1:
185         EFSYS_PROBE1(fail1, efx_rc_t, rc);
186
187         return (rc);
188 }
189
190 #endif  /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO */