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