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