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