net/bnxt: add locks in flow database
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_utils.c
index 3afaac6..24474e2 100644 (file)
@@ -418,6 +418,82 @@ ulp_blob_pad_push(struct ulp_blob *blob,
        return datalen;
 }
 
+/* Get data from src and put into dst using little-endian format */
+static void
+ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
+{
+       uint8_t bitoffs = bitpos % ULP_BLOB_BYTE;
+       uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
+       uint8_t mask, partial, shift;
+
+       shift = bitoffs;
+       partial = ULP_BLOB_BYTE - bitoffs;
+       if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
+               mask = ((1 << bitlen) - 1) << shift;
+               *dst = (src[index] & mask) >> shift;
+       } else {
+               mask = ((1 << partial) - 1) << shift;
+               *dst = (src[index] & mask) >> shift;
+               index++;
+               partial = bitlen - partial;
+               mask = ((1 << partial) - 1);
+               *dst |= (src[index] & mask) << (ULP_BLOB_BYTE - bitoffs);
+       }
+}
+
+/* Assuming that src is in little-Endian Format */
+static void
+ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
+               uint32_t offset, uint32_t len)
+{
+       uint32_t idx;
+       uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
+
+       /* iterate bytewise to get data */
+       for (idx = 0; idx < cnt; idx++) {
+               ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
+                              &dst[size - 1 - idx]);
+               offset += ULP_BLOB_BYTE;
+               len -= ULP_BLOB_BYTE;
+       }
+
+       /* Extract the last reminder data that is not 8 byte boundary */
+       if (len)
+               ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
+}
+
+/*
+ * 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)
+{
+       /* validate the arguments */
+       if (!blob || (offset + len) > blob->bitlen ||
+           ULP_BYTE_2_BITS(data_size) < len) {
+               BNXT_TF_DBG(ERR, "invalid argument\n");
+               return -1; /* failure */
+       }
+
+       if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE) {
+               BNXT_TF_DBG(ERR, "Big endian pull not implemented\n");
+               return -1; /* failure */
+       }
+       ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
+       return 0;
+}
+
 /*
  * Get the data portion of the binary blob.
  *
@@ -470,8 +546,8 @@ ulp_blob_encap_swap_idx_set(struct ulp_blob *blob)
 void
 ulp_blob_perform_encap_swap(struct ulp_blob *blob)
 {
-       uint32_t                i, idx = 0, end_idx = 0;
-       uint8_t         temp_val_1, temp_val_2;
+       uint32_t i, idx = 0, end_idx = 0, roundoff;
+       uint8_t temp_val_1, temp_val_2;
 
        /* validate the arguments */
        if (!blob) {
@@ -480,7 +556,11 @@ ulp_blob_perform_encap_swap(struct ulp_blob *blob)
        }
        idx = ULP_BITS_2_BYTE_NR(blob->encap_swap_idx);
        end_idx = ULP_BITS_2_BYTE(blob->write_idx);
-
+       roundoff = ULP_BYTE_2_BITS(ULP_BITS_2_BYTE(end_idx));
+       if (roundoff > end_idx) {
+               blob->write_idx += ULP_BYTE_2_BITS(roundoff - end_idx);
+               end_idx = roundoff;
+       }
        while (idx <= end_idx) {
                for (i = 0; i < 4; i = i + 2) {
                        temp_val_1 = blob->data[idx + i];
@@ -555,20 +635,35 @@ ulp_operand_read(uint8_t *operand,
  * dst [out] The destination buffer
  * src [in] The source buffer dst
  * size[in] size of the buffer.
+ * align[in] The alignment is either 8 or 16.
  */
 void
 ulp_encap_buffer_copy(uint8_t *dst,
                      const uint8_t *src,
-                     uint16_t size)
+                     uint16_t size,
+                     uint16_t align)
 {
-       uint16_t        idx = 0;
-
-       /* copy 2 bytes at a time. Write MSB to LSB */
-       while ((idx + sizeof(uint16_t)) <= size) {
-               memcpy(&dst[idx], &src[size - idx - sizeof(uint16_t)],
-                      sizeof(uint16_t));
-               idx += sizeof(uint16_t);
-       }
+       uint16_t        idx, tmp_size = 0;
+
+       do {
+               dst += tmp_size;
+               src += tmp_size;
+               idx = 0;
+               if (size > align) {
+                       tmp_size = align;
+                       size -= align;
+               } else {
+                       tmp_size = size;
+                       size = 0;
+               }
+               /* copy 2 bytes at a time. Write MSB to LSB */
+               while ((idx + sizeof(uint16_t)) <= tmp_size) {
+                       memcpy(&dst[idx],
+                              &src[tmp_size - idx - sizeof(uint16_t)],
+                              sizeof(uint16_t));
+                       idx += sizeof(uint16_t);
+               }
+       } while (size);
 }
 
 /*