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