xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3 
4 #include "internal.h"
5 #include "lib/clock.h"
6 
7 enum { CQ_OK = 0, CQ_EMPTY = -1, CQ_POLL_ERR = -2 };
8 
9 struct mlx5hws_send_ring_dep_wqe *
mlx5hws_send_add_new_dep_wqe(struct mlx5hws_send_engine * queue)10 mlx5hws_send_add_new_dep_wqe(struct mlx5hws_send_engine *queue)
11 {
12 	struct mlx5hws_send_ring_sq *send_sq = &queue->send_ring.send_sq;
13 	unsigned int idx = send_sq->head_dep_idx++ & (queue->num_entries - 1);
14 
15 	memset(&send_sq->dep_wqe[idx].wqe_data.tag, 0, MLX5HWS_MATCH_TAG_SZ);
16 
17 	return &send_sq->dep_wqe[idx];
18 }
19 
mlx5hws_send_abort_new_dep_wqe(struct mlx5hws_send_engine * queue)20 void mlx5hws_send_abort_new_dep_wqe(struct mlx5hws_send_engine *queue)
21 {
22 	queue->send_ring.send_sq.head_dep_idx--;
23 }
24 
mlx5hws_send_all_dep_wqe(struct mlx5hws_send_engine * queue)25 void mlx5hws_send_all_dep_wqe(struct mlx5hws_send_engine *queue)
26 {
27 	struct mlx5hws_send_ring_sq *send_sq = &queue->send_ring.send_sq;
28 	struct mlx5hws_send_ste_attr ste_attr = {0};
29 	struct mlx5hws_send_ring_dep_wqe *dep_wqe;
30 
31 	ste_attr.send_attr.opmod = MLX5HWS_WQE_GTA_OPMOD_STE;
32 	ste_attr.send_attr.opcode = MLX5HWS_WQE_OPCODE_TBL_ACCESS;
33 	ste_attr.send_attr.len = MLX5HWS_WQE_SZ_GTA_CTRL + MLX5HWS_WQE_SZ_GTA_DATA;
34 	ste_attr.gta_opcode = MLX5HWS_WQE_GTA_OP_ACTIVATE;
35 
36 	/* Fence first from previous depend WQEs  */
37 	ste_attr.send_attr.fence = 1;
38 
39 	while (send_sq->head_dep_idx != send_sq->tail_dep_idx) {
40 		dep_wqe = &send_sq->dep_wqe[send_sq->tail_dep_idx++ & (queue->num_entries - 1)];
41 
42 		/* Notify HW on the last WQE */
43 		ste_attr.send_attr.notify_hw = (send_sq->tail_dep_idx == send_sq->head_dep_idx);
44 		ste_attr.send_attr.user_data = dep_wqe->user_data;
45 		ste_attr.send_attr.rule = dep_wqe->rule;
46 
47 		ste_attr.rtc_0 = dep_wqe->rtc_0;
48 		ste_attr.rtc_1 = dep_wqe->rtc_1;
49 		ste_attr.retry_rtc_0 = dep_wqe->retry_rtc_0;
50 		ste_attr.retry_rtc_1 = dep_wqe->retry_rtc_1;
51 		ste_attr.used_id_rtc_0 = &dep_wqe->rule->rtc_0;
52 		ste_attr.used_id_rtc_1 = &dep_wqe->rule->rtc_1;
53 		ste_attr.wqe_ctrl = &dep_wqe->wqe_ctrl;
54 		ste_attr.wqe_data = &dep_wqe->wqe_data;
55 		ste_attr.direct_index = dep_wqe->direct_index;
56 
57 		mlx5hws_send_ste(queue, &ste_attr);
58 
59 		/* Fencing is done only on the first WQE */
60 		ste_attr.send_attr.fence = 0;
61 	}
62 }
63 
64 struct mlx5hws_send_engine_post_ctrl
mlx5hws_send_engine_post_start(struct mlx5hws_send_engine * queue)65 mlx5hws_send_engine_post_start(struct mlx5hws_send_engine *queue)
66 {
67 	struct mlx5hws_send_engine_post_ctrl ctrl;
68 
69 	ctrl.queue = queue;
70 	/* Currently only one send ring is supported */
71 	ctrl.send_ring = &queue->send_ring;
72 	ctrl.num_wqebbs = 0;
73 
74 	return ctrl;
75 }
76 
mlx5hws_send_engine_post_req_wqe(struct mlx5hws_send_engine_post_ctrl * ctrl,char ** buf,size_t * len)77 void mlx5hws_send_engine_post_req_wqe(struct mlx5hws_send_engine_post_ctrl *ctrl,
78 				      char **buf, size_t *len)
79 {
80 	struct mlx5hws_send_ring_sq *send_sq = &ctrl->send_ring->send_sq;
81 	unsigned int idx;
82 
83 	idx = (send_sq->cur_post + ctrl->num_wqebbs) & send_sq->buf_mask;
84 
85 	/* Note that *buf is a single MLX5_SEND_WQE_BB. It cannot be used
86 	 * as buffer of more than one WQE_BB, since the two MLX5_SEND_WQE_BB
87 	 * can be on 2 different kernel memory pages.
88 	 */
89 	*buf = mlx5_wq_cyc_get_wqe(&send_sq->wq, idx);
90 	*len = MLX5_SEND_WQE_BB;
91 
92 	if (!ctrl->num_wqebbs) {
93 		*buf += sizeof(struct mlx5hws_wqe_ctrl_seg);
94 		*len -= sizeof(struct mlx5hws_wqe_ctrl_seg);
95 	}
96 
97 	ctrl->num_wqebbs++;
98 }
99 
hws_send_engine_post_ring(struct mlx5hws_send_ring_sq * sq,struct mlx5hws_wqe_ctrl_seg * doorbell_cseg)100 static void hws_send_engine_post_ring(struct mlx5hws_send_ring_sq *sq,
101 				      struct mlx5hws_wqe_ctrl_seg *doorbell_cseg)
102 {
103 	/* ensure wqe is visible to device before updating doorbell record */
104 	dma_wmb();
105 
106 	*sq->wq.db = cpu_to_be32(sq->cur_post);
107 
108 	/* ensure doorbell record is visible to device before ringing the
109 	 * doorbell
110 	 */
111 	wmb();
112 
113 	mlx5_write64((__be32 *)doorbell_cseg, sq->uar_map);
114 
115 	/* Ensure doorbell is written on uar_page before poll_cq */
116 	WRITE_ONCE(doorbell_cseg, NULL);
117 }
118 
119 static void
hws_send_wqe_set_tag(struct mlx5hws_wqe_gta_data_seg_ste * wqe_data,struct mlx5hws_rule_match_tag * tag,bool is_jumbo)120 hws_send_wqe_set_tag(struct mlx5hws_wqe_gta_data_seg_ste *wqe_data,
121 		     struct mlx5hws_rule_match_tag *tag,
122 		     bool is_jumbo)
123 {
124 	if (is_jumbo) {
125 		/* Clear previous possibly dirty control */
126 		memset(wqe_data, 0, MLX5HWS_STE_CTRL_SZ);
127 		memcpy(wqe_data->jumbo, tag->jumbo, MLX5HWS_JUMBO_TAG_SZ);
128 	} else {
129 		/* Clear previous possibly dirty control and actions */
130 		memset(wqe_data, 0, MLX5HWS_STE_CTRL_SZ + MLX5HWS_ACTIONS_SZ);
131 		memcpy(wqe_data->tag, tag->match, MLX5HWS_MATCH_TAG_SZ);
132 	}
133 }
134 
mlx5hws_send_engine_post_end(struct mlx5hws_send_engine_post_ctrl * ctrl,struct mlx5hws_send_engine_post_attr * attr)135 void mlx5hws_send_engine_post_end(struct mlx5hws_send_engine_post_ctrl *ctrl,
136 				  struct mlx5hws_send_engine_post_attr *attr)
137 {
138 	struct mlx5hws_wqe_ctrl_seg *wqe_ctrl;
139 	struct mlx5hws_send_ring_sq *sq;
140 	unsigned int idx;
141 	u32 flags = 0;
142 
143 	sq = &ctrl->send_ring->send_sq;
144 	idx = sq->cur_post & sq->buf_mask;
145 	sq->last_idx = idx;
146 
147 	wqe_ctrl = mlx5_wq_cyc_get_wqe(&sq->wq, idx);
148 
149 	wqe_ctrl->opmod_idx_opcode =
150 		cpu_to_be32((attr->opmod << 24) |
151 			    ((sq->cur_post & 0xffff) << 8) |
152 			    attr->opcode);
153 	wqe_ctrl->qpn_ds =
154 		cpu_to_be32((attr->len + sizeof(struct mlx5hws_wqe_ctrl_seg)) / 16 |
155 				 sq->sqn << 8);
156 	wqe_ctrl->imm = cpu_to_be32(attr->id);
157 
158 	flags |= attr->notify_hw ? MLX5_WQE_CTRL_CQ_UPDATE : 0;
159 	flags |= attr->fence ? MLX5_WQE_CTRL_INITIATOR_SMALL_FENCE : 0;
160 	wqe_ctrl->flags = cpu_to_be32(flags);
161 
162 	sq->wr_priv[idx].id = attr->id;
163 	sq->wr_priv[idx].retry_id = attr->retry_id;
164 
165 	sq->wr_priv[idx].rule = attr->rule;
166 	sq->wr_priv[idx].user_data = attr->user_data;
167 	sq->wr_priv[idx].num_wqebbs = ctrl->num_wqebbs;
168 
169 	if (attr->rule) {
170 		sq->wr_priv[idx].rule->pending_wqes++;
171 		sq->wr_priv[idx].used_id = attr->used_id;
172 	}
173 
174 	sq->cur_post += ctrl->num_wqebbs;
175 
176 	if (attr->notify_hw)
177 		hws_send_engine_post_ring(sq, wqe_ctrl);
178 }
179 
hws_send_wqe(struct mlx5hws_send_engine * queue,struct mlx5hws_send_engine_post_attr * send_attr,struct mlx5hws_wqe_gta_ctrl_seg * send_wqe_ctrl,void * send_wqe_data,void * send_wqe_tag,bool is_jumbo,u8 gta_opcode,u32 direct_index)180 static void hws_send_wqe(struct mlx5hws_send_engine *queue,
181 			 struct mlx5hws_send_engine_post_attr *send_attr,
182 			 struct mlx5hws_wqe_gta_ctrl_seg *send_wqe_ctrl,
183 			 void *send_wqe_data,
184 			 void *send_wqe_tag,
185 			 bool is_jumbo,
186 			 u8 gta_opcode,
187 			 u32 direct_index)
188 {
189 	struct mlx5hws_wqe_gta_data_seg_ste *wqe_data;
190 	struct mlx5hws_wqe_gta_ctrl_seg *wqe_ctrl;
191 	struct mlx5hws_send_engine_post_ctrl ctrl;
192 	size_t wqe_len;
193 
194 	ctrl = mlx5hws_send_engine_post_start(queue);
195 	mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
196 	mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_data, &wqe_len);
197 
198 	wqe_ctrl->op_dirix = cpu_to_be32(gta_opcode << 28 | direct_index);
199 	memcpy(wqe_ctrl->stc_ix, send_wqe_ctrl->stc_ix,
200 	       sizeof(send_wqe_ctrl->stc_ix));
201 
202 	if (send_wqe_data)
203 		memcpy(wqe_data, send_wqe_data, sizeof(*wqe_data));
204 	else
205 		hws_send_wqe_set_tag(wqe_data, send_wqe_tag, is_jumbo);
206 
207 	mlx5hws_send_engine_post_end(&ctrl, send_attr);
208 }
209 
mlx5hws_send_ste(struct mlx5hws_send_engine * queue,struct mlx5hws_send_ste_attr * ste_attr)210 void mlx5hws_send_ste(struct mlx5hws_send_engine *queue,
211 		      struct mlx5hws_send_ste_attr *ste_attr)
212 {
213 	struct mlx5hws_send_engine_post_attr *send_attr = &ste_attr->send_attr;
214 	u8 notify_hw = send_attr->notify_hw;
215 	u8 fence = send_attr->fence;
216 
217 	if (ste_attr->rtc_1) {
218 		send_attr->id = ste_attr->rtc_1;
219 		send_attr->used_id = ste_attr->used_id_rtc_1;
220 		send_attr->retry_id = ste_attr->retry_rtc_1;
221 		send_attr->fence = fence;
222 		send_attr->notify_hw = notify_hw && !ste_attr->rtc_0;
223 		hws_send_wqe(queue, send_attr,
224 			     ste_attr->wqe_ctrl,
225 			     ste_attr->wqe_data,
226 			     ste_attr->wqe_tag,
227 			     ste_attr->wqe_tag_is_jumbo,
228 			     ste_attr->gta_opcode,
229 			     ste_attr->direct_index);
230 	}
231 
232 	if (ste_attr->rtc_0) {
233 		send_attr->id = ste_attr->rtc_0;
234 		send_attr->used_id = ste_attr->used_id_rtc_0;
235 		send_attr->retry_id = ste_attr->retry_rtc_0;
236 		send_attr->fence = fence && !ste_attr->rtc_1;
237 		send_attr->notify_hw = notify_hw;
238 		hws_send_wqe(queue, send_attr,
239 			     ste_attr->wqe_ctrl,
240 			     ste_attr->wqe_data,
241 			     ste_attr->wqe_tag,
242 			     ste_attr->wqe_tag_is_jumbo,
243 			     ste_attr->gta_opcode,
244 			     ste_attr->direct_index);
245 	}
246 
247 	/* Restore to original requested values */
248 	send_attr->notify_hw = notify_hw;
249 	send_attr->fence = fence;
250 }
251 
hws_send_engine_retry_post_send(struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_priv * priv,u16 wqe_cnt)252 static void hws_send_engine_retry_post_send(struct mlx5hws_send_engine *queue,
253 					    struct mlx5hws_send_ring_priv *priv,
254 					    u16 wqe_cnt)
255 {
256 	struct mlx5hws_send_engine_post_attr send_attr = {0};
257 	struct mlx5hws_wqe_gta_data_seg_ste *wqe_data;
258 	struct mlx5hws_wqe_gta_ctrl_seg *wqe_ctrl;
259 	struct mlx5hws_send_engine_post_ctrl ctrl;
260 	struct mlx5hws_send_ring_sq *send_sq;
261 	unsigned int idx;
262 	size_t wqe_len;
263 	char *p;
264 
265 	send_attr.rule = priv->rule;
266 	send_attr.opcode = MLX5HWS_WQE_OPCODE_TBL_ACCESS;
267 	send_attr.opmod = MLX5HWS_WQE_GTA_OPMOD_STE;
268 	send_attr.len = MLX5_SEND_WQE_BB * 2 - sizeof(struct mlx5hws_wqe_ctrl_seg);
269 	send_attr.notify_hw = 1;
270 	send_attr.fence = 0;
271 	send_attr.user_data = priv->user_data;
272 	send_attr.id = priv->retry_id;
273 	send_attr.used_id = priv->used_id;
274 
275 	ctrl = mlx5hws_send_engine_post_start(queue);
276 	mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
277 	mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_data, &wqe_len);
278 
279 	send_sq = &ctrl.send_ring->send_sq;
280 	idx = wqe_cnt & send_sq->buf_mask;
281 	p = mlx5_wq_cyc_get_wqe(&send_sq->wq, idx);
282 
283 	/* Copy old gta ctrl */
284 	memcpy(wqe_ctrl, p + sizeof(struct mlx5hws_wqe_ctrl_seg),
285 	       MLX5_SEND_WQE_BB - sizeof(struct mlx5hws_wqe_ctrl_seg));
286 
287 	idx = (wqe_cnt + 1) & send_sq->buf_mask;
288 	p = mlx5_wq_cyc_get_wqe(&send_sq->wq, idx);
289 
290 	/* Copy old gta data */
291 	memcpy(wqe_data, p, MLX5_SEND_WQE_BB);
292 
293 	mlx5hws_send_engine_post_end(&ctrl, &send_attr);
294 }
295 
mlx5hws_send_engine_flush_queue(struct mlx5hws_send_engine * queue)296 void mlx5hws_send_engine_flush_queue(struct mlx5hws_send_engine *queue)
297 {
298 	struct mlx5hws_send_ring_sq *sq = &queue->send_ring.send_sq;
299 	struct mlx5hws_wqe_ctrl_seg *wqe_ctrl;
300 
301 	wqe_ctrl = mlx5_wq_cyc_get_wqe(&sq->wq, sq->last_idx);
302 	wqe_ctrl->flags |= cpu_to_be32(MLX5_WQE_CTRL_CQ_UPDATE);
303 
304 	hws_send_engine_post_ring(sq, wqe_ctrl);
305 }
306 
307 static void
hws_send_engine_update_rule_resize(struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_priv * priv,enum mlx5hws_flow_op_status * status)308 hws_send_engine_update_rule_resize(struct mlx5hws_send_engine *queue,
309 				   struct mlx5hws_send_ring_priv *priv,
310 				   enum mlx5hws_flow_op_status *status)
311 {
312 	switch (priv->rule->resize_info->state) {
313 	case MLX5HWS_RULE_RESIZE_STATE_WRITING:
314 		if (priv->rule->status == MLX5HWS_RULE_STATUS_FAILING) {
315 			/* Backup original RTCs */
316 			u32 orig_rtc_0 = priv->rule->resize_info->rtc_0;
317 			u32 orig_rtc_1 = priv->rule->resize_info->rtc_1;
318 
319 			/* Delete partially failed move rule using resize_info */
320 			priv->rule->resize_info->rtc_0 = priv->rule->rtc_0;
321 			priv->rule->resize_info->rtc_1 = priv->rule->rtc_1;
322 
323 			/* Move rule to original RTC for future delete */
324 			priv->rule->rtc_0 = orig_rtc_0;
325 			priv->rule->rtc_1 = orig_rtc_1;
326 		}
327 		/* Clean leftovers */
328 		mlx5hws_rule_move_hws_remove(priv->rule, queue, priv->user_data);
329 		break;
330 
331 	case MLX5HWS_RULE_RESIZE_STATE_DELETING:
332 		if (priv->rule->status == MLX5HWS_RULE_STATUS_FAILING) {
333 			*status = MLX5HWS_FLOW_OP_ERROR;
334 		} else {
335 			*status = MLX5HWS_FLOW_OP_SUCCESS;
336 			priv->rule->matcher = priv->rule->matcher->resize_dst;
337 		}
338 		priv->rule->resize_info->state = MLX5HWS_RULE_RESIZE_STATE_IDLE;
339 		priv->rule->status = MLX5HWS_RULE_STATUS_CREATED;
340 		break;
341 
342 	default:
343 		break;
344 	}
345 }
346 
hws_rule_status_to_string(enum mlx5hws_rule_status status)347 static const char *hws_rule_status_to_string(enum mlx5hws_rule_status status)
348 {
349 	switch (status) {
350 	case MLX5HWS_RULE_STATUS_CREATING: return "CREATING";
351 	case MLX5HWS_RULE_STATUS_UPDATING: return "UPDATING";
352 	case MLX5HWS_RULE_STATUS_DELETING: return "DELETING";
353 	case MLX5HWS_RULE_STATUS_FAILING: return "FAILING";
354 	default: return "NA";
355 	}
356 }
357 
hws_rule_resize_state_to_string(u8 state)358 static const char *hws_rule_resize_state_to_string(u8 state)
359 {
360 	switch (state) {
361 	case MLX5HWS_RULE_RESIZE_STATE_IDLE: return "IDLE";
362 	case MLX5HWS_RULE_RESIZE_STATE_WRITING: return "WRITING";
363 	case MLX5HWS_RULE_RESIZE_STATE_DELETING: return "DELETING";
364 	default: return "UNKNOWN";
365 	}
366 }
367 
hws_gta_syndrome_to_string(u8 syndrome)368 static const char *hws_gta_syndrome_to_string(u8 syndrome)
369 {
370 	switch (syndrome) {
371 	case 1: return "SET_FLOW_FAIL";
372 	case 2: return "DISABLE_FLOW_FAIL";
373 	default: return "UNKNOWN";
374 	}
375 }
376 
hws_send_engine_dump_error_cqe(struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_priv * priv,struct mlx5_cqe64 * cqe)377 static void hws_send_engine_dump_error_cqe(struct mlx5hws_send_engine *queue,
378 					   struct mlx5hws_send_ring_priv *priv,
379 					   struct mlx5_cqe64 *cqe)
380 {
381 	u8 wqe_opcode = cqe ? be32_to_cpu(cqe->sop_drop_qpn) >> 24 : 0;
382 	struct mlx5hws_context *ctx = priv->rule->matcher->tbl->ctx;
383 	u32 opcode = cqe ? get_cqe_opcode(cqe) : 0;
384 	struct mlx5hws_rule *rule = priv->rule;
385 	u8 syndrome;
386 
387 	/* If something bad happens and lots of rules are failing, we don't
388 	 * want to pollute dmesg. Print only the first bad cqe per engine,
389 	 * the one that started the avalanche.
390 	 */
391 	if (queue->error_cqe_printed)
392 		return;
393 
394 	queue->error_cqe_printed = true;
395 
396 	if (mlx5hws_rule_move_in_progress(rule))
397 		mlx5hws_err(ctx,
398 			    "--- rule 0x%08llx: error completion moving rule: phase %s (%d), wqes left %d\n",
399 			    HWS_PTR_TO_ID(rule),
400 			    hws_rule_resize_state_to_string
401 				(rule->resize_info->state),
402 			    rule->resize_info->state,
403 			    rule->pending_wqes);
404 	else
405 		mlx5hws_err(ctx,
406 			    "--- rule 0x%08llx: error completion %s (%d), wqes left %d\n",
407 			    HWS_PTR_TO_ID(rule),
408 			    hws_rule_status_to_string(rule->status),
409 			    rule->status,
410 			    rule->pending_wqes);
411 
412 	mlx5hws_err(ctx, "    rule 0x%08llx: matcher 0x%llx %s\n",
413 		    HWS_PTR_TO_ID(rule),
414 		    HWS_PTR_TO_ID(rule->matcher),
415 		    (rule->matcher->flags & MLX5HWS_MATCHER_FLAGS_ISOLATED) ?
416 		    "(isolated)" : "");
417 
418 	if (!cqe) {
419 		mlx5hws_err(ctx, "    rule 0x%08llx: no CQE\n",
420 			    HWS_PTR_TO_ID(rule));
421 		return;
422 	}
423 
424 	mlx5hws_err(ctx, "    rule 0x%08llx: cqe->opcode      = %d %s\n",
425 		    HWS_PTR_TO_ID(rule), opcode,
426 		    opcode == MLX5_CQE_REQ ? "(MLX5_CQE_REQ)" :
427 		    opcode == MLX5_CQE_REQ_ERR ? "(MLX5_CQE_REQ_ERR)" : " ");
428 
429 	if (opcode == MLX5_CQE_REQ_ERR) {
430 		struct mlx5_err_cqe *err_cqe = (struct mlx5_err_cqe *)cqe;
431 
432 		mlx5hws_err(ctx,
433 			    "    rule 0x%08llx:  |--- hw_error_syndrome = 0x%x\n",
434 			    HWS_PTR_TO_ID(rule),
435 			    err_cqe->rsvd1[16]);
436 		mlx5hws_err(ctx,
437 			    "    rule 0x%08llx:  |--- hw_syndrome_type = 0x%x\n",
438 			    HWS_PTR_TO_ID(rule),
439 			    err_cqe->rsvd1[17] >> 4);
440 		mlx5hws_err(ctx,
441 			    "    rule 0x%08llx:  |--- vendor_err_synd = 0x%x\n",
442 			    HWS_PTR_TO_ID(rule),
443 			    err_cqe->vendor_err_synd);
444 		mlx5hws_err(ctx,
445 			    "    rule 0x%08llx:  |--- syndrome = 0x%x\n",
446 			    HWS_PTR_TO_ID(rule),
447 			    err_cqe->syndrome);
448 		mlx5hws_err(ctx,
449 			    "    rule 0x%08llx:  |--- WQE_CNT = 0x%04x\n",
450 			    HWS_PTR_TO_ID(rule),
451 			    (u32)be16_to_cpu(err_cqe->wqe_counter));
452 	}
453 
454 	mlx5hws_err(ctx,
455 		    "    rule 0x%08llx: cqe->byte_cnt      = 0x%08x\n",
456 		    HWS_PTR_TO_ID(rule), be32_to_cpu(cqe->byte_cnt));
457 	mlx5hws_err(ctx,
458 		    "    rule 0x%08llx:  |-- UPDATE STATUS = %s\n",
459 		    HWS_PTR_TO_ID(rule),
460 		    (be32_to_cpu(cqe->byte_cnt) & 0x80000000) ?
461 		    "FAILURE" : "SUCCESS");
462 	/* syndrome is in the lower 2 bits of byte_cnt */
463 	syndrome = be32_to_cpu(cqe->byte_cnt) & 3;
464 	mlx5hws_err(ctx,
465 		    "    rule 0x%08llx:  |------- SYNDROME = %s (%u)\n",
466 		    HWS_PTR_TO_ID(rule),
467 		    hws_gta_syndrome_to_string(syndrome), syndrome);
468 	mlx5hws_err(ctx,
469 		    "    rule 0x%08llx: cqe->sop_drop_qpn  = 0x%08x\n",
470 		    HWS_PTR_TO_ID(rule), be32_to_cpu(cqe->sop_drop_qpn));
471 	mlx5hws_err(ctx,
472 		    "    rule 0x%08llx:  |-send wqe opcode = 0x%02x %s\n",
473 		    HWS_PTR_TO_ID(rule), wqe_opcode,
474 		    wqe_opcode == MLX5HWS_WQE_OPCODE_TBL_ACCESS ?
475 		    "(MLX5HWS_WQE_OPCODE_TBL_ACCESS)" : "(UNKNOWN)");
476 	mlx5hws_err(ctx,
477 		    "    rule 0x%08llx:  |------------ qpn = 0x%06x\n",
478 		    HWS_PTR_TO_ID(rule),
479 		    be32_to_cpu(cqe->sop_drop_qpn) & 0xffffff);
480 }
481 
hws_send_engine_update_rule(struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_priv * priv,u16 wqe_cnt,enum mlx5hws_flow_op_status * status,struct mlx5_cqe64 * cqe)482 static void hws_send_engine_update_rule(struct mlx5hws_send_engine *queue,
483 					struct mlx5hws_send_ring_priv *priv,
484 					u16 wqe_cnt,
485 					enum mlx5hws_flow_op_status *status,
486 					struct mlx5_cqe64 *cqe)
487 {
488 	priv->rule->pending_wqes--;
489 
490 	if (unlikely(*status == MLX5HWS_FLOW_OP_ERROR)) {
491 		if (priv->retry_id) {
492 			/* If there is a retry_id, then it's not an error yet,
493 			 * retry to insert this rule in the collision RTC.
494 			 */
495 			hws_send_engine_retry_post_send(queue, priv, wqe_cnt);
496 			return;
497 		}
498 		hws_send_engine_dump_error_cqe(queue, priv, cqe);
499 		/* Some part of the rule failed */
500 		priv->rule->status = MLX5HWS_RULE_STATUS_FAILING;
501 		*priv->used_id = 0;
502 	} else {
503 		*priv->used_id = priv->id;
504 	}
505 
506 	/* Update rule status for the last completion */
507 	if (!priv->rule->pending_wqes) {
508 		if (unlikely(mlx5hws_rule_move_in_progress(priv->rule))) {
509 			hws_send_engine_update_rule_resize(queue, priv, status);
510 			return;
511 		}
512 
513 		if (unlikely(priv->rule->status == MLX5HWS_RULE_STATUS_FAILING)) {
514 			/* Rule completely failed and doesn't require cleanup */
515 			if (!priv->rule->rtc_0 && !priv->rule->rtc_1)
516 				priv->rule->status = MLX5HWS_RULE_STATUS_FAILED;
517 
518 			*status = MLX5HWS_FLOW_OP_ERROR;
519 		} else {
520 			/* Increase the status, this only works on good flow as
521 			 * the enum is arranged this way:
522 			 *  - creating -> created
523 			 *  - updating -> updated
524 			 *  - deleting -> deleted
525 			 */
526 			priv->rule->status++;
527 			*status = MLX5HWS_FLOW_OP_SUCCESS;
528 			if (priv->rule->status == MLX5HWS_RULE_STATUS_DELETED) {
529 				/* Rule was deleted, now we can safely release
530 				 * action STEs and clear resize info
531 				 */
532 				mlx5hws_rule_free_action_ste(&priv->rule->action_ste);
533 				mlx5hws_rule_clear_resize_info(priv->rule);
534 			} else if (priv->rule->status == MLX5HWS_RULE_STATUS_UPDATED) {
535 				/* Rule was updated, free the old action STEs */
536 				mlx5hws_rule_free_action_ste(&priv->rule->old_action_ste);
537 				/* Update completed - move the rule back to "created" */
538 				priv->rule->status = MLX5HWS_RULE_STATUS_CREATED;
539 			}
540 		}
541 	}
542 }
543 
hws_send_engine_update(struct mlx5hws_send_engine * queue,struct mlx5_cqe64 * cqe,struct mlx5hws_send_ring_priv * priv,struct mlx5hws_flow_op_result res[],s64 * i,u32 res_nb,u16 wqe_cnt)544 static void hws_send_engine_update(struct mlx5hws_send_engine *queue,
545 				   struct mlx5_cqe64 *cqe,
546 				   struct mlx5hws_send_ring_priv *priv,
547 				   struct mlx5hws_flow_op_result res[],
548 				   s64 *i,
549 				   u32 res_nb,
550 				   u16 wqe_cnt)
551 {
552 	enum mlx5hws_flow_op_status status;
553 
554 	if (!cqe || (likely(be32_to_cpu(cqe->byte_cnt) >> 31 == 0) &&
555 		     likely(get_cqe_opcode(cqe) == MLX5_CQE_REQ))) {
556 		status = MLX5HWS_FLOW_OP_SUCCESS;
557 	} else {
558 		status = MLX5HWS_FLOW_OP_ERROR;
559 	}
560 
561 	if (priv->user_data) {
562 		if (priv->rule) {
563 			hws_send_engine_update_rule(queue, priv, wqe_cnt,
564 						    &status, cqe);
565 			/* Completion is provided on the last rule WQE */
566 			if (priv->rule->pending_wqes)
567 				return;
568 		}
569 
570 		if (*i < res_nb) {
571 			res[*i].user_data = priv->user_data;
572 			res[*i].status = status;
573 			(*i)++;
574 			mlx5hws_send_engine_dec_rule(queue);
575 		} else {
576 			mlx5hws_send_engine_gen_comp(queue, priv->user_data, status);
577 		}
578 	}
579 }
580 
mlx5hws_parse_cqe(struct mlx5hws_send_ring_cq * cq,struct mlx5_cqe64 * cqe64)581 static int mlx5hws_parse_cqe(struct mlx5hws_send_ring_cq *cq,
582 			     struct mlx5_cqe64 *cqe64)
583 {
584 	if (unlikely(get_cqe_opcode(cqe64) != MLX5_CQE_REQ)) {
585 		struct mlx5_err_cqe *err_cqe = (struct mlx5_err_cqe *)cqe64;
586 
587 		mlx5_core_err(cq->mdev, "Bad OP in HWS SQ CQE: 0x%x\n", get_cqe_opcode(cqe64));
588 		mlx5_core_err(cq->mdev, "vendor_err_synd=%x\n", err_cqe->vendor_err_synd);
589 		mlx5_core_err(cq->mdev, "syndrome=%x\n", err_cqe->syndrome);
590 		print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET,
591 			       16, 1, err_cqe,
592 			       sizeof(*err_cqe), false);
593 		return CQ_POLL_ERR;
594 	}
595 
596 	return CQ_OK;
597 }
598 
mlx5hws_cq_poll_one(struct mlx5hws_send_ring_cq * cq)599 static int mlx5hws_cq_poll_one(struct mlx5hws_send_ring_cq *cq)
600 {
601 	struct mlx5_cqe64 *cqe64;
602 	int err;
603 
604 	cqe64 = mlx5_cqwq_get_cqe(&cq->wq);
605 	if (!cqe64) {
606 		if (unlikely(cq->mdev->state ==
607 			     MLX5_DEVICE_STATE_INTERNAL_ERROR)) {
608 			mlx5_core_dbg_once(cq->mdev,
609 					   "Polling CQ while device is shutting down\n");
610 			return CQ_POLL_ERR;
611 		}
612 		return CQ_EMPTY;
613 	}
614 
615 	mlx5_cqwq_pop(&cq->wq);
616 	err = mlx5hws_parse_cqe(cq, cqe64);
617 	mlx5_cqwq_update_db_record(&cq->wq);
618 
619 	return err;
620 }
621 
hws_send_engine_poll_cq(struct mlx5hws_send_engine * queue,struct mlx5hws_flow_op_result res[],s64 * polled,u32 res_nb)622 static void hws_send_engine_poll_cq(struct mlx5hws_send_engine *queue,
623 				    struct mlx5hws_flow_op_result res[],
624 				    s64 *polled,
625 				    u32 res_nb)
626 {
627 	struct mlx5hws_send_ring *send_ring = &queue->send_ring;
628 	struct mlx5hws_send_ring_cq *cq = &send_ring->send_cq;
629 	struct mlx5hws_send_ring_sq *sq = &send_ring->send_sq;
630 	struct mlx5hws_send_ring_priv *priv;
631 	struct mlx5_cqe64 *cqe;
632 	u8 cqe_opcode;
633 	u16 wqe_cnt;
634 
635 	cqe = mlx5_cqwq_get_cqe(&cq->wq);
636 	if (!cqe)
637 		return;
638 
639 	cqe_opcode = get_cqe_opcode(cqe);
640 	if (cqe_opcode == MLX5_CQE_INVALID)
641 		return;
642 
643 	if (unlikely(cqe_opcode != MLX5_CQE_REQ))
644 		queue->err = true;
645 
646 	wqe_cnt = be16_to_cpu(cqe->wqe_counter) & sq->buf_mask;
647 
648 	while (cq->poll_wqe != wqe_cnt) {
649 		priv = &sq->wr_priv[cq->poll_wqe];
650 		hws_send_engine_update(queue, NULL, priv, res, polled, res_nb, 0);
651 		cq->poll_wqe = (cq->poll_wqe + priv->num_wqebbs) & sq->buf_mask;
652 	}
653 
654 	priv = &sq->wr_priv[wqe_cnt];
655 	cq->poll_wqe = (wqe_cnt + priv->num_wqebbs) & sq->buf_mask;
656 	hws_send_engine_update(queue, cqe, priv, res, polled, res_nb, wqe_cnt);
657 	mlx5hws_cq_poll_one(cq);
658 }
659 
hws_send_engine_poll_list(struct mlx5hws_send_engine * queue,struct mlx5hws_flow_op_result res[],s64 * polled,u32 res_nb)660 static void hws_send_engine_poll_list(struct mlx5hws_send_engine *queue,
661 				      struct mlx5hws_flow_op_result res[],
662 				      s64 *polled,
663 				      u32 res_nb)
664 {
665 	struct mlx5hws_completed_poll *comp = &queue->completed;
666 
667 	while (comp->ci != comp->pi) {
668 		if (*polled < res_nb) {
669 			res[*polled].status =
670 				comp->entries[comp->ci].status;
671 			res[*polled].user_data =
672 				comp->entries[comp->ci].user_data;
673 			(*polled)++;
674 			comp->ci = (comp->ci + 1) & comp->mask;
675 			mlx5hws_send_engine_dec_rule(queue);
676 		} else {
677 			return;
678 		}
679 	}
680 }
681 
hws_send_engine_poll(struct mlx5hws_send_engine * queue,struct mlx5hws_flow_op_result res[],u32 res_nb)682 static int hws_send_engine_poll(struct mlx5hws_send_engine *queue,
683 				struct mlx5hws_flow_op_result res[],
684 				u32 res_nb)
685 {
686 	s64 polled = 0;
687 
688 	hws_send_engine_poll_list(queue, res, &polled, res_nb);
689 
690 	if (polled >= res_nb)
691 		return polled;
692 
693 	hws_send_engine_poll_cq(queue, res, &polled, res_nb);
694 
695 	return polled;
696 }
697 
mlx5hws_send_queue_poll(struct mlx5hws_context * ctx,u16 queue_id,struct mlx5hws_flow_op_result res[],u32 res_nb)698 int mlx5hws_send_queue_poll(struct mlx5hws_context *ctx,
699 			    u16 queue_id,
700 			    struct mlx5hws_flow_op_result res[],
701 			    u32 res_nb)
702 {
703 	return hws_send_engine_poll(&ctx->send_queue[queue_id], res, res_nb);
704 }
705 
hws_send_ring_alloc_sq(struct mlx5_core_dev * mdev,int numa_node,struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_sq * sq,void * sqc_data)706 static int hws_send_ring_alloc_sq(struct mlx5_core_dev *mdev,
707 				  int numa_node,
708 				  struct mlx5hws_send_engine *queue,
709 				  struct mlx5hws_send_ring_sq *sq,
710 				  void *sqc_data)
711 {
712 	void *sqc_wq = MLX5_ADDR_OF(sqc, sqc_data, wq);
713 	struct mlx5_wq_cyc *wq = &sq->wq;
714 	struct mlx5_wq_param param;
715 	size_t buf_sz;
716 	int err;
717 
718 	sq->uar_map = mdev->priv.bfreg.map;
719 	sq->mdev = mdev;
720 
721 	param.db_numa_node = numa_node;
722 	param.buf_numa_node = numa_node;
723 	err = mlx5_wq_cyc_create(mdev, &param, sqc_wq, wq, &sq->wq_ctrl);
724 	if (err)
725 		return err;
726 	wq->db = &wq->db[MLX5_SND_DBR];
727 
728 	buf_sz = queue->num_entries * MAX_WQES_PER_RULE;
729 	sq->dep_wqe = kzalloc_objs(*sq->dep_wqe, queue->num_entries);
730 	if (!sq->dep_wqe) {
731 		err = -ENOMEM;
732 		goto destroy_wq_cyc;
733 	}
734 
735 	sq->wr_priv = kzalloc(sizeof(*sq->wr_priv) * buf_sz, GFP_KERNEL);
736 	if (!sq->wr_priv) {
737 		err = -ENOMEM;
738 		goto free_dep_wqe;
739 	}
740 
741 	sq->buf_mask = (queue->num_entries * MAX_WQES_PER_RULE) - 1;
742 
743 	return 0;
744 
745 free_dep_wqe:
746 	kfree(sq->dep_wqe);
747 destroy_wq_cyc:
748 	mlx5_wq_destroy(&sq->wq_ctrl);
749 	return err;
750 }
751 
hws_send_ring_free_sq(struct mlx5hws_send_ring_sq * sq)752 static void hws_send_ring_free_sq(struct mlx5hws_send_ring_sq *sq)
753 {
754 	if (!sq)
755 		return;
756 	kfree(sq->wr_priv);
757 	kfree(sq->dep_wqe);
758 	mlx5_wq_destroy(&sq->wq_ctrl);
759 }
760 
hws_send_ring_create_sq(struct mlx5_core_dev * mdev,u32 pdn,void * sqc_data,struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_sq * sq,struct mlx5hws_send_ring_cq * cq)761 static int hws_send_ring_create_sq(struct mlx5_core_dev *mdev, u32 pdn,
762 				   void *sqc_data,
763 				   struct mlx5hws_send_engine *queue,
764 				   struct mlx5hws_send_ring_sq *sq,
765 				   struct mlx5hws_send_ring_cq *cq)
766 {
767 	void *in, *sqc, *wq;
768 	int inlen, err;
769 	u8 ts_format;
770 
771 	inlen = MLX5_ST_SZ_BYTES(create_sq_in) +
772 		sizeof(u64) * sq->wq_ctrl.buf.npages;
773 	in = kvzalloc(inlen, GFP_KERNEL);
774 	if (!in)
775 		return -ENOMEM;
776 
777 	sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
778 	wq = MLX5_ADDR_OF(sqc, sqc, wq);
779 
780 	memcpy(sqc, sqc_data, MLX5_ST_SZ_BYTES(sqc));
781 	MLX5_SET(sqc, sqc, cqn, cq->mcq.cqn);
782 
783 	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST);
784 	MLX5_SET(sqc, sqc, flush_in_error_en, 1);
785 	MLX5_SET(sqc, sqc, non_wire, 1);
786 
787 	ts_format = mlx5_is_real_time_sq(mdev) ? MLX5_TIMESTAMP_FORMAT_REAL_TIME :
788 						 MLX5_TIMESTAMP_FORMAT_FREE_RUNNING;
789 	MLX5_SET(sqc, sqc, ts_format, ts_format);
790 
791 	MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
792 	MLX5_SET(wq, wq, uar_page, mdev->priv.bfreg.index);
793 	MLX5_SET(wq, wq, log_wq_pg_sz, sq->wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT);
794 	MLX5_SET64(wq, wq, dbr_addr, sq->wq_ctrl.db.dma);
795 
796 	mlx5_fill_page_frag_array(&sq->wq_ctrl.buf,
797 				  (__be64 *)MLX5_ADDR_OF(wq, wq, pas));
798 
799 	err = mlx5_core_create_sq(mdev, in, inlen, &sq->sqn);
800 
801 	kvfree(in);
802 
803 	return err;
804 }
805 
hws_send_ring_destroy_sq(struct mlx5_core_dev * mdev,struct mlx5hws_send_ring_sq * sq)806 static void hws_send_ring_destroy_sq(struct mlx5_core_dev *mdev,
807 				     struct mlx5hws_send_ring_sq *sq)
808 {
809 	mlx5_core_destroy_sq(mdev, sq->sqn);
810 }
811 
hws_send_ring_set_sq_rdy(struct mlx5_core_dev * mdev,u32 sqn)812 static int hws_send_ring_set_sq_rdy(struct mlx5_core_dev *mdev, u32 sqn)
813 {
814 	void *in, *sqc;
815 	int inlen, err;
816 
817 	inlen = MLX5_ST_SZ_BYTES(modify_sq_in);
818 	in = kvzalloc(inlen, GFP_KERNEL);
819 	if (!in)
820 		return -ENOMEM;
821 
822 	MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST);
823 	sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
824 	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY);
825 
826 	err = mlx5_core_modify_sq(mdev, sqn, in);
827 
828 	kvfree(in);
829 
830 	return err;
831 }
832 
hws_send_ring_close_sq(struct mlx5hws_send_ring_sq * sq)833 static void hws_send_ring_close_sq(struct mlx5hws_send_ring_sq *sq)
834 {
835 	mlx5_core_destroy_sq(sq->mdev, sq->sqn);
836 	mlx5_wq_destroy(&sq->wq_ctrl);
837 	kfree(sq->wr_priv);
838 	kfree(sq->dep_wqe);
839 }
840 
hws_send_ring_create_sq_rdy(struct mlx5_core_dev * mdev,u32 pdn,void * sqc_data,struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_sq * sq,struct mlx5hws_send_ring_cq * cq)841 static int hws_send_ring_create_sq_rdy(struct mlx5_core_dev *mdev, u32 pdn,
842 				       void *sqc_data,
843 				       struct mlx5hws_send_engine *queue,
844 				       struct mlx5hws_send_ring_sq *sq,
845 				       struct mlx5hws_send_ring_cq *cq)
846 {
847 	int err;
848 
849 	err = hws_send_ring_create_sq(mdev, pdn, sqc_data, queue, sq, cq);
850 	if (err)
851 		return err;
852 
853 	err = hws_send_ring_set_sq_rdy(mdev, sq->sqn);
854 	if (err)
855 		hws_send_ring_destroy_sq(mdev, sq);
856 
857 	return err;
858 }
859 
hws_send_ring_open_sq(struct mlx5hws_context * ctx,int numa_node,struct mlx5hws_send_engine * queue,struct mlx5hws_send_ring_sq * sq,struct mlx5hws_send_ring_cq * cq)860 static int hws_send_ring_open_sq(struct mlx5hws_context *ctx,
861 				 int numa_node,
862 				 struct mlx5hws_send_engine *queue,
863 				 struct mlx5hws_send_ring_sq *sq,
864 				 struct mlx5hws_send_ring_cq *cq)
865 {
866 	size_t buf_sz, sq_log_buf_sz;
867 	void *sqc_data, *wq;
868 	int err;
869 
870 	sqc_data = kvzalloc(MLX5_ST_SZ_BYTES(sqc), GFP_KERNEL);
871 	if (!sqc_data)
872 		return -ENOMEM;
873 
874 	buf_sz = queue->num_entries * MAX_WQES_PER_RULE;
875 	sq_log_buf_sz = ilog2(roundup_pow_of_two(buf_sz));
876 
877 	wq = MLX5_ADDR_OF(sqc, sqc_data, wq);
878 	MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB));
879 	MLX5_SET(wq, wq, pd, ctx->pd_num);
880 	MLX5_SET(wq, wq, log_wq_sz, sq_log_buf_sz);
881 
882 	err = hws_send_ring_alloc_sq(ctx->mdev, numa_node, queue, sq, sqc_data);
883 	if (err)
884 		goto err_free_sqc;
885 
886 	err = hws_send_ring_create_sq_rdy(ctx->mdev, ctx->pd_num, sqc_data,
887 					  queue, sq, cq);
888 	if (err)
889 		goto err_free_sq;
890 
891 	kvfree(sqc_data);
892 
893 	return 0;
894 err_free_sq:
895 	hws_send_ring_free_sq(sq);
896 err_free_sqc:
897 	kvfree(sqc_data);
898 	return err;
899 }
900 
hws_send_ring_alloc_cq(struct mlx5_core_dev * mdev,int numa_node,struct mlx5hws_send_engine * queue,void * cqc_data,struct mlx5hws_send_ring_cq * cq)901 static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev,
902 				  int numa_node,
903 				  struct mlx5hws_send_engine *queue,
904 				  void *cqc_data,
905 				  struct mlx5hws_send_ring_cq *cq)
906 {
907 	struct mlx5_core_cq *mcq = &cq->mcq;
908 	struct mlx5_wq_param param;
909 	struct mlx5_cqe64 *cqe;
910 	int err;
911 	u32 i;
912 
913 	param.buf_numa_node = numa_node;
914 	param.db_numa_node = numa_node;
915 
916 	err = mlx5_cqwq_create(mdev, &param, cqc_data, &cq->wq, &cq->wq_ctrl);
917 	if (err)
918 		return err;
919 
920 	mcq->cqe_sz = 64;
921 	mcq->set_ci_db = cq->wq_ctrl.db.db;
922 	mcq->arm_db = cq->wq_ctrl.db.db + 1;
923 
924 	for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
925 		cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
926 		cqe->op_own = 0xf1;
927 	}
928 
929 	cq->mdev = mdev;
930 
931 	return 0;
932 }
933 
hws_send_ring_create_cq(struct mlx5_core_dev * mdev,struct mlx5hws_send_engine * queue,void * cqc_data,struct mlx5hws_send_ring_cq * cq)934 static int hws_send_ring_create_cq(struct mlx5_core_dev *mdev,
935 				   struct mlx5hws_send_engine *queue,
936 				   void *cqc_data,
937 				   struct mlx5hws_send_ring_cq *cq)
938 {
939 	u32 out[MLX5_ST_SZ_DW(create_cq_out)];
940 	struct mlx5_core_cq *mcq = &cq->mcq;
941 	void *in, *cqc;
942 	int inlen, eqn;
943 	int err;
944 
945 	err = mlx5_comp_eqn_get(mdev, 0, &eqn);
946 	if (err)
947 		return err;
948 
949 	inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
950 		sizeof(u64) * cq->wq_ctrl.buf.npages;
951 	in = kvzalloc(inlen, GFP_KERNEL);
952 	if (!in)
953 		return -ENOMEM;
954 
955 	cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
956 	memcpy(cqc, cqc_data, MLX5_ST_SZ_BYTES(cqc));
957 	mlx5_fill_page_frag_array(&cq->wq_ctrl.buf,
958 				  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
959 
960 	MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn);
961 	MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index);
962 	MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT);
963 	MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma);
964 
965 	err = mlx5_core_create_cq(mdev, mcq, in, inlen, out, sizeof(out));
966 
967 	kvfree(in);
968 
969 	return err;
970 }
971 
hws_send_ring_open_cq(struct mlx5_core_dev * mdev,struct mlx5hws_send_engine * queue,int numa_node,struct mlx5hws_send_ring_cq * cq)972 static int hws_send_ring_open_cq(struct mlx5_core_dev *mdev,
973 				 struct mlx5hws_send_engine *queue,
974 				 int numa_node,
975 				 struct mlx5hws_send_ring_cq *cq)
976 {
977 	void *cqc_data;
978 	int err;
979 
980 	cqc_data = kvzalloc(MLX5_ST_SZ_BYTES(cqc), GFP_KERNEL);
981 	if (!cqc_data)
982 		return -ENOMEM;
983 
984 	MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.bfreg.up->index);
985 	MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries));
986 
987 	err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq);
988 	if (err)
989 		goto err_out;
990 
991 	err = hws_send_ring_create_cq(mdev, queue, cqc_data, cq);
992 	if (err)
993 		goto err_free_cq;
994 
995 	kvfree(cqc_data);
996 
997 	return 0;
998 
999 err_free_cq:
1000 	mlx5_wq_destroy(&cq->wq_ctrl);
1001 err_out:
1002 	kvfree(cqc_data);
1003 	return err;
1004 }
1005 
hws_send_ring_close_cq(struct mlx5hws_send_ring_cq * cq)1006 static void hws_send_ring_close_cq(struct mlx5hws_send_ring_cq *cq)
1007 {
1008 	mlx5_core_destroy_cq(cq->mdev, &cq->mcq);
1009 	mlx5_wq_destroy(&cq->wq_ctrl);
1010 }
1011 
hws_send_ring_close(struct mlx5hws_send_engine * queue)1012 static void hws_send_ring_close(struct mlx5hws_send_engine *queue)
1013 {
1014 	hws_send_ring_close_sq(&queue->send_ring.send_sq);
1015 	hws_send_ring_close_cq(&queue->send_ring.send_cq);
1016 }
1017 
mlx5hws_send_ring_open(struct mlx5hws_context * ctx,struct mlx5hws_send_engine * queue)1018 static int mlx5hws_send_ring_open(struct mlx5hws_context *ctx,
1019 				  struct mlx5hws_send_engine *queue)
1020 {
1021 	int numa_node = dev_to_node(mlx5_core_dma_dev(ctx->mdev));
1022 	struct mlx5hws_send_ring *ring = &queue->send_ring;
1023 	int err;
1024 
1025 	err = hws_send_ring_open_cq(ctx->mdev, queue, numa_node, &ring->send_cq);
1026 	if (err)
1027 		return err;
1028 
1029 	err = hws_send_ring_open_sq(ctx, numa_node, queue, &ring->send_sq,
1030 				    &ring->send_cq);
1031 	if (err)
1032 		goto close_cq;
1033 
1034 	return err;
1035 
1036 close_cq:
1037 	hws_send_ring_close_cq(&ring->send_cq);
1038 	return err;
1039 }
1040 
mlx5hws_send_queue_close(struct mlx5hws_send_engine * queue)1041 static void mlx5hws_send_queue_close(struct mlx5hws_send_engine *queue)
1042 {
1043 	if (!queue->num_entries)
1044 		return; /* this queue wasn't initialized */
1045 
1046 	hws_send_ring_close(queue);
1047 	kfree(queue->completed.entries);
1048 }
1049 
mlx5hws_send_queue_open(struct mlx5hws_context * ctx,struct mlx5hws_send_engine * queue,u16 queue_size)1050 static int mlx5hws_send_queue_open(struct mlx5hws_context *ctx,
1051 				   struct mlx5hws_send_engine *queue,
1052 				   u16 queue_size)
1053 {
1054 	int err;
1055 
1056 	mutex_init(&queue->lock);
1057 
1058 	queue->num_entries = roundup_pow_of_two(queue_size);
1059 	queue->used_entries = 0;
1060 
1061 	queue->completed.entries = kzalloc_objs(queue->completed.entries[0],
1062 						queue->num_entries);
1063 	if (!queue->completed.entries)
1064 		return -ENOMEM;
1065 
1066 	queue->completed.pi = 0;
1067 	queue->completed.ci = 0;
1068 	queue->completed.mask = queue->num_entries - 1;
1069 	err = mlx5hws_send_ring_open(ctx, queue);
1070 	if (err)
1071 		goto free_completed_entries;
1072 
1073 	return 0;
1074 
1075 free_completed_entries:
1076 	kfree(queue->completed.entries);
1077 	return err;
1078 }
1079 
__hws_send_queues_close(struct mlx5hws_context * ctx,u16 queues)1080 static void __hws_send_queues_close(struct mlx5hws_context *ctx, u16 queues)
1081 {
1082 	while (queues--)
1083 		mlx5hws_send_queue_close(&ctx->send_queue[queues]);
1084 }
1085 
hws_send_queues_bwc_locks_destroy(struct mlx5hws_context * ctx)1086 static void hws_send_queues_bwc_locks_destroy(struct mlx5hws_context *ctx)
1087 {
1088 	int bwc_queues = mlx5hws_bwc_queues(ctx);
1089 	int i;
1090 
1091 	if (!mlx5hws_context_bwc_supported(ctx))
1092 		return;
1093 
1094 	for (i = 0; i < bwc_queues; i++) {
1095 		mutex_destroy(&ctx->bwc_send_queue_locks[i]);
1096 		lockdep_unregister_key(ctx->bwc_lock_class_keys + i);
1097 	}
1098 
1099 	kfree(ctx->bwc_lock_class_keys);
1100 	kfree(ctx->bwc_send_queue_locks);
1101 }
1102 
mlx5hws_send_queues_close(struct mlx5hws_context * ctx)1103 void mlx5hws_send_queues_close(struct mlx5hws_context *ctx)
1104 {
1105 	hws_send_queues_bwc_locks_destroy(ctx);
1106 	__hws_send_queues_close(ctx, ctx->queues);
1107 	kfree(ctx->send_queue);
1108 }
1109 
hws_bwc_send_queues_init(struct mlx5hws_context * ctx)1110 static int hws_bwc_send_queues_init(struct mlx5hws_context *ctx)
1111 {
1112 	/* Number of BWC queues is equal to number of the usual HWS queues */
1113 	int bwc_queues = ctx->queues - 1;
1114 	int i;
1115 
1116 	if (!mlx5hws_context_bwc_supported(ctx))
1117 		return 0;
1118 
1119 	ctx->bwc_send_queue_locks = kzalloc_objs(*ctx->bwc_send_queue_locks,
1120 						 bwc_queues);
1121 
1122 	if (!ctx->bwc_send_queue_locks)
1123 		return -ENOMEM;
1124 
1125 	ctx->bwc_lock_class_keys = kzalloc_objs(*ctx->bwc_lock_class_keys,
1126 						bwc_queues);
1127 	if (!ctx->bwc_lock_class_keys)
1128 		goto err_lock_class_keys;
1129 
1130 	ctx->queues += bwc_queues;
1131 
1132 	for (i = 0; i < bwc_queues; i++) {
1133 		mutex_init(&ctx->bwc_send_queue_locks[i]);
1134 		lockdep_register_key(ctx->bwc_lock_class_keys + i);
1135 		lockdep_set_class(ctx->bwc_send_queue_locks + i, ctx->bwc_lock_class_keys + i);
1136 	}
1137 
1138 	return 0;
1139 
1140 err_lock_class_keys:
1141 	kfree(ctx->bwc_send_queue_locks);
1142 	return -ENOMEM;
1143 }
1144 
mlx5hws_send_queues_open(struct mlx5hws_context * ctx,u16 queues,u16 queue_size)1145 int mlx5hws_send_queues_open(struct mlx5hws_context *ctx,
1146 			     u16 queues,
1147 			     u16 queue_size)
1148 {
1149 	int err = 0;
1150 	int i = 0;
1151 
1152 	/* Open one extra queue for control path */
1153 	ctx->queues = queues + 1;
1154 
1155 	/* open a separate set of queues and locks for bwc API */
1156 	err = hws_bwc_send_queues_init(ctx);
1157 	if (err)
1158 		return err;
1159 
1160 	ctx->send_queue = kzalloc_objs(*ctx->send_queue, ctx->queues);
1161 	if (!ctx->send_queue) {
1162 		err = -ENOMEM;
1163 		goto free_bwc_locks;
1164 	}
1165 
1166 	/* If native API isn't supported, skip the unused native queues:
1167 	 * initialize BWC queues and control queue only.
1168 	 */
1169 	if (!mlx5hws_context_native_supported(ctx))
1170 		i = mlx5hws_bwc_get_queue_id(ctx, 0);
1171 
1172 	for (; i < ctx->queues; i++) {
1173 		err = mlx5hws_send_queue_open(ctx, &ctx->send_queue[i], queue_size);
1174 		if (err)
1175 			goto close_send_queues;
1176 	}
1177 
1178 	return 0;
1179 
1180 close_send_queues:
1181 	 __hws_send_queues_close(ctx, i);
1182 
1183 	kfree(ctx->send_queue);
1184 
1185 free_bwc_locks:
1186 	hws_send_queues_bwc_locks_destroy(ctx);
1187 
1188 	return err;
1189 }
1190 
mlx5hws_send_queue_action(struct mlx5hws_context * ctx,u16 queue_id,u32 actions)1191 int mlx5hws_send_queue_action(struct mlx5hws_context *ctx,
1192 			      u16 queue_id,
1193 			      u32 actions)
1194 {
1195 	struct mlx5hws_send_ring_sq *send_sq;
1196 	struct mlx5hws_send_engine *queue;
1197 	bool wait_comp = false;
1198 	s64 polled = 0;
1199 
1200 	queue = &ctx->send_queue[queue_id];
1201 	send_sq = &queue->send_ring.send_sq;
1202 
1203 	switch (actions) {
1204 	case MLX5HWS_SEND_QUEUE_ACTION_DRAIN_SYNC:
1205 		wait_comp = true;
1206 		fallthrough;
1207 	case MLX5HWS_SEND_QUEUE_ACTION_DRAIN_ASYNC:
1208 		if (send_sq->head_dep_idx != send_sq->tail_dep_idx)
1209 			/* Send dependent WQEs to drain the queue */
1210 			mlx5hws_send_all_dep_wqe(queue);
1211 		else
1212 			/* Signal on the last posted WQE */
1213 			mlx5hws_send_engine_flush_queue(queue);
1214 
1215 		/* Poll queue until empty */
1216 		while (wait_comp && !mlx5hws_send_engine_empty(queue))
1217 			hws_send_engine_poll_cq(queue, NULL, &polled, 0);
1218 
1219 		break;
1220 	default:
1221 		return -EINVAL;
1222 	}
1223 
1224 	return 0;
1225 }
1226 
1227 static int
hws_send_wqe_fw(struct mlx5_core_dev * mdev,u32 pd_num,struct mlx5hws_send_engine_post_attr * send_attr,struct mlx5hws_wqe_gta_ctrl_seg * send_wqe_ctrl,void * send_wqe_match_data,void * send_wqe_match_tag,void * send_wqe_range_data,void * send_wqe_range_tag,bool is_jumbo,u8 gta_opcode)1228 hws_send_wqe_fw(struct mlx5_core_dev *mdev,
1229 		u32 pd_num,
1230 		struct mlx5hws_send_engine_post_attr *send_attr,
1231 		struct mlx5hws_wqe_gta_ctrl_seg *send_wqe_ctrl,
1232 		void *send_wqe_match_data,
1233 		void *send_wqe_match_tag,
1234 		void *send_wqe_range_data,
1235 		void *send_wqe_range_tag,
1236 		bool is_jumbo,
1237 		u8 gta_opcode)
1238 {
1239 	bool has_range = send_wqe_range_data || send_wqe_range_tag;
1240 	bool has_match = send_wqe_match_data || send_wqe_match_tag;
1241 	struct mlx5hws_wqe_gta_data_seg_ste gta_wqe_data0 = {0};
1242 	struct mlx5hws_wqe_gta_data_seg_ste gta_wqe_data1 = {0};
1243 	struct mlx5hws_wqe_gta_ctrl_seg gta_wqe_ctrl = {0};
1244 	struct mlx5hws_cmd_generate_wqe_attr attr = {0};
1245 	struct mlx5hws_wqe_ctrl_seg wqe_ctrl = {0};
1246 	struct mlx5_cqe64 cqe;
1247 	u32 flags = 0;
1248 	int ret;
1249 
1250 	/* Set WQE control */
1251 	wqe_ctrl.opmod_idx_opcode = cpu_to_be32((send_attr->opmod << 24) | send_attr->opcode);
1252 	wqe_ctrl.qpn_ds = cpu_to_be32((send_attr->len + sizeof(struct mlx5hws_wqe_ctrl_seg)) / 16);
1253 	flags |= send_attr->notify_hw ? MLX5_WQE_CTRL_CQ_UPDATE : 0;
1254 	wqe_ctrl.flags = cpu_to_be32(flags);
1255 	wqe_ctrl.imm = cpu_to_be32(send_attr->id);
1256 
1257 	/* Set GTA WQE CTRL */
1258 	memcpy(gta_wqe_ctrl.stc_ix, send_wqe_ctrl->stc_ix, sizeof(send_wqe_ctrl->stc_ix));
1259 	gta_wqe_ctrl.op_dirix = cpu_to_be32(gta_opcode << 28);
1260 
1261 	/* Set GTA match WQE DATA */
1262 	if (has_match) {
1263 		if (send_wqe_match_data)
1264 			memcpy(&gta_wqe_data0, send_wqe_match_data, sizeof(gta_wqe_data0));
1265 		else
1266 			hws_send_wqe_set_tag(&gta_wqe_data0, send_wqe_match_tag, is_jumbo);
1267 
1268 		gta_wqe_data0.rsvd1_definer = cpu_to_be32(send_attr->match_definer_id << 8);
1269 		attr.gta_data_0 = (u8 *)&gta_wqe_data0;
1270 	}
1271 
1272 	/* Set GTA range WQE DATA */
1273 	if (has_range) {
1274 		if (send_wqe_range_data)
1275 			memcpy(&gta_wqe_data1, send_wqe_range_data, sizeof(gta_wqe_data1));
1276 		else
1277 			hws_send_wqe_set_tag(&gta_wqe_data1, send_wqe_range_tag, false);
1278 
1279 		gta_wqe_data1.rsvd1_definer = cpu_to_be32(send_attr->range_definer_id << 8);
1280 		attr.gta_data_1 = (u8 *)&gta_wqe_data1;
1281 	}
1282 
1283 	attr.pdn = pd_num;
1284 	attr.wqe_ctrl = (u8 *)&wqe_ctrl;
1285 	attr.gta_ctrl = (u8 *)&gta_wqe_ctrl;
1286 
1287 send_wqe:
1288 	ret = mlx5hws_cmd_generate_wqe(mdev, &attr, &cqe);
1289 	if (ret) {
1290 		mlx5_core_err(mdev, "Failed to write WQE using command");
1291 		return ret;
1292 	}
1293 
1294 	if ((get_cqe_opcode(&cqe) == MLX5_CQE_REQ) &&
1295 	    (be32_to_cpu(cqe.byte_cnt) >> 31 == 0)) {
1296 		*send_attr->used_id = send_attr->id;
1297 		return 0;
1298 	}
1299 
1300 	/* Retry if rule failed */
1301 	if (send_attr->retry_id) {
1302 		wqe_ctrl.imm = cpu_to_be32(send_attr->retry_id);
1303 		send_attr->id = send_attr->retry_id;
1304 		send_attr->retry_id = 0;
1305 		goto send_wqe;
1306 	}
1307 
1308 	return -1;
1309 }
1310 
mlx5hws_send_stes_fw(struct mlx5hws_context * ctx,struct mlx5hws_send_engine * queue,struct mlx5hws_send_ste_attr * ste_attr)1311 void mlx5hws_send_stes_fw(struct mlx5hws_context *ctx,
1312 			  struct mlx5hws_send_engine *queue,
1313 			  struct mlx5hws_send_ste_attr *ste_attr)
1314 {
1315 	struct mlx5hws_send_engine_post_attr *send_attr = &ste_attr->send_attr;
1316 	struct mlx5hws_rule *rule = send_attr->rule;
1317 	struct mlx5_core_dev *mdev;
1318 	u16 queue_id;
1319 	u32 pdn;
1320 	int ret;
1321 
1322 	queue_id = queue - ctx->send_queue;
1323 	mdev = ctx->mdev;
1324 	pdn = ctx->pd_num;
1325 
1326 	/* Writing through FW can't HW fence, therefore we drain the queue */
1327 	if (send_attr->fence)
1328 		mlx5hws_send_queue_action(ctx,
1329 					  queue_id,
1330 					  MLX5HWS_SEND_QUEUE_ACTION_DRAIN_SYNC);
1331 
1332 	if (ste_attr->rtc_1) {
1333 		send_attr->id = ste_attr->rtc_1;
1334 		send_attr->used_id = ste_attr->used_id_rtc_1;
1335 		send_attr->retry_id = ste_attr->retry_rtc_1;
1336 		ret = hws_send_wqe_fw(mdev, pdn, send_attr,
1337 				      ste_attr->wqe_ctrl,
1338 				      ste_attr->wqe_data,
1339 				      ste_attr->wqe_tag,
1340 				      ste_attr->range_wqe_data,
1341 				      ste_attr->range_wqe_tag,
1342 				      ste_attr->wqe_tag_is_jumbo,
1343 				      ste_attr->gta_opcode);
1344 		if (ret)
1345 			goto fail_rule;
1346 	}
1347 
1348 	if (ste_attr->rtc_0) {
1349 		send_attr->id = ste_attr->rtc_0;
1350 		send_attr->used_id = ste_attr->used_id_rtc_0;
1351 		send_attr->retry_id = ste_attr->retry_rtc_0;
1352 		ret = hws_send_wqe_fw(mdev, pdn, send_attr,
1353 				      ste_attr->wqe_ctrl,
1354 				      ste_attr->wqe_data,
1355 				      ste_attr->wqe_tag,
1356 				      ste_attr->range_wqe_data,
1357 				      ste_attr->range_wqe_tag,
1358 				      ste_attr->wqe_tag_is_jumbo,
1359 				      ste_attr->gta_opcode);
1360 		if (ret)
1361 			goto fail_rule;
1362 	}
1363 
1364 	/* Increase the status, this only works on good flow as the enum
1365 	 * is arrange it away creating -> created -> deleting -> deleted
1366 	 */
1367 	if (likely(rule))
1368 		rule->status++;
1369 
1370 	mlx5hws_send_engine_gen_comp(queue, send_attr->user_data, MLX5HWS_FLOW_OP_SUCCESS);
1371 
1372 	return;
1373 
1374 fail_rule:
1375 	if (likely(rule))
1376 		rule->status = !rule->rtc_0 && !rule->rtc_1 ?
1377 			MLX5HWS_RULE_STATUS_FAILED : MLX5HWS_RULE_STATUS_FAILING;
1378 
1379 	mlx5hws_send_engine_gen_comp(queue, send_attr->user_data, MLX5HWS_FLOW_OP_ERROR);
1380 }
1381