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 : eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
628 : 0 : (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]) |
629 [ # # ]: 0 : (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_IE]);
630 : :
631 [ # # ]: 0 : if (roc_errata_cpt_has_ctx_fetch_issue()) {
632 : : ctx_ilen_valid = true;
633 : : /* Inbound SA size is max context size */
634 : : ctx_ilen = (PLT_ALIGN(ROC_OT_IPSEC_SA_SZ_MAX, ROC_ALIGN) / 128) - 1;
635 : : }
636 : :
637 : 0 : rc = cpt_lfs_alloc(&cpt->dev, eng_grpmsk, blkaddr[blknum], false, ctx_ilen_valid, ctx_ilen,
638 : : rxc_ena, rx_inject_qp);
639 [ # # ]: 0 : if (rc)
640 : 0 : goto lfs_detach;
641 : :
642 : 0 : rc = cpt_get_msix_offset(&cpt->dev, &rsp);
643 [ # # ]: 0 : if (rc)
644 : 0 : goto lfs_free;
645 : :
646 [ # # ]: 0 : for (i = 0; i < nb_lf; i++)
647 : 0 : cpt->lf_msix_off[i] =
648 [ # # ]: 0 : (cpt->lf_blkaddr[i] == RVU_BLOCK_ADDR_CPT1) ?
649 : 0 : rsp->cpt1_lf_msixoff[i] :
650 : 0 : rsp->cptlf_msixoff[i];
651 : :
652 : 0 : roc_cpt->nb_lf = nb_lf;
653 : :
654 : 0 : return 0;
655 : :
656 : : lfs_free:
657 : 0 : cpt_lfs_free(&cpt->dev);
658 : 0 : lfs_detach:
659 : 0 : cpt_lfs_detach(&cpt->dev);
660 : 0 : return rc;
661 : : }
662 : :
663 : : uint64_t
664 : 0 : cpt_get_blkaddr(struct dev *dev)
665 : : {
666 : : uint64_t reg;
667 : : uint64_t off;
668 : :
669 : : /* Reading the discovery register to know which CPT is the LF
670 : : * attached to. Assume CPT LF's of only one block are attached
671 : : * to a pffunc.
672 : : */
673 : : if (dev_is_vf(dev))
674 : : off = RVU_VF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
675 : : else
676 : : off = RVU_PF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
677 : :
678 [ # # ]: 0 : reg = plt_read64(dev->bar2 + off);
679 : :
680 [ # # ]: 0 : return reg & 0x1FFULL ? RVU_BLOCK_ADDR_CPT1 : RVU_BLOCK_ADDR_CPT0;
681 : : }
682 : :
683 : : int
684 : 0 : cpt_lf_init(struct roc_cpt_lf *lf)
685 : : {
686 : 0 : struct dev *dev = lf->dev;
687 : : uint64_t blkaddr;
688 : : void *iq_mem;
689 : : int rc;
690 : :
691 [ # # ]: 0 : if (lf->nb_desc == 0 || lf->nb_desc > CPT_LF_MAX_NB_DESC)
692 : 0 : lf->nb_desc = CPT_LF_DEFAULT_NB_DESC;
693 : :
694 : : /* Allocate memory for instruction queue for CPT LF. */
695 : 0 : iq_mem = plt_zmalloc(cpt_lf_iq_mem_calc(lf->nb_desc), ROC_ALIGN);
696 [ # # ]: 0 : if (iq_mem == NULL)
697 : : return -ENOMEM;
698 : : plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
699 : :
700 : 0 : blkaddr = cpt_get_blkaddr(dev);
701 : 0 : lf->rbase = dev->bar2 + ((blkaddr << 20) | (lf->lf_id << 12));
702 : 0 : lf->iq_vaddr = iq_mem;
703 : 0 : lf->lmt_base = dev->lmt_base;
704 : 0 : lf->pf_func = dev->pf_func;
705 : :
706 : : /* Initialize instruction queue */
707 : 0 : cpt_iq_init(lf);
708 : :
709 : 0 : rc = cpt_lf_register_irqs(lf);
710 [ # # ]: 0 : if (rc)
711 : 0 : goto disable_iq;
712 : :
713 : : return 0;
714 : :
715 : : disable_iq:
716 : 0 : roc_cpt_iq_disable(lf);
717 : 0 : plt_free(iq_mem);
718 : 0 : return rc;
719 : : }
720 : :
721 : : int
722 : 0 : roc_cpt_lf_init(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf)
723 : : {
724 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
725 : : int rc;
726 : :
727 : 0 : lf->dev = &cpt->dev;
728 : 0 : lf->roc_cpt = roc_cpt;
729 : 0 : lf->msixoff = cpt->lf_msix_off[lf->lf_id];
730 : 0 : lf->pci_dev = cpt->pci_dev;
731 : :
732 : 0 : rc = cpt_lf_init(lf);
733 [ # # ]: 0 : if (rc)
734 : : return rc;
735 : :
736 : : /* LF init successful */
737 : 0 : roc_cpt->lf[lf->lf_id] = lf;
738 : 0 : return rc;
739 : : }
740 : :
741 : : int
742 : 0 : roc_cpt_dev_init(struct roc_cpt *roc_cpt)
743 : : {
744 : : struct plt_pci_device *pci_dev;
745 : : uint16_t nb_lf_avail;
746 : : struct dev *dev;
747 : : struct cpt *cpt;
748 : : int rc;
749 : :
750 [ # # # # ]: 0 : if (roc_cpt == NULL || roc_cpt->pci_dev == NULL)
751 : : return -EINVAL;
752 : :
753 : : PLT_STATIC_ASSERT(sizeof(struct cpt) <= ROC_CPT_MEM_SZ);
754 : :
755 : : cpt = roc_cpt_to_cpt_priv(roc_cpt);
756 : : memset(cpt, 0, sizeof(*cpt));
757 : : pci_dev = roc_cpt->pci_dev;
758 : 0 : dev = &cpt->dev;
759 : :
760 : : /* Initialize device */
761 : 0 : rc = dev_init(dev, pci_dev);
762 [ # # ]: 0 : if (rc) {
763 : 0 : plt_err("Failed to init roc device");
764 : 0 : return rc;
765 : : }
766 : :
767 : 0 : cpt->pci_dev = pci_dev;
768 : 0 : roc_cpt->lmt_base = dev->lmt_base;
769 : :
770 : 0 : rc = cpt_hardware_caps_get(dev, roc_cpt);
771 [ # # ]: 0 : if (rc) {
772 : 0 : plt_err("Could not determine hardware capabilities");
773 : 0 : goto fail;
774 : : }
775 : :
776 : 0 : rc = cpt_available_lfs_get(&cpt->dev, &nb_lf_avail);
777 [ # # ]: 0 : if (rc) {
778 : 0 : plt_err("Could not get available lfs");
779 : 0 : goto fail;
780 : : }
781 : :
782 : : /* Reserve 1 CPT LF for inline inbound */
783 : 0 : nb_lf_avail = PLT_MIN(nb_lf_avail, (uint16_t)(ROC_CPT_MAX_LFS - 1));
784 : :
785 : 0 : roc_cpt->nb_lf_avail = nb_lf_avail;
786 : :
787 : 0 : dev->roc_cpt = roc_cpt;
788 : :
789 : : /* Set it to idev if not already present */
790 [ # # ]: 0 : if (!roc_idev_cpt_get())
791 : 0 : roc_idev_cpt_set(roc_cpt);
792 : :
793 : : return 0;
794 : :
795 : 0 : fail:
796 : 0 : dev_fini(dev, pci_dev);
797 : 0 : return rc;
798 : : }
799 : :
800 : : int
801 : 0 : roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, void *cptr, bool inval)
802 : : {
803 : : union cpt_lf_ctx_flush reg;
804 : : union cpt_lf_ctx_err err;
805 : :
806 [ # # ]: 0 : if (lf == NULL) {
807 : 0 : plt_err("Could not trigger CTX flush");
808 : 0 : return -ENOTSUP;
809 : : }
810 : :
811 : 0 : reg.u = 0;
812 : 0 : reg.s.inval = inval;
813 : 0 : reg.s.cptr = (uintptr_t)cptr >> 7;
814 : :
815 [ # # ]: 0 : plt_write64(reg.u, lf->rbase + CPT_LF_CTX_FLUSH);
816 : :
817 : : plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
818 : :
819 : : /* Read a CSR to ensure that the FLUSH operation is complete */
820 [ # # ]: 0 : err.u = plt_read64(lf->rbase + CPT_LF_CTX_ERR);
821 : :
822 [ # # # # ]: 0 : if (err.s.busy_sw_flush && inval) {
823 : 0 : plt_err("CTX entry could not be invalidated due to active usage.");
824 : 0 : return -EAGAIN;
825 : : }
826 : :
827 [ # # ]: 0 : if (err.s.flush_st_flt) {
828 : 0 : plt_err("CTX flush could not complete due to store fault");
829 : 0 : return -EFAULT;
830 : : }
831 : :
832 : : return 0;
833 : : }
834 : :
835 : : int
836 : 0 : roc_cpt_lf_ctx_reload(struct roc_cpt_lf *lf, void *cptr)
837 : : {
838 : : union cpt_lf_ctx_reload reg;
839 : :
840 [ # # ]: 0 : if (lf == NULL) {
841 : 0 : plt_err("Could not trigger CTX reload");
842 : 0 : return -ENOTSUP;
843 : : }
844 : :
845 : 0 : reg.u = 0;
846 : 0 : reg.s.cptr = (uintptr_t)cptr >> 7;
847 : :
848 : 0 : plt_write64(reg.u, lf->rbase + CPT_LF_CTX_RELOAD);
849 : :
850 : 0 : return 0;
851 : : }
852 : :
853 : : static int
854 : 0 : cpt_lf_reset(struct roc_cpt_lf *lf)
855 : : {
856 : : struct cpt_lf_rst_req *req;
857 : 0 : struct dev *dev = lf->dev;
858 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
859 : : int rc;
860 : :
861 : 0 : req = mbox_alloc_msg_cpt_lf_reset(mbox);
862 [ # # ]: 0 : if (req == NULL) {
863 : : rc = -EIO;
864 : 0 : goto exit;
865 : : }
866 : :
867 : 0 : req->slot = lf->lf_id;
868 : :
869 : 0 : rc = mbox_process(mbox);
870 : 0 : exit:
871 : : mbox_put(mbox);
872 : 0 : return rc;
873 : : }
874 : :
875 : : static void
876 : 0 : cpt_9k_lf_rst_lmtst(struct roc_cpt_lf *lf, uint8_t egrp)
877 : : {
878 : : struct cpt_inst_s inst;
879 : : uint64_t lmt_status;
880 : :
881 : : memset(&inst, 0, sizeof(struct cpt_inst_s));
882 : 0 : inst.w7.s.egrp = egrp;
883 : :
884 : 0 : plt_io_wmb();
885 : :
886 : : do {
887 : : /* Copy CPT command to LMTLINE */
888 : : roc_lmt_mov64((void *)lf->lmt_base, &inst);
889 : : lmt_status = roc_lmt_submit_ldeor(lf->io_addr);
890 : : } while (lmt_status == 0);
891 : : }
892 : :
893 : : static void
894 : : cpt_10k_lf_rst_lmtst(struct roc_cpt_lf *lf, uint8_t egrp)
895 : : {
896 : : uint64_t lmt_base, lmt_arg, io_addr;
897 : : struct cpt_inst_s *inst;
898 : : uint16_t lmt_id;
899 : :
900 : 0 : lmt_base = lf->lmt_base;
901 : : io_addr = lf->io_addr;
902 : :
903 : : io_addr |= ROC_CN10K_CPT_INST_DW_M1 << 4;
904 : : ROC_LMT_BASE_ID_GET(lmt_base, lmt_id);
905 : :
906 : 0 : inst = (struct cpt_inst_s *)lmt_base;
907 : : memset(inst, 0, sizeof(struct cpt_inst_s));
908 : : inst->w7.s.egrp = egrp;
909 : : lmt_arg = ROC_CN10K_CPT_LMT_ARG | (uint64_t)lmt_id;
910 : : roc_lmt_submit_steorl(lmt_arg, io_addr);
911 : : }
912 : :
913 : : static void
914 : 0 : roc_cpt_iq_reset(struct roc_cpt_lf *lf)
915 : : {
916 : : union cpt_lf_inprog lf_inprog = {.u = 0x0};
917 : : union cpt_lf_ctl lf_ctl = {.u = 0x0};
918 : :
919 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
920 [ # # # # ]: 0 : if (((lf_inprog.s.gwb_cnt & 0x1) == 0x1) &&
921 : : (lf_inprog.s.grb_partial == 0x0)) {
922 : 0 : lf_inprog.s.grp_drp = 1;
923 [ # # ]: 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
924 : :
925 [ # # ]: 0 : lf_ctl.u = plt_read64(lf->rbase + CPT_LF_CTL);
926 : 0 : lf_ctl.s.ena = 1;
927 [ # # ]: 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
928 : :
929 [ # # ]: 0 : if (roc_model_is_cn10k())
930 : : cpt_10k_lf_rst_lmtst(lf, ROC_CPT_DFLT_ENG_GRP_SE);
931 : : else
932 : 0 : cpt_9k_lf_rst_lmtst(lf, ROC_CPT_DFLT_ENG_GRP_SE);
933 : :
934 : 0 : plt_read64(lf->rbase + CPT_LF_INPROG);
935 : 0 : plt_delay_us(2);
936 : : }
937 [ # # ]: 0 : if (cpt_lf_reset(lf))
938 : 0 : plt_err("Invalid CPT LF to reset");
939 : 0 : }
940 : :
941 : : void
942 : 0 : cpt_lf_fini(struct roc_cpt_lf *lf)
943 : : {
944 : : /* Unregister IRQ's */
945 : : cpt_lf_unregister_irqs(lf);
946 : :
947 : : /* Disable IQ */
948 : 0 : roc_cpt_iq_disable(lf);
949 : 0 : roc_cpt_iq_reset(lf);
950 : :
951 : : /* Free memory */
952 : 0 : plt_free(lf->iq_vaddr);
953 : 0 : lf->iq_vaddr = NULL;
954 : 0 : }
955 : :
956 : : void
957 : 0 : roc_cpt_lf_reset(struct roc_cpt_lf *lf)
958 : : {
959 [ # # ]: 0 : if (lf == NULL)
960 : : return;
961 : :
962 : : cpt_lf_misc_intr_enb_dis(lf, false);
963 : : cpt_lf_done_intr_enb_dis(lf, false);
964 : 0 : roc_cpt_iq_disable(lf);
965 : 0 : roc_cpt_iq_reset(lf);
966 : : cpt_lf_misc_intr_enb_dis(lf, true);
967 : : cpt_lf_done_intr_enb_dis(lf, true);
968 : : }
969 : :
970 : : void
971 : 0 : roc_cpt_lf_fini(struct roc_cpt_lf *lf)
972 : : {
973 [ # # ]: 0 : if (lf == NULL)
974 : : return;
975 : 0 : lf->roc_cpt->lf[lf->lf_id] = NULL;
976 : 0 : cpt_lf_fini(lf);
977 : : }
978 : :
979 : : int
980 : 0 : roc_cpt_dev_fini(struct roc_cpt *roc_cpt)
981 : : {
982 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
983 : :
984 : : if (cpt == NULL)
985 : : return -EINVAL;
986 : :
987 : : /* Remove idev references */
988 [ # # ]: 0 : if (roc_idev_cpt_get() == roc_cpt)
989 : 0 : roc_idev_cpt_set(NULL);
990 : :
991 : 0 : roc_cpt->nb_lf_avail = 0;
992 : :
993 : 0 : roc_cpt->lmt_base = 0;
994 : :
995 : 0 : return dev_fini(&cpt->dev, cpt->pci_dev);
996 : : }
997 : :
998 : : void
999 : 0 : roc_cpt_dev_clear(struct roc_cpt *roc_cpt)
1000 : : {
1001 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
1002 : : int i;
1003 : :
1004 : : if (cpt == NULL)
1005 : : return;
1006 : :
1007 [ # # ]: 0 : if (roc_cpt->nb_lf == 0)
1008 : : return;
1009 : :
1010 [ # # ]: 0 : for (i = 0; i < roc_cpt->nb_lf; i++)
1011 : 0 : cpt->lf_msix_off[i] = 0;
1012 : :
1013 : 0 : roc_cpt->nb_lf = 0;
1014 : :
1015 : 0 : cpt_lfs_free(&cpt->dev);
1016 : :
1017 : 0 : cpt_lfs_detach(&cpt->dev);
1018 : : }
1019 : :
1020 : : int
1021 : 0 : roc_cpt_eng_grp_add(struct roc_cpt *roc_cpt, enum cpt_eng_type eng_type)
1022 : : {
1023 : : struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
1024 : : struct dev *dev = &cpt->dev;
1025 : : struct cpt_eng_grp_req *req;
1026 : : struct cpt_eng_grp_rsp *rsp;
1027 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
1028 : : int ret;
1029 : :
1030 : 0 : req = mbox_alloc_msg_cpt_eng_grp_get(mbox);
1031 [ # # ]: 0 : if (req == NULL) {
1032 : : ret = -EIO;
1033 : 0 : goto exit;
1034 : : }
1035 : :
1036 [ # # ]: 0 : switch (eng_type) {
1037 : : case CPT_ENG_TYPE_AE:
1038 : : case CPT_ENG_TYPE_SE:
1039 : : case CPT_ENG_TYPE_IE:
1040 : : break;
1041 : 0 : default:
1042 : : ret = -EINVAL;
1043 : 0 : goto exit;
1044 : : }
1045 : :
1046 : 0 : req->eng_type = eng_type;
1047 : 0 : ret = mbox_process_msg(dev->mbox, (void *)&rsp);
1048 [ # # ]: 0 : if (ret) {
1049 : : ret = -EIO;
1050 : 0 : goto exit;
1051 : : }
1052 : :
1053 [ # # ]: 0 : if (rsp->eng_grp_num > 8) {
1054 : 0 : plt_err("Invalid CPT engine group");
1055 : : ret = -ENOTSUP;
1056 : 0 : goto exit;
1057 : : }
1058 : :
1059 : 0 : roc_cpt->eng_grp[eng_type] = rsp->eng_grp_num;
1060 : :
1061 : 0 : ret = rsp->eng_grp_num;
1062 : 0 : exit:
1063 : : mbox_put(mbox);
1064 : 0 : return ret;
1065 : : }
1066 : :
1067 : : void
1068 : 0 : roc_cpt_iq_disable(struct roc_cpt_lf *lf)
1069 : : {
1070 : 0 : volatile union cpt_lf_q_grp_ptr grp_ptr = {.u = 0x0};
1071 : 0 : volatile union cpt_lf_inprog lf_inprog = {.u = 0x0};
1072 : : union cpt_lf_ctl lf_ctl = {.u = 0x0};
1073 : : int timeout = 20;
1074 : : int cnt;
1075 : :
1076 : : /* Disable instructions enqueuing */
1077 : 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
1078 : :
1079 : : /* Wait for instruction queue to become empty */
1080 : : do {
1081 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1082 [ # # ]: 0 : if (!lf_inprog.s.inflight)
1083 : : break;
1084 : :
1085 : : plt_delay_ms(20);
1086 [ # # ]: 0 : if (timeout-- < 0) {
1087 : 0 : plt_err("CPT LF %d is still busy", lf->lf_id);
1088 : 0 : break;
1089 : : }
1090 : :
1091 : : } while (1);
1092 : :
1093 : : /* Disable executions in the LF's queue.
1094 : : * The queue should be empty at this point
1095 : : */
1096 : 0 : lf_inprog.s.eena = 0x0;
1097 : 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
1098 : :
1099 : : /* Wait for instruction queue to become empty */
1100 : : cnt = 0;
1101 : : do {
1102 [ # # ]: 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1103 [ # # ]: 0 : if (lf_inprog.s.grb_partial)
1104 : : cnt = 0;
1105 : : else
1106 : 0 : cnt++;
1107 [ # # ]: 0 : grp_ptr.u = plt_read64(lf->rbase + CPT_LF_Q_GRP_PTR);
1108 [ # # # # ]: 0 : } while ((cnt < 10) && (grp_ptr.s.nq_ptr != grp_ptr.s.dq_ptr));
1109 : :
1110 : : cnt = 0;
1111 : : do {
1112 : 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1113 [ # # # # ]: 0 : if ((lf_inprog.s.inflight == 0) && (lf_inprog.s.gwb_cnt < 40) &&
1114 [ # # # # ]: 0 : ((lf_inprog.s.grb_cnt == 0) || (lf_inprog.s.grb_cnt == 40)))
1115 : 0 : cnt++;
1116 : : else
1117 : : cnt = 0;
1118 [ # # ]: 0 : } while (cnt < 10);
1119 : 0 : }
1120 : :
1121 : : void
1122 : 0 : roc_cpt_iq_enable(struct roc_cpt_lf *lf)
1123 : : {
1124 : : union cpt_lf_inprog lf_inprog;
1125 : : union cpt_lf_ctl lf_ctl;
1126 : :
1127 : : /* Disable command queue */
1128 : 0 : roc_cpt_iq_disable(lf);
1129 : :
1130 : : /* Enable instruction queue enqueuing */
1131 [ # # ]: 0 : lf_ctl.u = plt_read64(lf->rbase + CPT_LF_CTL);
1132 : 0 : lf_ctl.s.ena = 1;
1133 : 0 : lf_ctl.s.fc_ena = 1;
1134 : 0 : lf_ctl.s.fc_up_crossing = 0;
1135 : 0 : lf_ctl.s.fc_hyst_bits = plt_log2_u32(CPT_LF_FC_MIN_THRESHOLD);
1136 [ # # ]: 0 : plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
1137 : :
1138 : : /* Enable command queue execution */
1139 : 0 : lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
1140 : 0 : lf_inprog.s.eena = 1;
1141 [ # # ]: 0 : plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
1142 : :
1143 [ # # ]: 0 : if (roc_errata_cpt_has_ctx_fetch_issue()) {
1144 : : /* Enable flush on FLR */
1145 : 0 : plt_write64(1, lf->rbase + CPT_LF_CTX_CTL);
1146 : : }
1147 : :
1148 : 0 : cpt_lf_dump(lf);
1149 : 0 : }
1150 : :
1151 : : int
1152 : 0 : roc_cpt_lmtline_init(struct roc_cpt *roc_cpt, struct roc_cpt_lmtline *lmtline, int lf_id,
1153 : : bool is_dual)
1154 : : {
1155 : : struct roc_cpt_lf *lf;
1156 : :
1157 : 0 : lf = roc_cpt->lf[lf_id];
1158 [ # # ]: 0 : if (lf == NULL)
1159 : : return -ENOTSUP;
1160 : :
1161 : 0 : lmtline->io_addr = lf->io_addr;
1162 [ # # ]: 0 : lmtline->fc_thresh = lf->nb_desc - CPT_LF_FC_MIN_THRESHOLD;
1163 : :
1164 [ # # ]: 0 : if (roc_model_is_cn10k()) {
1165 [ # # ]: 0 : if (is_dual) {
1166 : 0 : lmtline->io_addr |= ROC_CN10K_TWO_CPT_INST_DW_M1 << 4;
1167 : 0 : lmtline->fc_thresh = lf->nb_desc - 2 * CPT_LF_FC_MIN_THRESHOLD;
1168 : : } else {
1169 : 0 : lmtline->io_addr |= ROC_CN10K_CPT_INST_DW_M1 << 4;
1170 : : }
1171 : : }
1172 : :
1173 : 0 : lmtline->fc_addr = lf->fc_addr;
1174 : 0 : lmtline->lmt_base = lf->lmt_base;
1175 : :
1176 : 0 : return 0;
1177 : : }
1178 : :
1179 : : int
1180 : 0 : roc_cpt_ctx_write(struct roc_cpt_lf *lf, void *sa_dptr, void *sa_cptr,
1181 : : uint16_t sa_len)
1182 : : {
1183 [ # # ]: 0 : uintptr_t lmt_base = lf->lmt_base;
1184 : : union cpt_res_s res, *hw_res;
1185 : : uint64_t lmt_arg, io_addr;
1186 : : struct cpt_inst_s *inst;
1187 : : uint16_t lmt_id;
1188 : : uint64_t *dptr;
1189 : : int i;
1190 : :
1191 [ # # ]: 0 : if (!plt_is_aligned(sa_cptr, 128)) {
1192 : 0 : plt_err("Context pointer should be 128B aligned");
1193 : 0 : return -EINVAL;
1194 : : }
1195 : :
1196 : : /* Use this lcore's LMT line as no one else is using it */
1197 : : ROC_LMT_BASE_ID_GET(lmt_base, lmt_id);
1198 : 0 : inst = (struct cpt_inst_s *)lmt_base;
1199 : :
1200 : : memset(inst, 0, sizeof(struct cpt_inst_s));
1201 : :
1202 : 0 : hw_res = plt_zmalloc(sizeof(*hw_res), ROC_CPT_RES_ALIGN);
1203 [ # # ]: 0 : if (hw_res == NULL) {
1204 : 0 : plt_err("Couldn't allocate memory for result address");
1205 : 0 : return -ENOMEM;
1206 : : }
1207 : :
1208 : 0 : dptr = plt_zmalloc(sa_len, 8);
1209 [ # # ]: 0 : if (dptr == NULL) {
1210 : 0 : plt_err("Couldn't allocate memory for SA dptr");
1211 : 0 : plt_free(hw_res);
1212 : 0 : return -ENOMEM;
1213 : : }
1214 : :
1215 [ # # ]: 0 : for (i = 0; i < (sa_len / 8); i++)
1216 [ # # ]: 0 : dptr[i] = plt_cpu_to_be_64(((uint64_t *)sa_dptr)[i]);
1217 : :
1218 : : /* Fill CPT_INST_S for WRITE_SA microcode op */
1219 : 0 : hw_res->cn10k.compcode = CPT_COMP_NOT_DONE;
1220 : 0 : inst->res_addr = (uint64_t)hw_res;
1221 : 0 : inst->dptr = (uint64_t)dptr;
1222 : 0 : inst->w4.s.param2 = sa_len >> 3;
1223 : 0 : inst->w4.s.dlen = sa_len;
1224 : 0 : inst->w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_WRITE_SA;
1225 : 0 : inst->w4.s.opcode_minor = ROC_IE_OT_MINOR_OP_WRITE_SA;
1226 : 0 : inst->w7.s.cptr = (uint64_t)sa_cptr;
1227 : 0 : inst->w7.s.ctx_val = 1;
1228 : 0 : inst->w7.s.egrp = ROC_CPT_DFLT_ENG_GRP_SE_IE;
1229 : :
1230 : : lmt_arg = ROC_CN10K_CPT_LMT_ARG | (uint64_t)lmt_id;
1231 : : io_addr = lf->io_addr | ROC_CN10K_CPT_INST_DW_M1 << 4;
1232 : :
1233 : : roc_lmt_submit_steorl(lmt_arg, io_addr);
1234 : 0 : plt_io_wmb();
1235 : :
1236 : : /* Use 1 min timeout for the poll */
1237 : 0 : const uint64_t timeout = plt_tsc_cycles() + 60 * plt_tsc_hz();
1238 : :
1239 : : /* Wait until CPT instruction completes */
1240 : : do {
1241 : 0 : res.u64[0] = __atomic_load_n(&hw_res->u64[0], __ATOMIC_RELAXED);
1242 [ # # ]: 0 : if (unlikely(plt_tsc_cycles() > timeout))
1243 : : break;
1244 [ # # ]: 0 : } while (res.cn10k.compcode == CPT_COMP_NOT_DONE);
1245 : :
1246 : 0 : plt_free(dptr);
1247 : 0 : plt_free(hw_res);
1248 : :
1249 [ # # ]: 0 : if (res.cn10k.compcode != CPT_COMP_GOOD || res.cn10k.uc_compcode) {
1250 : 0 : plt_err("Write SA operation timed out");
1251 : 0 : return -ETIMEDOUT;
1252 : : }
1253 : :
1254 : : return 0;
1255 : : }
1256 : :
1257 : : void
1258 : 0 : roc_cpt_int_misc_cb_register(roc_cpt_int_misc_cb_t cb, void *args)
1259 : : {
1260 [ # # ]: 0 : if (int_cb.cb != NULL)
1261 : : return;
1262 : :
1263 : 0 : int_cb.cb = cb;
1264 : 0 : int_cb.cb_args = args;
1265 : : }
1266 : :
1267 : : int
1268 : 0 : roc_cpt_int_misc_cb_unregister(roc_cpt_int_misc_cb_t cb, void *args)
1269 : : {
1270 [ # # ]: 0 : if (int_cb.cb == NULL)
1271 : : return 0;
1272 [ # # # # ]: 0 : if (int_cb.cb != cb || int_cb.cb_args != args)
1273 : : return -EINVAL;
1274 : :
1275 : 0 : int_cb.cb = NULL;
1276 : 0 : int_cb.cb_args = NULL;
1277 : 0 : return 0;
1278 : : }
|