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 LF_ENABLE_RETRY_CNT 8
9 : :
10 : : static int
11 : 0 : tim_fill_msix(struct roc_tim *roc_tim, uint16_t nb_ring)
12 : : {
13 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
14 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
15 : : struct dev *dev = &sso->dev;
16 : : struct msix_offset_rsp *rsp;
17 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
18 : : int i, rc;
19 : :
20 : 0 : mbox_alloc_msg_msix_offset(mbox);
21 : : rc = mbox_process_msg(mbox, (void **)&rsp);
22 [ # # ]: 0 : if (rc) {
23 : : rc = -EIO;
24 : 0 : goto exit;
25 : : }
26 : :
27 [ # # ]: 0 : for (i = 0; i < nb_ring; i++)
28 : 0 : tim->tim_msix_offsets[i] = rsp->timlf_msixoff[i];
29 : :
30 : : rc = 0;
31 : 0 : exit:
32 : : mbox_put(mbox);
33 : 0 : return rc;
34 : : }
35 : :
36 : : static void
37 : 0 : tim_err_desc(int rc)
38 : : {
39 [ # # # # : 0 : switch (rc) {
# # # # #
# # # # #
# # # #
# ]
40 : 0 : case TIM_AF_NO_RINGS_LEFT:
41 : 0 : plt_err("Unable to allocate new TIM ring.");
42 : 0 : break;
43 : 0 : case TIM_AF_INVALID_NPA_PF_FUNC:
44 : 0 : plt_err("Invalid NPA pf func.");
45 : 0 : break;
46 : 0 : case TIM_AF_INVALID_SSO_PF_FUNC:
47 : 0 : plt_err("Invalid SSO pf func.");
48 : 0 : break;
49 : 0 : case TIM_AF_RING_STILL_RUNNING:
50 : 0 : plt_err("Ring busy.");
51 : 0 : break;
52 : 0 : case TIM_AF_LF_INVALID:
53 : 0 : plt_err("Invalid Ring id.");
54 : 0 : break;
55 : 0 : case TIM_AF_CSIZE_NOT_ALIGNED:
56 : 0 : plt_err("Chunk size specified needs to be multiple of 16.");
57 : 0 : break;
58 : 0 : case TIM_AF_CSIZE_TOO_SMALL:
59 : 0 : plt_err("Chunk size too small.");
60 : 0 : break;
61 : 0 : case TIM_AF_CSIZE_TOO_BIG:
62 : 0 : plt_err("Chunk size too big.");
63 : 0 : break;
64 : 0 : case TIM_AF_INTERVAL_TOO_SMALL:
65 : 0 : plt_err("Bucket traversal interval too small.");
66 : 0 : break;
67 : 0 : case TIM_AF_INVALID_BIG_ENDIAN_VALUE:
68 : 0 : plt_err("Invalid Big endian value.");
69 : 0 : break;
70 : 0 : case TIM_AF_INVALID_CLOCK_SOURCE:
71 : 0 : plt_err("Invalid Clock source specified.");
72 : 0 : break;
73 : 0 : case TIM_AF_GPIO_CLK_SRC_NOT_ENABLED:
74 : 0 : plt_err("GPIO clock source not enabled.");
75 : 0 : break;
76 : 0 : case TIM_AF_INVALID_BSIZE:
77 : 0 : plt_err("Invalid bucket size.");
78 : 0 : break;
79 : 0 : case TIM_AF_INVALID_ENABLE_PERIODIC:
80 : 0 : plt_err("Invalid bucket size.");
81 : 0 : break;
82 : 0 : case TIM_AF_INVALID_ENABLE_DONTFREE:
83 : 0 : plt_err("Invalid Don't free value.");
84 : 0 : break;
85 : 0 : case TIM_AF_ENA_DONTFRE_NSET_PERIODIC:
86 : 0 : plt_err("Don't free bit not set when periodic is enabled.");
87 : 0 : break;
88 : 0 : case TIM_AF_RING_ALREADY_DISABLED:
89 : 0 : plt_err("Ring already stopped");
90 : 0 : break;
91 : 0 : case TIM_AF_LF_START_SYNC_FAIL:
92 : 0 : plt_err("Ring start sync failed.");
93 : 0 : break;
94 : 0 : default:
95 : 0 : plt_err("Unknown Error: %d", rc);
96 : : }
97 : 0 : }
98 : :
99 : : int
100 : 0 : roc_tim_capture_counters(struct roc_tim *roc_tim, uint64_t *counters, uint8_t nb_cntrs)
101 : : {
102 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
103 : : struct dev *dev = &sso->dev;
104 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
105 : : struct tim_capture_rsp *rsp;
106 : : int rc, i;
107 : :
108 : 0 : mbox_alloc_msg_tim_capture_counters(mbox);
109 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
110 [ # # ]: 0 : if (rc) {
111 : 0 : tim_err_desc(rc);
112 : : rc = -EIO;
113 : 0 : goto fail;
114 : : }
115 : :
116 [ # # ]: 0 : for (i = 0; i < nb_cntrs; i++)
117 : 0 : counters[i] = rsp->counters[i];
118 : :
119 : 0 : fail:
120 : : mbox_put(mbox);
121 : 0 : return rc;
122 : : }
123 : :
124 : : int
125 : 0 : roc_tim_lf_enable(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *start_tsc,
126 : : uint32_t *cur_bkt)
127 : : {
128 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
129 : : struct dev *dev = &sso->dev;
130 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
131 : : uint8_t retry_cnt = LF_ENABLE_RETRY_CNT;
132 : : struct tim_enable_rsp *rsp;
133 : : struct tim_ring_req *req;
134 : : int rc = -ENOSPC;
135 : :
136 : 0 : retry:
137 : 0 : req = mbox_alloc_msg_tim_enable_ring(mbox);
138 [ # # ]: 0 : if (req == NULL)
139 : 0 : goto fail;
140 : 0 : req->ring = ring_id;
141 : :
142 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
143 [ # # ]: 0 : if (rc) {
144 [ # # # # ]: 0 : if (rc == TIM_AF_LF_START_SYNC_FAIL && retry_cnt--)
145 : 0 : goto retry;
146 : :
147 : 0 : tim_err_desc(rc);
148 : : rc = -EIO;
149 : 0 : goto fail;
150 : : }
151 : :
152 [ # # ]: 0 : if (cur_bkt)
153 : 0 : *cur_bkt = rsp->currentbucket;
154 [ # # ]: 0 : if (start_tsc)
155 : 0 : *start_tsc = rsp->timestarted;
156 : :
157 : 0 : fail:
158 : : mbox_put(mbox);
159 : 0 : return rc;
160 : : }
161 : :
162 : : int
163 : 0 : roc_tim_lf_disable(struct roc_tim *roc_tim, uint8_t ring_id)
164 : : {
165 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
166 : : struct dev *dev = &sso->dev;
167 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
168 : : struct tim_ring_req *req;
169 : : int rc = -ENOSPC;
170 : :
171 : 0 : req = mbox_alloc_msg_tim_disable_ring(mbox);
172 [ # # ]: 0 : if (req == NULL)
173 : 0 : goto fail;
174 : 0 : req->ring = ring_id;
175 : :
176 : 0 : rc = mbox_process(mbox);
177 [ # # ]: 0 : if (rc) {
178 : 0 : tim_err_desc(rc);
179 : : rc = -EIO;
180 : : }
181 : :
182 : 0 : fail:
183 : : mbox_put(mbox);
184 : 0 : return rc;
185 : : }
186 : :
187 : : uintptr_t
188 : 0 : roc_tim_lf_base_get(struct roc_tim *roc_tim, uint8_t ring_id)
189 : : {
190 : 0 : struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
191 : :
192 : 0 : return dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12);
193 : : }
194 : :
195 : : int
196 : 0 : roc_tim_lf_config(struct roc_tim *roc_tim, uint8_t ring_id, enum roc_tim_clk_src clk_src,
197 : : uint8_t ena_periodic, uint8_t ena_dfb, uint8_t prio, uint32_t bucket_sz,
198 : : uint32_t chunk_sz, uint64_t interval, uint64_t intervalns, uint64_t clockfreq)
199 : : {
200 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
201 : : struct dev *dev = &sso->dev;
202 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
203 : : struct tim_config_req *req;
204 : : int rc = -ENOSPC;
205 : :
206 : 0 : req = mbox_alloc_msg_tim_config_ring(mbox);
207 [ # # ]: 0 : if (req == NULL)
208 : 0 : goto fail;
209 : 0 : req->ring = ring_id;
210 : 0 : req->bigendian = false;
211 : 0 : req->bucketsize = bucket_sz;
212 : 0 : req->chunksize = chunk_sz;
213 : 0 : req->clocksource = clk_src;
214 : 0 : req->enableperiodic = ena_periodic;
215 : 0 : req->enabledontfreebuffer = ena_dfb;
216 : 0 : req->interval_lo = interval;
217 : 0 : req->interval_hi = interval >> 32;
218 : 0 : req->intervalns = intervalns;
219 : 0 : req->clockfreq = clockfreq;
220 : 0 : req->priority = prio;
221 : 0 : req->gpioedge = TIM_GPIO_LTOH_TRANS;
222 : :
223 : 0 : rc = mbox_process(mbox);
224 [ # # ]: 0 : if (rc) {
225 : 0 : tim_err_desc(rc);
226 : : rc = -EIO;
227 : : }
228 : :
229 : 0 : fail:
230 : : mbox_put(mbox);
231 : 0 : return rc;
232 : : }
233 : :
234 : : int
235 : 0 : roc_tim_lf_config_hwwqe(struct roc_tim *roc_tim, uint8_t ring_id, struct roc_tim_hwwqe_cfg *cfg)
236 : : {
237 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
238 : : struct dev *dev = &sso->dev;
239 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
240 : : struct tim_cfg_hwwqe_req *req;
241 : : int rc = -ENOSPC;
242 : :
243 : 0 : req = mbox_alloc_msg_tim_config_hwwqe(mbox);
244 [ # # ]: 0 : if (req == NULL)
245 : 0 : goto fail;
246 : 0 : req->ring = ring_id;
247 : 0 : req->hwwqe_ena = cfg->hwwqe_ena;
248 : 0 : req->grp_ena = cfg->grp_ena;
249 : 0 : req->grp_tmo_cntr = cfg->grp_tmo_cyc;
250 : 0 : req->flw_ctrl_ena = cfg->flw_ctrl_ena;
251 : 0 : req->result_offset = cfg->result_offset;
252 : 0 : req->event_count_offset = cfg->event_count_offset;
253 : :
254 : 0 : req->wqe_rd_clr_ena = 1;
255 : 0 : req->npa_tmo_cntr = TIM_NPA_TMO;
256 : 0 : req->ins_min_gap = TIM_BUCKET_MIN_GAP;
257 : :
258 : 0 : rc = mbox_process(mbox);
259 [ # # ]: 0 : if (rc) {
260 : 0 : tim_err_desc(rc);
261 : : rc = -EIO;
262 : : }
263 : :
264 : 0 : fail:
265 : : mbox_put(mbox);
266 : 0 : return rc;
267 : : }
268 : :
269 : : int
270 : 0 : roc_tim_lf_interval(struct roc_tim *roc_tim, enum roc_tim_clk_src clk_src,
271 : : uint64_t clockfreq, uint64_t *intervalns,
272 : : uint64_t *interval)
273 : : {
274 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
275 : : struct dev *dev = &sso->dev;
276 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
277 : : struct tim_intvl_req *req;
278 : : struct tim_intvl_rsp *rsp;
279 : : int rc = -ENOSPC;
280 : :
281 : 0 : req = mbox_alloc_msg_tim_get_min_intvl(mbox);
282 [ # # ]: 0 : if (req == NULL)
283 : 0 : goto fail;
284 : :
285 : 0 : req->clockfreq = clockfreq;
286 : 0 : req->clocksource = clk_src;
287 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
288 [ # # ]: 0 : if (rc) {
289 : 0 : tim_err_desc(rc);
290 : : rc = -EIO;
291 : 0 : goto fail;
292 : : }
293 : :
294 : 0 : *intervalns = rsp->intvl_ns;
295 : 0 : *interval = rsp->intvl_cyc;
296 : :
297 : 0 : fail:
298 : : mbox_put(mbox);
299 : 0 : return rc;
300 : : }
301 : :
302 : : int
303 : 0 : roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk)
304 : : {
305 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
306 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
307 : : struct tim_ring_req *free_req;
308 : : struct tim_lf_alloc_req *req;
309 : : struct tim_lf_alloc_rsp *rsp;
310 : : struct dev *dev = &sso->dev;
311 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
312 : : int rc = -ENOSPC;
313 : :
314 : 0 : req = mbox_alloc_msg_tim_lf_alloc(mbox);
315 [ # # ]: 0 : if (req == NULL)
316 : 0 : goto fail;
317 : 0 : req->npa_pf_func = idev_npa_pffunc_get();
318 : 0 : req->sso_pf_func = idev_sso_pffunc_get();
319 : 0 : req->ring = ring_id;
320 : :
321 : : rc = mbox_process_msg(mbox, (void **)&rsp);
322 [ # # ]: 0 : if (rc) {
323 : 0 : tim_err_desc(rc);
324 : : rc = -EIO;
325 : 0 : goto fail;
326 : : }
327 : :
328 [ # # ]: 0 : if (clk)
329 : 0 : *clk = rsp->tenns_clk;
330 : :
331 : 0 : rc = tim_register_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
332 : 0 : tim->tim_msix_offsets[ring_id]);
333 [ # # ]: 0 : if (rc < 0) {
334 : 0 : plt_tim_dbg("Failed to register Ring[%d] IRQ", ring_id);
335 : 0 : free_req = mbox_alloc_msg_tim_lf_free(mbox);
336 [ # # ]: 0 : if (free_req == NULL) {
337 : : rc = -ENOSPC;
338 : 0 : goto fail;
339 : : }
340 : 0 : free_req->ring = ring_id;
341 : 0 : rc = mbox_process(mbox);
342 [ # # ]: 0 : if (rc)
343 : : rc = -EIO;
344 : : }
345 : :
346 : 0 : fail:
347 : 0 : mbox_put(dev->mbox);
348 : 0 : return rc;
349 : : }
350 : :
351 : : int
352 : 0 : roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id)
353 : : {
354 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
355 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
356 : : struct dev *dev = &sso->dev;
357 : : struct tim_ring_req *req;
358 : : int rc = -ENOSPC;
359 : :
360 : 0 : tim_unregister_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
361 : 0 : tim->tim_msix_offsets[ring_id]);
362 : :
363 : 0 : req = mbox_alloc_msg_tim_lf_free(mbox_get(dev->mbox));
364 [ # # ]: 0 : if (req == NULL)
365 : 0 : goto fail;
366 : 0 : req->ring = ring_id;
367 : :
368 : 0 : rc = mbox_process(dev->mbox);
369 [ # # ]: 0 : if (rc < 0) {
370 : 0 : tim_err_desc(rc);
371 : : rc = -EIO;
372 : 0 : goto fail;
373 : : }
374 : : rc = 0;
375 : :
376 : 0 : fail:
377 : 0 : mbox_put(dev->mbox);
378 : 0 : return rc;
379 : : }
380 : :
381 : : int
382 : 0 : tim_free_lf_count_get(struct dev *dev, uint16_t *nb_lfs)
383 : : {
384 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
385 : : struct free_rsrcs_rsp *rsrc_cnt;
386 : : int rc;
387 : :
388 : 0 : mbox_alloc_msg_free_rsrc_cnt(mbox);
389 : : rc = mbox_process_msg(mbox, (void **)&rsrc_cnt);
390 [ # # ]: 0 : if (rc) {
391 : 0 : plt_err("Failed to get free resource count");
392 : : mbox_put(mbox);
393 : 0 : return -EIO;
394 : : }
395 : :
396 : 0 : *nb_lfs = rsrc_cnt->tim;
397 : : mbox_put(mbox);
398 : :
399 : 0 : return 0;
400 : : }
401 : :
402 : : static int
403 : 0 : tim_hw_info_get(struct roc_tim *roc_tim)
404 : : {
405 : 0 : struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
406 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
407 : : struct tim_hw_info *rsp;
408 : : int rc;
409 : :
410 : 0 : mbox_alloc_msg_tim_get_hw_info(mbox);
411 : : rc = mbox_process_msg(mbox, (void **)&rsp);
412 [ # # ]: 0 : if (rc && rc != MBOX_MSG_INVALID) {
413 : 0 : plt_err("Failed to get TIM HW info");
414 : : rc = -EIO;
415 : 0 : goto exit;
416 : : }
417 : :
418 [ # # ]: 0 : if (rc != MBOX_MSG_INVALID)
419 : 0 : mbox_memcpy(&roc_tim->feat, &rsp->feat, sizeof(roc_tim->feat));
420 : :
421 : : rc = 0;
422 : 0 : exit:
423 : : mbox_put(mbox);
424 : 0 : return rc;
425 : : }
426 : :
427 : : int
428 : 0 : roc_tim_init(struct roc_tim *roc_tim)
429 : : {
430 : : struct rsrc_attach_req *attach_req;
431 : : struct rsrc_detach_req *detach_req;
432 : : uint16_t nb_lfs, nb_free_lfs;
433 : : struct sso *sso;
434 : : struct dev *dev;
435 : : int rc;
436 : :
437 [ # # # # ]: 0 : if (roc_tim == NULL || roc_tim->roc_sso == NULL)
438 : : return TIM_ERR_PARAM;
439 : :
440 : : sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
441 : 0 : dev = &sso->dev;
442 : 0 : dev->roc_tim = roc_tim;
443 : : PLT_STATIC_ASSERT(sizeof(struct tim) <= TIM_MEM_SZ);
444 : 0 : nb_lfs = roc_tim->nb_lfs;
445 : :
446 : 0 : rc = tim_hw_info_get(roc_tim);
447 [ # # ]: 0 : if (rc) {
448 : 0 : plt_tim_dbg("Failed to get TIM HW info");
449 : 0 : return 0;
450 : : }
451 : :
452 : 0 : rc = tim_free_lf_count_get(dev, &nb_free_lfs);
453 [ # # ]: 0 : if (rc) {
454 : 0 : plt_tim_dbg("Failed to get TIM resource count");
455 : : nb_lfs = 0;
456 : 0 : return nb_lfs;
457 : : }
458 : :
459 [ # # # # ]: 0 : if (nb_lfs && (nb_free_lfs < nb_lfs)) {
460 : 0 : plt_tim_dbg("Requested LFs : %d Available LFs : %d", nb_lfs, nb_free_lfs);
461 : : nb_lfs = 0;
462 : 0 : return nb_lfs;
463 : : }
464 : :
465 : 0 : mbox_get(dev->mbox);
466 : 0 : attach_req = mbox_alloc_msg_attach_resources(dev->mbox);
467 [ # # ]: 0 : if (attach_req == NULL) {
468 : : nb_lfs = 0;
469 : 0 : goto fail;
470 : : }
471 : 0 : attach_req->modify = true;
472 [ # # ]: 0 : attach_req->timlfs = nb_lfs ? nb_lfs : nb_free_lfs;
473 : 0 : nb_lfs = attach_req->timlfs;
474 : :
475 : 0 : rc = mbox_process(dev->mbox);
476 [ # # ]: 0 : if (rc) {
477 : 0 : plt_err("Unable to attach TIM LFs.");
478 : : nb_lfs = 0;
479 : 0 : goto fail;
480 : : }
481 : :
482 : 0 : mbox_put(dev->mbox);
483 : 0 : rc = tim_fill_msix(roc_tim, nb_lfs);
484 [ # # ]: 0 : if (rc < 0) {
485 : 0 : plt_err("Unable to get TIM MSIX vectors");
486 : :
487 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox_get(dev->mbox));
488 [ # # ]: 0 : if (detach_req == NULL) {
489 : : nb_lfs = 0;
490 : 0 : goto fail;
491 : : }
492 : 0 : detach_req->partial = true;
493 : 0 : detach_req->timlfs = true;
494 : 0 : mbox_process(dev->mbox);
495 : : nb_lfs = 0;
496 : : } else {
497 : 0 : goto done;
498 : : }
499 : :
500 : 0 : fail:
501 : 0 : mbox_put(dev->mbox);
502 : 0 : done:
503 : 0 : roc_tim->nb_lfs = nb_lfs;
504 : 0 : return nb_lfs;
505 : : }
506 : :
507 : : void
508 : 0 : roc_tim_fini(struct roc_tim *roc_tim)
509 : : {
510 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
511 : : struct rsrc_detach_req *detach_req;
512 : : struct dev *dev = &sso->dev;
513 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
514 : :
515 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox);
516 : : PLT_ASSERT(detach_req);
517 : 0 : detach_req->partial = true;
518 : 0 : detach_req->timlfs = true;
519 : :
520 : 0 : mbox_process(mbox);
521 : : mbox_put(mbox);
522 : 0 : }
|