xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_utils.c (revision c569279aded4bb8fdf83b09e0726fa07028dcef8)
188badb3aSMike Baucom /* SPDX-License-Identifier: BSD-3-Clause
2e6e8f03eSRandy Schacher  * Copyright(c) 2014-2023 Broadcom
388badb3aSMike Baucom  * All rights reserved.
488badb3aSMike Baucom  */
588badb3aSMike Baucom 
63fe124d2SKishore Padmanabha #include <rte_common.h>
788badb3aSMike Baucom #include "ulp_utils.h"
888badb3aSMike Baucom #include "bnxt_tf_common.h"
988badb3aSMike Baucom 
1088badb3aSMike Baucom /*
1188badb3aSMike Baucom  * Initialize the regfile structure for writing
1288badb3aSMike Baucom  *
1388badb3aSMike Baucom  * regfile [in] Ptr to a regfile instance
1488badb3aSMike Baucom  *
15*c569279aSShuanglin Wang  * returns zero on success
1688badb3aSMike Baucom  */
17*c569279aSShuanglin Wang int32_t
1888badb3aSMike Baucom ulp_regfile_init(struct ulp_regfile *regfile)
1988badb3aSMike Baucom {
2088badb3aSMike Baucom 	/* validate the arguments */
2188badb3aSMike Baucom 	if (!regfile) {
22dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
23*c569279aSShuanglin Wang 		return -EINVAL;
2488badb3aSMike Baucom 	}
2588badb3aSMike Baucom 	memset(regfile, 0, sizeof(struct ulp_regfile));
26*c569279aSShuanglin Wang 	return 0; /* Success */
2788badb3aSMike Baucom }
2888badb3aSMike Baucom 
2988badb3aSMike Baucom /*
3088badb3aSMike Baucom  * Read a value from the regfile
3188badb3aSMike Baucom  *
3288badb3aSMike Baucom  * regfile [in] The regfile instance. Must be initialized prior to being used
3388badb3aSMike Baucom  *
3488badb3aSMike Baucom  * field [in] The field to be read within the regfile.
3588badb3aSMike Baucom  *
3688badb3aSMike Baucom  * data [in/out]
3788badb3aSMike Baucom  *
38*c569279aSShuanglin Wang  * returns zero on success
3988badb3aSMike Baucom  */
40*c569279aSShuanglin Wang int32_t
4188badb3aSMike Baucom ulp_regfile_read(struct ulp_regfile *regfile,
42a2417601SKishore Padmanabha 		 enum bnxt_ulp_rf_idx field,
4388badb3aSMike Baucom 		 uint64_t *data)
4488badb3aSMike Baucom {
4588badb3aSMike Baucom 	/* validate the arguments */
46a2417601SKishore Padmanabha 	if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
47dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
48*c569279aSShuanglin Wang 		return -EINVAL;
4988badb3aSMike Baucom 	}
5088badb3aSMike Baucom 
5188badb3aSMike Baucom 	*data = regfile->entry[field].data;
52*c569279aSShuanglin Wang 	return 0;
5388badb3aSMike Baucom }
5488badb3aSMike Baucom 
5588badb3aSMike Baucom /*
5688badb3aSMike Baucom  * Write a value to the regfile
5788badb3aSMike Baucom  *
5888badb3aSMike Baucom  * regfile [in] The regfile instance.  Must be initialized prior to being used
5988badb3aSMike Baucom  *
6088badb3aSMike Baucom  * field [in] The field to be written within the regfile.
6188badb3aSMike Baucom  *
6288badb3aSMike Baucom  * data [in] The value is written into this variable.  It is going to be in the
6388badb3aSMike Baucom  * same byte order as it was written.
6488badb3aSMike Baucom  *
65f63aa27dSKishore Padmanabha  * size [in] The size in bytes of the value being written into this
6688badb3aSMike Baucom  * variable.
6788badb3aSMike Baucom  *
68a2417601SKishore Padmanabha  * returns 0 on success
6988badb3aSMike Baucom  */
70a2417601SKishore Padmanabha int32_t
7188badb3aSMike Baucom ulp_regfile_write(struct ulp_regfile *regfile,
72a2417601SKishore Padmanabha 		  enum bnxt_ulp_rf_idx field,
7388badb3aSMike Baucom 		  uint64_t data)
7488badb3aSMike Baucom {
7588badb3aSMike Baucom 	/* validate the arguments */
76a2417601SKishore Padmanabha 	if (!regfile || field >= BNXT_ULP_RF_IDX_LAST) {
77dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
78a2417601SKishore Padmanabha 		return -EINVAL; /* failure */
7988badb3aSMike Baucom 	}
8088badb3aSMike Baucom 
8188badb3aSMike Baucom 	regfile->entry[field].data = data;
82a2417601SKishore Padmanabha 	return 0; /* Success */
8388badb3aSMike Baucom }
8488badb3aSMike Baucom 
8588badb3aSMike Baucom static void
8688badb3aSMike Baucom ulp_bs_put_msb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
8788badb3aSMike Baucom {
8888badb3aSMike Baucom 	uint8_t bitoffs = bitpos % 8;
8988badb3aSMike Baucom 	uint16_t index  = bitpos / 8;
9088badb3aSMike Baucom 	uint8_t mask;
9188badb3aSMike Baucom 	uint8_t tmp;
9288badb3aSMike Baucom 	int8_t shift;
9388badb3aSMike Baucom 
9488badb3aSMike Baucom 	tmp = bs[index];
9588badb3aSMike Baucom 	mask = ((uint8_t)-1 >> (8 - bitlen));
9688badb3aSMike Baucom 	shift = 8 - bitoffs - bitlen;
9788badb3aSMike Baucom 	val &= mask;
9888badb3aSMike Baucom 
9988badb3aSMike Baucom 	if (shift >= 0) {
10088badb3aSMike Baucom 		tmp &= ~(mask << shift);
10188badb3aSMike Baucom 		tmp |= val << shift;
10288badb3aSMike Baucom 		bs[index] = tmp;
10388badb3aSMike Baucom 	} else {
10488badb3aSMike Baucom 		tmp &= ~((uint8_t)-1 >> bitoffs);
10588badb3aSMike Baucom 		tmp |= val >> -shift;
10688badb3aSMike Baucom 		bs[index++] = tmp;
10788badb3aSMike Baucom 
10888badb3aSMike Baucom 		tmp = bs[index];
10988badb3aSMike Baucom 		tmp &= ((uint8_t)-1 >> (bitlen - (8 - bitoffs)));
11088badb3aSMike Baucom 		tmp |= val << (8 + shift);
11188badb3aSMike Baucom 		bs[index] = tmp;
11288badb3aSMike Baucom 	}
11388badb3aSMike Baucom }
11488badb3aSMike Baucom 
11588badb3aSMike Baucom static void
11688badb3aSMike Baucom ulp_bs_put_lsb(uint8_t *bs, uint16_t bitpos, uint8_t bitlen, uint8_t val)
11788badb3aSMike Baucom {
11888badb3aSMike Baucom 	uint8_t bitoffs = bitpos % 8;
11988badb3aSMike Baucom 	uint16_t index  = bitpos / 8;
12088badb3aSMike Baucom 	uint8_t mask;
12188badb3aSMike Baucom 	uint8_t tmp;
12288badb3aSMike Baucom 	uint8_t shift;
12388badb3aSMike Baucom 	uint8_t partial;
12488badb3aSMike Baucom 
12588badb3aSMike Baucom 	tmp = bs[index];
12688badb3aSMike Baucom 	shift = bitoffs;
12788badb3aSMike Baucom 
12888badb3aSMike Baucom 	if (bitoffs + bitlen <= 8) {
12988badb3aSMike Baucom 		mask = ((1 << bitlen) - 1) << shift;
13088badb3aSMike Baucom 		tmp &= ~mask;
13188badb3aSMike Baucom 		tmp |= ((val << shift) & mask);
13288badb3aSMike Baucom 		bs[index] = tmp;
13388badb3aSMike Baucom 	} else {
13488badb3aSMike Baucom 		partial = 8 - bitoffs;
13588badb3aSMike Baucom 		mask = ((1 << partial) - 1) << shift;
13688badb3aSMike Baucom 		tmp &= ~mask;
13788badb3aSMike Baucom 		tmp |= ((val << shift) & mask);
13888badb3aSMike Baucom 		bs[index++] = tmp;
13988badb3aSMike Baucom 
14088badb3aSMike Baucom 		val >>= partial;
14188badb3aSMike Baucom 		partial = bitlen - partial;
14288badb3aSMike Baucom 		mask = ((1 << partial) - 1);
14388badb3aSMike Baucom 		tmp = bs[index];
14488badb3aSMike Baucom 		tmp &= ~mask;
14588badb3aSMike Baucom 		tmp |= (val & mask);
14688badb3aSMike Baucom 		bs[index] = tmp;
14788badb3aSMike Baucom 	}
14888badb3aSMike Baucom }
14988badb3aSMike Baucom 
150f634204bSKishore Padmanabha /*
151f634204bSKishore Padmanabha  * Add data to the byte array in Little endian format.
152f634204bSKishore Padmanabha  *
153f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
154f634204bSKishore Padmanabha  *
155f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
156f634204bSKishore Padmanabha  *
157f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
158f634204bSKishore Padmanabha  *
159f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
160f634204bSKishore Padmanabha  *
161f634204bSKishore Padmanabha  * returns the number of bits pushed.
162f634204bSKishore Padmanabha  */
163f634204bSKishore Padmanabha uint32_t
16488badb3aSMike Baucom ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
16588badb3aSMike Baucom {
16688badb3aSMike Baucom 	int i;
16788badb3aSMike Baucom 	int cnt = (len) / 8;
16888badb3aSMike Baucom 	int tlen = len;
16988badb3aSMike Baucom 
17088badb3aSMike Baucom 	if (cnt > 0 && !(len % 8))
17188badb3aSMike Baucom 		cnt -= 1;
17288badb3aSMike Baucom 
17388badb3aSMike Baucom 	for (i = 0; i < cnt; i++) {
17488badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, 8, val[cnt - i]);
17588badb3aSMike Baucom 		pos += 8;
17688badb3aSMike Baucom 		tlen -= 8;
17788badb3aSMike Baucom 	}
17888badb3aSMike Baucom 
17988badb3aSMike Baucom 	/* Handle the remainder bits */
18088badb3aSMike Baucom 	if (tlen)
18188badb3aSMike Baucom 		ulp_bs_put_lsb(bs, pos, tlen, val[0]);
18288badb3aSMike Baucom 	return len;
18388badb3aSMike Baucom }
18488badb3aSMike Baucom 
185f634204bSKishore Padmanabha /*
186f634204bSKishore Padmanabha  * Add data to the byte array in Big endian format.
187f634204bSKishore Padmanabha  *
188f634204bSKishore Padmanabha  * bs [in] The byte array where data is pushed
189f634204bSKishore Padmanabha  *
190f634204bSKishore Padmanabha  * pos [in] The offset where data is pushed
191f634204bSKishore Padmanabha  *
192f634204bSKishore Padmanabha  * len [in] The number of bits to be added to the data array.
193f634204bSKishore Padmanabha  *
194f634204bSKishore Padmanabha  * val [in] The data to be added to the data array.
195f634204bSKishore Padmanabha  *
196f634204bSKishore Padmanabha  * returns the number of bits pushed.
197f634204bSKishore Padmanabha  */
198f634204bSKishore Padmanabha uint32_t
19988badb3aSMike Baucom ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val)
20088badb3aSMike Baucom {
20188badb3aSMike Baucom 	int i;
20288badb3aSMike Baucom 	int cnt = (len + 7) / 8;
20388badb3aSMike Baucom 
20488badb3aSMike Baucom 	/* Handle any remainder bits */
20588badb3aSMike Baucom 	int tmp = len % 8;
20688badb3aSMike Baucom 
20788badb3aSMike Baucom 	if (!tmp)
20888badb3aSMike Baucom 		tmp = 8;
20988badb3aSMike Baucom 
21088badb3aSMike Baucom 	ulp_bs_put_msb(bs, pos, tmp, val[0]);
21188badb3aSMike Baucom 
21288badb3aSMike Baucom 	pos += tmp;
21388badb3aSMike Baucom 
21488badb3aSMike Baucom 	for (i = 1; i < cnt; i++) {
21588badb3aSMike Baucom 		ulp_bs_put_msb(bs, pos, 8, val[i]);
21688badb3aSMike Baucom 		pos += 8;
21788badb3aSMike Baucom 	}
21888badb3aSMike Baucom 
21988badb3aSMike Baucom 	return len;
22088badb3aSMike Baucom }
22188badb3aSMike Baucom 
22288badb3aSMike Baucom /*
22388badb3aSMike Baucom  * Initializes the blob structure for creating binary blob
22488badb3aSMike Baucom  *
22588badb3aSMike Baucom  * blob [in] The blob to be initialized
22688badb3aSMike Baucom  *
22788badb3aSMike Baucom  * bitlen [in] The bit length of the blob
22888badb3aSMike Baucom  *
22988badb3aSMike Baucom  * order [in] The byte order for the blob.  Currently only supporting
23088badb3aSMike Baucom  * big endian.  All fields are packed with this order.
23188badb3aSMike Baucom  *
232*c569279aSShuanglin Wang  * returns zero on success
2333fe124d2SKishore Padmanabha  * Notes - If bitlen is zero then set it to max.
23488badb3aSMike Baucom  */
235*c569279aSShuanglin Wang int32_t
23688badb3aSMike Baucom ulp_blob_init(struct ulp_blob *blob,
23788badb3aSMike Baucom 	      uint16_t bitlen,
23888badb3aSMike Baucom 	      enum bnxt_ulp_byte_order order)
23988badb3aSMike Baucom {
24088badb3aSMike Baucom 	/* validate the arguments */
24188badb3aSMike Baucom 	if (!blob || bitlen > (8 * sizeof(blob->data))) {
242dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
243*c569279aSShuanglin Wang 		return -EINVAL;
24488badb3aSMike Baucom 	}
2453fe124d2SKishore Padmanabha 	if (bitlen)
24688badb3aSMike Baucom 		blob->bitlen = bitlen;
2473fe124d2SKishore Padmanabha 	else
2483fe124d2SKishore Padmanabha 		blob->bitlen = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
24988badb3aSMike Baucom 	blob->byte_order = order;
25088badb3aSMike Baucom 	blob->write_idx = 0;
25188badb3aSMike Baucom 	memset(blob->data, 0, sizeof(blob->data));
252*c569279aSShuanglin Wang 	return 0; /* Success */
25388badb3aSMike Baucom }
25488badb3aSMike Baucom 
25588badb3aSMike Baucom /*
25688badb3aSMike Baucom  * Add data to the binary blob at the current offset.
25788badb3aSMike Baucom  *
25888badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
25988badb3aSMike Baucom  * be initialized prior to pushing data.
26088badb3aSMike Baucom  *
26188badb3aSMike Baucom  * data [in] A pointer to bytes to be added to the blob.
26288badb3aSMike Baucom  *
26388badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
26488badb3aSMike Baucom  *
26588badb3aSMike Baucom  * The offset of the data is updated after each push of data.
266*c569279aSShuanglin Wang  *
267*c569279aSShuanglin Wang  * returns zero on success
26888badb3aSMike Baucom  */
26988badb3aSMike Baucom #define ULP_BLOB_BYTE		8
27088badb3aSMike Baucom #define ULP_BLOB_BYTE_HEX	0xFF
27188badb3aSMike Baucom #define BLOB_MASK_CAL(x)	((0xFF << (x)) & 0xFF)
272*c569279aSShuanglin Wang int32_t
27388badb3aSMike Baucom ulp_blob_push(struct ulp_blob *blob,
27488badb3aSMike Baucom 	      uint8_t *data,
27588badb3aSMike Baucom 	      uint32_t datalen)
27688badb3aSMike Baucom {
27788badb3aSMike Baucom 	uint32_t rc;
27888badb3aSMike Baucom 
27988badb3aSMike Baucom 	/* validate the arguments */
28088badb3aSMike Baucom 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
281dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
282*c569279aSShuanglin Wang 		return -EINVAL;
28388badb3aSMike Baucom 	}
28488badb3aSMike Baucom 
28588badb3aSMike Baucom 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
28688badb3aSMike Baucom 		rc = ulp_bs_push_msb(blob->data,
28788badb3aSMike Baucom 				     blob->write_idx,
28888badb3aSMike Baucom 				     datalen,
28988badb3aSMike Baucom 				     data);
29088badb3aSMike Baucom 	else
29188badb3aSMike Baucom 		rc = ulp_bs_push_lsb(blob->data,
29288badb3aSMike Baucom 				     blob->write_idx,
29388badb3aSMike Baucom 				     datalen,
29488badb3aSMike Baucom 				     data);
29588badb3aSMike Baucom 	if (!rc) {
296dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to write blob\n");
297*c569279aSShuanglin Wang 		return -EINVAL;
29888badb3aSMike Baucom 	}
29988badb3aSMike Baucom 	blob->write_idx += datalen;
300*c569279aSShuanglin Wang 	return 0;
30188badb3aSMike Baucom }
30288badb3aSMike Baucom 
30388badb3aSMike Baucom /*
3047e604e7fSKishore Padmanabha  * Insert data into the binary blob at the given offset.
3057e604e7fSKishore Padmanabha  *
3067e604e7fSKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
3077e604e7fSKishore Padmanabha  * be initialized prior to pushing data.
3087e604e7fSKishore Padmanabha  *
3097e604e7fSKishore Padmanabha  * offset [in] The offset where the data needs to be inserted.
3107e604e7fSKishore Padmanabha  *
3117e604e7fSKishore Padmanabha  * data [in/out] A pointer to bytes to be added to the blob.
3127e604e7fSKishore Padmanabha  *
3137e604e7fSKishore Padmanabha  * datalen [in] The number of bits to be added to the blob.
3147e604e7fSKishore Padmanabha  *
3157e604e7fSKishore Padmanabha  * The offset of the data is updated after each push of data.
316*c569279aSShuanglin Wang  *
317*c569279aSShuanglin Wang  * returns zero on success
3187e604e7fSKishore Padmanabha  */
319*c569279aSShuanglin Wang int32_t
3207e604e7fSKishore Padmanabha ulp_blob_insert(struct ulp_blob *blob, uint32_t offset,
3217e604e7fSKishore Padmanabha 		uint8_t *data, uint32_t datalen)
3227e604e7fSKishore Padmanabha {
3237e604e7fSKishore Padmanabha 	uint32_t rc;
3247e604e7fSKishore Padmanabha 	uint8_t local_data[BNXT_ULP_FLMP_BLOB_SIZE];
3257e604e7fSKishore Padmanabha 	uint16_t mov_len;
3267e604e7fSKishore Padmanabha 
3277e604e7fSKishore Padmanabha 	/* validate the arguments */
3287e604e7fSKishore Padmanabha 	if (!blob || datalen > (uint32_t)(blob->bitlen - blob->write_idx) ||
3297e604e7fSKishore Padmanabha 	    offset > blob->write_idx) {
330dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
331*c569279aSShuanglin Wang 		return -EINVAL;
3327e604e7fSKishore Padmanabha 	}
3337e604e7fSKishore Padmanabha 
3347e604e7fSKishore Padmanabha 	mov_len = blob->write_idx - offset;
3357e604e7fSKishore Padmanabha 	/* If offset and data len are not 8 bit aligned then return error */
3367e604e7fSKishore Padmanabha 	if (ULP_BITS_IS_BYTE_NOT_ALIGNED(offset) ||
3377e604e7fSKishore Padmanabha 	    ULP_BITS_IS_BYTE_NOT_ALIGNED(datalen)) {
338dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument, not aligned\n");
339*c569279aSShuanglin Wang 		return -EINVAL;
3407e604e7fSKishore Padmanabha 	}
3417e604e7fSKishore Padmanabha 
3427e604e7fSKishore Padmanabha 	/* copy the data so we can move the data */
3437e604e7fSKishore Padmanabha 	memcpy(local_data, &blob->data[ULP_BITS_2_BYTE_NR(offset)],
3447e604e7fSKishore Padmanabha 	       ULP_BITS_2_BYTE(mov_len));
3457e604e7fSKishore Padmanabha 	blob->write_idx = offset;
3467e604e7fSKishore Padmanabha 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
3477e604e7fSKishore Padmanabha 		rc = ulp_bs_push_msb(blob->data,
3487e604e7fSKishore Padmanabha 				     blob->write_idx,
3497e604e7fSKishore Padmanabha 				     datalen,
3507e604e7fSKishore Padmanabha 				     data);
3517e604e7fSKishore Padmanabha 	else
3527e604e7fSKishore Padmanabha 		rc = ulp_bs_push_lsb(blob->data,
3537e604e7fSKishore Padmanabha 				     blob->write_idx,
3547e604e7fSKishore Padmanabha 				     datalen,
3557e604e7fSKishore Padmanabha 				     data);
3567e604e7fSKishore Padmanabha 	if (!rc) {
357dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to write blob\n");
358*c569279aSShuanglin Wang 		return -EINVAL;
3597e604e7fSKishore Padmanabha 	}
3607e604e7fSKishore Padmanabha 	/* copy the previously stored data */
3617e604e7fSKishore Padmanabha 	memcpy(&blob->data[ULP_BITS_2_BYTE_NR(offset + datalen)], local_data,
3627e604e7fSKishore Padmanabha 	       ULP_BITS_2_BYTE(mov_len));
3637e604e7fSKishore Padmanabha 	blob->write_idx += (mov_len + datalen);
364*c569279aSShuanglin Wang 	return 0;
3657e604e7fSKishore Padmanabha }
3667e604e7fSKishore Padmanabha 
3677e604e7fSKishore Padmanabha /*
36888badb3aSMike Baucom  * Add data to the binary blob at the current offset.
36988badb3aSMike Baucom  *
37088badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
37188badb3aSMike Baucom  * be initialized prior to pushing data.
37288badb3aSMike Baucom  *
37388badb3aSMike Baucom  * data [in] 64-bit value to be added to the blob.
37488badb3aSMike Baucom  *
37588badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
37688badb3aSMike Baucom  *
37788badb3aSMike Baucom  * The offset of the data is updated after each push of data.
37888badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
37988badb3aSMike Baucom  */
38088badb3aSMike Baucom uint8_t *
38188badb3aSMike Baucom ulp_blob_push_64(struct ulp_blob *blob,
38288badb3aSMike Baucom 		 uint64_t *data,
38388badb3aSMike Baucom 		 uint32_t datalen)
38488badb3aSMike Baucom {
38588badb3aSMike Baucom 	uint8_t *val = (uint8_t *)data;
38688badb3aSMike Baucom 	int rc;
38788badb3aSMike Baucom 
38888badb3aSMike Baucom 	int size = (datalen + 7) / 8;
38988badb3aSMike Baucom 
39088badb3aSMike Baucom 	if (!blob || !data ||
39188badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
392dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
393*c569279aSShuanglin Wang 		return NULL;
39488badb3aSMike Baucom 	}
39588badb3aSMike Baucom 
39688badb3aSMike Baucom 	rc = ulp_blob_push(blob, &val[8 - size], datalen);
397*c569279aSShuanglin Wang 	if (rc)
398*c569279aSShuanglin Wang 		return NULL;
39988badb3aSMike Baucom 
40088badb3aSMike Baucom 	return &val[8 - size];
40188badb3aSMike Baucom }
40288badb3aSMike Baucom 
40388badb3aSMike Baucom /*
404a2be13e1SKishore Padmanabha  * Add data to the binary blob at the current offset.
405a2be13e1SKishore Padmanabha  *
406a2be13e1SKishore Padmanabha  * blob [in] The blob that data is added to.  The blob must
407a2be13e1SKishore Padmanabha  * be initialized prior to pushing data.
408a2be13e1SKishore Padmanabha  *
409a2be13e1SKishore Padmanabha  * data [in] 32-bit value to be added to the blob.
410a2be13e1SKishore Padmanabha  *
411f63aa27dSKishore Padmanabha  * datalen [in] The number of bits to be added to the blob.
412a2be13e1SKishore Padmanabha  *
413a2be13e1SKishore Padmanabha  * The offset of the data is updated after each push of data.
414a2be13e1SKishore Padmanabha  * NULL returned on error, pointer pushed value otherwise.
415a2be13e1SKishore Padmanabha  */
416a2be13e1SKishore Padmanabha uint8_t *
417a2be13e1SKishore Padmanabha ulp_blob_push_32(struct ulp_blob *blob,
418a2be13e1SKishore Padmanabha 		 uint32_t *data,
419a2be13e1SKishore Padmanabha 		 uint32_t datalen)
420a2be13e1SKishore Padmanabha {
421a2be13e1SKishore Padmanabha 	uint8_t *val = (uint8_t *)data;
422a2be13e1SKishore Padmanabha 	uint32_t rc;
423a2be13e1SKishore Padmanabha 	uint32_t size = ULP_BITS_2_BYTE(datalen);
424a2be13e1SKishore Padmanabha 
425a2be13e1SKishore Padmanabha 	if (!data || size > sizeof(uint32_t)) {
426dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
427*c569279aSShuanglin Wang 		return NULL;
428a2be13e1SKishore Padmanabha 	}
429a2be13e1SKishore Padmanabha 
430a2be13e1SKishore Padmanabha 	rc = ulp_blob_push(blob, &val[sizeof(uint32_t) - size], datalen);
431*c569279aSShuanglin Wang 	if (rc)
432*c569279aSShuanglin Wang 		return NULL;
433a2be13e1SKishore Padmanabha 
434a2be13e1SKishore Padmanabha 	return &val[sizeof(uint32_t) - size];
435a2be13e1SKishore Padmanabha }
436a2be13e1SKishore Padmanabha 
437a2be13e1SKishore Padmanabha /*
43888badb3aSMike Baucom  * Add encap data to the binary blob at the current offset.
43988badb3aSMike Baucom  *
44088badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
44188badb3aSMike Baucom  * be initialized prior to pushing data.
44288badb3aSMike Baucom  *
44388badb3aSMike Baucom  * data [in] value to be added to the blob.
44488badb3aSMike Baucom  *
44588badb3aSMike Baucom  * datalen [in] The number of bits to be added to the blob.
44688badb3aSMike Baucom  *
44788badb3aSMike Baucom  * The offset of the data is updated after each push of data.
44888badb3aSMike Baucom  * NULL returned on error, pointer pushed value otherwise.
44988badb3aSMike Baucom  */
450286569d5SKishore Padmanabha int32_t
45188badb3aSMike Baucom ulp_blob_push_encap(struct ulp_blob *blob,
45288badb3aSMike Baucom 		    uint8_t *data,
45388badb3aSMike Baucom 		    uint32_t datalen)
45488badb3aSMike Baucom {
45588badb3aSMike Baucom 	uint8_t		*val = (uint8_t *)data;
45688badb3aSMike Baucom 	uint32_t	initial_size, write_size = datalen;
45788badb3aSMike Baucom 	uint32_t	size = 0;
45888badb3aSMike Baucom 
45988badb3aSMike Baucom 	if (!blob || !data ||
46088badb3aSMike Baucom 	    datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
461dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
462286569d5SKishore Padmanabha 		return -1;
46388badb3aSMike Baucom 	}
46488badb3aSMike Baucom 
46588badb3aSMike Baucom 	initial_size = ULP_BYTE_2_BITS(sizeof(uint64_t)) -
46688badb3aSMike Baucom 	    (blob->write_idx % ULP_BYTE_2_BITS(sizeof(uint64_t)));
46788badb3aSMike Baucom 	while (write_size > 0) {
46888badb3aSMike Baucom 		if (initial_size && write_size > initial_size) {
46988badb3aSMike Baucom 			size = initial_size;
47088badb3aSMike Baucom 			initial_size = 0;
47188badb3aSMike Baucom 		} else if (initial_size && write_size <= initial_size) {
47288badb3aSMike Baucom 			size = write_size;
47388badb3aSMike Baucom 			initial_size = 0;
47488badb3aSMike Baucom 		} else if (write_size > ULP_BYTE_2_BITS(sizeof(uint64_t))) {
47588badb3aSMike Baucom 			size = ULP_BYTE_2_BITS(sizeof(uint64_t));
47688badb3aSMike Baucom 		} else {
47788badb3aSMike Baucom 			size = write_size;
47888badb3aSMike Baucom 		}
479*c569279aSShuanglin Wang 		if (ulp_blob_push(blob, val, size)) {
480dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "push field failed\n");
481286569d5SKishore Padmanabha 			return -1;
48288badb3aSMike Baucom 		}
48388badb3aSMike Baucom 		val += ULP_BITS_2_BYTE(size);
48488badb3aSMike Baucom 		write_size -= size;
48588badb3aSMike Baucom 	}
48688badb3aSMike Baucom 	return datalen;
48788badb3aSMike Baucom }
48888badb3aSMike Baucom 
48988badb3aSMike Baucom /*
49088badb3aSMike Baucom  * Adds pad to an initialized blob at the current offset
49188badb3aSMike Baucom  *
49288badb3aSMike Baucom  * blob [in] The blob that data is added to.  The blob must
49388badb3aSMike Baucom  * be initialized prior to pushing data.
49488badb3aSMike Baucom  *
49588badb3aSMike Baucom  * datalen [in] The number of bits of pad to add
49688badb3aSMike Baucom  *
497a4651725SMike Baucom  * returns the number of pad bits added, -1 on failure
49888badb3aSMike Baucom  */
499a4651725SMike Baucom int32_t
50088badb3aSMike Baucom ulp_blob_pad_push(struct ulp_blob *blob,
50188badb3aSMike Baucom 		  uint32_t datalen)
50288badb3aSMike Baucom {
50388badb3aSMike Baucom 	if (datalen > (uint32_t)(blob->bitlen - blob->write_idx)) {
504dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Pad too large for blob\n");
505f634204bSKishore Padmanabha 		return -1;
50688badb3aSMike Baucom 	}
50788badb3aSMike Baucom 
50888badb3aSMike Baucom 	blob->write_idx += datalen;
50988badb3aSMike Baucom 	return datalen;
51088badb3aSMike Baucom }
51188badb3aSMike Baucom 
5123fe124d2SKishore Padmanabha /*
5133fe124d2SKishore Padmanabha  * Adds pad to an initialized blob at the current offset based on
5143fe124d2SKishore Padmanabha  * the alignment.
5153fe124d2SKishore Padmanabha  *
5163fe124d2SKishore Padmanabha  * blob [in] The blob that needs to be aligned
5173fe124d2SKishore Padmanabha  *
5183fe124d2SKishore Padmanabha  * align [in] Alignment in bits.
5193fe124d2SKishore Padmanabha  *
5203fe124d2SKishore Padmanabha  * returns the number of pad bits added, -1 on failure
5213fe124d2SKishore Padmanabha  */
5223fe124d2SKishore Padmanabha int32_t
5233fe124d2SKishore Padmanabha ulp_blob_pad_align(struct ulp_blob *blob,
5243fe124d2SKishore Padmanabha 		   uint32_t align)
5253fe124d2SKishore Padmanabha {
5263fe124d2SKishore Padmanabha 	int32_t pad = 0;
5273fe124d2SKishore Padmanabha 
5283fe124d2SKishore Padmanabha 	pad = RTE_ALIGN(blob->write_idx, align) - blob->write_idx;
5293fe124d2SKishore Padmanabha 	if (pad > (int32_t)(blob->bitlen - blob->write_idx)) {
530dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Pad too large for blob\n");
5313fe124d2SKishore Padmanabha 		return -1;
5323fe124d2SKishore Padmanabha 	}
5333fe124d2SKishore Padmanabha 	blob->write_idx += pad;
5343fe124d2SKishore Padmanabha 	return pad;
5353fe124d2SKishore Padmanabha }
5363fe124d2SKishore Padmanabha 
537afd35335SKishore Padmanabha /* Get data from src and put into dst using little-endian format */
538afd35335SKishore Padmanabha static void
539afd35335SKishore Padmanabha ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
540afd35335SKishore Padmanabha {
541afd35335SKishore Padmanabha 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
542afd35335SKishore Padmanabha 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
543afd35335SKishore Padmanabha 	uint8_t mask, partial, shift;
544afd35335SKishore Padmanabha 
545afd35335SKishore Padmanabha 	shift = bitoffs;
546afd35335SKishore Padmanabha 	partial = ULP_BLOB_BYTE - bitoffs;
547afd35335SKishore Padmanabha 	if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
548afd35335SKishore Padmanabha 		mask = ((1 << bitlen) - 1) << shift;
549afd35335SKishore Padmanabha 		*dst = (src[index] & mask) >> shift;
550afd35335SKishore Padmanabha 	} else {
551afd35335SKishore Padmanabha 		mask = ((1 << partial) - 1) << shift;
552afd35335SKishore Padmanabha 		*dst = (src[index] & mask) >> shift;
553afd35335SKishore Padmanabha 		index++;
554afd35335SKishore Padmanabha 		partial = bitlen - partial;
555afd35335SKishore Padmanabha 		mask = ((1 << partial) - 1);
556afd35335SKishore Padmanabha 		*dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
557afd35335SKishore Padmanabha 	}
558afd35335SKishore Padmanabha }
559afd35335SKishore Padmanabha 
560f634204bSKishore Padmanabha /*
561f634204bSKishore Padmanabha  * Get data from the byte array in Little endian format.
562f634204bSKishore Padmanabha  *
563f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
564f634204bSKishore Padmanabha  *
565f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
566f634204bSKishore Padmanabha  *
567f634204bSKishore Padmanabha  * size [in] The size of dst array in bytes
568f634204bSKishore Padmanabha  *
569f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
570f634204bSKishore Padmanabha  *
571f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
572f634204bSKishore Padmanabha  *
573f634204bSKishore Padmanabha  * returns None.
574f634204bSKishore Padmanabha  */
575f634204bSKishore Padmanabha void
576afd35335SKishore Padmanabha ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
577afd35335SKishore Padmanabha 		uint32_t offset, uint32_t len)
578afd35335SKishore Padmanabha {
579afd35335SKishore Padmanabha 	uint32_t idx;
580afd35335SKishore Padmanabha 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
581afd35335SKishore Padmanabha 
582afd35335SKishore Padmanabha 	/* iterate bytewise to get data */
583afd35335SKishore Padmanabha 	for (idx = 0; idx < cnt; idx++) {
584afd35335SKishore Padmanabha 		ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
585afd35335SKishore Padmanabha 			       &dst[size - 1 - idx]);
586afd35335SKishore Padmanabha 		offset += ULP_BLOB_BYTE;
587afd35335SKishore Padmanabha 		len -= ULP_BLOB_BYTE;
588afd35335SKishore Padmanabha 	}
589afd35335SKishore Padmanabha 
590afd35335SKishore Padmanabha 	/* Extract the last reminder data that is not 8 byte boundary */
591afd35335SKishore Padmanabha 	if (len)
592afd35335SKishore Padmanabha 		ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
593afd35335SKishore Padmanabha }
594afd35335SKishore Padmanabha 
595f634204bSKishore Padmanabha /* Get data from src and put into dst using big-endian format */
596f634204bSKishore Padmanabha static void
597f634204bSKishore Padmanabha ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
598f634204bSKishore Padmanabha {
599f634204bSKishore Padmanabha 	uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
600f634204bSKishore Padmanabha 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
601f634204bSKishore Padmanabha 	uint8_t mask;
602f634204bSKishore Padmanabha 	int32_t shift;
603f634204bSKishore Padmanabha 
604f634204bSKishore Padmanabha 	shift = ULP_BLOB_BYTE - bitoffs - bitlen;
605f634204bSKishore Padmanabha 	if (shift >= 0) {
606f634204bSKishore Padmanabha 		mask = 0xFF >> -bitlen;
607f634204bSKishore Padmanabha 		*dst = (src[index] >> shift) & mask;
608f634204bSKishore Padmanabha 	} else {
609f634204bSKishore Padmanabha 		*dst = (src[index] & (0xFF >> bitoffs)) << -shift;
610f634204bSKishore Padmanabha 		*dst |= src[index + 1] >> -shift;
611f634204bSKishore Padmanabha 	}
612f634204bSKishore Padmanabha }
613f634204bSKishore Padmanabha 
614f634204bSKishore Padmanabha /*
615f634204bSKishore Padmanabha  * Get data from the byte array in Big endian format.
616f634204bSKishore Padmanabha  *
617f634204bSKishore Padmanabha  * src [in] The byte array where data is extracted from
618f634204bSKishore Padmanabha  *
619f634204bSKishore Padmanabha  * dst [out] The byte array where data is pulled into
620f634204bSKishore Padmanabha  *
621f634204bSKishore Padmanabha  * offset [in] The offset where data is pulled
622f634204bSKishore Padmanabha  *
623f634204bSKishore Padmanabha  * len [in] The number of bits to be extracted from the data array
624f634204bSKishore Padmanabha  *
625f634204bSKishore Padmanabha  * returns None.
626f634204bSKishore Padmanabha  */
627f634204bSKishore Padmanabha void
628f634204bSKishore Padmanabha ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
629f634204bSKishore Padmanabha 		uint32_t offset, uint32_t len)
630f634204bSKishore Padmanabha {
631f634204bSKishore Padmanabha 	uint32_t idx;
632f634204bSKishore Padmanabha 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
633f634204bSKishore Padmanabha 
634f634204bSKishore Padmanabha 	/* iterate bytewise to get data */
635f634204bSKishore Padmanabha 	for (idx = 0; idx < cnt; idx++) {
636f634204bSKishore Padmanabha 		ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
637f634204bSKishore Padmanabha 		offset += ULP_BLOB_BYTE;
638f634204bSKishore Padmanabha 		len -= ULP_BLOB_BYTE;
639f634204bSKishore Padmanabha 	}
640f634204bSKishore Padmanabha 
641f634204bSKishore Padmanabha 	/* Extract the last reminder data that is not 8 byte boundary */
642f634204bSKishore Padmanabha 	if (len)
643f634204bSKishore Padmanabha 		ulp_bs_get_msb(src, offset, len, &dst[idx]);
644f634204bSKishore Padmanabha }
645f634204bSKishore Padmanabha 
646afd35335SKishore Padmanabha /*
647afd35335SKishore Padmanabha  * Extract data from the binary blob using given offset.
648afd35335SKishore Padmanabha  *
649afd35335SKishore Padmanabha  * blob [in] The blob that data is extracted from. The blob must
650afd35335SKishore Padmanabha  * be initialized prior to pulling data.
651afd35335SKishore Padmanabha  *
652afd35335SKishore Padmanabha  * data [in] A pointer to put the data.
653afd35335SKishore Padmanabha  * data_size [in] size of the data buffer in bytes.
654afd35335SKishore Padmanabha  *offset [in] - Offset in the blob to extract the data in bits format.
655afd35335SKishore Padmanabha  * len [in] The number of bits to be pulled from the blob.
656afd35335SKishore Padmanabha  *
657afd35335SKishore Padmanabha  * Output: zero on success, -1 on failure
658afd35335SKishore Padmanabha  */
659afd35335SKishore Padmanabha int32_t
660afd35335SKishore Padmanabha ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
661afd35335SKishore Padmanabha 	      uint16_t offset, uint16_t len)
662afd35335SKishore Padmanabha {
663afd35335SKishore Padmanabha 	/* validate the arguments */
664afd35335SKishore Padmanabha 	if (!blob || (offset + len) > blob->bitlen ||
665afd35335SKishore Padmanabha 	    ULP_BYTE_2_BITS(data_size) < len) {
666dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
667afd35335SKishore Padmanabha 		return -1; /* failure */
668afd35335SKishore Padmanabha 	}
669afd35335SKishore Padmanabha 
670f634204bSKishore Padmanabha 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
671f634204bSKishore Padmanabha 		ulp_bs_pull_msb(blob->data, data, offset, len);
672f634204bSKishore Padmanabha 	else
673afd35335SKishore Padmanabha 		ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
674afd35335SKishore Padmanabha 	return 0;
675afd35335SKishore Padmanabha }
676afd35335SKishore Padmanabha 
67788badb3aSMike Baucom /*
67888badb3aSMike Baucom  * Get the data portion of the binary blob.
67988badb3aSMike Baucom  *
68088badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
68188badb3aSMike Baucom  * initialized prior to pushing data.
68288badb3aSMike Baucom  *
683dd0191d5SShuanglin Wang  * datalen [out] The number of bits that are filled.
68488badb3aSMike Baucom  *
685dd0191d5SShuanglin Wang  * Returns a byte array of the blob data or NULL on error.
68688badb3aSMike Baucom  */
68788badb3aSMike Baucom uint8_t *
68888badb3aSMike Baucom ulp_blob_data_get(struct ulp_blob *blob,
68988badb3aSMike Baucom 		  uint16_t *datalen)
69088badb3aSMike Baucom {
69188badb3aSMike Baucom 	/* validate the arguments */
69288badb3aSMike Baucom 	if (!blob) {
693dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
69488badb3aSMike Baucom 		return NULL; /* failure */
69588badb3aSMike Baucom 	}
69688badb3aSMike Baucom 	*datalen = blob->write_idx;
69788badb3aSMike Baucom 	return blob->data;
69888badb3aSMike Baucom }
69988badb3aSMike Baucom 
70088badb3aSMike Baucom /*
7013fe124d2SKishore Padmanabha  * Get the data length of the binary blob.
7023fe124d2SKishore Padmanabha  *
7033fe124d2SKishore Padmanabha  * blob [in] The blob's data len to be retrieved.
7043fe124d2SKishore Padmanabha  *
7053fe124d2SKishore Padmanabha  * returns length of the binary blob
7063fe124d2SKishore Padmanabha  */
7073fe124d2SKishore Padmanabha uint16_t
7083fe124d2SKishore Padmanabha ulp_blob_data_len_get(struct ulp_blob *blob)
7093fe124d2SKishore Padmanabha {
7103fe124d2SKishore Padmanabha 	/* validate the arguments */
7113fe124d2SKishore Padmanabha 	if (!blob) {
712dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
7133fe124d2SKishore Padmanabha 		return 0; /* failure */
7143fe124d2SKishore Padmanabha 	}
7153fe124d2SKishore Padmanabha 	return blob->write_idx;
7163fe124d2SKishore Padmanabha }
7173fe124d2SKishore Padmanabha 
7183fe124d2SKishore Padmanabha /*
71988badb3aSMike Baucom  * Set the encap swap start index of the binary blob.
72088badb3aSMike Baucom  *
72188badb3aSMike Baucom  * blob [in] The blob's data to be retrieved. The blob must be
72288badb3aSMike Baucom  * initialized prior to pushing data.
72388badb3aSMike Baucom  *
72488badb3aSMike Baucom  * returns void.
72588badb3aSMike Baucom  */
72688badb3aSMike Baucom void
72788badb3aSMike Baucom ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
72888badb3aSMike Baucom {
72988badb3aSMike Baucom 	/* validate the arguments */
73088badb3aSMike Baucom 	if (!blob) {
731dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
73288badb3aSMike Baucom 		return; /* failure */
73388badb3aSMike Baucom 	}
73488badb3aSMike Baucom 	blob->encap_swap_idx = blob->write_idx;
73588badb3aSMike Baucom }
73688badb3aSMike Baucom 
73788badb3aSMike Baucom /*
73888badb3aSMike Baucom  * Perform the encap buffer swap to 64 bit reversal.
73988badb3aSMike Baucom  *
74088badb3aSMike Baucom  * blob [in] The blob's data to be used for swap.
74188badb3aSMike Baucom  *
74288badb3aSMike Baucom  * returns void.
74388badb3aSMike Baucom  */
74488badb3aSMike Baucom void
74588badb3aSMike Baucom ulp_blob_perform_encap_swap(struct ulp_blob *blob)
74688badb3aSMike Baucom {
7479238ac2aSKishore Padmanabha 	uint32_t i, idx = 0, end_idx = 0, roundoff;
74888badb3aSMike Baucom 	uint8_t temp_val_1, temp_val_2;
74988badb3aSMike Baucom 
75088badb3aSMike Baucom 	/* validate the arguments */
75188badb3aSMike Baucom 	if (!blob) {
752dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
75388badb3aSMike Baucom 		return; /* failure */
75488badb3aSMike Baucom 	}
755f0ca77fdSMike Baucom 	idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
75688badb3aSMike Baucom 	end_idx = ULP_BITS_2_BYTE(blob->write_idx);
7579238ac2aSKishore Padmanabha 	roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
7589238ac2aSKishore Padmanabha 	if (roundoff > end_idx) {
7599238ac2aSKishore Padmanabha 		blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
7609238ac2aSKishore Padmanabha 		end_idx = roundoff;
7619238ac2aSKishore Padmanabha 	}
76288badb3aSMike Baucom 	while (idx <= end_idx) {
76388badb3aSMike Baucom 		for (i = 0; i < 4; i = i + 2) {
76488badb3aSMike Baucom 			temp_val_1 = blob->data[idx + i];
76588badb3aSMike Baucom 			temp_val_2 = blob->data[idx + i + 1];
76688badb3aSMike Baucom 			blob->data[idx + i] = blob->data[idx + 6 - i];
76788badb3aSMike Baucom 			blob->data[idx + i + 1] = blob->data[idx + 7 - i];
76888badb3aSMike Baucom 			blob->data[idx + 7 - i] = temp_val_2;
76988badb3aSMike Baucom 			blob->data[idx + 6 - i] = temp_val_1;
77088badb3aSMike Baucom 		}
77188badb3aSMike Baucom 		idx += 8;
77288badb3aSMike Baucom 	}
77388badb3aSMike Baucom }
77488badb3aSMike Baucom 
77588badb3aSMike Baucom /*
776a4651725SMike Baucom  * Perform the blob buffer reversal byte wise.
777a4651725SMike Baucom  * This api makes the first byte the last and
778a4651725SMike Baucom  * vice-versa.
779a4651725SMike Baucom  *
780a4651725SMike Baucom  * blob [in] The blob's data to be used for swap.
7813fe124d2SKishore Padmanabha  * chunk_size[in] the swap is done within the chunk in bytes
782a4651725SMike Baucom  *
783a4651725SMike Baucom  * returns void.
784a4651725SMike Baucom  */
785a4651725SMike Baucom void
7863fe124d2SKishore Padmanabha ulp_blob_perform_byte_reverse(struct ulp_blob *blob,
7873fe124d2SKishore Padmanabha 			      uint32_t chunk_size)
788a4651725SMike Baucom {
7893fe124d2SKishore Padmanabha 	uint32_t idx = 0, jdx = 0, num = 0;
790a4651725SMike Baucom 	uint8_t xchar;
7913fe124d2SKishore Padmanabha 	uint8_t *buff;
792a4651725SMike Baucom 
793a4651725SMike Baucom 	/* validate the arguments */
794a4651725SMike Baucom 	if (!blob) {
795dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
796a4651725SMike Baucom 		return; /* failure */
797a4651725SMike Baucom 	}
798a4651725SMike Baucom 
7993fe124d2SKishore Padmanabha 	buff = blob->data;
8003fe124d2SKishore Padmanabha 	num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size;
8013fe124d2SKishore Padmanabha 	for (idx = 0; idx < num; idx++) {
8023fe124d2SKishore Padmanabha 		for (jdx = 0; jdx < chunk_size / 2; jdx++) {
8033fe124d2SKishore Padmanabha 			xchar = buff[jdx];
8043fe124d2SKishore Padmanabha 			buff[jdx] = buff[(chunk_size - 1) - jdx];
8053fe124d2SKishore Padmanabha 			buff[(chunk_size - 1) - jdx] = xchar;
8063fe124d2SKishore Padmanabha 		}
8073fe124d2SKishore Padmanabha 		buff += chunk_size;
808a4651725SMike Baucom 	}
809a4651725SMike Baucom }
810a4651725SMike Baucom 
811a4651725SMike Baucom /*
8127e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit word swap.
8137e604e7fSKishore Padmanabha  * This api makes the first 4 bytes the last in
8147e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
8157e604e7fSKishore Padmanabha  *
8167e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
8177e604e7fSKishore Padmanabha  *
8187e604e7fSKishore Padmanabha  * returns void.
8197e604e7fSKishore Padmanabha  */
8207e604e7fSKishore Padmanabha void
8217e604e7fSKishore Padmanabha ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
8227e604e7fSKishore Padmanabha {
8237e604e7fSKishore Padmanabha 	uint32_t i, j, num;
8247e604e7fSKishore Padmanabha 	uint8_t xchar;
8257e604e7fSKishore Padmanabha 	uint32_t word_size = ULP_64B_IN_BYTES / 2;
8267e604e7fSKishore Padmanabha 
8277e604e7fSKishore Padmanabha 	/* validate the arguments */
8287e604e7fSKishore Padmanabha 	if (!blob) {
829dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
8307e604e7fSKishore Padmanabha 		return; /* failure */
8317e604e7fSKishore Padmanabha 	}
8327e604e7fSKishore Padmanabha 	num = ULP_BITS_2_BYTE(blob->write_idx);
8337e604e7fSKishore Padmanabha 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
8347e604e7fSKishore Padmanabha 		for (j = 0; j < word_size; j++) {
8357e604e7fSKishore Padmanabha 			xchar = blob->data[i + j];
8367e604e7fSKishore Padmanabha 			blob->data[i + j] = blob->data[i + j + word_size];
8377e604e7fSKishore Padmanabha 			blob->data[i + j + word_size] = xchar;
8387e604e7fSKishore Padmanabha 		}
8397e604e7fSKishore Padmanabha 	}
8407e604e7fSKishore Padmanabha }
8417e604e7fSKishore Padmanabha 
8427e604e7fSKishore Padmanabha /*
8437e604e7fSKishore Padmanabha  * Perform the blob buffer 64 bit byte swap.
8447e604e7fSKishore Padmanabha  * This api makes the first byte the last in
8457e604e7fSKishore Padmanabha  * a given 64 bit value and vice-versa.
8467e604e7fSKishore Padmanabha  *
8477e604e7fSKishore Padmanabha  * blob [in] The blob's data to be used for swap.
8487e604e7fSKishore Padmanabha  *
8497e604e7fSKishore Padmanabha  * returns void.
8507e604e7fSKishore Padmanabha  */
8517e604e7fSKishore Padmanabha void
8527e604e7fSKishore Padmanabha ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
8537e604e7fSKishore Padmanabha {
8547e604e7fSKishore Padmanabha 	uint32_t i, j, num;
8557e604e7fSKishore Padmanabha 	uint8_t xchar;
8567e604e7fSKishore Padmanabha 	uint32_t offset = ULP_64B_IN_BYTES - 1;
8577e604e7fSKishore Padmanabha 
8587e604e7fSKishore Padmanabha 	/* validate the arguments */
8597e604e7fSKishore Padmanabha 	if (!blob) {
860dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
8617e604e7fSKishore Padmanabha 		return; /* failure */
8627e604e7fSKishore Padmanabha 	}
8637e604e7fSKishore Padmanabha 	num = ULP_BITS_2_BYTE(blob->write_idx);
8647e604e7fSKishore Padmanabha 	for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
8657e604e7fSKishore Padmanabha 		for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
8667e604e7fSKishore Padmanabha 			xchar = blob->data[i + j];
8677e604e7fSKishore Padmanabha 			blob->data[i + j] = blob->data[i + offset - j];
8687e604e7fSKishore Padmanabha 			blob->data[i + offset - j] = xchar;
8697e604e7fSKishore Padmanabha 		}
8707e604e7fSKishore Padmanabha 	}
8717e604e7fSKishore Padmanabha }
8727e604e7fSKishore Padmanabha 
8733fe124d2SKishore Padmanabha static int32_t
8743fe124d2SKishore Padmanabha ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
8753fe124d2SKishore Padmanabha 			 uint32_t block_size, uint32_t pad)
8763fe124d2SKishore Padmanabha {
8773fe124d2SKishore Padmanabha 	uint32_t i, k, write_bytes, remaining;
8783fe124d2SKishore Padmanabha 	uint16_t num;
8793fe124d2SKishore Padmanabha 	uint8_t *src_buf = ulp_blob_data_get(src, &num);
8803fe124d2SKishore Padmanabha 	uint8_t bluff;
8813fe124d2SKishore Padmanabha 
8823fe124d2SKishore Padmanabha 	for (i = 0; i < num;) {
8833fe124d2SKishore Padmanabha 		if (((dst->write_idx % block_size) + (num - i)) > block_size)
884dbd29c42SKishore Padmanabha 			write_bytes = block_size -
885dbd29c42SKishore Padmanabha 				(dst->write_idx % block_size);
8863fe124d2SKishore Padmanabha 		else
8873fe124d2SKishore Padmanabha 			write_bytes = num - i;
8883fe124d2SKishore Padmanabha 		for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) {
8893fe124d2SKishore Padmanabha 			ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
8903fe124d2SKishore Padmanabha 				       *src_buf);
8913fe124d2SKishore Padmanabha 			dst->write_idx += ULP_BLOB_BYTE;
8923fe124d2SKishore Padmanabha 			src_buf++;
8933fe124d2SKishore Padmanabha 		}
8943fe124d2SKishore Padmanabha 		remaining = write_bytes % ULP_BLOB_BYTE;
8953fe124d2SKishore Padmanabha 		if (remaining) {
8963fe124d2SKishore Padmanabha 			bluff = (*src_buf) & ((uint8_t)-1 <<
8973fe124d2SKishore Padmanabha 					      (ULP_BLOB_BYTE - remaining));
8983fe124d2SKishore Padmanabha 			ulp_bs_put_msb(dst->data, dst->write_idx,
8993fe124d2SKishore Padmanabha 				       ULP_BLOB_BYTE, bluff);
9003fe124d2SKishore Padmanabha 			dst->write_idx += remaining;
9013fe124d2SKishore Padmanabha 		}
9023fe124d2SKishore Padmanabha 		if (write_bytes != (num - i)) {
9033fe124d2SKishore Padmanabha 			/* add the padding */
9043fe124d2SKishore Padmanabha 			ulp_blob_pad_push(dst, pad);
9053fe124d2SKishore Padmanabha 			if (remaining) {
9063fe124d2SKishore Padmanabha 				ulp_bs_put_msb(dst->data, dst->write_idx,
9073fe124d2SKishore Padmanabha 					       ULP_BLOB_BYTE - remaining,
9083fe124d2SKishore Padmanabha 					       *src_buf);
9093fe124d2SKishore Padmanabha 				dst->write_idx += ULP_BLOB_BYTE - remaining;
9103fe124d2SKishore Padmanabha 				src_buf++;
9113fe124d2SKishore Padmanabha 			}
9123fe124d2SKishore Padmanabha 		}
9133fe124d2SKishore Padmanabha 		i += write_bytes;
9143fe124d2SKishore Padmanabha 	}
9153fe124d2SKishore Padmanabha 	return 0;
9163fe124d2SKishore Padmanabha }
9173fe124d2SKishore Padmanabha 
9183fe124d2SKishore Padmanabha /*
9193fe124d2SKishore Padmanabha  * Perform the blob buffer merge.
9203fe124d2SKishore Padmanabha  * This api makes the src blob merged to the dst blob.
9213fe124d2SKishore Padmanabha  * The block size and pad size help in padding the dst blob
9223fe124d2SKishore Padmanabha  *
9233fe124d2SKishore Padmanabha  * dst [in] The destination blob, the blob to be merged.
9243fe124d2SKishore Padmanabha  * src [in] The src blob.
925dd0191d5SShuanglin Wang  * block_size [in] The size of the block in bytes after which padding gets
926dd0191d5SShuanglin Wang  *                 applied.
9273fe124d2SKishore Padmanabha  * pad [in] The size of the pad to be applied.
9283fe124d2SKishore Padmanabha  *
9293fe124d2SKishore Padmanabha  * returns 0 on success.
9303fe124d2SKishore Padmanabha  */
9313fe124d2SKishore Padmanabha int32_t
9323fe124d2SKishore Padmanabha ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
9333fe124d2SKishore Padmanabha 		     uint32_t block_size, uint32_t pad)
9343fe124d2SKishore Padmanabha {
9353fe124d2SKishore Padmanabha 	if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE &&
9363fe124d2SKishore Padmanabha 	    src->byte_order == BNXT_ULP_BYTE_ORDER_BE)
9373fe124d2SKishore Padmanabha 		return ulp_blob_msb_block_merge(dst, src, block_size, pad);
9383fe124d2SKishore Padmanabha 
939dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(ERR, "block merge not implemented yet\n");
9403fe124d2SKishore Padmanabha 	return -EINVAL;
9413fe124d2SKishore Padmanabha }
9423fe124d2SKishore Padmanabha 
9433fe124d2SKishore Padmanabha int32_t
9443fe124d2SKishore Padmanabha ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src,
9453fe124d2SKishore Padmanabha 		uint16_t src_offset, uint16_t src_len)
9463fe124d2SKishore Padmanabha {
947dd0191d5SShuanglin Wang 	uint32_t k, remaining = 0;
9483fe124d2SKishore Padmanabha 	uint16_t num;
9493fe124d2SKishore Padmanabha 	uint8_t bluff;
9503fe124d2SKishore Padmanabha 	uint8_t *src_buf = ulp_blob_data_get(src, &num);
9513fe124d2SKishore Padmanabha 
9523fe124d2SKishore Padmanabha 	if ((src_offset + src_len) > num)
9533fe124d2SKishore Padmanabha 		return -EINVAL;
9543fe124d2SKishore Padmanabha 
9553fe124d2SKishore Padmanabha 	/* Only supporting BE for now */
9563fe124d2SKishore Padmanabha 	if (src->byte_order != BNXT_ULP_BYTE_ORDER_BE ||
9573fe124d2SKishore Padmanabha 	    dst->byte_order != BNXT_ULP_BYTE_ORDER_BE)
9583fe124d2SKishore Padmanabha 		return -EINVAL;
9593fe124d2SKishore Padmanabha 
9603fe124d2SKishore Padmanabha 	/* Handle if the source offset is not on a byte boundary */
9613fe124d2SKishore Padmanabha 	remaining = src_offset % ULP_BLOB_BYTE;
9623fe124d2SKishore Padmanabha 	if (remaining) {
9633fe124d2SKishore Padmanabha 		bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >>
9643fe124d2SKishore Padmanabha 				      (ULP_BLOB_BYTE - remaining));
9653fe124d2SKishore Padmanabha 		ulp_bs_put_msb(dst->data, dst->write_idx,
9663fe124d2SKishore Padmanabha 			       ULP_BLOB_BYTE, bluff);
9673fe124d2SKishore Padmanabha 		dst->write_idx += remaining;
9682730e7f9SKishore Padmanabha 		src_offset += remaining;
9693fe124d2SKishore Padmanabha 	}
9703fe124d2SKishore Padmanabha 
9712730e7f9SKishore Padmanabha 	src_buf += ULP_BITS_2_BYTE_NR(src_offset);
9722730e7f9SKishore Padmanabha 
9733fe124d2SKishore Padmanabha 	/* Push the byte aligned pieces */
9743fe124d2SKishore Padmanabha 	for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) {
9753fe124d2SKishore Padmanabha 		ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
9763fe124d2SKishore Padmanabha 			       *src_buf);
9773fe124d2SKishore Padmanabha 		dst->write_idx += ULP_BLOB_BYTE;
9783fe124d2SKishore Padmanabha 		src_buf++;
9793fe124d2SKishore Padmanabha 	}
9803fe124d2SKishore Padmanabha 
9813fe124d2SKishore Padmanabha 	/* Handle the remaining if length is not a byte boundary */
982dd0191d5SShuanglin Wang 	if (src_len > remaining)
983dd0191d5SShuanglin Wang 		remaining = (src_len - remaining) % ULP_BLOB_BYTE;
984dd0191d5SShuanglin Wang 	else
985dd0191d5SShuanglin Wang 		remaining = 0;
9863fe124d2SKishore Padmanabha 	if (remaining) {
9873fe124d2SKishore Padmanabha 		bluff = (*src_buf) & ((uint8_t)-1 <<
9883fe124d2SKishore Padmanabha 				      (ULP_BLOB_BYTE - remaining));
9893fe124d2SKishore Padmanabha 		ulp_bs_put_msb(dst->data, dst->write_idx,
9903fe124d2SKishore Padmanabha 			       ULP_BLOB_BYTE, bluff);
9913fe124d2SKishore Padmanabha 		dst->write_idx += remaining;
9923fe124d2SKishore Padmanabha 	}
9933fe124d2SKishore Padmanabha 
9943fe124d2SKishore Padmanabha 	return 0;
9953fe124d2SKishore Padmanabha }
9963fe124d2SKishore Padmanabha 
9977e604e7fSKishore Padmanabha /*
998f63aa27dSKishore Padmanabha  * Perform the blob buffer copy.
999f63aa27dSKishore Padmanabha  * This api makes the src blob merged to the dst blob.
1000f63aa27dSKishore Padmanabha  *
1001f63aa27dSKishore Padmanabha  * dst [in] The destination blob, the blob to be merged.
1002f63aa27dSKishore Padmanabha  * src [in] The src blob.
1003f63aa27dSKishore Padmanabha  *
1004f63aa27dSKishore Padmanabha  * returns 0 on success.
1005f63aa27dSKishore Padmanabha  */
1006f63aa27dSKishore Padmanabha int32_t
1007f63aa27dSKishore Padmanabha ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src)
1008f63aa27dSKishore Padmanabha {
1009f63aa27dSKishore Padmanabha 	if ((dst->write_idx + src->write_idx) > dst->bitlen) {
1010dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "source buffer too large\n");
1011f63aa27dSKishore Padmanabha 		return -EINVAL;
1012f63aa27dSKishore Padmanabha 	}
1013f63aa27dSKishore Padmanabha 	if (ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) ||
1014f63aa27dSKishore Padmanabha 	    ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx)) {
1015dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "source buffer is not aligned\n");
1016f63aa27dSKishore Padmanabha 		return -EINVAL;
1017f63aa27dSKishore Padmanabha 	}
1018f63aa27dSKishore Padmanabha 	memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)],
1019f63aa27dSKishore Padmanabha 	       src->data, ULP_BITS_2_BYTE_NR(src->write_idx));
1020f63aa27dSKishore Padmanabha 	dst->write_idx += src->write_idx;
1021f63aa27dSKishore Padmanabha 	return 0;
1022f63aa27dSKishore Padmanabha }
1023f63aa27dSKishore Padmanabha 
1024f63aa27dSKishore Padmanabha /*
102588badb3aSMike Baucom  * Read data from the operand
102688badb3aSMike Baucom  *
102788badb3aSMike Baucom  * operand [in] A pointer to a 16 Byte operand
102888badb3aSMike Baucom  *
102988badb3aSMike Baucom  * val [in/out] The variable to copy the operand to
103088badb3aSMike Baucom  *
103188badb3aSMike Baucom  * bytes [in] The number of bytes to read into val
103288badb3aSMike Baucom  *
1033*c569279aSShuanglin Wang  * returns zero on success.
103488badb3aSMike Baucom  */
1035*c569279aSShuanglin Wang int32_t
103688badb3aSMike Baucom ulp_operand_read(uint8_t *operand,
103788badb3aSMike Baucom 		 uint8_t *val,
103888badb3aSMike Baucom 		 uint16_t bytes)
103988badb3aSMike Baucom {
104088badb3aSMike Baucom 	/* validate the arguments */
104188badb3aSMike Baucom 	if (!operand || !val) {
1042dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
1043*c569279aSShuanglin Wang 		return -EINVAL;
104488badb3aSMike Baucom 	}
104588badb3aSMike Baucom 	memcpy(val, operand, bytes);
1046*c569279aSShuanglin Wang 	return 0;
104788badb3aSMike Baucom }
104888badb3aSMike Baucom 
104988badb3aSMike Baucom /*
105088badb3aSMike Baucom  * Check the buffer is empty
105188badb3aSMike Baucom  *
105288badb3aSMike Baucom  * buf [in] The buffer
105388badb3aSMike Baucom  * size [in] The size of the buffer
105488badb3aSMike Baucom  *
105588badb3aSMike Baucom  */
105688badb3aSMike Baucom int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size)
105788badb3aSMike Baucom {
105888badb3aSMike Baucom 	return buf[0] == 0 && !memcmp(buf, buf + 1, size - 1);
105988badb3aSMike Baucom }
10602bbcdee8SKishore Padmanabha 
10612bbcdee8SKishore Padmanabha /* Function to check if bitmap is zero.Return 1 on success */
10622bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size)
10632bbcdee8SKishore Padmanabha {
10642bbcdee8SKishore Padmanabha 	while (size-- > 0) {
10652bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
10662bbcdee8SKishore Padmanabha 			return 0;
10672bbcdee8SKishore Padmanabha 		bitmap++;
10682bbcdee8SKishore Padmanabha 	}
10692bbcdee8SKishore Padmanabha 	return 1;
10702bbcdee8SKishore Padmanabha }
10712bbcdee8SKishore Padmanabha 
10722bbcdee8SKishore Padmanabha /* Function to check if bitmap is ones. Return 1 on success */
10732bbcdee8SKishore Padmanabha uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size)
10742bbcdee8SKishore Padmanabha {
10752bbcdee8SKishore Padmanabha 	while (size-- > 0) {
10762bbcdee8SKishore Padmanabha 		if (*bitmap != 0xFF)
10772bbcdee8SKishore Padmanabha 			return 0;
10782bbcdee8SKishore Padmanabha 		bitmap++;
10792bbcdee8SKishore Padmanabha 	}
10802bbcdee8SKishore Padmanabha 	return 1;
10812bbcdee8SKishore Padmanabha }
10822bbcdee8SKishore Padmanabha 
10832bbcdee8SKishore Padmanabha /* Function to check if bitmap is not zero. Return 1 on success */
1084741172beSKishore Padmanabha uint32_t ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size)
10852bbcdee8SKishore Padmanabha {
10862bbcdee8SKishore Padmanabha 	while (size-- > 0) {
10872bbcdee8SKishore Padmanabha 		if (*bitmap != 0)
10882bbcdee8SKishore Padmanabha 			return 1;
10892bbcdee8SKishore Padmanabha 		bitmap++;
10902bbcdee8SKishore Padmanabha 	}
10912bbcdee8SKishore Padmanabha 	return 0;
10922bbcdee8SKishore Padmanabha }
10930001cc58SKishore Padmanabha 
10940001cc58SKishore Padmanabha /* returns 0 if input is power of 2 */
10950001cc58SKishore Padmanabha int32_t ulp_util_is_power_of_2(uint64_t x)
10960001cc58SKishore Padmanabha {
10970001cc58SKishore Padmanabha 	if (((x - 1) & x))
10980001cc58SKishore Padmanabha 		return -1;
10990001cc58SKishore Padmanabha 	return 0;
11000001cc58SKishore Padmanabha }
1101