Branch data Line data Source code
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 : : #define CPT_IQ_FC_LEN 128
9 : : #define CPT_IQ_GRP_LEN 16
10 : :
11 : : #define CPT_IQ_NB_DESC_MULTIPLIER 40
12 : :
13 : : /* The effective queue size to software is (CPT_LF_Q_SIZE[SIZE_DIV40] - 1 - 8).
14 : : *
15 : : * CPT requires 320 free entries (+8). And 40 entries are required for
16 : : * allowing CPT to discard packet when the queues are full (+1).
17 : : */
18 : : #define CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc) \
19 : : (PLT_DIV_CEIL(nb_desc, CPT_IQ_NB_DESC_MULTIPLIER) + 1 + 8)
20 : :
21 : : #define CPT_IQ_GRP_SIZE(nb_desc) \
22 : : (CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc) * CPT_IQ_GRP_LEN)
23 : :
24 : : #define CPT_LF_MAX_NB_DESC 128000
25 : : #define CPT_LF_DEFAULT_NB_DESC 1024
26 : : #define CPT_LF_FC_MIN_THRESHOLD 32
27 : :
28 : : static struct cpt_int_cb {
29 : : roc_cpt_int_misc_cb_t cb;
30 : : void *cb_args;
31 : : } int_cb;
32 : :
33 : : static void
34 : : cpt_lf_misc_intr_enb_dis(struct roc_cpt_lf *lf, bool enb)
35 : : {
36 : : /* Enable all cpt lf error irqs except RQ_DISABLED and CQ_DISABLED */
37 : : if (enb)
38 : 0 : plt_write64((BIT_ULL(6) | BIT_ULL(5) | BIT_ULL(3) | BIT_ULL(2) |
39 : : BIT_ULL(1)),
40 : : lf->rbase + CPT_LF_MISC_INT_ENA_W1S);
41 : : else
42 : 0 : plt_write64((BIT_ULL(6) | BIT_ULL(5) | BIT_ULL(3) | BIT_ULL(2) |
43 : : BIT_ULL(1)),
44 : : lf->rbase + CPT_LF_MISC_INT_ENA_W1C);
45 : : }
46 : :
47 : : static void
48 : 0 : cpt_lf_misc_irq(void *param)
49 : : {
50 : : struct roc_cpt_lf *lf = (struct roc_cpt_lf *)param;
51 : 0 : struct dev *dev = lf->dev;
52 : : uint64_t intr;
53 : :
54 [ # # ]: 0 : intr = plt_read64(lf->rbase + CPT_LF_MISC_INT);
55 [ # # ]: 0 : if (intr == 0)
56 : : return;
57 : :
58 : 0 : plt_err("Err_irq=0x%" PRIx64 " pf=%d, vf=%d", intr, dev->pf, dev->vf);
59 : :
60 : : /* Dump lf registers */
61 : 0 : cpt_lf_print(lf);
62 : :
63 : : /* Clear interrupt */
64 [ # # ]: 0 : plt_write64(intr, lf->rbase + CPT_LF_MISC_INT);
65 : :
66 [ # # ]: 0 : if (int_cb.cb != NULL) {
67 : 0 : lf->error_event_pending = 1;
68 : 0 : int_cb.cb(lf, int_cb.cb_args);
69 : : }
70 : : }
71 : :
72 : : static int
73 : 0 : cpt_lf_register_misc_irq(struct roc_cpt_lf *lf)
74 : : {
75 : 0 : struct plt_pci_device *pci_dev = lf->pci_dev;
76 : : struct plt_intr_handle *handle;
77 : : int rc, vec;
78 : :
79 : 0 : handle = pci_dev->intr_handle;
80 : :
81 : 0 : vec = lf->msixoff + CPT_LF_INT_VEC_MISC;
82 : : /* Clear err interrupt */
83 : : cpt_lf_misc_intr_enb_dis(lf, false);
84 : : /* Set used interrupt vectors */
85 : 0 : rc = dev_irq_register(handle, cpt_lf_misc_irq, lf, vec);
86 : : /* Enable all dev interrupt except for RQ_DISABLED */
87 : : cpt_lf_misc_intr_enb_dis(lf, true);
88 : :
89 : 0 : return rc;
90 : : }
91 : :
92 : : static void
93 : 0 : cpt_lf_unregister_misc_irq(struct roc_cpt_lf *lf)
94 : : {
95 : 0 : struct plt_pci_device *pci_dev = lf->pci_dev;
96 : : struct plt_intr_handle *handle;
97 : : int vec;
98 : :
99 : 0 : handle = pci_dev->intr_handle;
100 : :
101 : 0 : vec = lf->msixoff + CPT_LF_INT_VEC_MISC;
102 : : /* Clear err interrupt */
103 : : cpt_lf_misc_intr_enb_dis(lf, false);
104 : 0 : dev_irq_unregister(handle, cpt_lf_misc_irq, lf, vec);
105 : 0 : }
106 : :
107 : : static void
108 : : cpt_lf_done_intr_enb_dis(struct roc_cpt_lf *lf, bool enb)
109 : : {
110 : : if (enb)
111 : 0 : plt_write64(0x1, lf->rbase + CPT_LF_DONE_INT_ENA_W1S);
112 : : else
113 : 0 : plt_write64(0x1, lf->rbase + CPT_LF_DONE_INT_ENA_W1C);
114 : : }
115 : :
116 : : static void
117 : 0 : cpt_lf_done_irq(void *param)
118 : : {
119 : : struct roc_cpt_lf *lf = param;
120 : : uint64_t done_wait;
121 : : uint64_t intr;
122 : :
123 : : /* Read the number of completed requests */
124 [ # # ]: 0 : intr = plt_read64(lf->rbase + CPT_LF_DONE);
125 [ # # ]: 0 : if (intr == 0)
126 : : return;
127 : :
128 : 0 : done_wait = plt_read64(lf->rbase + CPT_LF_DONE_WAIT);
129 : :
130 : : /* Acknowledge the number of completed requests */
131 : 0 : plt_write64(intr, lf->rbase + CPT_LF_DONE_ACK);
132 : :
133 : 0 : plt_write64(done_wait, lf->rbase + CPT_LF_DONE_WAIT);
134 : : }
135 : :
136 : : static int
137 : 0 : cpt_lf_register_done_irq(struct roc_cpt_lf *lf)
138 : : {
139 : 0 : struct plt_pci_device *pci_dev = lf->pci_dev;
140 : : struct plt_intr_handle *handle;
141 : : int rc, vec;
142 : :
143 : 0 : handle = pci_dev->intr_handle;
144 : :
145 : 0 : vec = lf->msixoff + CPT_LF_INT_VEC_DONE;
146 : :
147 : : /* Clear done interrupt */
148 : : cpt_lf_done_intr_enb_dis(lf, false);
149 : :
150 : : /* Set used interrupt vectors */
151 : 0 : rc = dev_irq_register(handle, cpt_lf_done_irq, lf, vec);
152 : :
153 : : /* Enable done interrupt */
154 : : cpt_lf_done_intr_enb_dis(lf, true);
155 : :
156 : 0 : return rc;
157 : : }
158 : :
159 : : static void
160 : 0 : cpt_lf_unregister_done_irq(struct roc_cpt_lf *lf)
161 : : {
162 : 0 : struct plt_pci_device *pci_dev = lf->pci_dev;
163 : : struct plt_intr_handle *handle;
164 : : int vec;
165 : :
166 : 0 : handle = pci_dev->intr_handle;
167 : :
168 : 0 : vec = lf->msixoff + CPT_LF_INT_VEC_DONE;
169 : :
170 : : /* Clear done interrupt */
171 : : cpt_lf_done_intr_enb_dis(lf, false);
172 : 0 : dev_irq_unregister(handle, cpt_lf_done_irq, lf, vec);
173 : 0 : }
174 : :
175 : : static int
176 : 0 : cpt_lf_register_irqs(struct roc_cpt_lf *lf)
177 : : {
178 : : int rc;
179 : :
180 [ # # ]: 0 : if (lf->msixoff == MSIX_VECTOR_INVALID) {
181 : 0 : plt_err("Invalid CPTLF MSIX vector offset vector: 0x%x",
182 : : lf->msixoff);
183 : 0 : return -EINVAL;
184 : : }
185 : :
186 : : /* Register lf err interrupt */
187 : 0 : rc = cpt_lf_register_misc_irq(lf);
188 [ # # ]: 0 : if (rc)
189 : 0 : plt_err("Error registering IRQs");
190 : :
191 : 0 : rc = cpt_lf_register_done_irq(lf);
192 [ # # ]: 0 : if (rc)
193 : 0 : plt_err("Error registering IRQs");
194 : :
195 : : return rc;
196 : : }
197 : :
198 : : static void
199 : : cpt_lf_unregister_irqs(struct roc_cpt_lf *lf)
200 : : {
201 : 0 : cpt_lf_unregister_misc_irq(lf);
202 : 0 : cpt_lf_unregister_done_irq(lf);
203 : : }
204 : :
205 : : static void
206 : 0 : cpt_lf_dump(struct roc_cpt_lf *lf)
207 : : {
208 : 0 : plt_cpt_dbg("CPT LF");
209 : 0 : plt_cpt_dbg("RBASE: 0x%016" PRIx64, lf->rbase);
210 : 0 : plt_cpt_dbg("LMT_BASE: 0x%016" PRIx64, lf->lmt_base);
211 : 0 : plt_cpt_dbg("MSIXOFF: 0x%x", lf->msixoff);
212 : 0 : plt_cpt_dbg("LF_ID: 0x%x", lf->lf_id);
213 : 0 : plt_cpt_dbg("NB DESC: %d", lf->nb_desc);
214 : 0 : plt_cpt_dbg("FC_ADDR: 0x%016" PRIx64, (uintptr_t)lf->fc_addr);
215 : 0 : plt_cpt_dbg("CQ.VADDR: 0x%016" PRIx64, (uintptr_t)lf->iq_vaddr);
216 : :
217 : 0 : plt_cpt_dbg("CPT LF REG:");
218 : 0 : plt_cpt_dbg("LF_CTL[0x%016llx]: 0x%016" PRIx64, CPT_LF_CTL,
219 : : plt_read64(lf->rbase + CPT_LF_CTL));
220 : 0 : plt_cpt_dbg("LF_INPROG[0x%016llx]: 0x%016" PRIx64, CPT_LF_INPROG,
221 : : plt_read64(lf->rbase + CPT_LF_INPROG));
222 : :
223 : 0 : plt_cpt_dbg("Q_BASE[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_BASE,
224 : : plt_read64(lf->rbase + CPT_LF_Q_BASE));
225 : 0 : plt_cpt_dbg("Q_SIZE[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_SIZE,
226 : : plt_read64(lf->rbase + CPT_LF_Q_SIZE));
227 : 0 : plt_cpt_dbg("Q_INST_PTR[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_INST_PTR,
228 : : plt_read64(lf->rbase + CPT_LF_Q_INST_PTR));
229 : 0 : plt_cpt_dbg("Q_GRP_PTR[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_GRP_PTR,
230 : : plt_read64(lf->rbase + CPT_LF_Q_GRP_PTR));
231 : 0 : }
232 : :
233 : : int
234 : 0 : cpt_lf_outb_cfg(struct dev *dev, uint16_t sso_pf_func, uint16_t nix_pf_func,
235 : : uint8_t lf_id, bool ena)
236 : : {
237 : : struct cpt_inline_ipsec_cfg_msg *req;
238 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
239 : : int rc;
240 : :
241 : 0 : req = mbox_alloc_msg_cpt_inline_ipsec_cfg(mbox);
242 [ # # ]: 0 : if (req == NULL) {
243 : : rc = -ENOSPC;
244 : 0 : goto exit;
245 : : }
246 : :
247 : 0 : req->dir = CPT_INLINE_OUTBOUND;
248 : 0 : req->slot = lf_id;
249 [ # # ]: 0 : if (ena) {
250 : 0 : req->enable = 1;
251 : 0 : req->sso_pf_func = sso_pf_func;
252 : 0 : req->nix_pf_func = nix_pf_func;
253 : : } else {
254 : 0 : req->enable = 0;
255 : : }
256 : :
257 : 0 : rc = mbox_process(mbox);
258 : 0 : exit:
259 : : mbox_put(mbox);
260 : 0 : return rc;
261 : : }
262 : :
263 : : int
264 : 0 : roc_cpt_inline_ipsec_cfg(struct dev *cpt_dev, uint8_t lf_id,
265 : : struct roc_nix *roc_nix)
266 : : {
267 : 0 : bool ena = roc_nix ? true : false;
268 : : uint16_t nix_pf_func = 0;
269 : : uint16_t sso_pf_func = 0;
270 : :
271 [ # # ]: 0 : if (ena) {
272 : 0 : nix_pf_func = roc_nix_get_pf_func(roc_nix);
273 : 0 : sso_pf_func = idev_sso_pffunc_get();
274 : : }
275 : :
276 : 0 : return cpt_lf_outb_cfg(cpt_dev, sso_pf_func, nix_pf_func, lf_id, ena);
277 : : }
278 : :
279 : : int
280 : 0 : roc_cpt_inline_ipsec_inb_cfg_read(struct roc_cpt *roc_cpt,
281 : : struct roc_cpt_inline_ipsec_inb_cfg *cfg)
282 : : {
283 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
284 : : struct nix_inline_ipsec_cfg *inb_cfg;
285 : : struct dev *dev = &cpt->dev;
286 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
287 : : struct msg_req *req;
288 : : int rc;
289 : :
290 : 0 : req = mbox_alloc_msg_nix_read_inline_ipsec_cfg(mbox);
291 [ # # ]: 0 : if (req == NULL) {
292 : : rc = -EIO;
293 : 0 : goto exit;
294 : : }
295 : :
296 : : rc = mbox_process_msg(mbox, (void *)&inb_cfg);
297 [ # # ]: 0 : if (rc) {
298 : : rc = -EIO;
299 : 0 : goto exit;
300 : : }
301 : 0 : cfg->cpt_credit = inb_cfg->cpt_credit;
302 : 0 : cfg->egrp = inb_cfg->gen_cfg.egrp;
303 : 0 : cfg->opcode = inb_cfg->gen_cfg.opcode;
304 : 0 : cfg->param1 = inb_cfg->gen_cfg.param1;
305 : 0 : cfg->param2 = inb_cfg->gen_cfg.param2;
306 : 0 : cfg->bpid = inb_cfg->bpid;
307 : 0 : cfg->credit_th = inb_cfg->credit_th;
308 : 0 : exit:
309 : : mbox_put(mbox);
310 : 0 : return rc;
311 : : }
312 : :
313 : : int
314 : 0 : roc_cpt_inline_ipsec_inb_cfg(struct roc_cpt *roc_cpt, struct roc_cpt_inline_ipsec_inb_cfg *cfg)
315 : : {
316 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
317 : : struct cpt_rx_inline_lf_cfg_msg *req;
318 : : struct mbox *mbox;
319 : : int rc;
320 : :
321 : 0 : mbox = mbox_get(cpt->dev.mbox);
322 : :
323 : 0 : req = mbox_alloc_msg_cpt_rx_inline_lf_cfg(mbox);
324 [ # # ]: 0 : if (req == NULL) {
325 : : rc = -ENOSPC;
326 : 0 : goto exit;
327 : : }
328 : :
329 : 0 : req->sso_pf_func = idev_sso_pffunc_get();
330 : 0 : req->param1 = cfg->param1;
331 : 0 : req->param2 = cfg->param2;
332 : 0 : req->opcode = cfg->opcode;
333 : 0 : req->bpid = cfg->bpid;
334 : 0 : req->ctx_ilen_valid = cfg->ctx_ilen_valid;
335 : 0 : req->ctx_ilen = cfg->ctx_ilen;
336 : :
337 : 0 : rc = mbox_process(mbox);
338 : 0 : exit:
339 : : mbox_put(mbox);
340 : 0 : return rc;
341 : : }
342 : :
343 : : int
344 : 0 : roc_cpt_rxc_time_cfg(struct roc_cpt *roc_cpt, struct roc_cpt_rxc_time_cfg *cfg)
345 : : {
346 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
347 : : struct cpt_rxc_time_cfg_req *req;
348 : : struct dev *dev = &cpt->dev;
349 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
350 : : int rc;
351 : :
352 : 0 : req = mbox_alloc_msg_cpt_rxc_time_cfg(mbox);
353 [ # # ]: 0 : if (req == NULL) {
354 : : rc = -ENOSPC;
355 : 0 : goto exit;
356 : : }
357 : :
358 : 0 : req->blkaddr = 0;
359 : :
360 : : /* The step value is in microseconds. */
361 : 0 : req->step = cfg->step;
362 : :
363 : : /* The timeout will be: limit * step microseconds */
364 : 0 : req->zombie_limit = cfg->zombie_limit;
365 : 0 : req->zombie_thres = cfg->zombie_thres;
366 : :
367 : : /* The timeout will be: limit * step microseconds */
368 : 0 : req->active_limit = cfg->active_limit;
369 : 0 : req->active_thres = cfg->active_thres;
370 : :
371 : 0 : rc = mbox_process(mbox);
372 : 0 : exit:
373 : : mbox_put(mbox);
374 : 0 : return rc;
375 : : }
376 : :
377 : : int
378 : 0 : cpt_get_msix_offset(struct dev *dev, struct msix_offset_rsp **msix_rsp)
379 : : {
380 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
381 : : int rc;
382 : :
383 : : /* Get MSIX vector offsets */
384 : 0 : mbox_alloc_msg_msix_offset(mbox);
385 : : rc = mbox_process_msg(mbox, (void *)msix_rsp);
386 : : mbox_put(mbox);
387 : :
388 : 0 : return rc;
389 : : }
390 : :
391 : : int
392 : 0 : cpt_lfs_attach(struct dev *dev, uint8_t blkaddr, bool modify, uint16_t nb_lf)
393 : : {
394 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
395 : : struct rsrc_attach_req *req;
396 : : int rc;
397 : :
398 [ # # ]: 0 : if (blkaddr != RVU_BLOCK_ADDR_CPT0 && blkaddr != RVU_BLOCK_ADDR_CPT1) {
399 : : rc = -EINVAL;
400 : 0 : goto exit;
401 : : }
402 : :
403 : : /* Attach CPT(lf) */
404 : 0 : req = mbox_alloc_msg_attach_resources(mbox);
405 [ # # ]: 0 : if (req == NULL) {
406 : : rc = -ENOSPC;
407 : 0 : goto exit;
408 : : }
409 : :
410 : 0 : req->cptlfs = nb_lf;
411 : 0 : req->modify = modify;
412 : 0 : req->cpt_blkaddr = blkaddr;
413 : :
414 : 0 : rc = mbox_process(mbox);
415 : 0 : exit:
416 : : mbox_put(mbox);
417 : 0 : return rc;
418 : : }
419 : :
420 : : int
421 : 0 : cpt_lfs_detach(struct dev *dev)
422 : : {
423 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
424 : : struct rsrc_detach_req *req;
425 : : int rc;
426 : :
427 : 0 : req = mbox_alloc_msg_detach_resources(mbox);
428 [ # # ]: 0 : if (req == NULL) {
429 : : rc = -ENOSPC;
430 : 0 : goto exit;
431 : : }
432 : :
433 : 0 : req->cptlfs = 1;
434 : 0 : req->partial = 1;
435 : :
436 : 0 : rc = mbox_process(mbox);
437 : 0 : exit:
438 : : mbox_put(mbox);
439 : 0 : return rc;
440 : : }
441 : :
442 : : static int
443 : 0 : cpt_available_lfs_get(struct dev *dev, uint16_t *nb_lf)
444 : : {
445 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
446 : : struct free_rsrcs_rsp *rsp;
447 : : int rc;
448 : :
449 : 0 : mbox_alloc_msg_free_rsrc_cnt(mbox);
450 : :
451 : : rc = mbox_process_msg(mbox, (void *)&rsp);
452 [ # # ]: 0 : if (rc) {
453 : : rc = -EIO;
454 : 0 : goto exit;
455 : : }
456 : :
457 : 0 : *nb_lf = PLT_MAX((uint16_t)rsp->cpt, (uint16_t)rsp->cpt1);
458 : : rc = 0;
459 : 0 : exit:
460 : : mbox_put(mbox);
461 : 0 : return rc;
462 : : }
463 : :
464 : : int
465 : 0 : cpt_lfs_alloc(struct dev *dev, uint8_t eng_grpmsk, uint8_t blkaddr, bool inl_dev_sso,
466 : : bool ctx_ilen_valid, uint8_t ctx_ilen, bool rxc_ena, uint16_t rx_inject_qp)
467 : : {
468 : : struct cpt_lf_alloc_req_msg *req;
469 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
470 : : int rc;
471 : :
472 [ # # ]: 0 : if (blkaddr != RVU_BLOCK_ADDR_CPT0 && blkaddr != RVU_BLOCK_ADDR_CPT1) {
473 : : rc = -EINVAL;
474 : 0 : goto exit;
475 : : }
476 : :
477 : 0 : req = mbox_alloc_msg_cpt_lf_alloc(mbox);
478 [ # # ]: 0 : if (!req) {
479 : : rc = -ENOSPC;
480 : 0 : goto exit;
481 : : }
482 : :
483 : 0 : req->nix_pf_func = 0;
484 [ # # # # ]: 0 : if (inl_dev_sso && nix_inl_dev_pffunc_get())
485 : 0 : req->sso_pf_func = nix_inl_dev_pffunc_get();
486 : : else
487 : 0 : req->sso_pf_func = idev_sso_pffunc_get();
488 : 0 : req->eng_grpmsk = eng_grpmsk;
489 : 0 : req->blkaddr = blkaddr;
490 : 0 : req->ctx_ilen_valid = ctx_ilen_valid;
491 : 0 : req->ctx_ilen = ctx_ilen;
492 [ # # ]: 0 : if (rxc_ena) {
493 : 0 : req->rxc_ena = 1;
494 : 0 : req->rxc_ena_lf_id = rx_inject_qp;
495 : : }
496 : :
497 : 0 : rc = mbox_process(mbox);
498 : 0 : exit:
499 : : mbox_put(mbox);
500 : 0 : return rc;
501 : : }
502 : :
503 : : int
504 : 0 : cpt_lfs_free(struct dev *dev)
505 : : {
506 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
507 : : int rc;
508 : :
509 : 0 : mbox_alloc_msg_cpt_lf_free(mbox);
510 : :
511 : 0 : rc = mbox_process(mbox);
512 : : mbox_put(mbox);
513 : 0 : return rc;
514 : : }
515 : :
516 : : static int
517 : 0 : cpt_hardware_caps_get(struct dev *dev, struct roc_cpt *roc_cpt)
518 : : {
519 : : struct cpt_caps_rsp_msg *rsp;
520 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
521 : : int ret;
522 : :
523 : 0 : mbox_alloc_msg_cpt_caps_get(mbox);
524 : :
525 : : ret = mbox_process_msg(mbox, (void *)&rsp);
526 [ # # ]: 0 : if (ret) {
527 : : ret = -EIO;
528 : 0 : goto exit;
529 : : }
530 : :
531 : 0 : roc_cpt->cpt_revision = rsp->cpt_revision;
532 : 0 : mbox_memcpy(roc_cpt->hw_caps, rsp->eng_caps,
533 : : sizeof(union cpt_eng_caps) * CPT_MAX_ENG_TYPES);
534 : :
535 : : ret = 0;
536 : :
537 : 0 : exit:
538 : : mbox_put(mbox);
539 : 0 : return ret;
540 : : }
541 : :
542 : : static uint32_t
543 : : cpt_lf_iq_mem_calc(uint32_t nb_desc)
544 : : {
545 : : uint32_t len;
546 : :
547 : : /* Space for instruction group memory */
548 : 0 : len = CPT_IQ_GRP_SIZE(nb_desc);
549 : :
550 : : /* Align to 128B */
551 : 0 : len = PLT_ALIGN(len, ROC_ALIGN);
552 : :
553 : : /* Space for FC */
554 : 0 : len += CPT_IQ_FC_LEN;
555 : :
556 : : /* For instruction queues */
557 : 0 : len += PLT_ALIGN(CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc) *
558 : : CPT_IQ_NB_DESC_MULTIPLIER *
559 : : sizeof(struct cpt_inst_s),
560 : : ROC_ALIGN);
561 : :
562 : : return len;
563 : : }
564 : :
565 : : static inline void
566 : 0 : cpt_iq_init(struct roc_cpt_lf *lf)
567 : : {
568 : 0 : union cpt_lf_q_size lf_q_size = {.u = 0x0};
569 : : union cpt_lf_q_base lf_q_base = {.u = 0x0};
570 : : uintptr_t addr;
571 : :
572 : 0 : lf->io_addr = lf->rbase + CPT_LF_NQX(0);
573 : :
574 : : /* Disable command queue */
575 : 0 : roc_cpt_iq_disable(lf);
576 : :
577 : : /* Set command queue base address */
578 : 0 : addr = (uintptr_t)lf->iq_vaddr +
579 : 0 : PLT_ALIGN(CPT_IQ_GRP_SIZE(lf->nb_desc), ROC_ALIGN);
580 : :
581 : : lf_q_base.u = addr;
582 : :
583 : 0 : plt_write64(lf_q_base.u, lf->rbase + CPT_LF_Q_BASE);
584 : :
585 : : /* Set command queue size */
586 : 0 : lf_q_size.s.size_div40 = CPT_IQ_NB_DESC_SIZE_DIV40(lf->nb_desc);
587 : 0 : plt_write64(lf_q_size.u, lf->rbase + CPT_LF_Q_SIZE);
588 : :
589 : 0 : lf->fc_addr = (uint64_t *)addr;
590 : 0 : }
591 : :
592 : : int
593 : 0 : roc_cpt_dev_configure(struct roc_cpt *roc_cpt, int nb_lf, bool rxc_ena, uint16_t rx_inject_qp)
594 : : {
595 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
596 : : uint8_t blkaddr[ROC_CPT_MAX_BLKS];
597 : : struct msix_offset_rsp *rsp;
598 : : bool ctx_ilen_valid = false;
599 : : uint16_t ctx_ilen = 0;
600 : : uint8_t eng_grpmsk;
601 : : int blknum = 0;
602 : : int rc, i;
603 : :
604 : 0 : blkaddr[0] = RVU_BLOCK_ADDR_CPT0;
605 : 0 : blkaddr[1] = RVU_BLOCK_ADDR_CPT1;
606 : :
607 [ # # ]: 0 : if ((roc_cpt->cpt_revision == ROC_CPT_REVISION_ID_98XX) &&
608 [ # # ]: 0 : (cpt->dev.pf_func & 0x1))
609 : : blknum = (blknum + 1) % ROC_CPT_MAX_BLKS;
610 : :
611 : : /* Request LF resources */
612 : 0 : rc = cpt_lfs_attach(&cpt->dev, blkaddr[blknum], true, nb_lf);
613 : :
614 : : /* Request LFs from another block if current block has less LFs */
615 [ # # # # ]: 0 : if (roc_cpt->cpt_revision == ROC_CPT_REVISION_ID_98XX && rc == ENOSPC) {
616 : 0 : blknum = (blknum + 1) % ROC_CPT_MAX_BLKS;
617 : 0 : rc = cpt_lfs_attach(&cpt->dev, blkaddr[blknum], true, nb_lf);
618 : : }
619 [ # # ]: 0 : if (rc) {
620 : 0 : plt_err("Could not attach LFs");
621 : 0 : return rc;
622 : : }
623 : :
624 [ # # ]: 0 : for (i = 0; i < nb_lf; i++)
625 : 0 : cpt->lf_blkaddr[i] = blkaddr[blknum];
626 : :
627 [ # # ]: 0 : if (roc_cpt_has_ie_engines())
628 : 0 : eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
629 : 0 : (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]) |
630 : 0 : (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_IE]);
631 : : else
632 : 0 : eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
633 : 0 : (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]);
634 : :
635 [ # # ]: 0 : if (roc_errata_cpt_has_ctx_fetch_issue()) {
636 : : ctx_ilen_valid = true;
637 : : /* Inbound SA size is max context size */
638 : : ctx_ilen = (PLT_ALIGN(ROC_OT_IPSEC_SA_SZ_MAX, ROC_ALIGN) / 128) - 1;
639 : : }
640 : :
641 : 0 : rc = cpt_lfs_alloc(&cpt->dev, eng_grpmsk, blkaddr[blknum], false, ctx_ilen_valid, ctx_ilen,
642 : : rxc_ena, rx_inject_qp);
643 [ # # ]: 0 : if (rc)
644 : 0 : goto lfs_detach;
645 : :
646 : 0 : rc = cpt_get_msix_offset(&cpt->dev, &rsp);
647 [ # # ]: 0 : if (rc)
648 : 0 : goto lfs_free;
649 : :
650 [ # # ]: 0 : for (i = 0; i < nb_lf; i++)
651 : 0 : cpt->lf_msix_off[i] =
652 [ # # ]: 0 : (cpt->lf_blkaddr[i] == RVU_BLOCK_ADDR_CPT1) ?
653 : 0 : rsp->cpt1_lf_msixoff[i] :
654 : 0 : rsp->cptlf_msixoff[i];
655 : :
656 : 0 : roc_cpt->nb_lf = nb_lf;
657 : :
658 : 0 : return 0;
659 : :
660 : : lfs_free:
661 : 0 : cpt_lfs_free(&cpt->dev);
662 : 0 : lfs_detach:
663 : 0 : cpt_lfs_detach(&cpt->dev);
664 : 0 : return rc;
665 : : }
666 : :
667 : : uint64_t
668 : 0 : cpt_get_blkaddr(struct dev *dev)
669 : : {
670 : : uint64_t reg;
671 : : uint64_t off;
672 : :
673 : : /* Reading the discovery register to know which CPT is the LF
674 : : * attached to. Assume CPT LF's of only one block are attached
675 : : * to a pffunc.
676 : : */
677 : : if (dev_is_vf(dev))
678 : : off = RVU_VF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
679 : : else
680 : : off = RVU_PF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
681 : :
682 [ # # ]: 0 : reg = plt_read64(dev->bar2 + off);
683 : :
684 [ # # ]: 0 : return reg & 0x1FFULL ? RVU_BLOCK_ADDR_CPT1 : RVU_BLOCK_ADDR_CPT0;
685 : : }
686 : :
687 : : int
688 : 0 : cpt_lf_init(struct roc_cpt_lf *lf)
689 : : {
690 : 0 : struct dev *dev = lf->dev;
691 : : uint64_t blkaddr;
692 : : void *iq_mem;
693 : : int rc;
694 : :
695 [ # # ]: 0 : if (lf->nb_desc == 0 || lf->nb_desc > CPT_LF_MAX_NB_DESC)
696 : 0 : lf->nb_desc = CPT_LF_DEFAULT_NB_DESC;
697 : :
698 : : /* Allocate memory for instruction queue for CPT LF. */
699 : 0 : iq_mem = plt_zmalloc(cpt_lf_iq_mem_calc(lf->nb_desc), ROC_ALIGN);
700 [ # # ]: 0 : if (iq_mem == NULL)
701 : : return -ENOMEM;
702 : : plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
703 : :
704 : 0 : blkaddr = cpt_get_blkaddr(dev);
705 : 0 : lf->rbase = dev->bar2 + ((blkaddr << 20) | (lf->lf_id << 12));
706 : 0 : lf->iq_vaddr = iq_mem;
707 : 0 : lf->lmt_base = dev->lmt_base;
708 : 0 : lf->pf_func = dev->pf_func;
709 : :
710 : : /* Initialize instruction queue */
711 : 0 : cpt_iq_init(lf);
712 : :
713 : 0 : rc = cpt_lf_register_irqs(lf);
714 [ # # ]: 0 : if (rc)
715 : 0 : goto disable_iq;
716 : :
717 : : return 0;
718 : :
719 : : disable_iq:
720 : 0 : roc_cpt_iq_disable(lf);
721 : 0 : plt_free(iq_mem);
722 : 0 : return rc;
723 : : }
724 : :
725 : : int
726 : 0 : roc_cpt_lf_init(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf)
727 : : {
728 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
729 : : int rc;
730 : :
731 : 0 : lf->dev = &cpt->dev;
732 : 0 : lf->roc_cpt = roc_cpt;
733 : 0 : lf->msixoff = cpt->lf_msix_off[lf->lf_id];
734 : 0 : lf->pci_dev = cpt->pci_dev;
735 : :
736 : 0 : rc = cpt_lf_init(lf);
737 [ # # ]: 0 : if (rc)
738 : : return rc;
739 : :
740 : : /* LF init successful */
741 : 0 : roc_cpt->lf[lf->lf_id] = lf;
742 : 0 : return rc;
743 : : }
744 : :
745 : : int
746 : 0 : roc_cpt_dev_init(struct roc_cpt *roc_cpt)
747 : : {
748 : : struct plt_pci_device *pci_dev;
749 : : uint16_t nb_lf_avail;
750 : : struct dev *dev;
751 : : struct cpt *cpt;
752 : : int rc;
753 : :
754 [ # # # # ]: 0 : if (roc_cpt == NULL || roc_cpt->pci_dev == NULL)
755 : : return -EINVAL;
756 : :
757 : : PLT_STATIC_ASSERT(sizeof(struct cpt) <= ROC_CPT_MEM_SZ);
758 : :
759 : : cpt = roc_cpt_to_cpt_priv(roc_cpt);
760 : : memset(cpt, 0, sizeof(*cpt));
761 : : pci_dev = roc_cpt->pci_dev;
762 : 0 : dev = &cpt->dev;
763 : :
764 : : /* Initialize device */
765 : 0 : rc = dev_init(dev, pci_dev);
766 [ # # ]: 0 : if (rc) {
767 : 0 : plt_err("Failed to init roc device");
768 : 0 : return rc;
769 : : }
770 : :
771 : 0 : cpt->pci_dev = pci_dev;
772 : 0 : roc_cpt->lmt_base = dev->lmt_base;
773 : :
774 : 0 : rc = cpt_hardware_caps_get(dev, roc_cpt);
775 [ # # ]: 0 : if (rc) {
776 : 0 : plt_err("Could not determine hardware capabilities");
777 : 0 : goto fail;
778 : : }
779 : :
780 : 0 : rc = cpt_available_lfs_get(&cpt->dev, &nb_lf_avail);
781 [ # # ]: 0 : if (rc) {
782 : 0 : plt_err("Could not get available lfs");
783 : 0 : goto fail;
784 : : }
785 : :
786 : : /* Reserve 1 CPT LF for inline inbound */
787 : 0 : nb_lf_avail = PLT_MIN(nb_lf_avail, (uint16_t)(ROC_CPT_MAX_LFS - 1));
788 : :
789 : 0 : roc_cpt->nb_lf_avail = nb_lf_avail;
790 : :
791 : 0 : dev->roc_cpt = roc_cpt;
792 : :
793 : : /* Set it to idev if not already present */
794 [ # # ]: 0 : if (!roc_idev_cpt_get())
795 : 0 : roc_idev_cpt_set(roc_cpt);
796 : :
797 : : return 0;
798 : :
799 : 0 : fail:
800 : 0 : dev_fini(dev, pci_dev);
801 : 0 : return rc;
802 : : }
803 : :
804 : : int
805 : 0 : roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, void *cptr, bool inval)
806 : : {
807 : : union cpt_lf_ctx_flush reg;
808 : : union cpt_lf_ctx_err err;
809 : :
810 [ # # ]: 0 : if (lf == NULL) {
811 : 0 : plt_err("Could not trigger CTX flush");
812 : 0 : return -ENOTSUP;
813 : : }
814 : :
815 : 0 : reg.u = 0;
816 : 0 : reg.s.inval = inval;
817 : 0 : reg.s.cptr = (uintptr_t)cptr >> 7;
818 : :
819 [ # # ]: 0 : plt_write64(reg.u, lf->rbase + CPT_LF_CTX_FLUSH);
820 : :
821 : : plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
822 : :
823 : : /* Read a CSR to ensure that the FLUSH operation is complete */
824 [ # # ]: 0 : err.u = plt_read64(lf->rbase + CPT_LF_CTX_ERR);
825 : :
826 [ # # # # ]: 0 : if (err.s.busy_sw_flush && inval) {
827 : 0 : plt_err("CTX entry could not be invalidated due to active usage.");
828 : 0 : return -EAGAIN;
829 : : }
830 : :
831 [ # # ]: 0 : if (err.s.flush_st_flt) {
832 : 0 : plt_err("CTX flush could not complete due to store fault");
833 : 0 : return -EFAULT;
834 : : }
835 : :
836 : : return 0;
837 : : }
838 : :
839 : : int
840 : 0 : roc_cpt_lf_ctx_reload(struct roc_cpt_lf *lf, void *cptr)
841 : : {
842 : : union cpt_lf_ctx_reload reg;
843 : :
844 [ # # ]: 0 : if (lf == NULL) {
845 : 0 : plt_err("Could not trigger CTX reload");
846 : 0 : return -ENOTSUP;
847 : : }
848 : :
849 : 0 : reg.u = 0;
850 : 0 : reg.s.cptr = (uintptr_t)cptr >> 7;
851 : :
852 : 0 : plt_write64(reg.u, lf->rbase + CPT_LF_CTX_RELOAD);
853 : :
854 : 0 : return 0;
855 : : }
856 : :
857 : : static int
858 : 0 : cpt_lf_reset(struct roc_cpt_lf *lf)
859 : : {
860 : : struct cpt_lf_rst_req *req;
861 : 0 : struct dev *dev = lf->dev;
862 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
863 : : int rc;
864 : :
865 : 0 : req = mbox_alloc_msg_cpt_lf_reset(mbox);
866 [ # # ]: 0 : if (req == NULL) {
867 : : rc = -EIO;
868 : 0 : goto exit;
869 : : }
870 : :
871 : 0 : req->slot = lf->lf_id;
872 : :
873 : 0 : rc = mbox_process(mbox);
874 : 0 : exit:
875 : : mbox_put(mbox);
876 : 0 : return rc;
877 : : }
878 : :
879 : : static void
880 : 0 : cpt_9k_lf_rst_lmtst(struct roc_cpt_lf *lf, uint8_t egrp)
881 : : {
882 : : struct cpt_inst_s inst;
883 : : uint64_t lmt_status;
884 : :
885 : : memset(&inst, 0, sizeof(struct cpt_inst_s));
886 : 0 : inst.w7.s.egrp = egrp;
887 : :
888 : 0 : plt_io_wmb();
889 : :
890 : : do {
891 : : /* Copy CPT command to LMTLINE */
892 : : roc_lmt_mov64((void *)lf->lmt_base, &inst);
893 : : lmt_status = roc_lmt_submit_ldeor(lf->io_addr);
894 : : } while (lmt_status == 0);
895 : : }
896 : :
897 : : static void
898 : : cpt_10k_lf_rst_lmtst(struct roc_cpt_lf *lf, uint8_t egrp)
899 : : {
900 : : uint64_t lmt_base, lmt_arg, io_addr;
901 : : struct cpt_inst_s *inst;
902 : : uint16_t lmt_id;
903 : :
904 : 0 : lmt_base = lf->lmt_base;
905 : : io_addr = lf->io_addr;
906 : :
907 : : io_addr |= ROC_CN10K_CPT_INST_DW_M1 << 4;
908 : : ROC_LMT_BASE_ID_GET(lmt_base, lmt_id);
909 : :
910 : 0 : inst = (struct cpt_inst_s *)lmt_base;
911 : : memset(inst, 0, sizeof(struct cpt_inst_s));
912 : : inst->w7.s.egrp = egrp;
913 : : lmt_arg = ROC_CN10K_CPT_LMT_ARG | (uint64_t)lmt_id;
914 : : roc_lmt_submit_steorl(lmt_arg, io_addr);
915 : : }
916 : :
917 : : static void
918 : 0 : roc_cpt_iq_reset(struct roc_cpt_lf *lf)
919 : : {
920 : : union cpt_lf_inprog lf_inprog = {.u = 0x0};
921 : : union cpt_lf_ctl lf_ctl = {.u = 0x0};
922 : :
923 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
924 [ # # # # ]: 0 : if (((lf_inprog.s.gwb_cnt & 0x1) == 0x1) &&
925 : : (lf_inprog.s.grb_partial == 0x0)) {
926 : 0 : lf_inprog.s.grp_drp = 1;
927 [ # # ]: 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
928 : :
929 [ # # ]: 0 : lf_ctl.u = plt_read64(lf->rbase + CPT_LF_CTL);
930 : 0 : lf_ctl.s.ena = 1;
931 [ # # ]: 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
932 : :
933 [ # # ]: 0 : if (roc_model_is_cn9k())
934 : 0 : cpt_9k_lf_rst_lmtst(lf, ROC_LEGACY_CPT_DFLT_ENG_GRP_SE);
935 : : else
936 : : cpt_10k_lf_rst_lmtst(lf, ROC_LEGACY_CPT_DFLT_ENG_GRP_SE);
937 : :
938 : 0 : plt_read64(lf->rbase + CPT_LF_INPROG);
939 : 0 : plt_delay_us(2);
940 : : }
941 [ # # ]: 0 : if (cpt_lf_reset(lf))
942 : 0 : plt_err("Invalid CPT LF to reset");
943 : 0 : }
944 : :
945 : : void
946 : 0 : cpt_lf_fini(struct roc_cpt_lf *lf)
947 : : {
948 : : /* Unregister IRQ's */
949 : : cpt_lf_unregister_irqs(lf);
950 : :
951 : : /* Disable IQ */
952 : 0 : roc_cpt_iq_disable(lf);
953 : 0 : roc_cpt_iq_reset(lf);
954 : :
955 : : /* Free memory */
956 : 0 : plt_free(lf->iq_vaddr);
957 : 0 : lf->iq_vaddr = NULL;
958 : 0 : }
959 : :
960 : : void
961 : 0 : roc_cpt_lf_reset(struct roc_cpt_lf *lf)
962 : : {
963 [ # # ]: 0 : if (lf == NULL)
964 : : return;
965 : :
966 : : cpt_lf_misc_intr_enb_dis(lf, false);
967 : : cpt_lf_done_intr_enb_dis(lf, false);
968 : 0 : roc_cpt_iq_disable(lf);
969 : 0 : roc_cpt_iq_reset(lf);
970 : : cpt_lf_misc_intr_enb_dis(lf, true);
971 : : cpt_lf_done_intr_enb_dis(lf, true);
972 : : }
973 : :
974 : : void
975 : 0 : roc_cpt_lf_fini(struct roc_cpt_lf *lf)
976 : : {
977 [ # # ]: 0 : if (lf == NULL)
978 : : return;
979 : 0 : lf->roc_cpt->lf[lf->lf_id] = NULL;
980 : 0 : cpt_lf_fini(lf);
981 : : }
982 : :
983 : : int
984 : 0 : roc_cpt_dev_fini(struct roc_cpt *roc_cpt)
985 : : {
986 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
987 : :
988 : : if (cpt == NULL)
989 : : return -EINVAL;
990 : :
991 : : /* Remove idev references */
992 [ # # ]: 0 : if (roc_idev_cpt_get() == roc_cpt)
993 : 0 : roc_idev_cpt_set(NULL);
994 : :
995 : 0 : roc_cpt->nb_lf_avail = 0;
996 : :
997 : 0 : roc_cpt->lmt_base = 0;
998 : :
999 : 0 : return dev_fini(&cpt->dev, cpt->pci_dev);
1000 : : }
1001 : :
1002 : : void
1003 : 0 : roc_cpt_dev_clear(struct roc_cpt *roc_cpt)
1004 : : {
1005 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
1006 : : int i;
1007 : :
1008 : : if (cpt == NULL)
1009 : : return;
1010 : :
1011 [ # # ]: 0 : if (roc_cpt->nb_lf == 0)
1012 : : return;
1013 : :
1014 [ # # ]: 0 : for (i = 0; i < roc_cpt->nb_lf; i++)
1015 : 0 : cpt->lf_msix_off[i] = 0;
1016 : :
1017 : 0 : roc_cpt->nb_lf = 0;
1018 : :
1019 : 0 : cpt_lfs_free(&cpt->dev);
1020 : :
1021 : 0 : cpt_lfs_detach(&cpt->dev);
1022 : : }
1023 : :
1024 : : int
1025 : 0 : roc_cpt_eng_grp_add(struct roc_cpt *roc_cpt, enum cpt_eng_type eng_type)
1026 : : {
1027 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
1028 : : struct dev *dev = &cpt->dev;
1029 : : struct cpt_eng_grp_req *req;
1030 : : struct cpt_eng_grp_rsp *rsp;
1031 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
1032 : : int ret;
1033 : :
1034 : 0 : req = mbox_alloc_msg_cpt_eng_grp_get(mbox);
1035 [ # # ]: 0 : if (req == NULL) {
1036 : : ret = -EIO;
1037 : 0 : goto exit;
1038 : : }
1039 : :
1040 [ # # ]: 0 : switch (eng_type) {
1041 : : case CPT_ENG_TYPE_AE:
1042 : : case CPT_ENG_TYPE_SE:
1043 : : case CPT_ENG_TYPE_IE:
1044 : : break;
1045 : 0 : default:
1046 : : ret = -EINVAL;
1047 : 0 : goto exit;
1048 : : }
1049 : :
1050 : 0 : req->eng_type = eng_type;
1051 : 0 : ret = mbox_process_msg(dev->mbox, (void *)&rsp);
1052 [ # # ]: 0 : if (ret) {
1053 : : ret = -EIO;
1054 : 0 : goto exit;
1055 : : }
1056 : :
1057 [ # # ]: 0 : if (rsp->eng_grp_num > 8) {
1058 : 0 : plt_err("Invalid CPT engine group");
1059 : : ret = -ENOTSUP;
1060 : 0 : goto exit;
1061 : : }
1062 : :
1063 : 0 : roc_cpt->eng_grp[eng_type] = rsp->eng_grp_num;
1064 : :
1065 : 0 : ret = rsp->eng_grp_num;
1066 : 0 : exit:
1067 : : mbox_put(mbox);
1068 : 0 : return ret;
1069 : : }
1070 : :
1071 : : void
1072 : 0 : roc_cpt_iq_disable(struct roc_cpt_lf *lf)
1073 : : {
1074 : 0 : volatile union cpt_lf_q_grp_ptr grp_ptr = {.u = 0x0};
1075 : 0 : volatile union cpt_lf_inprog lf_inprog = {.u = 0x0};
1076 : : union cpt_lf_ctl lf_ctl = {.u = 0x0};
1077 : : int timeout = 20;
1078 : : int cnt;
1079 : :
1080 : : /* Disable instructions enqueuing */
1081 : 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
1082 : :
1083 : : /* Wait for instruction queue to become empty */
1084 : : do {
1085 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1086 [ # # ]: 0 : if (!lf_inprog.s.inflight)
1087 : : break;
1088 : :
1089 : : plt_delay_ms(20);
1090 [ # # ]: 0 : if (timeout-- < 0) {
1091 : 0 : plt_err("CPT LF %d is still busy", lf->lf_id);
1092 : 0 : break;
1093 : : }
1094 : :
1095 : : } while (1);
1096 : :
1097 : : /* Disable executions in the LF's queue.
1098 : : * The queue should be empty at this point
1099 : : */
1100 : 0 : lf_inprog.s.eena = 0x0;
1101 : 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
1102 : :
1103 : : /* Wait for instruction queue to become empty */
1104 : : cnt = 0;
1105 : : do {
1106 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1107 [ # # ]: 0 : if (lf_inprog.s.grb_partial)
1108 : : cnt = 0;
1109 : : else
1110 : 0 : cnt++;
1111 [ # # ]: 0 : grp_ptr.u = plt_read64(lf->rbase + CPT_LF_Q_GRP_PTR);
1112 [ # # # # ]: 0 : } while ((cnt < 10) && (grp_ptr.s.nq_ptr != grp_ptr.s.dq_ptr));
1113 : :
1114 : : cnt = 0;
1115 : : do {
1116 : 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1117 [ # # # # ]: 0 : if ((lf_inprog.s.inflight == 0) && (lf_inprog.s.gwb_cnt < 40) &&
1118 [ # # # # ]: 0 : ((lf_inprog.s.grb_cnt == 0) || (lf_inprog.s.grb_cnt == 40)))
1119 : 0 : cnt++;
1120 : : else
1121 : : cnt = 0;
1122 [ # # ]: 0 : } while (cnt < 10);
1123 : 0 : }
1124 : :
1125 : : void
1126 : 0 : roc_cpt_iq_enable(struct roc_cpt_lf *lf)
1127 : : {
1128 : : union cpt_lf_inprog lf_inprog;
1129 : : union cpt_lf_ctl lf_ctl;
1130 : :
1131 : : /* Disable command queue */
1132 : 0 : roc_cpt_iq_disable(lf);
1133 : :
1134 : : /* Enable instruction queue enqueuing */
1135 [ # # ]: 0 : lf_ctl.u = plt_read64(lf->rbase + CPT_LF_CTL);
1136 : 0 : lf_ctl.s.ena = 1;
1137 : 0 : lf_ctl.s.fc_ena = 1;
1138 : 0 : lf_ctl.s.fc_up_crossing = 0;
1139 : 0 : lf_ctl.s.fc_hyst_bits = plt_log2_u32(CPT_LF_FC_MIN_THRESHOLD);
1140 [ # # ]: 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
1141 : :
1142 : : /* Enable command queue execution */
1143 : 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1144 : 0 : lf_inprog.s.eena = 1;
1145 [ # # ]: 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
1146 : :
1147 [ # # ]: 0 : if (roc_errata_cpt_has_ctx_fetch_issue()) {
1148 : : /* Enable flush on FLR */
1149 : 0 : plt_write64(1, lf->rbase + CPT_LF_CTX_CTL);
1150 : : }
1151 : :
1152 : 0 : cpt_lf_dump(lf);
1153 : 0 : }
1154 : :
1155 : : int
1156 : 0 : roc_cpt_lmtline_init(struct roc_cpt *roc_cpt, struct roc_cpt_lmtline *lmtline, int lf_id,
1157 : : bool is_dual)
1158 : : {
1159 : : struct roc_cpt_lf *lf;
1160 : :
1161 : 0 : lf = roc_cpt->lf[lf_id];
1162 [ # # ]: 0 : if (lf == NULL)
1163 : : return -ENOTSUP;
1164 : :
1165 : 0 : lmtline->io_addr = lf->io_addr;
1166 [ # # ]: 0 : lmtline->fc_thresh = lf->nb_desc - CPT_LF_FC_MIN_THRESHOLD;
1167 : :
1168 [ # # ]: 0 : if (roc_model_is_cn10k()) {
1169 [ # # ]: 0 : if (is_dual) {
1170 : 0 : lmtline->io_addr |= ROC_CN10K_TWO_CPT_INST_DW_M1 << 4;
1171 : 0 : lmtline->fc_thresh = lf->nb_desc - 2 * CPT_LF_FC_MIN_THRESHOLD;
1172 : : } else {
1173 : 0 : lmtline->io_addr |= ROC_CN10K_CPT_INST_DW_M1 << 4;
1174 : : }
1175 : : }
1176 : :
1177 : 0 : lmtline->fc_addr = lf->fc_addr;
1178 : 0 : lmtline->lmt_base = lf->lmt_base;
1179 : :
1180 : 0 : return 0;
1181 : : }
1182 : :
1183 : : int
1184 [ # # ]: 0 : roc_cpt_ctx_write(struct roc_cpt_lf *lf, void *sa_dptr, void *sa_cptr,
1185 : : uint16_t sa_len)
1186 : : {
1187 : : union cpt_res_s res, *hw_res;
1188 : : uint64_t lmt_arg, io_addr;
1189 : : struct cpt_inst_s *inst;
1190 : : uintptr_t lmt_base;
1191 : : uint16_t lmt_id;
1192 : : uint64_t *dptr;
1193 : : uint8_t egrp;
1194 : : int i;
1195 : :
1196 [ # # ]: 0 : if (!plt_is_aligned(sa_cptr, 128)) {
1197 : 0 : plt_err("Context pointer should be 128B aligned");
1198 : 0 : return -EINVAL;
1199 : : }
1200 : :
1201 [ # # ]: 0 : if (lf == NULL) {
1202 : 0 : plt_err("Invalid CPT LF");
1203 : 0 : return -EINVAL;
1204 : : }
1205 : :
1206 [ # # ]: 0 : if (lf->roc_cpt == NULL) {
1207 [ # # ]: 0 : if (roc_cpt_has_ie_engines())
1208 : : egrp = ROC_LEGACY_CPT_DFLT_ENG_GRP_SE_IE;
1209 : : else
1210 : : egrp = ROC_CPT_DFLT_ENG_GRP_SE;
1211 : : } else {
1212 [ # # ]: 0 : if (roc_cpt_has_ie_engines())
1213 : 0 : egrp = lf->roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
1214 : : else
1215 : 0 : egrp = lf->roc_cpt->eng_grp[CPT_ENG_TYPE_SE];
1216 : : }
1217 : :
1218 : 0 : lmt_base = lf->lmt_base;
1219 : :
1220 : : /* Use this lcore's LMT line as no one else is using it */
1221 : : ROC_LMT_BASE_ID_GET(lmt_base, lmt_id);
1222 : 0 : inst = (struct cpt_inst_s *)lmt_base;
1223 : :
1224 : : memset(inst, 0, sizeof(struct cpt_inst_s));
1225 : :
1226 : 0 : hw_res = plt_zmalloc(sizeof(*hw_res), ROC_CPT_RES_ALIGN);
1227 [ # # ]: 0 : if (hw_res == NULL) {
1228 : 0 : plt_err("Couldn't allocate memory for result address");
1229 : 0 : return -ENOMEM;
1230 : : }
1231 : :
1232 : 0 : dptr = plt_zmalloc(sa_len, 8);
1233 [ # # ]: 0 : if (dptr == NULL) {
1234 : 0 : plt_err("Couldn't allocate memory for SA dptr");
1235 : 0 : plt_free(hw_res);
1236 : 0 : return -ENOMEM;
1237 : : }
1238 : :
1239 [ # # ]: 0 : for (i = 0; i < (sa_len / 8); i++)
1240 [ # # ]: 0 : dptr[i] = plt_cpu_to_be_64(((uint64_t *)sa_dptr)[i]);
1241 : :
1242 : : /* Fill CPT_INST_S for WRITE_SA microcode op */
1243 : 0 : hw_res->cn10k.compcode = CPT_COMP_NOT_DONE;
1244 : 0 : inst->res_addr = (uint64_t)hw_res;
1245 : 0 : inst->dptr = (uint64_t)dptr;
1246 : 0 : inst->w4.s.param2 = sa_len >> 3;
1247 : 0 : inst->w4.s.dlen = sa_len;
1248 : 0 : inst->w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_WRITE_SA;
1249 : 0 : inst->w4.s.opcode_minor = ROC_IE_OT_MINOR_OP_WRITE_SA;
1250 : 0 : inst->w7.s.cptr = (uint64_t)sa_cptr;
1251 : 0 : inst->w7.s.ctx_val = 1;
1252 : 0 : inst->w7.s.egrp = egrp;
1253 : :
1254 : : lmt_arg = ROC_CN10K_CPT_LMT_ARG | (uint64_t)lmt_id;
1255 : : io_addr = lf->io_addr | ROC_CN10K_CPT_INST_DW_M1 << 4;
1256 : :
1257 : : roc_lmt_submit_steorl(lmt_arg, io_addr);
1258 : 0 : plt_io_wmb();
1259 : :
1260 : : /* Use 1 min timeout for the poll */
1261 : 0 : const uint64_t timeout = plt_tsc_cycles() + 60 * plt_tsc_hz();
1262 : :
1263 : : /* Wait until CPT instruction completes */
1264 : : do {
1265 : 0 : res.u64[0] = __atomic_load_n(&hw_res->u64[0], __ATOMIC_RELAXED);
1266 [ # # ]: 0 : if (unlikely(plt_tsc_cycles() > timeout))
1267 : : break;
1268 [ # # ]: 0 : } while (res.cn10k.compcode == CPT_COMP_NOT_DONE);
1269 : :
1270 : 0 : plt_free(dptr);
1271 : 0 : plt_free(hw_res);
1272 : :
1273 [ # # ]: 0 : if (res.cn10k.compcode != CPT_COMP_GOOD || res.cn10k.uc_compcode) {
1274 : 0 : plt_err("Write SA operation timed out");
1275 : 0 : return -ETIMEDOUT;
1276 : : }
1277 : :
1278 : : return 0;
1279 : : }
1280 : :
1281 : : void
1282 : 0 : roc_cpt_int_misc_cb_register(roc_cpt_int_misc_cb_t cb, void *args)
1283 : : {
1284 [ # # ]: 0 : if (int_cb.cb != NULL)
1285 : : return;
1286 : :
1287 : 0 : int_cb.cb = cb;
1288 : 0 : int_cb.cb_args = args;
1289 : : }
1290 : :
1291 : : int
1292 : 0 : roc_cpt_int_misc_cb_unregister(roc_cpt_int_misc_cb_t cb, void *args)
1293 : : {
1294 [ # # ]: 0 : if (int_cb.cb == NULL)
1295 : : return 0;
1296 [ # # # # ]: 0 : if (int_cb.cb != cb || int_cb.cb_args != args)
1297 : : return -EINVAL;
1298 : :
1299 : 0 : int_cb.cb = NULL;
1300 : 0 : int_cb.cb_args = NULL;
1301 : 0 : return 0;
1302 : : }
1303 : :
1304 : : bool
1305 [ # # ]: 0 : roc_cpt_has_ie_engines(void)
1306 : : {
1307 [ # # # # ]: 0 : if (roc_model_is_cn9k() || roc_model_is_cn10k())
1308 : 0 : return true;
1309 : :
1310 : : return false;
1311 : : }
|