net/bnxt: identify duplicate flows
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_utils.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include "ulp_utils.h"
7 #include "bnxt_tf_common.h"
8
9 /*
10  * Initialize the regfile structure for writing
11  *
12  * regfile [in] Ptr to a regfile instance
13  *
14  * returns 0 on error or 1 on success
15  */
16 uint32_t
17 ulp_regfile_init(struct ulp_regfile *regfile)
18 {
19         /* validate the arguments */
20         if (!regfile) {
21                 BNXT_TF_DBG(ERR, "invalid argument\n");
22                 return 0; /* failure */
23         }
24         memset(regfile, 0, sizeof(struct ulp_regfile));
25         return 1; /* Success */
26 }
27
28 /*
29  * Read a value from the regfile
30  *
31  * regfile [in] The regfile instance. Must be initialized prior to being used
32  *
33  * field [in] The field to be read within the regfile.
34  *
35  * data [in/out]
36  *
37  * returns size, zero on failure
38  */
39 uint32_t
40 ulp_regfile_read(struct ulp_regfile *regfile,
41                  enum bnxt_ulp_rf_idx field,
42                  uint64_t *data)
43 {
44         /* validate the arguments */
45         if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
46                 BNXT_TF_DBG(ERR, "invalid argument\n");
47                 return 0; /* failure */
48         }
49
50         *data = regfile->entry[field].data;
51         return sizeof(*data);
52 }
53
54 /*
55  * Write a value to the regfile
56  *
57  * regfile [in] The regfile instance.  Must be initialized prior to being used
58  *
59  * field [in] The field to be written within the regfile.
60  *
61  * data [in] The value is written into this variable.  It is going to be in the
62  * same byte order as it was written.
63  *
64  * size [in] The size in bytes of the value beingritten into this
65  * variable.
66  *
67  * returns 0 on success
68  */
69 int32_t
70 ulp_regfile_write(struct ulp_regfile *regfile,
71                   enum bnxt_ulp_rf_idx field,
72                   uint64_t data)
73 {
74         /* validate the arguments */
75         if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
76                 BNXT_TF_DBG(ERR, "invalid argument\n");
77                 return -EINVAL; /* failure */
78         }
79
80         regfile->entry[field].data = data;
81         return 0; /* Success */
82 }
83
84 static void
85 ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
86 {
87         uint8_t bitoffs = bitpos % 8;
88         uint16_t index  = bitpos / 8;
89         uint8_t mask;
90         uint8_t tmp;
91         int8_t shift;
92
93         tmp = bs[index];
94         mask = ((uint8_t)-1 >> (8 - bitlen));
95         shift = 8 - bitoffs - bitlen;
96         val &= mask;
97
98         if (shift >= 0) {
99                 tmp &= ~(mask << shift);
100                 tmp |= val << shift;
101                 bs[index] = tmp;
102         } else {
103                 tmp &= ~((uint8_t)-1 >> bitoffs);
104                 tmp |= val >> -shift;
105                 bs[index++] = tmp;
106
107                 tmp = bs[index];
108                 tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
109                 tmp |= val << (8 + shift);
110                 bs[index] = tmp;
111         }
112 }
113
114 static void
115 ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
116 {
117         uint8_t bitoffs = bitpos % 8;
118         uint16_t index  = bitpos / 8;
119         uint8_t mask;
120         uint8_t tmp;
121         uint8_t shift;
122         uint8_t partial;
123
124         tmp = bs[index];
125         shift = bitoffs;
126
127         if (bitoffs + bitlen <= 8) {
128                 mask = ((1 << bitlen) - 1) << shift;
129                 tmp &= ~mask;
130                 tmp |= ((val << shift) & mask);
131                 bs[index] = tmp;
132         } else {
133                 partial = 8 - bitoffs;
134                 mask = ((1 << partial) - 1) << shift;
135                 tmp &= ~mask;
136                 tmp |= ((val << shift) & mask);
137                 bs[index++] = tmp;
138
139                 val >>= partial;
140                 partial = bitlen - partial;
141                 mask = ((1 << partial) - 1);
142                 tmp = bs[index];
143                 tmp &= ~mask;
144                 tmp |= (val & mask);
145                 bs[index] = tmp;
146         }
147 }
148
149 /*
150  * Add data to the byte array in Little endian format.
151  *
152  * bs [in] The byte array where data is pushed
153  *
154  * pos [in] The offset where data is pushed
155  *
156  * len [in] The number of bits to be added to the data array.
157  *
158  * val [in] The data to be added to the data array.
159  *
160  * returns the number of bits pushed.
161  */
162 uint32_t
163 ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
164 {
165         int i;
166         int cnt = (len) / 8;
167         int tlen = len;
168
169         if (cnt > 0 && !(len % 8))
170                 cnt -= 1;
171
172         for (i = 0; i < cnt; i++) {
173                 ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
174                 pos += 8;
175                 tlen -= 8;
176         }
177
178         /* Handle the remainder bits */
179         if (tlen)
180                 ulp_bs_put_lsb(bs, pos, tlen, val[0]);
181         return len;
182 }
183
184 /*
185  * Add data to the byte array in Big endian format.
186  *
187  * bs [in] The byte array where data is pushed
188  *
189  * pos [in] The offset where data is pushed
190  *
191  * len [in] The number of bits to be added to the data array.
192  *
193  * val [in] The data to be added to the data array.
194  *
195  * returns the number of bits pushed.
196  */
197 uint32_t
198 ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
199 {
200         int i;
201         int cnt = (len + 7) / 8;
202         int tlen = len;
203
204         /* Handle any remainder bits */
205         int tmp = len % 8;
206
207         if (!tmp)
208                 tmp = 8;
209
210         ulp_bs_put_msb(bs, pos, tmp, val[0]);
211
212         pos += tmp;
213         tlen -= tmp;
214
215         for (i = 1; i < cnt; i++) {
216                 ulp_bs_put_msb(bs, pos, 8, val[i]);
217                 pos += 8;
218                 tlen -= 8;
219         }
220
221         return len;
222 }
223
224 /*
225  * Initializes the blob structure for creating binary blob
226  *
227  * blob [in] The blob to be initialized
228  *
229  * bitlen [in] The bit length of the blob
230  *
231  * order [in] The byte order for the blob.  Currently only supporting
232  * big endian.  All fields are packed with this order.
233  *
234  * returns 0 on error or 1 on success
235  */
236 uint32_t
237 ulp_blob_init(struct ulp_blob *blob,
238               uint16_t bitlen,
239               enum bnxt_ulp_byte_order order)
240 {
241         /* validate the arguments */
242         if (!blob || bitlen > (8 * sizeof(blob->data))) {
243                 BNXT_TF_DBG(ERR, "invalid argument\n");
244                 return 0; /* failure */
245         }
246         blob->bitlen = bitlen;
247         blob->byte_order = order;
248         blob->write_idx = 0;
249         memset(blob->data, 0, sizeof(blob->data));
250         return 1; /* Success */
251 }
252
253 /*
254  * Add data to the binary blob at the current offset.
255  *
256  * blob [in] The blob that data is added to.  The blob must
257  * be initialized prior to pushing data.
258  *
259  * data [in] A pointer to bytes to be added to the blob.
260  *
261  * datalen [in] The number of bits to be added to the blob.
262  *
263  * The offset of the data is updated after each push of data.
264  * NULL returned on error.
265  */
266 #define ULP_BLOB_BYTE           8
267 #define ULP_BLOB_BYTE_HEX       0xFF
268 #define BLOB_MASK_CAL(x)        ((0xFF << (x)) & 0xFF)
269 uint32_t
270 ulp_blob_push(struct ulp_blob *blob,
271               uint8_t *data,
272               uint32_t datalen)
273 {
274         uint32_t rc;
275
276         /* validate the arguments */
277         if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
278                 BNXT_TF_DBG(ERR, "invalid argument\n");
279                 return 0; /* failure */
280         }
281
282         if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
283                 rc = ulp_bs_push_msb(blob->data,
284                                      blob->write_idx,
285                                      datalen,
286                                      data);
287         else
288                 rc = ulp_bs_push_lsb(blob->data,
289                                      blob->write_idx,
290                                      datalen,
291                                      data);
292         if (!rc) {
293                 BNXT_TF_DBG(ERR, "Failed ro write blob\n");
294                 return 0;
295         }
296         blob->write_idx += datalen;
297         return datalen;
298 }
299
300 /*
301  * Insert data into the binary blob at the given offset.
302  *
303  * blob [in] The blob that data is added to.  The blob must
304  * be initialized prior to pushing data.
305  *
306  * offset [in] The offset where the data needs to be inserted.
307  *
308  * data [in/out] A pointer to bytes to be added to the blob.
309  *
310  * datalen [in] The number of bits to be added to the blob.
311  *
312  * The offset of the data is updated after each push of data.
313  * NULL returned on error.
314  */
315 uint32_t
316 ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
317                 uint8_t *data, uint32_t datalen)
318 {
319         uint32_t rc;
320         uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
321         uint16_t mov_len;
322
323         /* validate the arguments */
324         if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
325             offset > blob->write_idx) {
326                 BNXT_TF_DBG(ERR, "invalid argument\n");
327                 return 0; /* failure */
328         }
329
330         mov_len = blob->write_idx - offset;
331         /* If offset and data len are not 8 bit aligned then return error */
332         if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
333             ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) {
334                 BNXT_TF_DBG(ERR, "invalid argument, not aligned\n");
335                 return 0; /* failure */
336         }
337
338         /* copy the data so we can move the data */
339         memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
340                ULP_BITS_2_BYTE(mov_len));
341         blob->write_idx = offset;
342         if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
343                 rc = ulp_bs_push_msb(blob->data,
344                                      blob->write_idx,
345                                      datalen,
346                                      data);
347         else
348                 rc = ulp_bs_push_lsb(blob->data,
349                                      blob->write_idx,
350                                      datalen,
351                                      data);
352         if (!rc) {
353                 BNXT_TF_DBG(ERR, "Failed ro write blob\n");
354                 return 0;
355         }
356         /* copy the previously stored data */
357         memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
358                ULP_BITS_2_BYTE(mov_len));
359         blob->write_idx += (mov_len + datalen);
360         return datalen;
361 }
362
363 /*
364  * Add data to the binary blob at the current offset.
365  *
366  * blob [in] The blob that data is added to.  The blob must
367  * be initialized prior to pushing data.
368  *
369  * data [in] 64-bit value to be added to the blob.
370  *
371  * datalen [in] The number of bits to be added to the blob.
372  *
373  * The offset of the data is updated after each push of data.
374  * NULL returned on error, pointer pushed value otherwise.
375  */
376 uint8_t *
377 ulp_blob_push_64(struct ulp_blob *blob,
378                  uint64_t *data,
379                  uint32_t datalen)
380 {
381         uint8_t *val = (uint8_t *)data;
382         int rc;
383
384         int size = (datalen + 7) / 8;
385
386         if (!blob || !data ||
387             datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
388                 BNXT_TF_DBG(ERR, "invalid argument\n");
389                 return 0;
390         }
391
392         rc = ulp_blob_push(blob, &val[8 - size], datalen);
393         if (!rc)
394                 return 0;
395
396         return &val[8 - size];
397 }
398
399 /*
400  * Add data to the binary blob at the current offset.
401  *
402  * blob [in] The blob that data is added to.  The blob must
403  * be initialized prior to pushing data.
404  *
405  * data [in] 32-bit value to be added to the blob.
406  *
407  * datalen [in] The number of bits to be added ot the blob.
408  *
409  * The offset of the data is updated after each push of data.
410  * NULL returned on error, pointer pushed value otherwise.
411  */
412 uint8_t *
413 ulp_blob_push_32(struct ulp_blob *blob,
414                  uint32_t *data,
415                  uint32_t datalen)
416 {
417         uint8_t *val = (uint8_t *)data;
418         uint32_t rc;
419         uint32_t size = ULP_BITS_2_BYTE(datalen);
420
421         if (!data || size > sizeof(uint32_t)) {
422                 BNXT_TF_DBG(ERR, "invalid argument\n");
423                 return 0;
424         }
425
426         rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
427         if (!rc)
428                 return 0;
429
430         return &val[sizeof(uint32_t) - size];
431 }
432
433 /*
434  * Add encap data to the binary blob at the current offset.
435  *
436  * blob [in] The blob that data is added to.  The blob must
437  * be initialized prior to pushing data.
438  *
439  * data [in] value to be added to the blob.
440  *
441  * datalen [in] The number of bits to be added to the blob.
442  *
443  * The offset of the data is updated after each push of data.
444  * NULL returned on error, pointer pushed value otherwise.
445  */
446 uint32_t
447 ulp_blob_push_encap(struct ulp_blob *blob,
448                     uint8_t *data,
449                     uint32_t datalen)
450 {
451         uint8_t         *val = (uint8_t *)data;
452         uint32_t        initial_size, write_size = datalen;
453         uint32_t        size = 0;
454
455         if (!blob || !data ||
456             datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
457                 BNXT_TF_DBG(ERR, "invalid argument\n");
458                 return 0;
459         }
460
461         initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
462             (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
463         while (write_size > 0) {
464                 if (initial_size && write_size > initial_size) {
465                         size = initial_size;
466                         initial_size = 0;
467                 } else if (initial_size && write_size <= initial_size) {
468                         size = write_size;
469                         initial_size = 0;
470                 } else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
471                         size = ULP_BYTE_2_BITS(sizeof(uint64_t));
472                 } else {
473                         size = write_size;
474                 }
475                 if (!ulp_blob_push(blob, val, size)) {
476                         BNXT_TF_DBG(ERR, "push field failed\n");
477                         return 0;
478                 }
479                 val += ULP_BITS_2_BYTE(size);
480                 write_size -= size;
481         }
482         return datalen;
483 }
484
485 /*
486  * Adds pad to an initialized blob at the current offset
487  *
488  * blob [in] The blob that data is added to.  The blob must
489  * be initialized prior to pushing data.
490  *
491  * datalen [in] The number of bits of pad to add
492  *
493  * returns the number of pad bits added, -1 on failure
494  */
495 int32_t
496 ulp_blob_pad_push(struct ulp_blob *blob,
497                   uint32_t datalen)
498 {
499         if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
500                 BNXT_TF_DBG(ERR, "Pad too large for blob\n");
501                 return -1;
502         }
503
504         blob->write_idx += datalen;
505         return datalen;
506 }
507
508 /* Get data from src and put into dst using little-endian format */
509 static void
510 ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
511 {
512         uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
513         uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
514         uint8_t mask, partial, shift;
515
516         shift = bitoffs;
517         partial = ULP_BLOB_BYTE - bitoffs;
518         if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
519                 mask = ((1 << bitlen) - 1) << shift;
520                 *dst = (src[index] & mask) >> shift;
521         } else {
522                 mask = ((1 << partial) - 1) << shift;
523                 *dst = (src[index] & mask) >> shift;
524                 index++;
525                 partial = bitlen - partial;
526                 mask = ((1 << partial) - 1);
527                 *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
528         }
529 }
530
531 /*
532  * Get data from the byte array in Little endian format.
533  *
534  * src [in] The byte array where data is extracted from
535  *
536  * dst [out] The byte array where data is pulled into
537  *
538  * size [in] The size of dst array in bytes
539  *
540  * offset [in] The offset where data is pulled
541  *
542  * len [in] The number of bits to be extracted from the data array
543  *
544  * returns None.
545  */
546 void
547 ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
548                 uint32_t offset, uint32_t len)
549 {
550         uint32_t idx;
551         uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
552
553         /* iterate bytewise to get data */
554         for (idx = 0; idx < cnt; idx++) {
555                 ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
556                                &dst[size - 1 - idx]);
557                 offset += ULP_BLOB_BYTE;
558                 len -= ULP_BLOB_BYTE;
559         }
560
561         /* Extract the last reminder data that is not 8 byte boundary */
562         if (len)
563                 ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
564 }
565
566 /* Get data from src and put into dst using big-endian format */
567 static void
568 ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
569 {
570         uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
571         uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
572         uint8_t mask;
573         int32_t shift;
574
575         shift = ULP_BLOB_BYTE - bitoffs - bitlen;
576         if (shift >= 0) {
577                 mask = 0xFF >> -bitlen;
578                 *dst = (src[index] >> shift) & mask;
579         } else {
580                 *dst = (src[index] & (0xFF >> bitoffs)) << -shift;
581                 *dst |= src[index + 1] >> -shift;
582         }
583 }
584
585 /*
586  * Get data from the byte array in Big endian format.
587  *
588  * src [in] The byte array where data is extracted from
589  *
590  * dst [out] The byte array where data is pulled into
591  *
592  * offset [in] The offset where data is pulled
593  *
594  * len [in] The number of bits to be extracted from the data array
595  *
596  * returns None.
597  */
598 void
599 ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
600                 uint32_t offset, uint32_t len)
601 {
602         uint32_t idx;
603         uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
604
605         /* iterate bytewise to get data */
606         for (idx = 0; idx < cnt; idx++) {
607                 ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
608                 offset += ULP_BLOB_BYTE;
609                 len -= ULP_BLOB_BYTE;
610         }
611
612         /* Extract the last reminder data that is not 8 byte boundary */
613         if (len)
614                 ulp_bs_get_msb(src, offset, len, &dst[idx]);
615 }
616
617 /*
618  * Extract data from the binary blob using given offset.
619  *
620  * blob [in] The blob that data is extracted from. The blob must
621  * be initialized prior to pulling data.
622  *
623  * data [in] A pointer to put the data.
624  * data_size [in] size of the data buffer in bytes.
625  *offset [in] - Offset in the blob to extract the data in bits format.
626  * len [in] The number of bits to be pulled from the blob.
627  *
628  * Output: zero on success, -1 on failure
629  */
630 int32_t
631 ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
632               uint16_t offset, uint16_t len)
633 {
634         /* validate the arguments */
635         if (!blob || (offset + len) > blob->bitlen ||
636             ULP_BYTE_2_BITS(data_size) < len) {
637                 BNXT_TF_DBG(ERR, "invalid argument\n");
638                 return -1; /* failure */
639         }
640
641         if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
642                 ulp_bs_pull_msb(blob->data, data, offset, len);
643         else
644                 ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
645         return 0;
646 }
647
648 /*
649  * Get the data portion of the binary blob.
650  *
651  * blob [in] The blob's data to be retrieved. The blob must be
652  * initialized prior to pushing data.
653  *
654  * datalen [out] The number of bits to that are filled.
655  *
656  * returns a byte array of the blob data.  Returns NULL on error.
657  */
658 uint8_t *
659 ulp_blob_data_get(struct ulp_blob *blob,
660                   uint16_t *datalen)
661 {
662         /* validate the arguments */
663         if (!blob) {
664                 BNXT_TF_DBG(ERR, "invalid argument\n");
665                 return NULL; /* failure */
666         }
667         *datalen = blob->write_idx;
668         return blob->data;
669 }
670
671 /*
672  * Set the encap swap start index of the binary blob.
673  *
674  * blob [in] The blob's data to be retrieved. The blob must be
675  * initialized prior to pushing data.
676  *
677  * returns void.
678  */
679 void
680 ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
681 {
682         /* validate the arguments */
683         if (!blob) {
684                 BNXT_TF_DBG(ERR, "invalid argument\n");
685                 return; /* failure */
686         }
687         blob->encap_swap_idx = blob->write_idx;
688 }
689
690 /*
691  * Perform the encap buffer swap to 64 bit reversal.
692  *
693  * blob [in] The blob's data to be used for swap.
694  *
695  * returns void.
696  */
697 void
698 ulp_blob_perform_encap_swap(struct ulp_blob *blob)
699 {
700         uint32_t i, idx = 0, end_idx = 0, roundoff;
701         uint8_t temp_val_1, temp_val_2;
702
703         /* validate the arguments */
704         if (!blob) {
705                 BNXT_TF_DBG(ERR, "invalid argument\n");
706                 return; /* failure */
707         }
708         idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
709         end_idx = ULP_BITS_2_BYTE(blob->write_idx);
710         roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
711         if (roundoff > end_idx) {
712                 blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
713                 end_idx = roundoff;
714         }
715         while (idx <= end_idx) {
716                 for (i = 0; i < 4; i = i + 2) {
717                         temp_val_1 = blob->data[idx + i];
718                         temp_val_2 = blob->data[idx + i + 1];
719                         blob->data[idx + i] = blob->data[idx + 6 - i];
720                         blob->data[idx + i + 1] = blob->data[idx + 7 - i];
721                         blob->data[idx + 7 - i] = temp_val_2;
722                         blob->data[idx + 6 - i] = temp_val_1;
723                 }
724                 idx += 8;
725         }
726 }
727
728 /*
729  * Perform the blob buffer reversal byte wise.
730  * This api makes the first byte the last and
731  * vice-versa.
732  *
733  * blob [in] The blob's data to be used for swap.
734  *
735  * returns void.
736  */
737 void
738 ulp_blob_perform_byte_reverse(struct ulp_blob *blob)
739 {
740         uint32_t idx = 0, num = 0;
741         uint8_t xchar;
742
743         /* validate the arguments */
744         if (!blob) {
745                 BNXT_TF_DBG(ERR, "invalid argument\n");
746                 return; /* failure */
747         }
748
749         num = ULP_BITS_2_BYTE_NR(blob->write_idx);
750         for (idx = 0; idx < (num / 2); idx++) {
751                 xchar = blob->data[idx];
752                 blob->data[idx] = blob->data[(num - 1) - idx];
753                 blob->data[(num - 1) - idx] = xchar;
754         }
755 }
756
757 /*
758  * Perform the blob buffer 64 bit word swap.
759  * This api makes the first 4 bytes the last in
760  * a given 64 bit value and vice-versa.
761  *
762  * blob [in] The blob's data to be used for swap.
763  *
764  * returns void.
765  */
766 void
767 ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
768 {
769         uint32_t i, j, num;
770         uint8_t xchar;
771         uint32_t word_size = ULP_64B_IN_BYTES / 2;
772
773         /* validate the arguments */
774         if (!blob) {
775                 BNXT_TF_DBG(ERR, "invalid argument\n");
776                 return; /* failure */
777         }
778         num = ULP_BITS_2_BYTE(blob->write_idx);
779         for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
780                 for (j = 0; j < word_size; j++) {
781                         xchar = blob->data[i + j];
782                         blob->data[i + j] = blob->data[i + j + word_size];
783                         blob->data[i + j + word_size] = xchar;
784                 }
785         }
786 }
787
788 /*
789  * Perform the blob buffer 64 bit byte swap.
790  * This api makes the first byte the last in
791  * a given 64 bit value and vice-versa.
792  *
793  * blob [in] The blob's data to be used for swap.
794  *
795  * returns void.
796  */
797 void
798 ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
799 {
800         uint32_t i, j, num;
801         uint8_t xchar;
802         uint32_t offset = ULP_64B_IN_BYTES - 1;
803
804         /* validate the arguments */
805         if (!blob) {
806                 BNXT_TF_DBG(ERR, "invalid argument\n");
807                 return; /* failure */
808         }
809         num = ULP_BITS_2_BYTE(blob->write_idx);
810         for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
811                 for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
812                         xchar = blob->data[i + j];
813                         blob->data[i + j] = blob->data[i + offset - j];
814                         blob->data[i + offset - j] = xchar;
815                 }
816         }
817 }
818
819 /*
820  * Read data from the operand
821  *
822  * operand [in] A pointer to a 16 Byte operand
823  *
824  * val [in/out] The variable to copy the operand to
825  *
826  * bytes [in] The number of bytes to read into val
827  *
828  * returns number of bits read, zero on error
829  */
830 uint16_t
831 ulp_operand_read(uint8_t *operand,
832                  uint8_t *val,
833                  uint16_t bytes)
834 {
835         /* validate the arguments */
836         if (!operand || !val) {
837                 BNXT_TF_DBG(ERR, "invalid argument\n");
838                 return 0; /* failure */
839         }
840         memcpy(val, operand, bytes);
841         return bytes;
842 }
843
844 /*
845  * copy the buffer in the encap format which is 2 bytes.
846  * The MSB of the src is placed at the LSB of dst.
847  *
848  * dst [out] The destination buffer
849  * src [in] The source buffer dst
850  * size[in] size of the buffer.
851  * align[in] The alignment is either 8 or 16.
852  */
853 void
854 ulp_encap_buffer_copy(uint8_t *dst,
855                       const uint8_t *src,
856                       uint16_t size,
857                       uint16_t align)
858 {
859         uint16_t        idx, tmp_size = 0;
860
861         do {
862                 dst += tmp_size;
863                 src += tmp_size;
864                 idx = 0;
865                 if (size > align) {
866                         tmp_size = align;
867                         size -= align;
868                 } else {
869                         tmp_size = size;
870                         size = 0;
871                 }
872                 /* copy 2 bytes at a time. Write MSB to LSB */
873                 while ((idx + sizeof(uint16_t)) <= tmp_size) {
874                         memcpy(&dst[idx],
875                                &src[tmp_size - idx - sizeof(uint16_t)],
876                                sizeof(uint16_t));
877                         idx += sizeof(uint16_t);
878                 }
879         } while (size);
880 }
881
882 /*
883  * Check the buffer is empty
884  *
885  * buf [in] The buffer
886  * size [in] The size of the buffer
887  *
888  */
889 int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
890 {
891         return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
892 }
893
894 /* Function to check if bitmap is zero.Return 1 on success */
895 uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
896 {
897         while (size-- > 0) {
898                 if (*bitmap != 0)
899                         return 0;
900                 bitmap++;
901         }
902         return 1;
903 }
904
905 /* Function to check if bitmap is ones. Return 1 on success */
906 uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
907 {
908         while (size-- > 0) {
909                 if (*bitmap != 0xFF)
910                         return 0;
911                 bitmap++;
912         }
913         return 1;
914 }
915
916 /* Function to check if bitmap is not zero. Return 1 on success */
917 uint32_t ulp_bitmap_notzero(uint8_t *bitmap, int32_t size)
918 {
919         while (size-- > 0) {
920                 if (*bitmap != 0)
921                         return 1;
922                 bitmap++;
923         }
924         return 0;
925 }