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