xref: /dpdk/drivers/common/cnxk/roc_nix_fc.c (revision ff1400aa)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "roc_api.h"
6 #include "roc_priv.h"
7 
8 static inline struct mbox *
get_mbox(struct roc_nix * roc_nix)9 get_mbox(struct roc_nix *roc_nix)
10 {
11 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
12 	struct dev *dev = &nix->dev;
13 
14 	return dev->mbox;
15 }
16 
17 static int
nix_fc_rxchan_bpid_get(struct roc_nix * roc_nix,struct roc_nix_fc_cfg * fc_cfg)18 nix_fc_rxchan_bpid_get(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
19 {
20 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
21 
22 	if (nix->chan_cnt != 0)
23 		fc_cfg->rxchan_cfg.enable = true;
24 	else
25 		fc_cfg->rxchan_cfg.enable = false;
26 
27 	fc_cfg->type = ROC_NIX_FC_RXCHAN_CFG;
28 
29 	return 0;
30 }
31 
32 static int
nix_fc_rxchan_bpid_set(struct roc_nix * roc_nix,bool enable)33 nix_fc_rxchan_bpid_set(struct roc_nix *roc_nix, bool enable)
34 {
35 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
36 	struct mbox *mbox = get_mbox(roc_nix);
37 	struct nix_bp_cfg_req *req;
38 	struct nix_bp_cfg_rsp *rsp;
39 	int rc = -ENOSPC, i;
40 
41 	if (enable) {
42 		req = mbox_alloc_msg_nix_bp_enable(mbox);
43 		if (req == NULL)
44 			return rc;
45 
46 		req->chan_base = 0;
47 		if (roc_nix_is_lbk(roc_nix) || roc_nix_is_sdp(roc_nix))
48 			req->chan_cnt = NIX_LBK_MAX_CHAN;
49 		else
50 			req->chan_cnt = NIX_CGX_MAX_CHAN;
51 
52 		req->bpid_per_chan = true;
53 
54 		rc = mbox_process_msg(mbox, (void *)&rsp);
55 		if (rc || (req->chan_cnt != rsp->chan_cnt))
56 			goto exit;
57 
58 		nix->chan_cnt = rsp->chan_cnt;
59 		for (i = 0; i < rsp->chan_cnt; i++)
60 			nix->bpid[i] = rsp->chan_bpid[i] & 0x1FF;
61 	} else {
62 		req = mbox_alloc_msg_nix_bp_disable(mbox);
63 		if (req == NULL)
64 			return rc;
65 		req->chan_base = 0;
66 		req->chan_cnt = nix->chan_cnt;
67 
68 		rc = mbox_process(mbox);
69 		if (rc)
70 			goto exit;
71 
72 		memset(nix->bpid, 0, sizeof(uint16_t) * NIX_MAX_CHAN);
73 		nix->chan_cnt = 0;
74 	}
75 
76 	if (roc_model_is_cn9k())
77 		goto exit;
78 
79 	/* Enable backpressure on CPT if inline inb is enabled */
80 	if (enable && roc_nix_inl_inb_is_enabled(roc_nix)) {
81 		req = mbox_alloc_msg_nix_cpt_bp_enable(mbox);
82 		if (req == NULL)
83 			return rc;
84 		req->chan_base = 0;
85 		req->chan_cnt = 1;
86 		req->bpid_per_chan = 0;
87 
88 		rc = mbox_process_msg(mbox, (void *)&rsp);
89 		if (rc)
90 			goto exit;
91 	} else {
92 		req = mbox_alloc_msg_nix_cpt_bp_disable(mbox);
93 		if (req == NULL)
94 			return rc;
95 		req->chan_base = 0;
96 		req->chan_cnt = 1;
97 		req->bpid_per_chan = 0;
98 
99 		rc = mbox_process_msg(mbox, (void *)&rsp);
100 		if (rc)
101 			goto exit;
102 	}
103 
104 exit:
105 	return rc;
106 }
107 
108 static int
nix_fc_cq_config_get(struct roc_nix * roc_nix,struct roc_nix_fc_cfg * fc_cfg)109 nix_fc_cq_config_get(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
110 {
111 	struct mbox *mbox = get_mbox(roc_nix);
112 	struct nix_aq_enq_rsp *rsp;
113 	int rc;
114 
115 	if (roc_model_is_cn9k()) {
116 		struct nix_aq_enq_req *aq;
117 
118 		aq = mbox_alloc_msg_nix_aq_enq(mbox);
119 		if (!aq)
120 			return -ENOSPC;
121 
122 		aq->qidx = fc_cfg->cq_cfg.rq;
123 		aq->ctype = NIX_AQ_CTYPE_CQ;
124 		aq->op = NIX_AQ_INSTOP_READ;
125 	} else {
126 		struct nix_cn10k_aq_enq_req *aq;
127 
128 		aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
129 		if (!aq)
130 			return -ENOSPC;
131 
132 		aq->qidx = fc_cfg->cq_cfg.rq;
133 		aq->ctype = NIX_AQ_CTYPE_CQ;
134 		aq->op = NIX_AQ_INSTOP_READ;
135 	}
136 
137 	rc = mbox_process_msg(mbox, (void *)&rsp);
138 	if (rc)
139 		goto exit;
140 
141 	fc_cfg->cq_cfg.cq_drop = rsp->cq.bp;
142 	fc_cfg->cq_cfg.enable = rsp->cq.bp_ena;
143 	fc_cfg->type = ROC_NIX_FC_CQ_CFG;
144 
145 exit:
146 	return rc;
147 }
148 
149 static int
nix_fc_cq_config_set(struct roc_nix * roc_nix,struct roc_nix_fc_cfg * fc_cfg)150 nix_fc_cq_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
151 {
152 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
153 	struct mbox *mbox = get_mbox(roc_nix);
154 
155 	if (roc_model_is_cn9k()) {
156 		struct nix_aq_enq_req *aq;
157 
158 		aq = mbox_alloc_msg_nix_aq_enq(mbox);
159 		if (!aq)
160 			return -ENOSPC;
161 
162 		aq->qidx = fc_cfg->cq_cfg.rq;
163 		aq->ctype = NIX_AQ_CTYPE_CQ;
164 		aq->op = NIX_AQ_INSTOP_WRITE;
165 
166 		if (fc_cfg->cq_cfg.enable) {
167 			aq->cq.bpid = nix->bpid[fc_cfg->cq_cfg.tc];
168 			aq->cq_mask.bpid = ~(aq->cq_mask.bpid);
169 			aq->cq.bp = fc_cfg->cq_cfg.cq_drop;
170 			aq->cq_mask.bp = ~(aq->cq_mask.bp);
171 		}
172 
173 		aq->cq.bp_ena = !!(fc_cfg->cq_cfg.enable);
174 		aq->cq_mask.bp_ena = ~(aq->cq_mask.bp_ena);
175 	} else {
176 		struct nix_cn10k_aq_enq_req *aq;
177 
178 		aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
179 		if (!aq)
180 			return -ENOSPC;
181 
182 		aq->qidx = fc_cfg->cq_cfg.rq;
183 		aq->ctype = NIX_AQ_CTYPE_CQ;
184 		aq->op = NIX_AQ_INSTOP_WRITE;
185 
186 		if (fc_cfg->cq_cfg.enable) {
187 			aq->cq.bpid = nix->bpid[fc_cfg->cq_cfg.tc];
188 			aq->cq_mask.bpid = ~(aq->cq_mask.bpid);
189 			aq->cq.bp = fc_cfg->cq_cfg.cq_drop;
190 			aq->cq_mask.bp = ~(aq->cq_mask.bp);
191 		}
192 
193 		aq->cq.bp_ena = !!(fc_cfg->cq_cfg.enable);
194 		aq->cq_mask.bp_ena = ~(aq->cq_mask.bp_ena);
195 	}
196 
197 	return mbox_process(mbox);
198 }
199 
200 int
roc_nix_fc_config_get(struct roc_nix * roc_nix,struct roc_nix_fc_cfg * fc_cfg)201 roc_nix_fc_config_get(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
202 {
203 	if (!roc_nix_is_pf(roc_nix) && !roc_nix_is_lbk(roc_nix) &&
204 	    !roc_nix_is_sdp(roc_nix))
205 		return 0;
206 
207 	if (fc_cfg->type == ROC_NIX_FC_CQ_CFG)
208 		return nix_fc_cq_config_get(roc_nix, fc_cfg);
209 	else if (fc_cfg->type == ROC_NIX_FC_RXCHAN_CFG)
210 		return nix_fc_rxchan_bpid_get(roc_nix, fc_cfg);
211 	else if (fc_cfg->type == ROC_NIX_FC_TM_CFG)
212 		return nix_tm_bp_config_get(roc_nix, &fc_cfg->tm_cfg.enable);
213 
214 	return -EINVAL;
215 }
216 
217 int
roc_nix_fc_config_set(struct roc_nix * roc_nix,struct roc_nix_fc_cfg * fc_cfg)218 roc_nix_fc_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
219 {
220 	if (!roc_nix_is_pf(roc_nix) && !roc_nix_is_lbk(roc_nix) &&
221 	    !roc_nix_is_sdp(roc_nix))
222 		return 0;
223 
224 	if (fc_cfg->type == ROC_NIX_FC_CQ_CFG)
225 		return nix_fc_cq_config_set(roc_nix, fc_cfg);
226 	else if (fc_cfg->type == ROC_NIX_FC_RXCHAN_CFG)
227 		return nix_fc_rxchan_bpid_set(roc_nix,
228 					      fc_cfg->rxchan_cfg.enable);
229 	else if (fc_cfg->type == ROC_NIX_FC_TM_CFG)
230 		return nix_tm_bp_config_set(roc_nix, fc_cfg->tm_cfg.sq,
231 					    fc_cfg->tm_cfg.tc,
232 					    fc_cfg->tm_cfg.enable);
233 
234 	return -EINVAL;
235 }
236 
237 enum roc_nix_fc_mode
roc_nix_fc_mode_get(struct roc_nix * roc_nix)238 roc_nix_fc_mode_get(struct roc_nix *roc_nix)
239 {
240 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
241 	struct mbox *mbox = get_mbox(roc_nix);
242 	struct cgx_pause_frm_cfg *req, *rsp;
243 	enum roc_nix_fc_mode mode;
244 	int rc = -ENOSPC;
245 
246 	/* Flow control on LBK link is always available */
247 	if (roc_nix_is_lbk(roc_nix)) {
248 		if (nix->tx_pause && nix->rx_pause)
249 			return ROC_NIX_FC_FULL;
250 		else if (nix->rx_pause)
251 			return ROC_NIX_FC_RX;
252 		else if (nix->tx_pause)
253 			return ROC_NIX_FC_TX;
254 		else
255 			return ROC_NIX_FC_NONE;
256 	}
257 
258 	req = mbox_alloc_msg_cgx_cfg_pause_frm(mbox);
259 	if (req == NULL)
260 		return rc;
261 	req->set = 0;
262 
263 	rc = mbox_process_msg(mbox, (void *)&rsp);
264 	if (rc)
265 		goto exit;
266 
267 	if (rsp->rx_pause && rsp->tx_pause)
268 		mode = ROC_NIX_FC_FULL;
269 	else if (rsp->rx_pause)
270 		mode = ROC_NIX_FC_RX;
271 	else if (rsp->tx_pause)
272 		mode = ROC_NIX_FC_TX;
273 	else
274 		mode = ROC_NIX_FC_NONE;
275 
276 	nix->rx_pause = rsp->rx_pause;
277 	nix->tx_pause = rsp->tx_pause;
278 	return mode;
279 
280 exit:
281 	return ROC_NIX_FC_NONE;
282 }
283 
284 int
roc_nix_fc_mode_set(struct roc_nix * roc_nix,enum roc_nix_fc_mode mode)285 roc_nix_fc_mode_set(struct roc_nix *roc_nix, enum roc_nix_fc_mode mode)
286 {
287 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
288 	struct mbox *mbox = get_mbox(roc_nix);
289 	struct cgx_pause_frm_cfg *req;
290 	uint8_t tx_pause, rx_pause;
291 	int rc = -ENOSPC;
292 
293 	rx_pause = (mode == ROC_NIX_FC_FULL) || (mode == ROC_NIX_FC_RX);
294 	tx_pause = (mode == ROC_NIX_FC_FULL) || (mode == ROC_NIX_FC_TX);
295 
296 	/* Nothing much to do for LBK links */
297 	if (roc_nix_is_lbk(roc_nix)) {
298 		nix->rx_pause = rx_pause;
299 		nix->tx_pause = tx_pause;
300 		return 0;
301 	}
302 
303 	req = mbox_alloc_msg_cgx_cfg_pause_frm(mbox);
304 	if (req == NULL)
305 		return rc;
306 	req->set = 1;
307 	req->rx_pause = rx_pause;
308 	req->tx_pause = tx_pause;
309 
310 	rc = mbox_process(mbox);
311 	if (rc)
312 		goto exit;
313 
314 	nix->rx_pause = rx_pause;
315 	nix->tx_pause = tx_pause;
316 
317 exit:
318 	return rc;
319 }
320 
321 void
rox_nix_fc_npa_bp_cfg(struct roc_nix * roc_nix,uint64_t pool_id,uint8_t ena,uint8_t force)322 rox_nix_fc_npa_bp_cfg(struct roc_nix *roc_nix, uint64_t pool_id, uint8_t ena,
323 		      uint8_t force)
324 {
325 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
326 	struct npa_lf *lf = idev_npa_obj_get();
327 	struct npa_aq_enq_req *req;
328 	struct npa_aq_enq_rsp *rsp;
329 	struct mbox *mbox;
330 	uint32_t limit;
331 	int rc;
332 
333 	if (roc_nix_is_sdp(roc_nix))
334 		return;
335 
336 	if (!lf)
337 		return;
338 	mbox = lf->mbox;
339 
340 	req = mbox_alloc_msg_npa_aq_enq(mbox);
341 	if (req == NULL)
342 		return;
343 
344 	req->aura_id = roc_npa_aura_handle_to_aura(pool_id);
345 	req->ctype = NPA_AQ_CTYPE_AURA;
346 	req->op = NPA_AQ_INSTOP_READ;
347 
348 	rc = mbox_process_msg(mbox, (void *)&rsp);
349 	if (rc)
350 		return;
351 
352 	limit = rsp->aura.limit;
353 	/* BP is already enabled. */
354 	if (rsp->aura.bp_ena) {
355 		uint16_t bpid;
356 		bool nix1;
357 
358 		nix1 = !!(rsp->aura.bp_ena & 0x2);
359 		if (nix1)
360 			bpid = rsp->aura.nix1_bpid;
361 		else
362 			bpid = rsp->aura.nix0_bpid;
363 
364 		/* If BP ids don't match disable BP. */
365 		if (((nix1 != nix->is_nix1) || (bpid != nix->bpid[0])) &&
366 		    !force) {
367 			req = mbox_alloc_msg_npa_aq_enq(mbox);
368 			if (req == NULL)
369 				return;
370 
371 			req->aura_id = roc_npa_aura_handle_to_aura(pool_id);
372 			req->ctype = NPA_AQ_CTYPE_AURA;
373 			req->op = NPA_AQ_INSTOP_WRITE;
374 
375 			req->aura.bp_ena = 0;
376 			req->aura_mask.bp_ena = ~(req->aura_mask.bp_ena);
377 
378 			mbox_process(mbox);
379 		}
380 		return;
381 	}
382 
383 	/* BP was previously enabled but now disabled skip. */
384 	if (rsp->aura.bp)
385 		return;
386 
387 	req = mbox_alloc_msg_npa_aq_enq(mbox);
388 	if (req == NULL)
389 		return;
390 
391 	req->aura_id = roc_npa_aura_handle_to_aura(pool_id);
392 	req->ctype = NPA_AQ_CTYPE_AURA;
393 	req->op = NPA_AQ_INSTOP_WRITE;
394 
395 	if (ena) {
396 		if (nix->is_nix1) {
397 			req->aura.nix1_bpid = nix->bpid[0];
398 			req->aura_mask.nix1_bpid = ~(req->aura_mask.nix1_bpid);
399 		} else {
400 			req->aura.nix0_bpid = nix->bpid[0];
401 			req->aura_mask.nix0_bpid = ~(req->aura_mask.nix0_bpid);
402 		}
403 		req->aura.bp = NIX_RQ_AURA_THRESH(
404 			limit > 128 ? 256 : limit); /* 95% of size*/
405 		req->aura_mask.bp = ~(req->aura_mask.bp);
406 	}
407 
408 	req->aura.bp_ena = (!!ena << nix->is_nix1);
409 	req->aura_mask.bp_ena = ~(req->aura_mask.bp_ena);
410 
411 	mbox_process(mbox);
412 }
413 
414 int
roc_nix_pfc_mode_set(struct roc_nix * roc_nix,struct roc_nix_pfc_cfg * pfc_cfg)415 roc_nix_pfc_mode_set(struct roc_nix *roc_nix, struct roc_nix_pfc_cfg *pfc_cfg)
416 {
417 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
418 	struct mbox *mbox = get_mbox(roc_nix);
419 	uint8_t tx_pause, rx_pause;
420 	struct cgx_pfc_cfg *req;
421 	struct cgx_pfc_rsp *rsp;
422 	int rc = -ENOSPC;
423 
424 	if (roc_nix_is_lbk(roc_nix))
425 		return NIX_ERR_OP_NOTSUP;
426 
427 	rx_pause = (pfc_cfg->mode == ROC_NIX_FC_FULL) ||
428 		   (pfc_cfg->mode == ROC_NIX_FC_RX);
429 	tx_pause = (pfc_cfg->mode == ROC_NIX_FC_FULL) ||
430 		   (pfc_cfg->mode == ROC_NIX_FC_TX);
431 
432 	req = mbox_alloc_msg_cgx_prio_flow_ctrl_cfg(mbox);
433 	if (req == NULL)
434 		goto exit;
435 
436 	req->pfc_en = pfc_cfg->tc;
437 	req->rx_pause = rx_pause;
438 	req->tx_pause = tx_pause;
439 
440 	rc = mbox_process_msg(mbox, (void *)&rsp);
441 	if (rc)
442 		goto exit;
443 
444 	nix->rx_pause = rsp->rx_pause;
445 	nix->tx_pause = rsp->tx_pause;
446 	if (rsp->tx_pause)
447 		nix->cev |= BIT(pfc_cfg->tc);
448 	else
449 		nix->cev &= ~BIT(pfc_cfg->tc);
450 
451 exit:
452 	return rc;
453 }
454 
455 int
roc_nix_pfc_mode_get(struct roc_nix * roc_nix,struct roc_nix_pfc_cfg * pfc_cfg)456 roc_nix_pfc_mode_get(struct roc_nix *roc_nix, struct roc_nix_pfc_cfg *pfc_cfg)
457 {
458 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
459 
460 	if (roc_nix_is_lbk(roc_nix))
461 		return NIX_ERR_OP_NOTSUP;
462 
463 	pfc_cfg->tc = nix->cev;
464 
465 	if (nix->rx_pause && nix->tx_pause)
466 		pfc_cfg->mode = ROC_NIX_FC_FULL;
467 	else if (nix->rx_pause)
468 		pfc_cfg->mode = ROC_NIX_FC_RX;
469 	else if (nix->tx_pause)
470 		pfc_cfg->mode = ROC_NIX_FC_TX;
471 	else
472 		pfc_cfg->mode = ROC_NIX_FC_NONE;
473 
474 	return 0;
475 }
476 
477 uint16_t
roc_nix_chan_count_get(struct roc_nix * roc_nix)478 roc_nix_chan_count_get(struct roc_nix *roc_nix)
479 {
480 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
481 
482 	return nix->chan_cnt;
483 }
484