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