Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #ifndef _ROC_NPA_H_
6 : : #define _ROC_NPA_H_
7 : :
8 : : #include <stdint.h>
9 : :
10 : : #include "hw/npa.h"
11 : :
12 : : #include "roc_bits.h"
13 : : #include "roc_constants.h"
14 : : #if defined(__aarch64__)
15 : : #include "roc_io.h"
16 : : #else
17 : : #include "roc_io_generic.h"
18 : : #endif
19 : : #include "roc_model.h"
20 : : #include "roc_npa_dp.h"
21 : :
22 : : #define ROC_AURA_OP_LIMIT_MASK (BIT_ULL(36) - 1)
23 : :
24 : : #define ROC_NPA_MAX_BLOCK_SZ_CN9K (128 * 1024)
25 : : #define ROC_NPA_MAX_BLOCK_SZ_CN10K (128 * 1024)
26 : : #define ROC_NPA_MAX_BLOCK_SZ_CN20K (256 * 1024)
27 : : #define ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS 512
28 : : #define ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS 15U
29 : : #define ROC_CN10K_NPA_BATCH_FREE_BURST_MAX 16U
30 : :
31 : : /* This value controls how much of the present average resource level is used to
32 : : * calculate the new resource level.
33 : : */
34 : : #define ROC_NPA_AVG_CONT 0xE0
35 : :
36 : : /* 16 CASP instructions can be outstanding in CN9k, but we use only 15
37 : : * outstanding CASPs as we run out of registers.
38 : : */
39 : : #define ROC_CN9K_NPA_BULK_ALLOC_MAX_PTRS 30
40 : :
41 : : static inline uint32_t
42 : : roc_npa_max_block_size(void)
43 : : {
44 [ # # ]: 0 : if (roc_model_is_cn20k())
45 : : return ROC_NPA_MAX_BLOCK_SZ_CN20K;
46 : : else if (roc_model_is_cn10k())
47 : : return ROC_NPA_MAX_BLOCK_SZ_CN10K;
48 : : else
49 : : return ROC_NPA_MAX_BLOCK_SZ_CN9K;
50 : : }
51 : :
52 : : /*
53 : : * Generate 64bit handle to have optimized alloc and free aura operation.
54 : : * 0 - ROC_AURA_ID_MASK for storing the aura_id.
55 : : * [ROC_AURA_ID_MASK+1, (2^64 - 1)] for storing the lf base address.
56 : : * This scheme is valid when OS can give ROC_AURA_ID_MASK
57 : : * aligned address for lf base address.
58 : : */
59 : : static inline uint64_t
60 : : roc_npa_aura_handle_gen(uint32_t aura_id, uintptr_t addr)
61 : : {
62 : : uint64_t val;
63 : :
64 : 0 : val = aura_id & ROC_AURA_ID_MASK;
65 [ # # # # : 0 : return (uint64_t)addr | val;
# # ]
66 : : }
67 : :
68 : : static inline uint64_t
69 : : roc_npa_aura_op_alloc(uint64_t aura_handle, const int drop)
70 : : {
71 : : uint64_t wdata = roc_npa_aura_handle_to_aura(aura_handle);
72 : : int64_t *addr;
73 : :
74 : : if (drop)
75 : : wdata |= BIT_ULL(63); /* DROP */
76 : :
77 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
78 : : NPA_LF_AURA_OP_ALLOCX(0));
79 : : return roc_atomic64_add_nosync(wdata, addr);
80 : : }
81 : :
82 : : static inline uint64_t
83 : : roc_npa_aura_op_cnt_get(uint64_t aura_handle)
84 : : {
85 : : uint64_t wdata, shift;
86 : : int64_t *addr;
87 : : uint64_t reg;
88 : :
89 : : shift = roc_model_is_cn20k() ? 47 : 44;
90 : : wdata = roc_npa_aura_handle_to_aura(aura_handle) << shift;
91 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
92 : : NPA_LF_AURA_OP_CNT);
93 : : reg = roc_atomic64_add_nosync(wdata, addr);
94 : :
95 : : if (reg & BIT_ULL(42) /* OP_ERR */)
96 : : return 0;
97 : : else
98 : : return reg & 0xFFFFFFFFF;
99 : : }
100 : :
101 : : static inline void
102 : : roc_npa_aura_op_cnt_set(uint64_t aura_handle, const int sign, uint64_t count)
103 : : {
104 : 0 : uint64_t reg = count & (BIT_ULL(36) - 1);
105 : : uint64_t shift;
106 : :
107 : : if (sign)
108 [ # # # # ]: 0 : reg |= BIT_ULL(43); /* CNT_ADD */
109 : :
110 [ # # # # : 0 : shift = roc_model_is_cn20k() ? 47 : 44;
# # ]
111 : 0 : reg |= (roc_npa_aura_handle_to_aura(aura_handle) << shift);
112 : :
113 : 0 : plt_write64(reg, roc_npa_aura_handle_to_base(aura_handle) +
114 : : NPA_LF_AURA_OP_CNT);
115 : 0 : }
116 : :
117 : : static inline uint64_t
118 : : roc_npa_aura_op_limit_get(uint64_t aura_handle)
119 : : {
120 : : uint64_t wdata, shift;
121 : : int64_t *addr;
122 : : uint64_t reg;
123 : :
124 : : shift = roc_model_is_cn20k() ? 47 : 44;
125 : : wdata = roc_npa_aura_handle_to_aura(aura_handle) << shift;
126 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
127 : : NPA_LF_AURA_OP_LIMIT);
128 : : reg = roc_atomic64_add_nosync(wdata, addr);
129 : :
130 : : if (reg & BIT_ULL(42) /* OP_ERR */)
131 : : return 0;
132 : : else
133 : : return reg & ROC_AURA_OP_LIMIT_MASK;
134 : : }
135 : :
136 : : static inline void
137 : : roc_npa_aura_op_limit_set(uint64_t aura_handle, uint64_t limit)
138 : : {
139 : : uint64_t reg = limit & ROC_AURA_OP_LIMIT_MASK;
140 : : uint64_t shift;
141 : :
142 : : shift = roc_model_is_cn20k() ? 47 : 44;
143 : : reg |= (roc_npa_aura_handle_to_aura(aura_handle) << shift);
144 : :
145 : : plt_write64(reg, roc_npa_aura_handle_to_base(aura_handle) +
146 : : NPA_LF_AURA_OP_LIMIT);
147 : : }
148 : :
149 : : static inline uint64_t
150 : : roc_npa_aura_op_available(uint64_t aura_handle)
151 : : {
152 : : uint64_t wdata, shift;
153 : : uint64_t reg;
154 : : int64_t *addr;
155 : :
156 : : shift = roc_model_is_cn20k() ? 47 : 44;
157 : : wdata = roc_npa_aura_handle_to_aura(aura_handle) << shift;
158 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
159 : : NPA_LF_POOL_OP_AVAILABLE);
160 : : reg = roc_atomic64_add_nosync(wdata, addr);
161 : :
162 : : if (reg & BIT_ULL(42) /* OP_ERR */)
163 : : return 0;
164 : : else
165 : : return reg & 0xFFFFFFFFF;
166 : : }
167 : :
168 : : /* Wait for a given timeout, repeatedly checking whether the available
169 : : * pointers has reached the given count. Returns the available pointer
170 : : * count if it has reached the given count or if timeout has expired
171 : : */
172 : : static inline uint32_t
173 : : roc_npa_aura_op_available_wait(uint64_t aura_handle, uint32_t count,
174 : : uint32_t tmo_ms)
175 : : {
176 : : #define OP_AVAIL_WAIT_MS_DEFAULT (100)
177 : : #define OP_AVAIL_CHECK_INTERVAL_MS (1)
178 : : uint32_t op_avail;
179 : : int retry;
180 : :
181 : : tmo_ms = tmo_ms ? tmo_ms : OP_AVAIL_WAIT_MS_DEFAULT;
182 : :
183 : : retry = tmo_ms / OP_AVAIL_CHECK_INTERVAL_MS;
184 : : op_avail = roc_npa_aura_op_available(aura_handle);
185 [ # # # # ]: 0 : while (retry && (op_avail < count)) {
186 : : plt_delay_ms(OP_AVAIL_CHECK_INTERVAL_MS);
187 : : op_avail = roc_npa_aura_op_available(aura_handle);
188 : 0 : retry--;
189 : : }
190 : :
191 : : return op_avail;
192 : : }
193 : :
194 : : static inline void
195 : : roc_npa_pool_op_dpc_reset(uint64_t aura_handle, uint8_t counter_id)
196 : : {
197 : : plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
198 : : NPA_LF_DPCX_ALLOC_CNT(counter_id));
199 : : plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
200 : : NPA_LF_DPCX_FREE_CNT(counter_id));
201 : : plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
202 : : NPA_LF_DPCX_OUTST_BUF_CNT(counter_id));
203 : : plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
204 : : NPA_LF_DPCX_CNT_HI_WM(counter_id));
205 : : }
206 : :
207 : : static inline uint64_t
208 : : roc_npa_pool_op_dpc_alloc_count(uint64_t aura_handle, uint8_t counter_id)
209 : : {
210 : : return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
211 : : NPA_LF_DPCX_ALLOC_CNT(counter_id));
212 : : }
213 : :
214 : : static inline uint64_t
215 : : roc_npa_pool_op_dpc_free_count(uint64_t aura_handle, uint8_t counter_id)
216 : : {
217 : : return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
218 : : NPA_LF_DPCX_FREE_CNT(counter_id));
219 : : }
220 : :
221 : : static inline uint64_t
222 : : roc_npa_pool_op_dpc_outst_buf_count(uint64_t aura_handle, uint8_t counter_id)
223 : : {
224 : : return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
225 : : NPA_LF_DPCX_OUTST_BUF_CNT(counter_id));
226 : : }
227 : :
228 : : static inline uint64_t
229 : : roc_npa_pool_op_dpc_high_wm_count(uint64_t aura_handle, uint8_t counter_id)
230 : : {
231 : : return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
232 : : NPA_LF_DPCX_CNT_HI_WM(counter_id));
233 : : }
234 : :
235 : : static inline uint64_t
236 : : roc_npa_pool_op_performance_counter(uint64_t aura_handle, const int drop)
237 : : {
238 : : union {
239 : : uint64_t u;
240 : : struct npa_aura_op_wdata_s s;
241 : : } op_wdata;
242 : : int64_t *addr;
243 : : uint64_t reg;
244 : :
245 : : op_wdata.u = 0;
246 : : op_wdata.s.aura = roc_npa_aura_handle_to_aura(aura_handle);
247 : : if (drop)
248 : : op_wdata.s.drop |= BIT_ULL(63); /* DROP */
249 : :
250 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
251 : : NPA_LF_POOL_OP_PC);
252 : :
253 : : reg = roc_atomic64_add_nosync(op_wdata.u, addr);
254 : : /*
255 : : * NPA_LF_POOL_OP_PC Read Data
256 : : *
257 : : * 63 49 48 48 47 0
258 : : * -----------------------------
259 : : * | Reserved | OP_ERR | OP_PC |
260 : : * -----------------------------
261 : : */
262 : :
263 : : if (reg & BIT_ULL(48) /* OP_ERR */)
264 : : return 0;
265 : : else
266 : : return reg & 0xFFFFFFFFFFFF;
267 : : }
268 : :
269 : : static inline int
270 : : roc_npa_aura_batch_alloc_issue(uint64_t aura_handle, uint64_t *buf,
271 : : unsigned int num, const int dis_wait,
272 : : const int drop)
273 : : {
274 : : int64_t *addr;
275 : : uint64_t res;
276 : : union {
277 : : uint64_t u;
278 : : struct npa_batch_alloc_compare_s compare_s;
279 : : } cmp;
280 : :
281 [ # # # # : 0 : if (num > ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS)
# # ]
282 : : return -1;
283 : :
284 : : addr = (int64_t *)(roc_npa_aura_handle_to_base(aura_handle) +
285 : : NPA_LF_AURA_BATCH_ALLOC);
286 [ # # # # ]: 0 : cmp.u = 0;
287 : 0 : cmp.compare_s.aura = roc_npa_aura_handle_to_aura(aura_handle);
288 : 0 : cmp.compare_s.drop = drop;
289 : : cmp.compare_s.stype = ALLOC_STYPE_STF;
290 : : cmp.compare_s.dis_wait = dis_wait;
291 : 0 : cmp.compare_s.count = num;
292 : :
293 : 0 : res = roc_atomic64_casl(cmp.u, (uint64_t)buf, addr);
294 [ # # # # : 0 : if (res != ALLOC_RESULT_ACCEPTED && res != ALLOC_RESULT_NOCORE)
# # ]
295 : 0 : return -1;
296 : :
297 : : return 0;
298 : : }
299 : :
300 : : /*
301 : : * Wait for a batch alloc operation on a cache line to complete.
302 : : */
303 : : static inline void
304 : 0 : roc_npa_batch_alloc_wait(uint64_t *cache_line, unsigned int wait_us)
305 : : {
306 : 0 : const uint64_t ticks = (uint64_t)wait_us * plt_tsc_hz() / (uint64_t)1E6;
307 : : const uint64_t start = plt_tsc_cycles();
308 : :
309 : : /* Batch alloc status code is updated in bits [5:6] of the first word
310 : : * of the 128 byte cache line.
311 : : */
312 [ # # ]: 0 : while (((__atomic_load_n(cache_line, __ATOMIC_ACQUIRE) >> 5) & 0x3) ==
313 : : ALLOC_CCODE_INVAL)
314 [ # # # # ]: 0 : if (wait_us && (plt_tsc_cycles() - start) >= ticks)
315 : : break;
316 : 0 : }
317 : :
318 : : /*
319 : : * Count the number of pointers in a single batch alloc cache line.
320 : : */
321 : : static inline unsigned int
322 : : roc_npa_aura_batch_alloc_count_line(uint64_t *line, unsigned int wait_us)
323 : : {
324 : : struct npa_batch_alloc_status_s *status;
325 : :
326 : : status = (struct npa_batch_alloc_status_s *)line;
327 : : roc_npa_batch_alloc_wait(line, wait_us);
328 : :
329 : : return status->count;
330 : : }
331 : :
332 : : /*
333 : : * Count the number of pointers in a sequence of batch alloc cache lines.
334 : : */
335 : : static inline unsigned int
336 : : roc_npa_aura_batch_alloc_count(uint64_t *aligned_buf, unsigned int num,
337 : : unsigned int wait_us)
338 : : {
339 : : unsigned int count, i;
340 : :
341 [ # # ]: 0 : if (num > ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS)
342 : : return 0;
343 : :
344 : : count = 0;
345 : : /* Check each ROC cache line one by one */
346 [ # # ]: 0 : for (i = 0; i < num; i += (ROC_ALIGN >> 3)) {
347 : : struct npa_batch_alloc_status_s *status;
348 : :
349 : 0 : status = (struct npa_batch_alloc_status_s *)&aligned_buf[i];
350 : :
351 : 0 : roc_npa_batch_alloc_wait(&aligned_buf[i], wait_us);
352 : :
353 : 0 : count += status->count;
354 : : }
355 : :
356 : : return count;
357 : : }
358 : :
359 : : /*
360 : : * Extract allocated pointers from a single batch alloc cache line. This api
361 : : * only extracts the required number of pointers from the cache line and it
362 : : * adjusts the statsus->count so that a subsequent call to this api can
363 : : * extract the remaining pointers in the cache line appropriately.
364 : : */
365 : : static inline unsigned int
366 : : roc_npa_aura_batch_alloc_extract_line(uint64_t *buf, uint64_t *line,
367 : : unsigned int num, unsigned int *rem)
368 : : {
369 : : struct npa_batch_alloc_status_s *status;
370 : : unsigned int avail;
371 : :
372 : : status = (struct npa_batch_alloc_status_s *)line;
373 : : roc_npa_batch_alloc_wait(line, 0);
374 : : avail = status->count;
375 : : num = avail > num ? num : avail;
376 : : if (num)
377 : : memcpy(buf, &line[avail - num], num * sizeof(uint64_t));
378 : : avail -= num;
379 : : if (avail == 0) {
380 : : /* Clear the lowest 7 bits of the first pointer */
381 : : buf[0] &= ~0x7FUL;
382 : : status->ccode = 0;
383 : : }
384 : : status->count = avail;
385 : : *rem = avail;
386 : :
387 : : return num;
388 : : }
389 : :
390 : : /*
391 : : * Extract all allocated pointers from a sequence of batch alloc cache lines.
392 : : */
393 : : static inline unsigned int
394 : 0 : roc_npa_aura_batch_alloc_extract(uint64_t *buf, uint64_t *aligned_buf,
395 : : unsigned int num)
396 : : {
397 : : unsigned int count, i;
398 : :
399 [ # # ]: 0 : if (num > ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS)
400 : : return 0;
401 : :
402 : : count = 0;
403 : : /* Check each ROC cache line one by one */
404 [ # # ]: 0 : for (i = 0; i < num; i += (ROC_ALIGN >> 3)) {
405 : : struct npa_batch_alloc_status_s *status;
406 : : int line_count;
407 : :
408 : 0 : status = (struct npa_batch_alloc_status_s *)&aligned_buf[i];
409 : :
410 : 0 : roc_npa_batch_alloc_wait(&aligned_buf[i], 0);
411 : :
412 : 0 : line_count = status->count;
413 : :
414 : : /* Clear the status from the cache line */
415 : 0 : status->ccode = 0;
416 : 0 : status->count = 0;
417 : :
418 : : /* 'Compress' the allocated buffers as there can
419 : : * be 'holes' at the end of the 128 byte cache
420 : : * lines.
421 : : */
422 : 0 : memmove(&buf[count], &aligned_buf[i],
423 : : line_count * sizeof(uint64_t));
424 : :
425 : 0 : count += line_count;
426 : : }
427 : :
428 : : return count;
429 : : }
430 : :
431 : : static inline void
432 : : roc_npa_aura_op_bulk_free(uint64_t aura_handle, uint64_t const *buf,
433 : : unsigned int num, const int fabs)
434 : : {
435 : : unsigned int i;
436 : :
437 [ # # ]: 0 : for (i = 0; i < num; i++) {
438 : 0 : const uint64_t inbuf = buf[i];
439 : :
440 : : roc_npa_aura_op_free(aura_handle, fabs, inbuf);
441 : : }
442 : : }
443 : :
444 : : /*
445 : : * Issue a batch alloc operation on a sequence of cache lines, wait for the
446 : : * batch alloc to complete and copy the pointers out into the user buffer.
447 : : */
448 : : static inline unsigned int
449 : : roc_npa_aura_op_batch_alloc(uint64_t aura_handle, uint64_t *buf,
450 : : unsigned int num, uint64_t *aligned_buf,
451 : : unsigned int aligned_buf_sz, const int dis_wait,
452 : : const int drop, const int partial)
453 : : {
454 : : unsigned int count, chunk, num_alloc;
455 : :
456 : : /* The buffer should be 128 byte cache line aligned */
457 : : if (((uint64_t)aligned_buf & (ROC_ALIGN - 1)) != 0)
458 : : return 0;
459 : :
460 : : count = 0;
461 : : while (num) {
462 : : /* Make sure that the pointers allocated fit into the cache
463 : : * lines reserved.
464 : : */
465 : : chunk = aligned_buf_sz / sizeof(uint64_t);
466 : : chunk = PLT_MIN(num, chunk);
467 : : chunk = PLT_MIN((int)chunk, ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS);
468 : :
469 : : if (roc_npa_aura_batch_alloc_issue(aura_handle, aligned_buf,
470 : : chunk, dis_wait, drop))
471 : : break;
472 : :
473 : : num_alloc = roc_npa_aura_batch_alloc_extract(buf, aligned_buf,
474 : : chunk);
475 : :
476 : : count += num_alloc;
477 : : buf += num_alloc;
478 : : num -= num_alloc;
479 : :
480 : : if (num_alloc != chunk)
481 : : break;
482 : : }
483 : :
484 : : /* If the requested number of pointers was not allocated and if partial
485 : : * alloc is not desired, then free allocated pointers.
486 : : */
487 : : if (unlikely(num != 0 && !partial)) {
488 : : roc_npa_aura_op_bulk_free(aura_handle, buf - count, count, 1);
489 : : count = 0;
490 : : }
491 : :
492 : : return count;
493 : : }
494 : :
495 : : static inline void
496 : : roc_npa_aura_batch_free(uint64_t aura_handle, uint64_t const *buf,
497 : : unsigned int num, const int fabs, uint64_t lmt_addr,
498 : : uint64_t lmt_id)
499 : : {
500 : : uint64_t addr, tar_addr, free0;
501 : : volatile uint64_t *lmt_data;
502 : : unsigned int i;
503 : :
504 [ # # ]: 0 : lmt_data = (uint64_t *)lmt_addr;
505 : :
506 : : addr = roc_npa_aura_handle_to_base(aura_handle) +
507 : : NPA_LF_AURA_BATCH_FREE0;
508 : :
509 : : /*
510 : : * NPA_LF_AURA_BATCH_FREE0
511 : : *
512 : : * 63 63 62 33 32 32 31 20 19 0
513 : : * -----------------------------------------
514 : : * | FABS | Rsvd | COUNT_EOT | Rsvd | AURA |
515 : : * -----------------------------------------
516 : : */
517 : : free0 = roc_npa_aura_handle_to_aura(aura_handle);
518 [ # # ]: 0 : free0 |= ((uint64_t)!!fabs << 63);
519 : 0 : free0 |= ((uint64_t)(num & 0x1) << 32);
520 : :
521 : : /* tar_addr[4:6] is LMTST size-1 in units of 128b */
522 : : tar_addr = addr | ((num >> 1) << 4);
523 : :
524 : 0 : lmt_data[0] = free0;
525 [ # # ]: 0 : for (i = 0; i < num; i++)
526 : 0 : lmt_data[i + 1] = buf[i];
527 : :
528 : : roc_lmt_submit_steorl(lmt_id, tar_addr);
529 : 0 : plt_io_wmb();
530 : 0 : }
531 : :
532 : : static inline void
533 [ # # ]: 0 : roc_npa_aura_batch_free_burst(uint64_t aura_handle, uint64_t const *buf,
534 : : unsigned int num, const int fabs,
535 : : uint64_t lmt_addr, uint64_t lmt_id)
536 : : {
537 : : uint64_t addr, tar_addr, free0, send_data, lmtline;
538 : : uint64_t *lmt_data;
539 : :
540 : : /* 63 52 51 20 19 7 6 4 3 0
541 : : * ----------------------------------------
542 : : * | RSVD | ADDR | RSVD | LMTST SZ(0) | 0 |
543 : : * ----------------------------------------
544 : : */
545 : : addr = roc_npa_aura_handle_to_base(aura_handle) +
546 : : NPA_LF_AURA_BATCH_FREE0;
547 : : tar_addr = addr | (0x7 << 4);
548 : :
549 : : /* 63 63 62 33 32 32 31 20 19 0
550 : : * -----------------------------------------
551 : : * | FABS | Rsvd | COUNT_EOT | Rsvd | AURA |
552 : : * -----------------------------------------
553 : : */
554 : : free0 = roc_npa_aura_handle_to_aura(aura_handle);
555 [ # # ]: 0 : free0 |= ((uint64_t)!!fabs << 63);
556 : 0 : free0 |= (0x1UL << 32);
557 : :
558 : : /* Fill the lmt lines */
559 : 0 : lmt_data = (uint64_t *)lmt_addr;
560 : : lmtline = 0;
561 [ # # ]: 0 : while (num) {
562 : 0 : lmt_data[lmtline * 16] = free0;
563 : 0 : memcpy(&lmt_data[(lmtline * 16) + 1], buf,
564 : : ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS * sizeof(uint64_t));
565 : 0 : lmtline++;
566 : 0 : num -= ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS;
567 : 0 : buf += ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS;
568 : : }
569 : :
570 : : /* 63 19 18 16 15 12 11 11 10 0
571 : : * ---------------------------------------------------------------
572 : : * | LMTST SZ(15) ... LMTST SZ(1) | Rsvd | CNTM1 | Rsvd | LMT_ID |
573 : : * ---------------------------------------------------------------
574 : : */
575 : : send_data = lmt_id | ((lmtline - 1) << 12) | (0x1FFFFFFFFFFFUL << 19);
576 : : roc_lmt_submit_steorl(send_data, tar_addr);
577 : 0 : plt_io_wmb();
578 : 0 : }
579 : :
580 : : static inline void
581 : 0 : roc_npa_aura_op_batch_free(uint64_t aura_handle, uint64_t const *buf,
582 : : unsigned int num, const int fabs, uint64_t lmt_addr,
583 : : uint64_t lmt_id)
584 : : {
585 : : unsigned int max_burst, chunk, bnum;
586 : :
587 : : max_burst = ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS *
588 : : ROC_CN10K_NPA_BATCH_FREE_BURST_MAX;
589 : 0 : bnum = num / ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS;
590 : 0 : bnum *= ROC_CN10K_NPA_BATCH_FREE_MAX_PTRS;
591 : : num -= bnum;
592 : :
593 [ # # ]: 0 : while (bnum) {
594 : 0 : chunk = (bnum >= max_burst) ? max_burst : bnum;
595 : 0 : roc_npa_aura_batch_free_burst(aura_handle, buf, chunk, fabs,
596 : : lmt_addr, lmt_id);
597 : 0 : buf += chunk;
598 : 0 : bnum -= chunk;
599 : : }
600 : :
601 [ # # ]: 0 : if (num)
602 : : roc_npa_aura_batch_free(aura_handle, buf, num, fabs, lmt_addr,
603 : : lmt_id);
604 : 0 : }
605 : :
606 : : static inline unsigned int
607 : : roc_npa_aura_bulk_alloc(uint64_t aura_handle, uint64_t *buf, unsigned int num,
608 : : const int drop)
609 : : {
610 : : #if defined(__aarch64__)
611 : : uint64_t wdata = roc_npa_aura_handle_to_aura(aura_handle);
612 : : unsigned int i, count;
613 : : uint64_t addr;
614 : :
615 : : if (drop)
616 : : wdata |= BIT_ULL(63); /* DROP */
617 : :
618 : : addr = roc_npa_aura_handle_to_base(aura_handle) +
619 : : NPA_LF_AURA_OP_ALLOCX(0);
620 : :
621 : : switch (num) {
622 : : case 30:
623 : : asm volatile(
624 : : ".arch_extension lse\n"
625 : : "mov v18.d[0], %[dst]\n"
626 : : "mov v18.d[1], %[loc]\n"
627 : : "mov v19.d[0], %[wdata]\n"
628 : : "mov v19.d[1], x30\n"
629 : : "mov v20.d[0], x24\n"
630 : : "mov v20.d[1], x25\n"
631 : : "mov v21.d[0], x26\n"
632 : : "mov v21.d[1], x27\n"
633 : : "mov v22.d[0], x28\n"
634 : : "mov v22.d[1], x29\n"
635 : : "mov x28, v19.d[0]\n"
636 : : "mov x29, v19.d[0]\n"
637 : : "mov x30, v18.d[1]\n"
638 : : "casp x0, x1, x28, x29, [x30]\n"
639 : : "casp x2, x3, x28, x29, [x30]\n"
640 : : "casp x4, x5, x28, x29, [x30]\n"
641 : : "casp x6, x7, x28, x29, [x30]\n"
642 : : "casp x8, x9, x28, x29, [x30]\n"
643 : : "casp x10, x11, x28, x29, [x30]\n"
644 : : "casp x12, x13, x28, x29, [x30]\n"
645 : : "casp x14, x15, x28, x29, [x30]\n"
646 : : "casp x16, x17, x28, x29, [x30]\n"
647 : : "casp x18, x19, x28, x29, [x30]\n"
648 : : "casp x20, x21, x28, x29, [x30]\n"
649 : : "casp x22, x23, x28, x29, [x30]\n"
650 : : "casp x24, x25, x28, x29, [x30]\n"
651 : : "casp x26, x27, x28, x29, [x30]\n"
652 : : "casp x28, x29, x28, x29, [x30]\n"
653 : : "mov x30, v18.d[0]\n"
654 : : "stp x0, x1, [x30]\n"
655 : : "stp x2, x3, [x30, #16]\n"
656 : : "stp x4, x5, [x30, #32]\n"
657 : : "stp x6, x7, [x30, #48]\n"
658 : : "stp x8, x9, [x30, #64]\n"
659 : : "stp x10, x11, [x30, #80]\n"
660 : : "stp x12, x13, [x30, #96]\n"
661 : : "stp x14, x15, [x30, #112]\n"
662 : : "stp x16, x17, [x30, #128]\n"
663 : : "stp x18, x19, [x30, #144]\n"
664 : : "stp x20, x21, [x30, #160]\n"
665 : : "stp x22, x23, [x30, #176]\n"
666 : : "stp x24, x25, [x30, #192]\n"
667 : : "stp x26, x27, [x30, #208]\n"
668 : : "stp x28, x29, [x30, #224]\n"
669 : : "mov %[dst], v18.d[0]\n"
670 : : "mov %[loc], v18.d[1]\n"
671 : : "mov %[wdata], v19.d[0]\n"
672 : : "mov x30, v19.d[1]\n"
673 : : "mov x24, v20.d[0]\n"
674 : : "mov x25, v20.d[1]\n"
675 : : "mov x26, v21.d[0]\n"
676 : : "mov x27, v21.d[1]\n"
677 : : "mov x28, v22.d[0]\n"
678 : : "mov x29, v22.d[1]\n"
679 : : :
680 : : : [wdata] "r"(wdata), [loc] "r"(addr), [dst] "r"(buf)
681 : : : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6",
682 : : "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14",
683 : : "x15", "x16", "x17", "x18", "x19", "x20", "x21",
684 : : "x22", "x23", "v18", "v19", "v20", "v21", "v22");
685 : : break;
686 : : case 16:
687 : : asm volatile(
688 : : ".arch_extension lse\n"
689 : : "mov x16, %[wdata]\n"
690 : : "mov x17, %[wdata]\n"
691 : : "casp x0, x1, x16, x17, [%[loc]]\n"
692 : : "casp x2, x3, x16, x17, [%[loc]]\n"
693 : : "casp x4, x5, x16, x17, [%[loc]]\n"
694 : : "casp x6, x7, x16, x17, [%[loc]]\n"
695 : : "casp x8, x9, x16, x17, [%[loc]]\n"
696 : : "casp x10, x11, x16, x17, [%[loc]]\n"
697 : : "casp x12, x13, x16, x17, [%[loc]]\n"
698 : : "casp x14, x15, x16, x17, [%[loc]]\n"
699 : : "stp x0, x1, [%[dst]]\n"
700 : : "stp x2, x3, [%[dst], #16]\n"
701 : : "stp x4, x5, [%[dst], #32]\n"
702 : : "stp x6, x7, [%[dst], #48]\n"
703 : : "stp x8, x9, [%[dst], #64]\n"
704 : : "stp x10, x11, [%[dst], #80]\n"
705 : : "stp x12, x13, [%[dst], #96]\n"
706 : : "stp x14, x15, [%[dst], #112]\n"
707 : : :
708 : : : [wdata] "r"(wdata), [dst] "r"(buf), [loc] "r"(addr)
709 : : : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6",
710 : : "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14",
711 : : "x15", "x16", "x17");
712 : : break;
713 : : case 8:
714 : : asm volatile(
715 : : ".arch_extension lse\n"
716 : : "mov x16, %[wdata]\n"
717 : : "mov x17, %[wdata]\n"
718 : : "casp x0, x1, x16, x17, [%[loc]]\n"
719 : : "casp x2, x3, x16, x17, [%[loc]]\n"
720 : : "casp x4, x5, x16, x17, [%[loc]]\n"
721 : : "casp x6, x7, x16, x17, [%[loc]]\n"
722 : : "stp x0, x1, [%[dst]]\n"
723 : : "stp x2, x3, [%[dst], #16]\n"
724 : : "stp x4, x5, [%[dst], #32]\n"
725 : : "stp x6, x7, [%[dst], #48]\n"
726 : : :
727 : : : [wdata] "r"(wdata), [dst] "r"(buf), [loc] "r"(addr)
728 : : : "memory", "x0", "x1", "x2", "x3", "x4", "x5", "x6",
729 : : "x7", "x16", "x17");
730 : : break;
731 : : case 4:
732 : : asm volatile(
733 : : ".arch_extension lse\n"
734 : : "mov x16, %[wdata]\n"
735 : : "mov x17, %[wdata]\n"
736 : : "casp x0, x1, x16, x17, [%[loc]]\n"
737 : : "casp x2, x3, x16, x17, [%[loc]]\n"
738 : : "stp x0, x1, [%[dst]]\n"
739 : : "stp x2, x3, [%[dst], #16]\n"
740 : : :
741 : : : [wdata] "r"(wdata), [dst] "r"(buf), [loc] "r"(addr)
742 : : : "memory", "x0", "x1", "x2", "x3", "x16", "x17");
743 : : break;
744 : : case 2:
745 : : asm volatile(
746 : : ".arch_extension lse\n"
747 : : "mov x16, %[wdata]\n"
748 : : "mov x17, %[wdata]\n"
749 : : "casp x0, x1, x16, x17, [%[loc]]\n"
750 : : "stp x0, x1, [%[dst]]\n"
751 : : :
752 : : : [wdata] "r"(wdata), [dst] "r"(buf), [loc] "r"(addr)
753 : : : "memory", "x0", "x1", "x16", "x17");
754 : : break;
755 : : case 1:
756 : : buf[0] = roc_npa_aura_op_alloc(aura_handle, drop);
757 : : return !!buf[0];
758 : : }
759 : :
760 : : /* Pack the pointers */
761 : : for (i = 0, count = 0; i < num; i++)
762 : : if (buf[i])
763 : : buf[count++] = buf[i];
764 : :
765 : : return count;
766 : : #else
767 : : unsigned int i, count;
768 : :
769 [ # # ]: 0 : for (i = 0, count = 0; i < num; i++) {
770 : 0 : buf[count] = roc_npa_aura_op_alloc(aura_handle, drop);
771 : : if (buf[count])
772 : : count++;
773 : : }
774 : :
775 : : return count;
776 : : #endif
777 : : }
778 : :
779 : : static inline unsigned int
780 : : roc_npa_aura_op_bulk_alloc(uint64_t aura_handle, uint64_t *buf,
781 : : unsigned int num, const int drop, const int partial)
782 : : {
783 : : unsigned int chunk, count, num_alloc;
784 : :
785 : : count = 0;
786 [ # # ]: 0 : while (num) {
787 : : chunk = (num >= ROC_CN9K_NPA_BULK_ALLOC_MAX_PTRS) ?
788 [ # # ]: 0 : ROC_CN9K_NPA_BULK_ALLOC_MAX_PTRS :
789 : : plt_align32prevpow2(num);
790 : :
791 : : num_alloc =
792 : : roc_npa_aura_bulk_alloc(aura_handle, buf, chunk, drop);
793 : :
794 : : count += num_alloc;
795 : : buf += num_alloc;
796 : : num -= num_alloc;
797 : :
798 [ # # ]: 0 : if (unlikely(num_alloc != chunk))
799 : : break;
800 : : }
801 : :
802 : : /* If the requested number of pointers was not allocated and if partial
803 : : * alloc is not desired, then free allocated pointers.
804 : : */
805 : : if (unlikely(num != 0 && !partial)) {
806 : : roc_npa_aura_op_bulk_free(aura_handle, buf - count, count, 1);
807 : : count = 0;
808 : : }
809 : :
810 : : return count;
811 : : }
812 : :
813 : : struct roc_npa {
814 : : struct plt_pci_device *pci_dev;
815 : :
816 : : #define ROC_NPA_MEM_SZ (1 * 1024)
817 : : uint8_t reserved[ROC_NPA_MEM_SZ] __plt_cache_aligned;
818 : : } __plt_cache_aligned;
819 : :
820 : : int __roc_api roc_npa_dev_init(struct roc_npa *roc_npa);
821 : : int __roc_api roc_npa_dev_fini(struct roc_npa *roc_npa);
822 : :
823 : : /* Flags to pool create */
824 : : #define ROC_NPA_ZERO_AURA_F BIT(0)
825 : : #define ROC_NPA_FORCE_OPAQUE_MODE_F BIT(1)
826 : : #define ROC_NPA_HALO_F BIT(2)
827 : :
828 : : /* Enumerations */
829 : : enum roc_npa_buf_type {
830 : : /* Aura used for normal pkts */
831 : : ROC_NPA_BUF_TYPE_PACKET = 0,
832 : : /* Aura used for ipsec pkts */
833 : : ROC_NPA_BUF_TYPE_PACKET_IPSEC,
834 : : /* Aura used as vwqe for normal pkts */
835 : : ROC_NPA_BUF_TYPE_VWQE,
836 : : /* Aura used as vwqe for ipsec pkts */
837 : : ROC_NPA_BUF_TYPE_VWQE_IPSEC,
838 : : /* Aura used as SQB for SQ */
839 : : ROC_NPA_BUF_TYPE_SQB,
840 : : /* Aura used for general buffer */
841 : : ROC_NPA_BUF_TYPE_BUF,
842 : : /* Aura used for timeout pool */
843 : : ROC_NPA_BUF_TYPE_TIMEOUT,
844 : : ROC_NPA_BUF_TYPE_END,
845 : : };
846 : :
847 : : /* NPA pool */
848 : : int __roc_api roc_npa_pool_create(uint64_t *aura_handle, uint32_t block_size,
849 : : uint32_t block_count, struct npa_aura_s *aura,
850 : : struct npa_pool_s *pool, uint32_t flags);
851 : : int __roc_api roc_npa_aura_limit_modify(uint64_t aura_handle,
852 : : uint16_t aura_limit);
853 : : int __roc_api roc_npa_pool_destroy(uint64_t aura_handle);
854 : : int __roc_api roc_npa_pool_range_update_check(uint64_t aura_handle);
855 : : void __roc_api roc_npa_aura_op_range_set(uint64_t aura_handle,
856 : : uint64_t start_iova,
857 : : uint64_t end_iova);
858 : : void __roc_api roc_npa_aura_op_range_get(uint64_t aura_handle,
859 : : uint64_t *start_iova,
860 : : uint64_t *end_iova);
861 : : void __roc_api roc_npa_pool_op_range_set(uint64_t aura_handle,
862 : : uint64_t start_iova,
863 : : uint64_t end_iova);
864 : : int __roc_api roc_npa_aura_create(uint64_t *aura_handle, uint32_t block_count,
865 : : struct npa_aura_s *aura, int pool_id,
866 : : uint32_t flags);
867 : : int __roc_api roc_npa_aura_destroy(uint64_t aura_handle);
868 : : uint64_t __roc_api roc_npa_zero_aura_handle(void);
869 : : int __roc_api roc_npa_buf_type_update(uint64_t aura_handle, enum roc_npa_buf_type type, int cnt);
870 : : uint64_t __roc_api roc_npa_buf_type_mask(uint64_t aura_handle);
871 : : uint64_t __roc_api roc_npa_buf_type_limit_get(uint64_t type_mask);
872 : : int __roc_api roc_npa_aura_bp_configure(uint64_t aura_id, uint16_t bpid, uint8_t bp_intf,
873 : : uint8_t bp_thresh, bool enable);
874 : : int __roc_api roc_npa_pool_bp_configure(uint64_t pool_id, uint16_t bpid, uint8_t bp_thresh,
875 : : uint8_t bp_class, bool enable);
876 : :
877 : : /* Init callbacks */
878 : : typedef int (*roc_npa_lf_init_cb_t)(struct plt_pci_device *pci_dev);
879 : : int __roc_api roc_npa_lf_init_cb_register(roc_npa_lf_init_cb_t cb);
880 : :
881 : : /* Utility functions */
882 : : uint16_t __roc_api roc_npa_pf_func_get(void);
883 : :
884 : : /* Debug */
885 : : int __roc_api roc_npa_ctx_dump(void);
886 : : int __roc_api roc_npa_dump(void);
887 : :
888 : : /* Reset operation performance counter. */
889 : : int __roc_api roc_npa_pool_op_pc_reset(uint64_t aura_handle);
890 : :
891 : : int __roc_api roc_npa_aura_drop_set(uint64_t aura_handle, uint64_t limit,
892 : : bool ena);
893 : :
894 : : void __roc_api roc_npa_dev_lock(void);
895 : : void __roc_api roc_npa_dev_unlock(void);
896 : : int __roc_api roc_npa_dpc_alloc(uint8_t *counter_id, uint16_t conf);
897 : : int __roc_api roc_npa_dpc_free(uint8_t counter_id);
898 : : int __roc_api roc_npa_pool_dpc_enable(uint64_t aura_handle, uint8_t counter_id, uint32_t flags);
899 : : int __roc_api roc_npa_pool_dpc_disable(uint64_t aura_handle, uint32_t flags);
900 : :
901 : : #endif /* _ROC_NPA_H_ */
|