/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2014-2021 Broadcom * All rights reserved. */ #ifndef _ULP_UTILS_H_ #define _ULP_UTILS_H_ #include "bnxt.h" #include "ulp_template_db_enum.h" #define ULP_BUFFER_ALIGN_8_BITS 8 #define ULP_BUFFER_ALIGN_8_BYTE 8 #define ULP_BUFFER_ALIGN_16_BYTE 16 #define ULP_BUFFER_ALIGN_64_BYTE 64 #define ULP_64B_IN_BYTES 8 /* * Macros for bitmap sets and gets * These macros can be used if the val are power of 2. */ #define ULP_BITMAP_SET(bitmap, val) ((bitmap) |= (val)) #define ULP_BITMAP_RESET(bitmap, val) ((bitmap) &= ~(val)) #define ULP_BITMAP_ISSET(bitmap, val) ((bitmap) & (val)) #define ULP_BITMAP_CMP(b1, b2) memcmp(&(b1)->bits, \ &(b2)->bits, sizeof((b1)->bits)) /* * Macros for bitmap sets and gets * These macros can be used if the val are not power of 2 and * are simple index values. */ #define ULP_INDEX_BITMAP_SIZE (sizeof(uint64_t) * 8) #define ULP_INDEX_BITMAP_CSET(i) (1UL << \ ((ULP_INDEX_BITMAP_SIZE - 1) - \ ((i) % ULP_INDEX_BITMAP_SIZE))) #define ULP_INDEX_BITMAP_SET(b, i) ((b) |= \ (1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \ ((i) % ULP_INDEX_BITMAP_SIZE)))) #define ULP_INDEX_BITMAP_RESET(b, i) ((b) &= \ (~(1UL << ((ULP_INDEX_BITMAP_SIZE - 1) - \ ((i) % ULP_INDEX_BITMAP_SIZE))))) #define ULP_INDEX_BITMAP_GET(b, i) (((b) >> \ ((ULP_INDEX_BITMAP_SIZE - 1) - \ ((i) % ULP_INDEX_BITMAP_SIZE))) & 1) #define ULP_DEVICE_PARAMS_INDEX(tid, dev_id) \ (((tid) << BNXT_ULP_LOG2_MAX_NUM_DEV) | (dev_id)) /* Macro to convert bytes to bits */ #define ULP_BYTE_2_BITS(byte_x) ((byte_x) * 8) /* Macro to convert bits to bytes */ #define ULP_BITS_2_BYTE(bits_x) (((bits_x) + 7) / 8) /* Macro to convert bits to bytes with no round off*/ #define ULP_BITS_2_BYTE_NR(bits_x) ((bits_x) / 8) /* Macro to round off to next multiple of 8*/ #define ULP_BYTE_ROUND_OFF_8(x) (((x) + 7) & ~7) /* Macro to check bits are byte aligned */ #define ULP_BITS_IS_BYTE_NOT_ALIGNED(x) ((x) % 8) /* Macros to read the computed fields */ #define ULP_COMP_FLD_IDX_RD(params, idx) \ rte_be_to_cpu_64((params)->comp_fld[(idx)]) #define ULP_COMP_FLD_IDX_WR(params, idx, val) \ ((params)->comp_fld[(idx)] = rte_cpu_to_be_64((uint64_t)(val))) /* * Making the blob statically sized to 128 bytes for now. * The blob must be initialized with ulp_blob_init prior to using. */ #define BNXT_ULP_FLMP_BLOB_SIZE (128) #define BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS ULP_BYTE_2_BITS(BNXT_ULP_FLMP_BLOB_SIZE) struct ulp_blob { enum bnxt_ulp_byte_order byte_order; uint16_t write_idx; uint16_t bitlen; uint8_t data[BNXT_ULP_FLMP_BLOB_SIZE]; uint16_t encap_swap_idx; }; /* * The data can likely be only 32 bits for now. Just size check * the data when being written. */ #define ULP_REGFILE_ENTRY_SIZE (sizeof(uint32_t)) struct ulp_regfile_entry { uint64_t data; uint32_t size; }; struct ulp_regfile { struct ulp_regfile_entry entry[BNXT_ULP_RF_IDX_LAST]; }; /* * Initialize the regfile structure for writing * * regfile [in] Ptr to a regfile instance * * returns 0 on error or 1 on success */ uint32_t ulp_regfile_init(struct ulp_regfile *regfile); /* * Read a value from the regfile * * regfile [in] The regfile instance. Must be initialized prior to being used * * field [in] The field to be read within the regfile. * * returns the byte array */ uint32_t ulp_regfile_read(struct ulp_regfile *regfile, enum bnxt_ulp_rf_idx field, uint64_t *data); /* * Write a value to the regfile * * regfile [in] The regfile instance. Must be initialized prior to being used * * field [in] The field to be written within the regfile. * * data [in] The value is written into this variable. It is going to be in the * same byte order as it was written. * * returns zero on success */ int32_t ulp_regfile_write(struct ulp_regfile *regfile, enum bnxt_ulp_rf_idx field, uint64_t data); /* * Add data to the byte array in Little endian format. * * bs [in] The byte array where data is pushed * * pos [in] The offset where data is pushed * * len [in] The number of bits to be added to the data array. * * val [in] The data to be added to the data array. * * returns the number of bits pushed. */ uint32_t ulp_bs_push_lsb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val); /* * Add data to the byte array in Big endian format. * * bs [in] The byte array where data is pushed * * pos [in] The offset where data is pushed * * len [in] The number of bits to be added to the data array. * * val [in] The data to be added to the data array. * * returns the number of bits pushed. */ uint32_t ulp_bs_push_msb(uint8_t *bs, uint16_t pos, uint8_t len, uint8_t *val); /* * Initializes the blob structure for creating binary blob * * blob [in] The blob to be initialized * * bitlen [in] The bit length of the blob * * order [in] The byte order for the blob. Currently only supporting * big endian. All fields are packed with this order. * * returns 0 on error or 1 on success */ uint32_t ulp_blob_init(struct ulp_blob *blob, uint16_t bitlen, enum bnxt_ulp_byte_order order); /* * Add data to the binary blob at the current offset. * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * data [in] A pointer to bytes to be added to the blob. * * datalen [in] The number of bits to be added to the blob. * * The offset of the data is updated after each push of data. * NULL returned on error. */ uint32_t ulp_blob_push(struct ulp_blob *blob, uint8_t *data, uint32_t datalen); /* * Insert data into the binary blob at the given offset. * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * offset [in] The offset where the data needs to be inserted. * * data [in/out] A pointer to bytes to be added to the blob. * * datalen [in] The number of bits to be added to the blob. * * The offset of the data is updated after each push of data. * NULL returned on error. */ uint32_t ulp_blob_insert(struct ulp_blob *blob, uint32_t offset, uint8_t *data, uint32_t datalen); /* * Add data to the binary blob at the current offset. * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * data [in] 64-bit value to be added to the blob. * * datalen [in] The number of bits to be added to the blob. * * The offset of the data is updated after each push of data. * NULL returned on error, ptr to pushed data otherwise */ uint8_t * ulp_blob_push_64(struct ulp_blob *blob, uint64_t *data, uint32_t datalen); /* * Add data to the binary blob at the current offset. * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * data [in] 32-bit value to be added to the blob. * * datalen [in] The number of bits to be added ot the blob. * * The offset of the data is updated after each push of data. * NULL returned on error, pointer pushed value otherwise. */ uint8_t * ulp_blob_push_32(struct ulp_blob *blob, uint32_t *data, uint32_t datalen); /* * Add encap data to the binary blob at the current offset. * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * data [in] value to be added to the blob. * * datalen [in] The number of bits to be added to the blob. * * The offset of the data is updated after each push of data. * NULL returned on error, pointer pushed value otherwise. */ int32_t ulp_blob_push_encap(struct ulp_blob *blob, uint8_t *data, uint32_t datalen); /* * Get the data portion of the binary blob. * * blob [in] The blob's data to be retrieved. The blob must be * initialized prior to pushing data. * * datalen [out] The number of bits to that are filled. * * returns a byte array of the blob data. Returns NULL on error. */ uint8_t * ulp_blob_data_get(struct ulp_blob *blob, uint16_t *datalen); /* * Get the data length of the binary blob. * * blob [in] The blob's data len to be retrieved. * * returns length of the binary blob */ uint16_t ulp_blob_data_len_get(struct ulp_blob *blob); /* * Get data from the byte array in Little endian format. * * src [in] The byte array where data is extracted from * * dst [out] The byte array where data is pulled into * * size [in] The size of dst array in bytes * * offset [in] The offset where data is pulled * * len [in] The number of bits to be extracted from the data array * * returns None. */ void ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size, uint32_t offset, uint32_t len); /* * Get data from the byte array in Big endian format. * * src [in] The byte array where data is extracted from * * dst [out] The byte array where data is pulled into * * offset [in] The offset where data is pulled * * len [in] The number of bits to be extracted from the data array * * returns None. */ void ulp_bs_pull_msb(uint8_t *src, uint8_t *dst, uint32_t offset, uint32_t len); /* * Extract data from the binary blob using given offset. * * blob [in] The blob that data is extracted from. The blob must * be initialized prior to pulling data. * * data [in] A pointer to put the data. * data_size [in] size of the data buffer in bytes. *offset [in] - Offset in the blob to extract the data in bits format. * len [in] The number of bits to be pulled from the blob. * * Output: zero on success, -1 on failure */ int32_t ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size, uint16_t offset, uint16_t len); /* * Adds pad to an initialized blob at the current offset * * blob [in] The blob that data is added to. The blob must * be initialized prior to pushing data. * * datalen [in] The number of bits of pad to add * * returns the number of pad bits added, -1 on failure */ int32_t ulp_blob_pad_push(struct ulp_blob *blob, uint32_t datalen); /* * Adds pad to an initialized blob at the current offset based on * the alignment. * * blob [in] The blob that needs to be aligned * * align [in] Alignment in bits. * * returns the number of pad bits added, -1 on failure */ int32_t ulp_blob_pad_align(struct ulp_blob *blob, uint32_t align); /* * Set the 64 bit swap start index of the binary blob. * * blob [in] The blob's data to be retrieved. The blob must be * initialized prior to pushing data. * * returns void. */ void ulp_blob_encap_swap_idx_set(struct ulp_blob *blob); /* * Perform the encap buffer swap to 64 bit reversal. * * blob [in] The blob's data to be used for swap. * * returns void. */ void ulp_blob_perform_encap_swap(struct ulp_blob *blob); /* * Perform the blob buffer reversal byte wise. * This api makes the first byte the last and * vice-versa. * * blob [in] The blob's data to be used for swap. * chunk_size[in] the swap is done within the chunk in bytes * * returns void. */ void ulp_blob_perform_byte_reverse(struct ulp_blob *blob, uint32_t chunk_size); /* * Perform the blob buffer 64 bit word swap. * This api makes the first 4 bytes the last in * a given 64 bit value and vice-versa. * * blob [in] The blob's data to be used for swap. * * returns void. */ void ulp_blob_perform_64B_word_swap(struct ulp_blob *blob); /* * Perform the blob buffer 64 bit byte swap. * This api makes the first byte the last in * a given 64 bit value and vice-versa. * * blob [in] The blob's data to be used for swap. * * returns void. */ void ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob); /* * Perform the blob buffer merge. * This api makes the src blob merged to the dst blob. * The block size and pad size help in padding the dst blob * * dst [in] The destination blob, the blob to be merged. * src [in] The src blob. * block_size [in] The size of the block after which padding gets applied. * pad [in] The size of the pad to be applied. * * returns 0 on success. */ int32_t ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src, uint32_t block_size, uint32_t pad); /* * Append bits from src blob to dst blob. * Only works on BE blobs * * dst [in/out] The destination blob to append to * * src [in] The src blob to append from * * src_offset [in] The bit offset from src to start at * * src_len [in] The number of bits to append to dst * * returns 0 on success, non-zero on error */ int32_t ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src, uint16_t src_offset, uint16_t src_len); /* * Perform the blob buffer copy. * This api makes the src blob merged to the dst blob. * * dst [in] The destination blob, the blob to be merged. * src [in] The src blob. * * returns 0 on success. */ int32_t ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src); /* * Read data from the operand * * operand [in] A pointer to a 16 Byte operand * * val [in/out] The variable to copy the operand to * * bitlen [in] The number of bits to read into val * * returns number of bits read, zero on error */ uint16_t ulp_operand_read(uint8_t *operand, uint8_t *val, uint16_t bitlen); /* * Check the buffer is empty * * buf [in] The buffer * size [in] The size of the buffer */ int32_t ulp_buffer_is_empty(const uint8_t *buf, uint32_t size); /* Function to check if bitmap is zero.Return 1 on success */ uint32_t ulp_bitmap_is_zero(uint8_t *bitmap, int32_t size); /* Function to check if bitmap is ones. Return 1 on success */ uint32_t ulp_bitmap_is_ones(uint8_t *bitmap, int32_t size); /* Function to check if bitmap is not zero. Return 1 on success */ uint32_t ulp_bitmap_notzero(const uint8_t *bitmap, int32_t size); /* returns 0 if input is power of 2 */ int32_t ulp_util_is_power_of_2(uint64_t x); #endif /* _ULP_UTILS_H_ */