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