Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3 : : */
4 : :
5 : : #include "mlx5dr_internal.h"
6 : :
7 : : struct mlx5dr_send_ring_dep_wqe *
8 : 0 : mlx5dr_send_add_new_dep_wqe(struct mlx5dr_send_engine *queue)
9 : : {
10 : : struct mlx5dr_send_ring_sq *send_sq = &queue->send_ring->send_sq;
11 : 0 : unsigned int idx = send_sq->head_dep_idx++ & (queue->num_entries - 1);
12 : :
13 : 0 : memset(&send_sq->dep_wqe[idx].wqe_data.tag, 0, MLX5DR_MATCH_TAG_SZ);
14 : :
15 : 0 : return &send_sq->dep_wqe[idx];
16 : : }
17 : :
18 : 0 : void mlx5dr_send_abort_new_dep_wqe(struct mlx5dr_send_engine *queue)
19 : : {
20 : 0 : queue->send_ring->send_sq.head_dep_idx--;
21 : 0 : }
22 : :
23 : 0 : void mlx5dr_send_all_dep_wqe(struct mlx5dr_send_engine *queue)
24 : : {
25 : : struct mlx5dr_send_ring_sq *send_sq = &queue->send_ring->send_sq;
26 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
27 : : struct mlx5dr_send_ring_dep_wqe *dep_wqe;
28 : :
29 : : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
30 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
31 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
32 : : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
33 : :
34 : : /* Fence first from previous depend WQEs */
35 : 0 : ste_attr.send_attr.fence = 1;
36 : :
37 [ # # ]: 0 : while (send_sq->head_dep_idx != send_sq->tail_dep_idx) {
38 : 0 : dep_wqe = &send_sq->dep_wqe[send_sq->tail_dep_idx++ & (queue->num_entries - 1)];
39 : :
40 : : /* Notify HW on the last WQE */
41 : 0 : ste_attr.send_attr.notify_hw = (send_sq->tail_dep_idx == send_sq->head_dep_idx);
42 : 0 : ste_attr.send_attr.user_data = dep_wqe->user_data;
43 : 0 : ste_attr.send_attr.rule = dep_wqe->rule;
44 : :
45 : 0 : ste_attr.rtc_0 = dep_wqe->rtc_0;
46 : 0 : ste_attr.rtc_1 = dep_wqe->rtc_1;
47 : 0 : ste_attr.retry_rtc_0 = dep_wqe->retry_rtc_0;
48 : 0 : ste_attr.retry_rtc_1 = dep_wqe->retry_rtc_1;
49 : 0 : ste_attr.used_id_rtc_0 = &dep_wqe->rule->rtc_0;
50 : 0 : ste_attr.used_id_rtc_1 = &dep_wqe->rule->rtc_1;
51 : 0 : ste_attr.wqe_ctrl = &dep_wqe->wqe_ctrl;
52 : 0 : ste_attr.wqe_data = &dep_wqe->wqe_data;
53 : :
54 : 0 : mlx5dr_send_ste(queue, &ste_attr);
55 : :
56 : : /* Fencing is done only on the first WQE */
57 : 0 : ste_attr.send_attr.fence = 0;
58 : : }
59 : 0 : }
60 : :
61 : : struct mlx5dr_send_engine_post_ctrl
62 : 0 : mlx5dr_send_engine_post_start(struct mlx5dr_send_engine *queue)
63 : : {
64 : : struct mlx5dr_send_engine_post_ctrl ctrl;
65 : :
66 : : ctrl.queue = queue;
67 : : /* Currently only one send ring is supported */
68 : 0 : ctrl.send_ring = &queue->send_ring[0];
69 : : ctrl.num_wqebbs = 0;
70 : :
71 : 0 : return ctrl;
72 : : }
73 : :
74 : 0 : void mlx5dr_send_engine_post_req_wqe(struct mlx5dr_send_engine_post_ctrl *ctrl,
75 : : char **buf, size_t *len)
76 : : {
77 : 0 : struct mlx5dr_send_ring_sq *send_sq = &ctrl->send_ring->send_sq;
78 : : unsigned int idx;
79 : :
80 : 0 : idx = (send_sq->cur_post + ctrl->num_wqebbs) & send_sq->buf_mask;
81 : :
82 : 0 : *buf = send_sq->buf + (idx << MLX5_SEND_WQE_SHIFT);
83 : 0 : *len = MLX5_SEND_WQE_BB;
84 : :
85 [ # # ]: 0 : if (!ctrl->num_wqebbs) {
86 : 0 : *buf += sizeof(struct mlx5dr_wqe_ctrl_seg);
87 : 0 : *len -= sizeof(struct mlx5dr_wqe_ctrl_seg);
88 : : }
89 : :
90 : 0 : ctrl->num_wqebbs++;
91 : 0 : }
92 : :
93 : : static void mlx5dr_send_engine_post_ring(struct mlx5dr_send_ring_sq *sq,
94 : : struct mlx5dv_devx_uar *uar,
95 : : struct mlx5dr_wqe_ctrl_seg *wqe_ctrl)
96 : : {
97 : 0 : rte_compiler_barrier();
98 [ # # # # ]: 0 : sq->db[MLX5_SND_DBR] = rte_cpu_to_be_32(sq->cur_post);
99 : :
100 : : rte_wmb();
101 : 0 : mlx5dr_uar_write64_relaxed(*((uint64_t *)wqe_ctrl), uar->reg_addr);
102 : : rte_wmb();
103 : 0 : }
104 : :
105 : : static void
106 : 0 : mlx5dr_send_wqe_set_tag(struct mlx5dr_wqe_gta_data_seg_ste *wqe_data,
107 : : struct mlx5dr_rule_match_tag *tag,
108 : : bool is_jumbo)
109 : : {
110 [ # # ]: 0 : if (is_jumbo) {
111 : : /* Clear previous possibly dirty control */
112 : : memset(wqe_data, 0, MLX5DR_STE_CTRL_SZ);
113 : 0 : memcpy(wqe_data->jumbo, tag->jumbo, MLX5DR_JUMBO_TAG_SZ);
114 : : } else {
115 : : /* Clear previous possibly dirty control and actions */
116 : : memset(wqe_data, 0, MLX5DR_STE_CTRL_SZ + MLX5DR_ACTIONS_SZ);
117 : 0 : memcpy(wqe_data->tag, tag->match, MLX5DR_MATCH_TAG_SZ);
118 : : }
119 : 0 : }
120 : :
121 : 0 : void mlx5dr_send_engine_post_end(struct mlx5dr_send_engine_post_ctrl *ctrl,
122 : : struct mlx5dr_send_engine_post_attr *attr)
123 : : {
124 : : struct mlx5dr_wqe_ctrl_seg *wqe_ctrl;
125 : : struct mlx5dr_send_ring_sq *sq;
126 : : uint32_t flags = 0;
127 : : unsigned int idx;
128 : :
129 : 0 : sq = &ctrl->send_ring->send_sq;
130 : 0 : idx = sq->cur_post & sq->buf_mask;
131 : 0 : sq->last_idx = idx;
132 : :
133 : 0 : wqe_ctrl = (void *)(sq->buf + (idx << MLX5_SEND_WQE_SHIFT));
134 : :
135 : 0 : wqe_ctrl->opmod_idx_opcode =
136 [ # # ]: 0 : rte_cpu_to_be_32((attr->opmod << 24) |
137 : : ((sq->cur_post & 0xffff) << 8) |
138 : : attr->opcode);
139 : 0 : wqe_ctrl->qpn_ds =
140 [ # # ]: 0 : rte_cpu_to_be_32((attr->len + sizeof(struct mlx5dr_wqe_ctrl_seg)) / 16 |
141 : : sq->sqn << 8);
142 : :
143 [ # # ]: 0 : wqe_ctrl->imm = rte_cpu_to_be_32(attr->id);
144 : :
145 [ # # ]: 0 : flags |= attr->notify_hw ? MLX5_WQE_CTRL_CQ_UPDATE : 0;
146 [ # # ]: 0 : flags |= attr->fence ? MLX5_WQE_CTRL_INITIATOR_SMALL_FENCE : 0;
147 [ # # ]: 0 : wqe_ctrl->flags = rte_cpu_to_be_32(flags);
148 : :
149 : 0 : sq->wr_priv[idx].id = attr->id;
150 : 0 : sq->wr_priv[idx].retry_id = attr->retry_id;
151 : :
152 : 0 : sq->wr_priv[idx].rule = attr->rule;
153 : 0 : sq->wr_priv[idx].user_data = attr->user_data;
154 : 0 : sq->wr_priv[idx].num_wqebbs = ctrl->num_wqebbs;
155 : :
156 [ # # ]: 0 : if (attr->rule) {
157 : 0 : sq->wr_priv[idx].rule->pending_wqes++;
158 : 0 : sq->wr_priv[idx].used_id = attr->used_id;
159 : : }
160 : :
161 : 0 : sq->cur_post += ctrl->num_wqebbs;
162 : :
163 [ # # ]: 0 : if (attr->notify_hw)
164 : 0 : mlx5dr_send_engine_post_ring(sq, ctrl->queue->uar, wqe_ctrl);
165 : 0 : }
166 : :
167 : 0 : static void mlx5dr_send_wqe(struct mlx5dr_send_engine *queue,
168 : : struct mlx5dr_send_engine_post_attr *send_attr,
169 : : struct mlx5dr_wqe_gta_ctrl_seg *send_wqe_ctrl,
170 : : void *send_wqe_data,
171 : : void *send_wqe_tag,
172 : : bool is_jumbo,
173 : : uint8_t gta_opcode,
174 : : uint32_t direct_index)
175 : : {
176 : : struct mlx5dr_wqe_gta_data_seg_ste *wqe_data;
177 : : struct mlx5dr_wqe_gta_ctrl_seg *wqe_ctrl;
178 : : struct mlx5dr_send_engine_post_ctrl ctrl;
179 : : size_t wqe_len;
180 : :
181 : 0 : ctrl = mlx5dr_send_engine_post_start(queue);
182 : 0 : mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
183 : 0 : mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_data, &wqe_len);
184 : :
185 [ # # ]: 0 : wqe_ctrl->op_dirix = htobe32(gta_opcode << 28 | direct_index);
186 [ # # ]: 0 : memcpy(wqe_ctrl->stc_ix, send_wqe_ctrl->stc_ix, sizeof(send_wqe_ctrl->stc_ix));
187 : :
188 [ # # ]: 0 : if (send_wqe_data)
189 : 0 : memcpy(wqe_data, send_wqe_data, sizeof(*wqe_data));
190 : : else
191 : 0 : mlx5dr_send_wqe_set_tag(wqe_data, send_wqe_tag, is_jumbo);
192 : :
193 : 0 : mlx5dr_send_engine_post_end(&ctrl, send_attr);
194 : 0 : }
195 : :
196 : 0 : void mlx5dr_send_ste(struct mlx5dr_send_engine *queue,
197 : : struct mlx5dr_send_ste_attr *ste_attr)
198 : : {
199 : 0 : struct mlx5dr_send_engine_post_attr *send_attr = &ste_attr->send_attr;
200 : 0 : uint8_t notify_hw = send_attr->notify_hw;
201 : 0 : uint8_t fence = send_attr->fence;
202 : :
203 [ # # ]: 0 : if (ste_attr->rtc_1) {
204 : 0 : send_attr->id = ste_attr->rtc_1;
205 : 0 : send_attr->used_id = ste_attr->used_id_rtc_1;
206 : 0 : send_attr->retry_id = ste_attr->retry_rtc_1;
207 : : send_attr->fence = fence;
208 [ # # # # ]: 0 : send_attr->notify_hw = notify_hw && !ste_attr->rtc_0;
209 : 0 : mlx5dr_send_wqe(queue, send_attr,
210 : : ste_attr->wqe_ctrl,
211 : 0 : ste_attr->wqe_data,
212 : 0 : ste_attr->wqe_tag,
213 : 0 : ste_attr->wqe_tag_is_jumbo,
214 : 0 : ste_attr->gta_opcode,
215 : : ste_attr->direct_index);
216 : : }
217 : :
218 [ # # ]: 0 : if (ste_attr->rtc_0) {
219 : 0 : send_attr->id = ste_attr->rtc_0;
220 : 0 : send_attr->used_id = ste_attr->used_id_rtc_0;
221 : 0 : send_attr->retry_id = ste_attr->retry_rtc_0;
222 [ # # # # ]: 0 : send_attr->fence = fence && !ste_attr->rtc_1;
223 : 0 : send_attr->notify_hw = notify_hw;
224 : 0 : mlx5dr_send_wqe(queue, send_attr,
225 : : ste_attr->wqe_ctrl,
226 : 0 : ste_attr->wqe_data,
227 : 0 : ste_attr->wqe_tag,
228 : 0 : ste_attr->wqe_tag_is_jumbo,
229 : 0 : ste_attr->gta_opcode,
230 : : ste_attr->direct_index);
231 : : }
232 : :
233 : : /* Restore to ortginal requested values */
234 : 0 : send_attr->notify_hw = notify_hw;
235 : 0 : send_attr->fence = fence;
236 : 0 : }
237 : :
238 : : static
239 : 0 : int mlx5dr_send_wqe_fw(struct ibv_context *ibv_ctx,
240 : : uint32_t pd_num,
241 : : struct mlx5dr_send_engine_post_attr *send_attr,
242 : : struct mlx5dr_wqe_gta_ctrl_seg *send_wqe_ctrl,
243 : : void *send_wqe_match_data,
244 : : void *send_wqe_match_tag,
245 : : void *send_wqe_range_data,
246 : : void *send_wqe_range_tag,
247 : : bool is_jumbo,
248 : : uint8_t gta_opcode)
249 : : {
250 : 0 : bool has_range = send_wqe_range_data || send_wqe_range_tag;
251 : 0 : bool has_match = send_wqe_match_data || send_wqe_match_tag;
252 : 0 : struct mlx5dr_wqe_gta_data_seg_ste gta_wqe_data0 = {0};
253 : 0 : struct mlx5dr_wqe_gta_data_seg_ste gta_wqe_data1 = {0};
254 : 0 : struct mlx5dr_wqe_gta_ctrl_seg gta_wqe_ctrl = {0};
255 : 0 : struct mlx5dr_cmd_generate_wqe_attr attr = {0};
256 : : struct mlx5dr_wqe_ctrl_seg wqe_ctrl = {0};
257 : : struct mlx5_cqe64 cqe;
258 : : uint32_t flags = 0;
259 : : int ret;
260 : :
261 : : /* Set WQE control */
262 : 0 : wqe_ctrl.opmod_idx_opcode =
263 [ # # ]: 0 : rte_cpu_to_be_32((send_attr->opmod << 24) | send_attr->opcode);
264 : 0 : wqe_ctrl.qpn_ds =
265 [ # # ]: 0 : rte_cpu_to_be_32((send_attr->len + sizeof(struct mlx5dr_wqe_ctrl_seg)) / 16);
266 [ # # ]: 0 : flags |= send_attr->notify_hw ? MLX5_WQE_CTRL_CQ_UPDATE : 0;
267 [ # # ]: 0 : wqe_ctrl.flags = rte_cpu_to_be_32(flags);
268 [ # # ]: 0 : wqe_ctrl.imm = rte_cpu_to_be_32(send_attr->id);
269 : :
270 : : /* Set GTA WQE CTRL */
271 [ # # ]: 0 : memcpy(gta_wqe_ctrl.stc_ix, send_wqe_ctrl->stc_ix, sizeof(send_wqe_ctrl->stc_ix));
272 [ # # ]: 0 : gta_wqe_ctrl.op_dirix = htobe32(gta_opcode << 28);
273 : :
274 : : /* Set GTA match WQE DATA */
275 [ # # ]: 0 : if (has_match) {
276 [ # # ]: 0 : if (send_wqe_match_data)
277 : : memcpy(>a_wqe_data0, send_wqe_match_data, sizeof(gta_wqe_data0));
278 : : else
279 : 0 : mlx5dr_send_wqe_set_tag(>a_wqe_data0, send_wqe_match_tag, is_jumbo);
280 : :
281 : 0 : gta_wqe_data0.rsvd1_definer = htobe32(send_attr->match_definer_id << 8);
282 : 0 : attr.gta_data_0 = (uint8_t *)>a_wqe_data0;
283 : : }
284 : :
285 : : /* Set GTA range WQE DATA */
286 [ # # ]: 0 : if (has_range) {
287 [ # # ]: 0 : if (send_wqe_range_data)
288 : : memcpy(>a_wqe_data1, send_wqe_range_data, sizeof(gta_wqe_data1));
289 : : else
290 : 0 : mlx5dr_send_wqe_set_tag(>a_wqe_data1, send_wqe_range_tag, false);
291 : :
292 : 0 : gta_wqe_data1.rsvd1_definer = htobe32(send_attr->range_definer_id << 8);
293 : 0 : attr.gta_data_1 = (uint8_t *)>a_wqe_data1;
294 : : }
295 : :
296 : 0 : attr.pdn = pd_num;
297 : 0 : attr.wqe_ctrl = (uint8_t *)&wqe_ctrl;
298 : 0 : attr.gta_ctrl = (uint8_t *)>a_wqe_ctrl;
299 : :
300 : 0 : send_wqe:
301 : 0 : ret = mlx5dr_cmd_generate_wqe(ibv_ctx, &attr, &cqe);
302 [ # # ]: 0 : if (ret) {
303 : 0 : DR_LOG(ERR, "Failed to write WQE using command");
304 : 0 : return ret;
305 : : }
306 : :
307 [ # # # # ]: 0 : if ((mlx5dv_get_cqe_opcode(&cqe) == MLX5_CQE_REQ) &&
308 [ # # ]: 0 : (rte_be_to_cpu_32(cqe.byte_cnt) >> 31 == 0)) {
309 : 0 : *send_attr->used_id = send_attr->id;
310 : 0 : return 0;
311 : : }
312 : :
313 : : /* Retry if rule failed */
314 [ # # ]: 0 : if (send_attr->retry_id) {
315 [ # # ]: 0 : wqe_ctrl.imm = rte_cpu_to_be_32(send_attr->retry_id);
316 : 0 : send_attr->id = send_attr->retry_id;
317 : 0 : send_attr->retry_id = 0;
318 : 0 : goto send_wqe;
319 : : }
320 : :
321 : : return -1;
322 : : }
323 : :
324 : 0 : void mlx5dr_send_stes_fw(struct mlx5dr_send_engine *queue,
325 : : struct mlx5dr_send_ste_attr *ste_attr)
326 : : {
327 : 0 : struct mlx5dr_send_engine_post_attr *send_attr = &ste_attr->send_attr;
328 : 0 : struct mlx5dr_rule *rule = send_attr->rule;
329 : : struct ibv_context *ibv_ctx;
330 : : struct mlx5dr_context *ctx;
331 : : uint16_t queue_id;
332 : : uint32_t pdn;
333 : : int ret;
334 : :
335 : 0 : ctx = rule->matcher->tbl->ctx;
336 : 0 : queue_id = queue - ctx->send_queue;
337 : 0 : ibv_ctx = ctx->ibv_ctx;
338 : 0 : pdn = ctx->pd_num;
339 : :
340 : : /* Writing through FW can't HW fence, therefore we drain the queue */
341 [ # # ]: 0 : if (send_attr->fence)
342 : 0 : mlx5dr_send_queue_action(ctx,
343 : : queue_id,
344 : : MLX5DR_SEND_QUEUE_ACTION_DRAIN_SYNC);
345 : :
346 [ # # ]: 0 : if (ste_attr->rtc_1) {
347 : 0 : send_attr->id = ste_attr->rtc_1;
348 : 0 : send_attr->used_id = ste_attr->used_id_rtc_1;
349 : 0 : send_attr->retry_id = ste_attr->retry_rtc_1;
350 : 0 : ret = mlx5dr_send_wqe_fw(ibv_ctx, pdn, send_attr,
351 : : ste_attr->wqe_ctrl,
352 : 0 : ste_attr->wqe_data,
353 : 0 : ste_attr->wqe_tag,
354 : 0 : ste_attr->range_wqe_data,
355 : 0 : ste_attr->range_wqe_tag,
356 : 0 : ste_attr->wqe_tag_is_jumbo,
357 : 0 : ste_attr->gta_opcode);
358 [ # # ]: 0 : if (ret)
359 : 0 : goto fail_rule;
360 : : }
361 : :
362 [ # # ]: 0 : if (ste_attr->rtc_0) {
363 : 0 : send_attr->id = ste_attr->rtc_0;
364 : 0 : send_attr->used_id = ste_attr->used_id_rtc_0;
365 : 0 : send_attr->retry_id = ste_attr->retry_rtc_0;
366 : 0 : ret = mlx5dr_send_wqe_fw(ibv_ctx, pdn, send_attr,
367 : : ste_attr->wqe_ctrl,
368 : 0 : ste_attr->wqe_data,
369 : 0 : ste_attr->wqe_tag,
370 : 0 : ste_attr->range_wqe_data,
371 : 0 : ste_attr->range_wqe_tag,
372 : 0 : ste_attr->wqe_tag_is_jumbo,
373 : 0 : ste_attr->gta_opcode);
374 [ # # ]: 0 : if (ret)
375 : 0 : goto fail_rule;
376 : : }
377 : :
378 : : /* Increase the status, this only works on good flow as the enum
379 : : * is arrange it away creating -> created -> deleting -> deleted
380 : : */
381 : 0 : rule->status++;
382 : 0 : mlx5dr_send_engine_gen_comp(queue, send_attr->user_data, RTE_FLOW_OP_SUCCESS);
383 : : return;
384 : :
385 : 0 : fail_rule:
386 [ # # ]: 0 : rule->status = !rule->rtc_0 && !rule->rtc_1 ?
387 : : MLX5DR_RULE_STATUS_FAILED : MLX5DR_RULE_STATUS_FAILING;
388 : 0 : mlx5dr_send_engine_gen_comp(queue, send_attr->user_data, RTE_FLOW_OP_ERROR);
389 : : }
390 : :
391 : 0 : static void mlx5dr_send_engine_retry_post_send(struct mlx5dr_send_engine *queue,
392 : : struct mlx5dr_send_ring_priv *priv,
393 : : uint16_t wqe_cnt)
394 : : {
395 : 0 : struct mlx5dr_send_engine_post_attr send_attr = {0};
396 : : struct mlx5dr_wqe_gta_data_seg_ste *wqe_data;
397 : : struct mlx5dr_wqe_gta_ctrl_seg *wqe_ctrl;
398 : : struct mlx5dr_send_engine_post_ctrl ctrl;
399 : : struct mlx5dr_send_ring_sq *send_sq;
400 : : unsigned int idx;
401 : : size_t wqe_len;
402 : : char *p;
403 : :
404 : 0 : send_attr.rule = priv->rule;
405 : 0 : send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
406 : : send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
407 : 0 : send_attr.len = MLX5_SEND_WQE_BB * 2 - sizeof(struct mlx5dr_wqe_ctrl_seg);
408 : 0 : send_attr.notify_hw = 1;
409 : : send_attr.fence = 0;
410 : 0 : send_attr.user_data = priv->user_data;
411 : 0 : send_attr.id = priv->retry_id;
412 : 0 : send_attr.used_id = priv->used_id;
413 : :
414 : 0 : ctrl = mlx5dr_send_engine_post_start(queue);
415 : 0 : mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
416 : 0 : mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_data, &wqe_len);
417 : :
418 : 0 : send_sq = &ctrl.send_ring->send_sq;
419 : 0 : idx = wqe_cnt & send_sq->buf_mask;
420 : 0 : p = send_sq->buf + (idx << MLX5_SEND_WQE_SHIFT);
421 : :
422 : : /* Copy old gta ctrl */
423 : 0 : memcpy(wqe_ctrl, p + sizeof(struct mlx5dr_wqe_ctrl_seg),
424 : : MLX5_SEND_WQE_BB - sizeof(struct mlx5dr_wqe_ctrl_seg));
425 : :
426 : 0 : idx = (wqe_cnt + 1) & send_sq->buf_mask;
427 : 0 : p = send_sq->buf + (idx << MLX5_SEND_WQE_SHIFT);
428 : :
429 : : /* Copy old gta data */
430 : 0 : memcpy(wqe_data, p, MLX5_SEND_WQE_BB);
431 : :
432 : 0 : mlx5dr_send_engine_post_end(&ctrl, &send_attr);
433 : 0 : }
434 : :
435 : 0 : void mlx5dr_send_engine_flush_queue(struct mlx5dr_send_engine *queue)
436 : : {
437 : : struct mlx5dr_send_ring_sq *sq = &queue->send_ring[0].send_sq;
438 : : struct mlx5dr_wqe_ctrl_seg *wqe_ctrl;
439 : :
440 : 0 : wqe_ctrl = (void *)(sq->buf + (sq->last_idx << MLX5_SEND_WQE_SHIFT));
441 : :
442 : 0 : wqe_ctrl->flags |= rte_cpu_to_be_32(MLX5_WQE_CTRL_CQ_UPDATE);
443 : :
444 : 0 : mlx5dr_send_engine_post_ring(sq, queue->uar, wqe_ctrl);
445 : 0 : }
446 : :
447 : 0 : static void mlx5dr_send_engine_update_rule(struct mlx5dr_send_engine *queue,
448 : : struct mlx5dr_send_ring_priv *priv,
449 : : uint16_t wqe_cnt,
450 : : enum rte_flow_op_status *status)
451 : : {
452 : 0 : priv->rule->pending_wqes--;
453 : :
454 [ # # ]: 0 : if (*status == RTE_FLOW_OP_ERROR) {
455 [ # # ]: 0 : if (priv->retry_id) {
456 : 0 : mlx5dr_send_engine_retry_post_send(queue, priv, wqe_cnt);
457 : 0 : return;
458 : : }
459 : : /* Some part of the rule failed */
460 : 0 : priv->rule->status = MLX5DR_RULE_STATUS_FAILING;
461 : 0 : *priv->used_id = 0;
462 : : } else {
463 : 0 : *priv->used_id = priv->id;
464 : : }
465 : :
466 : : /* Update rule status for the last completion */
467 [ # # ]: 0 : if (!priv->rule->pending_wqes) {
468 [ # # ]: 0 : if (unlikely(priv->rule->status == MLX5DR_RULE_STATUS_FAILING)) {
469 : : /* Rule completely failed and doesn't require cleanup */
470 [ # # ]: 0 : if (!priv->rule->rtc_0 && !priv->rule->rtc_1)
471 : 0 : priv->rule->status = MLX5DR_RULE_STATUS_FAILED;
472 : :
473 : 0 : *status = RTE_FLOW_OP_ERROR;
474 : : } else {
475 : : /* Increase the status, this only works on good flow as the enum
476 : : * is arrange it away creating -> created -> deleting -> deleted
477 : : */
478 : 0 : priv->rule->status++;
479 : 0 : *status = RTE_FLOW_OP_SUCCESS;
480 : : /* Rule was deleted now we can safely release action STEs */
481 [ # # ]: 0 : if (priv->rule->status == MLX5DR_RULE_STATUS_DELETED)
482 : 0 : mlx5dr_rule_free_action_ste_idx(priv->rule);
483 : : }
484 : : }
485 : : }
486 : :
487 : 0 : static void mlx5dr_send_engine_update(struct mlx5dr_send_engine *queue,
488 : : struct mlx5_cqe64 *cqe,
489 : : struct mlx5dr_send_ring_priv *priv,
490 : : struct rte_flow_op_result res[],
491 : : int64_t *i,
492 : : uint32_t res_nb,
493 : : uint16_t wqe_cnt)
494 : : {
495 : : enum rte_flow_op_status status;
496 : :
497 [ # # # # : 0 : if (!cqe || (likely(rte_be_to_cpu_32(cqe->byte_cnt) >> 31 == 0) &&
# # ]
498 [ # # ]: 0 : likely(mlx5dv_get_cqe_opcode(cqe) == MLX5_CQE_REQ))) {
499 : 0 : status = RTE_FLOW_OP_SUCCESS;
500 : : } else {
501 : 0 : status = RTE_FLOW_OP_ERROR;
502 : : }
503 : :
504 [ # # ]: 0 : if (priv->user_data) {
505 [ # # ]: 0 : if (priv->rule) {
506 : 0 : mlx5dr_send_engine_update_rule(queue, priv, wqe_cnt, &status);
507 : : /* Completion is provided on the last rule WQE */
508 [ # # ]: 0 : if (priv->rule->pending_wqes)
509 : 0 : return;
510 : : }
511 : :
512 [ # # ]: 0 : if (*i < res_nb) {
513 : 0 : res[*i].user_data = priv->user_data;
514 : 0 : res[*i].status = status;
515 : 0 : (*i)++;
516 : : mlx5dr_send_engine_dec_rule(queue);
517 : : } else {
518 : 0 : mlx5dr_send_engine_gen_comp(queue, priv->user_data, status);
519 : : }
520 : : }
521 : : }
522 : :
523 : 0 : static void mlx5dr_send_engine_poll_cq(struct mlx5dr_send_engine *queue,
524 : : struct mlx5dr_send_ring *send_ring,
525 : : struct rte_flow_op_result res[],
526 : : int64_t *i,
527 : : uint32_t res_nb)
528 : : {
529 : : struct mlx5dr_send_ring_cq *cq = &send_ring->send_cq;
530 : : struct mlx5dr_send_ring_sq *sq = &send_ring->send_sq;
531 : 0 : uint32_t cq_idx = cq->cons_index & cq->ncqe_mask;
532 : : struct mlx5dr_send_ring_priv *priv;
533 : : struct mlx5_cqe64 *cqe;
534 : : uint32_t offset_cqe64;
535 : : uint8_t cqe_opcode;
536 : : uint8_t cqe_owner;
537 : : uint16_t wqe_cnt;
538 : : uint8_t sw_own;
539 : :
540 : : offset_cqe64 = RTE_CACHE_LINE_SIZE - sizeof(struct mlx5_cqe64);
541 : 0 : cqe = (void *)(cq->buf + (cq_idx << cq->cqe_log_sz) + offset_cqe64);
542 : :
543 [ # # ]: 0 : sw_own = (cq->cons_index & cq->ncqe) ? 1 : 0;
544 : : cqe_opcode = mlx5dv_get_cqe_opcode(cqe);
545 : : cqe_owner = mlx5dv_get_cqe_owner(cqe);
546 : :
547 : 0 : if (cqe_opcode == MLX5_CQE_INVALID ||
548 [ # # ]: 0 : cqe_owner != sw_own)
549 : : return;
550 : :
551 [ # # ]: 0 : if (unlikely(mlx5dv_get_cqe_opcode(cqe) != MLX5_CQE_REQ))
552 : 0 : queue->err = true;
553 : :
554 : 0 : rte_io_rmb();
555 : :
556 : 0 : wqe_cnt = be16toh(cqe->wqe_counter) & sq->buf_mask;
557 : :
558 [ # # ]: 0 : while (cq->poll_wqe != wqe_cnt) {
559 : 0 : priv = &sq->wr_priv[cq->poll_wqe];
560 : 0 : mlx5dr_send_engine_update(queue, NULL, priv, res, i, res_nb, 0);
561 : 0 : cq->poll_wqe = (cq->poll_wqe + priv->num_wqebbs) & sq->buf_mask;
562 : : }
563 : :
564 : 0 : priv = &sq->wr_priv[wqe_cnt];
565 : 0 : cq->poll_wqe = (wqe_cnt + priv->num_wqebbs) & sq->buf_mask;
566 : 0 : mlx5dr_send_engine_update(queue, cqe, priv, res, i, res_nb, wqe_cnt);
567 : 0 : cq->cons_index++;
568 : : }
569 : :
570 : : static void mlx5dr_send_engine_poll_cqs(struct mlx5dr_send_engine *queue,
571 : : struct rte_flow_op_result res[],
572 : : int64_t *polled,
573 : : uint32_t res_nb)
574 : : {
575 : : int j;
576 : :
577 : : for (j = 0; j < MLX5DR_NUM_SEND_RINGS; j++) {
578 : 0 : mlx5dr_send_engine_poll_cq(queue, &queue->send_ring[j],
579 : : res, polled, res_nb);
580 : :
581 : 0 : *queue->send_ring[j].send_cq.db =
582 : 0 : htobe32(queue->send_ring[j].send_cq.cons_index & 0xffffff);
583 : : }
584 : : }
585 : :
586 : 0 : static void mlx5dr_send_engine_poll_list(struct mlx5dr_send_engine *queue,
587 : : struct rte_flow_op_result res[],
588 : : int64_t *polled,
589 : : uint32_t res_nb)
590 : : {
591 : : struct mlx5dr_completed_poll *comp = &queue->completed;
592 : :
593 [ # # ]: 0 : while (comp->ci != comp->pi) {
594 [ # # ]: 0 : if (*polled < res_nb) {
595 : 0 : res[*polled].status =
596 : 0 : comp->entries[comp->ci].status;
597 : 0 : res[*polled].user_data =
598 : 0 : comp->entries[comp->ci].user_data;
599 : 0 : (*polled)++;
600 : 0 : comp->ci = (comp->ci + 1) & comp->mask;
601 : : mlx5dr_send_engine_dec_rule(queue);
602 : : } else {
603 : : return;
604 : : }
605 : : }
606 : : }
607 : :
608 : 0 : static int mlx5dr_send_engine_poll(struct mlx5dr_send_engine *queue,
609 : : struct rte_flow_op_result res[],
610 : : uint32_t res_nb)
611 : : {
612 : 0 : int64_t polled = 0;
613 : :
614 : 0 : mlx5dr_send_engine_poll_list(queue, res, &polled, res_nb);
615 : :
616 [ # # ]: 0 : if (polled >= res_nb)
617 : 0 : return polled;
618 : :
619 : : mlx5dr_send_engine_poll_cqs(queue, res, &polled, res_nb);
620 : :
621 : 0 : return polled;
622 : : }
623 : :
624 : 0 : int mlx5dr_send_queue_poll(struct mlx5dr_context *ctx,
625 : : uint16_t queue_id,
626 : : struct rte_flow_op_result res[],
627 : : uint32_t res_nb)
628 : : {
629 : 0 : return mlx5dr_send_engine_poll(&ctx->send_queue[queue_id],
630 : : res, res_nb);
631 : : }
632 : :
633 : 0 : static int mlx5dr_send_ring_create_sq_obj(struct mlx5dr_context *ctx,
634 : : struct mlx5dr_send_engine *queue,
635 : : struct mlx5dr_send_ring_sq *sq,
636 : : struct mlx5dr_send_ring_cq *cq,
637 : : size_t log_wq_sz)
638 : : {
639 : 0 : struct mlx5dr_cmd_sq_create_attr attr = {0};
640 : : int err;
641 : :
642 : 0 : attr.cqn = cq->cqn;
643 : 0 : attr.pdn = ctx->pd_num;
644 : 0 : attr.page_id = queue->uar->page_id;
645 : 0 : attr.dbr_id = sq->db_umem->umem_id;
646 : 0 : attr.wq_id = sq->buf_umem->umem_id;
647 : 0 : attr.log_wq_sz = log_wq_sz;
648 [ # # ]: 0 : if (ctx->caps->sq_ts_format == MLX5_HCA_CAP_TIMESTAMP_FORMAT_FR)
649 : : attr.ts_format = MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING;
650 : : else
651 : 0 : attr.ts_format = MLX5_QPC_TIMESTAMP_FORMAT_DEFAULT;
652 : :
653 : 0 : sq->obj = mlx5dr_cmd_sq_create(ctx->ibv_ctx, &attr);
654 [ # # ]: 0 : if (!sq->obj)
655 : 0 : return rte_errno;
656 : :
657 : 0 : sq->sqn = sq->obj->id;
658 : :
659 : 0 : err = mlx5dr_cmd_sq_modify_rdy(sq->obj);
660 [ # # ]: 0 : if (err)
661 : 0 : goto free_sq;
662 : :
663 : : return 0;
664 : :
665 : : free_sq:
666 : 0 : mlx5dr_cmd_destroy_obj(sq->obj);
667 : :
668 : 0 : return err;
669 : : }
670 : :
671 : 0 : static int mlx5dr_send_ring_open_sq(struct mlx5dr_context *ctx,
672 : : struct mlx5dr_send_engine *queue,
673 : : struct mlx5dr_send_ring_sq *sq,
674 : : struct mlx5dr_send_ring_cq *cq)
675 : : {
676 : : size_t sq_log_buf_sz;
677 : : size_t buf_aligned;
678 : : size_t sq_buf_sz;
679 : : size_t page_size;
680 : : size_t buf_sz;
681 : : int err;
682 : :
683 : 0 : buf_sz = queue->num_entries * MAX_WQES_PER_RULE;
684 : 0 : sq_log_buf_sz = log2above(buf_sz);
685 : 0 : sq_buf_sz = 1 << (sq_log_buf_sz + log2above(MLX5_SEND_WQE_BB));
686 : 0 : sq->reg_addr = queue->uar->reg_addr;
687 : :
688 : 0 : page_size = sysconf(_SC_PAGESIZE);
689 : : buf_aligned = align(sq_buf_sz, page_size);
690 : 0 : err = posix_memalign((void **)&sq->buf, page_size, buf_aligned);
691 [ # # ]: 0 : if (err) {
692 : 0 : rte_errno = ENOMEM;
693 : 0 : return err;
694 : : }
695 : 0 : memset(sq->buf, 0, buf_aligned);
696 : :
697 : 0 : err = posix_memalign((void **)&sq->db, 8, 8);
698 [ # # ]: 0 : if (err)
699 : 0 : goto free_buf;
700 : :
701 : 0 : sq->buf_umem = mlx5_glue->devx_umem_reg(ctx->ibv_ctx, sq->buf, sq_buf_sz, 0);
702 : :
703 [ # # ]: 0 : if (!sq->buf_umem) {
704 : 0 : err = errno;
705 : 0 : goto free_db;
706 : : }
707 : :
708 : 0 : sq->db_umem = mlx5_glue->devx_umem_reg(ctx->ibv_ctx, sq->db, 8, 0);
709 [ # # ]: 0 : if (!sq->db_umem) {
710 : 0 : err = errno;
711 : 0 : goto free_buf_umem;
712 : : }
713 : :
714 : 0 : err = mlx5dr_send_ring_create_sq_obj(ctx, queue, sq, cq, sq_log_buf_sz);
715 : :
716 [ # # ]: 0 : if (err)
717 : 0 : goto free_db_umem;
718 : :
719 : 0 : sq->wr_priv = simple_malloc(sizeof(*sq->wr_priv) * buf_sz);
720 [ # # ]: 0 : if (!sq->wr_priv) {
721 : : err = ENOMEM;
722 : 0 : goto destroy_sq_obj;
723 : : }
724 : :
725 : 0 : sq->dep_wqe = simple_calloc(queue->num_entries, sizeof(*sq->dep_wqe));
726 [ # # ]: 0 : if (!sq->dep_wqe) {
727 : : err = ENOMEM;
728 : 0 : goto destroy_wr_priv;
729 : : }
730 : :
731 : 0 : sq->buf_mask = buf_sz - 1;
732 : :
733 : 0 : return 0;
734 : :
735 : : destroy_wr_priv:
736 : 0 : simple_free(sq->wr_priv);
737 : 0 : destroy_sq_obj:
738 : 0 : mlx5dr_cmd_destroy_obj(sq->obj);
739 : 0 : free_db_umem:
740 : 0 : mlx5_glue->devx_umem_dereg(sq->db_umem);
741 : 0 : free_buf_umem:
742 : 0 : mlx5_glue->devx_umem_dereg(sq->buf_umem);
743 : 0 : free_db:
744 : 0 : free(sq->db);
745 : 0 : free_buf:
746 : 0 : free(sq->buf);
747 : 0 : rte_errno = err;
748 : 0 : return err;
749 : : }
750 : :
751 : 0 : static void mlx5dr_send_ring_close_sq(struct mlx5dr_send_ring_sq *sq)
752 : : {
753 : 0 : simple_free(sq->dep_wqe);
754 : 0 : mlx5dr_cmd_destroy_obj(sq->obj);
755 : 0 : mlx5_glue->devx_umem_dereg(sq->db_umem);
756 : 0 : mlx5_glue->devx_umem_dereg(sq->buf_umem);
757 : 0 : simple_free(sq->wr_priv);
758 : 0 : free(sq->db);
759 : 0 : free(sq->buf);
760 : 0 : }
761 : :
762 : 0 : static int mlx5dr_send_ring_open_cq(struct mlx5dr_context *ctx,
763 : : struct mlx5dr_send_engine *queue,
764 : : struct mlx5dr_send_ring_cq *cq)
765 : : {
766 : 0 : struct mlx5dv_cq mlx5_cq = {0};
767 : : struct mlx5dv_obj obj;
768 : : struct ibv_cq *ibv_cq;
769 : : size_t cq_size;
770 : : int err;
771 : :
772 : 0 : cq_size = queue->num_entries;
773 : 0 : ibv_cq = mlx5_glue->create_cq(ctx->ibv_ctx, cq_size, NULL, NULL, 0);
774 [ # # ]: 0 : if (!ibv_cq) {
775 : 0 : DR_LOG(ERR, "Failed to create CQ");
776 : 0 : rte_errno = errno;
777 : 0 : return rte_errno;
778 : : }
779 : :
780 : 0 : obj.cq.in = ibv_cq;
781 : 0 : obj.cq.out = &mlx5_cq;
782 : 0 : err = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_CQ);
783 [ # # ]: 0 : if (err) {
784 : 0 : err = errno;
785 : 0 : goto close_cq;
786 : : }
787 : :
788 : 0 : cq->buf = mlx5_cq.buf;
789 : 0 : cq->db = mlx5_cq.dbrec;
790 : 0 : cq->ncqe = mlx5_cq.cqe_cnt;
791 : 0 : cq->cqe_sz = mlx5_cq.cqe_size;
792 : 0 : cq->cqe_log_sz = log2above(cq->cqe_sz);
793 : 0 : cq->ncqe_mask = cq->ncqe - 1;
794 : 0 : cq->buf_sz = cq->cqe_sz * cq->ncqe;
795 : 0 : cq->cqn = mlx5_cq.cqn;
796 : 0 : cq->ibv_cq = ibv_cq;
797 : :
798 : 0 : return 0;
799 : :
800 : : close_cq:
801 : 0 : mlx5_glue->destroy_cq(ibv_cq);
802 : 0 : rte_errno = err;
803 : 0 : return err;
804 : : }
805 : :
806 : : static void mlx5dr_send_ring_close_cq(struct mlx5dr_send_ring_cq *cq)
807 : : {
808 : 0 : mlx5_glue->destroy_cq(cq->ibv_cq);
809 : : }
810 : :
811 : : static void mlx5dr_send_ring_close(struct mlx5dr_send_ring *ring)
812 : : {
813 : 0 : mlx5dr_send_ring_close_sq(&ring->send_sq);
814 : : mlx5dr_send_ring_close_cq(&ring->send_cq);
815 : 0 : }
816 : :
817 : 0 : static int mlx5dr_send_ring_open(struct mlx5dr_context *ctx,
818 : : struct mlx5dr_send_engine *queue,
819 : : struct mlx5dr_send_ring *ring)
820 : : {
821 : : int err;
822 : :
823 : 0 : err = mlx5dr_send_ring_open_cq(ctx, queue, &ring->send_cq);
824 [ # # ]: 0 : if (err)
825 : : return err;
826 : :
827 : 0 : err = mlx5dr_send_ring_open_sq(ctx, queue, &ring->send_sq, &ring->send_cq);
828 [ # # ]: 0 : if (err)
829 : 0 : goto close_cq;
830 : :
831 : : return err;
832 : :
833 : : close_cq:
834 : : mlx5dr_send_ring_close_cq(&ring->send_cq);
835 : :
836 : 0 : return err;
837 : : }
838 : :
839 : 0 : static void __mlx5dr_send_rings_close(struct mlx5dr_send_engine *queue,
840 : : uint16_t i)
841 : : {
842 [ # # ]: 0 : while (i--)
843 : 0 : mlx5dr_send_ring_close(&queue->send_ring[i]);
844 : 0 : }
845 : :
846 : : static void mlx5dr_send_rings_close(struct mlx5dr_send_engine *queue)
847 : : {
848 : 0 : __mlx5dr_send_rings_close(queue, queue->rings);
849 : : }
850 : :
851 : 0 : static int mlx5dr_send_rings_open(struct mlx5dr_context *ctx,
852 : : struct mlx5dr_send_engine *queue)
853 : : {
854 : : uint16_t i;
855 : : int err;
856 : :
857 [ # # ]: 0 : for (i = 0; i < queue->rings; i++) {
858 : 0 : err = mlx5dr_send_ring_open(ctx, queue, &queue->send_ring[i]);
859 [ # # ]: 0 : if (err)
860 : 0 : goto free_rings;
861 : : }
862 : :
863 : : return 0;
864 : :
865 : : free_rings:
866 : 0 : __mlx5dr_send_rings_close(queue, i);
867 : :
868 : 0 : return err;
869 : : }
870 : :
871 : 0 : void mlx5dr_send_queue_close(struct mlx5dr_send_engine *queue)
872 : : {
873 : : mlx5dr_send_rings_close(queue);
874 : 0 : simple_free(queue->completed.entries);
875 : 0 : mlx5_glue->devx_free_uar(queue->uar);
876 : 0 : }
877 : :
878 : 0 : int mlx5dr_send_queue_open(struct mlx5dr_context *ctx,
879 : : struct mlx5dr_send_engine *queue,
880 : : uint16_t queue_size)
881 : : {
882 : : struct mlx5dv_devx_uar *uar;
883 : : int err;
884 : :
885 : : #ifdef MLX5DV_UAR_ALLOC_TYPE_NC
886 : 0 : uar = mlx5_glue->devx_alloc_uar(ctx->ibv_ctx, MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC);
887 [ # # ]: 0 : if (!uar) {
888 : 0 : rte_errno = errno;
889 : 0 : return rte_errno;
890 : : }
891 : : #else
892 : : uar = NULL;
893 : : rte_errno = ENOTSUP;
894 : : return rte_errno;
895 : : #endif
896 : :
897 : 0 : queue->uar = uar;
898 : 0 : queue->rings = MLX5DR_NUM_SEND_RINGS;
899 [ # # ]: 0 : queue->num_entries = roundup_pow_of_two(queue_size);
900 : 0 : queue->used_entries = 0;
901 : 0 : queue->th_entries = queue->num_entries;
902 : :
903 : 0 : queue->completed.entries = simple_calloc(queue->num_entries,
904 : : sizeof(queue->completed.entries[0]));
905 [ # # ]: 0 : if (!queue->completed.entries) {
906 : 0 : rte_errno = ENOMEM;
907 : 0 : goto free_uar;
908 : : }
909 : 0 : queue->completed.pi = 0;
910 : 0 : queue->completed.ci = 0;
911 : 0 : queue->completed.mask = queue->num_entries - 1;
912 : :
913 : 0 : err = mlx5dr_send_rings_open(ctx, queue);
914 [ # # ]: 0 : if (err)
915 : 0 : goto free_completed_entries;
916 : :
917 : : return 0;
918 : :
919 : : free_completed_entries:
920 : 0 : simple_free(queue->completed.entries);
921 : 0 : free_uar:
922 : 0 : mlx5_glue->devx_free_uar(uar);
923 : 0 : return rte_errno;
924 : : }
925 : :
926 : : static void __mlx5dr_send_queues_close(struct mlx5dr_context *ctx, uint16_t queues)
927 : : {
928 : : struct mlx5dr_send_engine *queue;
929 : :
930 [ # # # # ]: 0 : while (queues--) {
931 : 0 : queue = &ctx->send_queue[queues];
932 : :
933 : 0 : mlx5dr_send_queue_close(queue);
934 : : }
935 : : }
936 : :
937 : 0 : void mlx5dr_send_queues_close(struct mlx5dr_context *ctx)
938 : : {
939 : 0 : __mlx5dr_send_queues_close(ctx, ctx->queues);
940 : 0 : simple_free(ctx->send_queue);
941 : 0 : }
942 : :
943 : 0 : int mlx5dr_send_queues_open(struct mlx5dr_context *ctx,
944 : : uint16_t queues,
945 : : uint16_t queue_size)
946 : : {
947 : : int err = 0;
948 : : uint32_t i;
949 : :
950 : : /* Open one extra queue for control path */
951 : 0 : ctx->queues = queues + 1;
952 : :
953 : 0 : ctx->send_queue = simple_calloc(ctx->queues, sizeof(*ctx->send_queue));
954 [ # # ]: 0 : if (!ctx->send_queue) {
955 : 0 : rte_errno = ENOMEM;
956 : 0 : return rte_errno;
957 : : }
958 : :
959 [ # # ]: 0 : for (i = 0; i < ctx->queues; i++) {
960 : 0 : err = mlx5dr_send_queue_open(ctx, &ctx->send_queue[i], queue_size);
961 [ # # ]: 0 : if (err)
962 : 0 : goto close_send_queues;
963 : : }
964 : :
965 : : return 0;
966 : :
967 : : close_send_queues:
968 : 0 : __mlx5dr_send_queues_close(ctx, i);
969 : :
970 : 0 : simple_free(ctx->send_queue);
971 : :
972 : 0 : return err;
973 : : }
974 : :
975 : 0 : int mlx5dr_send_queue_action(struct mlx5dr_context *ctx,
976 : : uint16_t queue_id,
977 : : uint32_t actions)
978 : : {
979 : : struct mlx5dr_send_ring_sq *send_sq;
980 : : struct mlx5dr_send_engine *queue;
981 : : bool wait_comp = false;
982 : 0 : int64_t polled = 0;
983 : :
984 : 0 : queue = &ctx->send_queue[queue_id];
985 : : send_sq = &queue->send_ring->send_sq;
986 : :
987 [ # # # ]: 0 : switch (actions) {
988 : 0 : case MLX5DR_SEND_QUEUE_ACTION_DRAIN_SYNC:
989 : : wait_comp = true;
990 : : /* FALLTHROUGH */
991 : 0 : case MLX5DR_SEND_QUEUE_ACTION_DRAIN_ASYNC:
992 [ # # ]: 0 : if (send_sq->head_dep_idx != send_sq->tail_dep_idx)
993 : : /* Send dependent WQEs to drain the queue */
994 : 0 : mlx5dr_send_all_dep_wqe(queue);
995 : : else
996 : : /* Signal on the last posted WQE */
997 : 0 : mlx5dr_send_engine_flush_queue(queue);
998 : :
999 : : /* Poll queue until empty */
1000 [ # # # # ]: 0 : while (wait_comp && !mlx5dr_send_engine_empty(queue))
1001 : : mlx5dr_send_engine_poll_cqs(queue, NULL, &polled, 0);
1002 : :
1003 : : break;
1004 : 0 : default:
1005 : 0 : rte_errno = EINVAL;
1006 : 0 : return -rte_errno;
1007 : : }
1008 : :
1009 : : return 0;
1010 : : }
|