[Accel-config] Re: [PATCH v2 6/7] accel-config/test: add 4 dif operations support
Dave Jiang <dave.jiang at intel.com> Thu, 17 Feb 2022 14:46:21 -0700
| Newsgroups | dev.linux.lists.accel-config |
|---|---|
| Message-ID | <[email protected]> |
On 2/16/2022 5:26 AM, Tony Zhu wrote:
> Add Data Integrity Field (DIF) check, insert, strip, and update
> operation support while transferring data.
>
> Signed-off-by: Tony Zhu <tony.zhu(a)intel.com>
> ---
> test/dsa.c | 729 ++++++++++++++++++++++++++++++++++++++++++++++++
> test/dsa.h | 44 +++
> test/dsa_test.c | 104 +++++++
> test/prep.c | 189 +++++++++++++
> 4 files changed, 1066 insertions(+)
>
> diff --git a/test/dsa.c b/test/dsa.c
> index 9a10267..cc8cb2c 100644
> --- a/test/dsa.c
> +++ b/test/dsa.c
> @@ -23,6 +23,37 @@ unsigned int ms_timeout = 5000;
> int debug_logging;
> static int umwait_support;
>
> +unsigned int dif_blk_arr[] = {512, 520, 4096, 4104};
> +
> +/*ANINDYA Logic to get blk_sz_flg*/
What is ANINDYA?
> +int get_dif_blksz_flg(unsigned long xfer_size)
> +{
> + int blk_idx_flg = 3;
> +
> + while (blk_idx_flg) {
> + if (xfer_size % dif_blk_arr[blk_idx_flg] == 0)
> + break;
> + blk_idx_flg--;
> + }
> + return blk_idx_flg;
> +}
> +
> +/* ASD Logic */
What is ASD? And what is this comment trying to say?
DJ
> +unsigned long get_blks(unsigned long xfer_size)
> +{
> + int blk_idx_flg = 3;
> + unsigned long num_blks;
> +
> + while (blk_idx_flg) {
> + if (xfer_size % dif_blk_arr[blk_idx_flg] == 0)
> + break;
> + blk_idx_flg--;
> + }
> +
> + num_blks = xfer_size / dif_blk_arr[blk_idx_flg];
> + return num_blks;
> +}
> +
> static inline void cpuid(unsigned int *eax, unsigned int *ebx,
> unsigned int *ecx, unsigned int *edx)
> {
> @@ -477,6 +508,196 @@ int init_copy_crc(struct task *tsk, int tflags, int opcode, unsigned long xfer_s
> return DSA_STATUS_OK;
> }
>
> +int init_dif_check(struct task *tsk, int tflags, int opcode, unsigned long xfer_size)
> +{
> + unsigned long buf_size;
> + unsigned long force_align = ADDR_ALIGNMENT;
> + unsigned char *src;
> + unsigned int dif_reftag;
> + unsigned int dif_apptag;
> + unsigned int dif_guardtag;
> + unsigned long blks = 0;
> + unsigned long i;
> + unsigned long dif_size;
> +
> + tsk->pattern = 0x0123456789abcdef;
> + tsk->opcode = opcode;
> + tsk->test_flags = tflags;
> + tsk->xfer_size = xfer_size;
> +
> + tsk->apptag = 0xFACE;
> + tsk->reftag = 0xABBA;
> +
> + tsk->blk_idx_flg = get_dif_blksz_flg(tsk->xfer_size);
> + blks = tsk->xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + tsk->blks = blks;
> +
> + buf_size = tsk->xfer_size / blks;
> + /* 8 bytes for inclusion of tags */
> + tsk->xfer_size += 8 * blks;
> + tsk->src1 = aligned_alloc(force_align, tsk->xfer_size);
> + if (!tsk->src1)
> + return -ENOMEM;
> + src = (unsigned char *)tsk->src1;
> + dif_reftag = tsk->reftag;
> + dif_apptag = tsk->apptag;
> +
> + for (i = 1; i <= blks; i++) {
> + dif_size = (buf_size + 8) * (i - 1);
> + memset_pattern((src + dif_size), tsk->pattern, buf_size);
> + dif_guardtag = dsa_calculate_crc_t10dif((src + dif_size), buf_size, 0);
> + src[buf_size + DIF_BLK_GRD_1 + dif_size] = (dif_guardtag >> 8) & 0xFF;
> + src[buf_size + DIF_BLK_GRD_2 + dif_size] = dif_guardtag & 0xFF;
> + src[buf_size + DIF_APP_TAG_1 + dif_size] = (dif_apptag >> 8) & 0xFF;
> + src[buf_size + DIF_APP_TAG_2 + dif_size] = (dif_apptag) & 0xFF;
> + src[buf_size + DIF_REF_TAG_1 + dif_size] = (dif_reftag >> 24) & 0xFF;
> + src[buf_size + DIF_REF_TAG_2 + dif_size] = (dif_reftag >> 16) & 0xFF;
> + src[buf_size + DIF_REF_TAG_3 + dif_size] = (dif_reftag >> 8) & 0xFF;
> + src[buf_size + DIF_REF_TAG_4 + dif_size] = dif_reftag & 0xFF;
> + dif_reftag++;
> + }
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int init_dif_ins(struct task *tsk, int tflags, int opcode, unsigned long xfer_size)
> +{
> + unsigned long force_align = ADDR_ALIGNMENT;
> + unsigned long blks = 0;
> +
> + tsk->pattern = 0x0123456789abcdef;
> + tsk->opcode = opcode;
> + tsk->test_flags = tflags;
> + tsk->xfer_size = xfer_size;
> +
> + tsk->apptag = 0xFACE;
> + tsk->reftag = 0xABBA;
> + tsk->blk_idx_flg = get_dif_blksz_flg(tsk->xfer_size);
> + blks = tsk->xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + tsk->blks = blks;
> +
> + tsk->src1 = aligned_alloc(force_align, xfer_size);
> + if (!tsk->src1)
> + return -ENOMEM;
> + memset_pattern(tsk->src1, tsk->pattern, xfer_size);
> + blks = get_blks(xfer_size);
> + xfer_size += 8 * blks;
> + tsk->dst1 = aligned_alloc(force_align, xfer_size);
> + if (!tsk->dst1)
> + return -ENOMEM;
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int init_dif_strp(struct task *tsk, int tflags, int opcode, unsigned long xfer_size)
> +{
> + unsigned long buf_size;
> + unsigned long force_align = ADDR_ALIGNMENT;
> + unsigned char *src;
> + unsigned int dif_reftag;
> + unsigned int dif_apptag;
> + unsigned int dif_guardtag;
> + unsigned long blks = 0;
> + unsigned long i;
> + unsigned long dif_size;
> +
> + tsk->pattern = 0x0123456789abcdef;
> + tsk->opcode = opcode;
> + tsk->test_flags = tflags;
> + tsk->xfer_size = xfer_size;
> +
> + tsk->apptag = 0xFACE;
> + tsk->reftag = 0xABBA;
> +
> + tsk->blk_idx_flg = get_dif_blksz_flg(tsk->xfer_size);
> + blks = tsk->xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + tsk->blks = blks;
> + buf_size = tsk->xfer_size / blks;
> + /* 8 bytes for inclusion of tags */
> + tsk->xfer_size += 8 * blks;
> + tsk->src1 = aligned_alloc(force_align, tsk->xfer_size);
> + if (!tsk->src1)
> + return -ENOMEM;
> +
> + src = (unsigned char *)tsk->src1;
> + dif_reftag = tsk->reftag;
> + dif_apptag = tsk->apptag;
> +
> + for (i = 1; i <= blks; i++) {
> + dif_size = (buf_size + 8) * (i - 1);
> + memset_pattern((src + dif_size), tsk->pattern, buf_size);
> + dif_guardtag = dsa_calculate_crc_t10dif((src + dif_size), buf_size, 0);
> + src[buf_size + DIF_BLK_GRD_1 + dif_size] = (dif_guardtag >> 8) & 0xFF;
> + src[buf_size + DIF_BLK_GRD_2 + dif_size] = dif_guardtag & 0xFF;
> + src[buf_size + DIF_APP_TAG_1 + dif_size] = (dif_apptag >> 8) & 0xFF;
> + src[buf_size + DIF_APP_TAG_2 + dif_size] = (dif_apptag) & 0xFF;
> + src[buf_size + DIF_REF_TAG_1 + dif_size] = (dif_reftag >> 24) & 0xFF;
> + src[buf_size + DIF_REF_TAG_2 + dif_size] = (dif_reftag >> 16) & 0xFF;
> + src[buf_size + DIF_REF_TAG_3 + dif_size] = (dif_reftag >> 8) & 0xFF;
> + src[buf_size + DIF_REF_TAG_4 + dif_size] = dif_reftag & 0xFF;
> + dif_reftag++;
> + }
> +
> + tsk->dst1 = aligned_alloc(force_align, tsk->xfer_size - 8 * blks);
> + if (!tsk->dst1)
> + return -ENOMEM;
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int init_dif_updt(struct task *tsk, int tflags, int opcode, unsigned long xfer_size)
> +{
> + unsigned long buf_size;
> + unsigned long force_align = ADDR_ALIGNMENT;
> + unsigned char *src;
> + unsigned int dif_reftag;
> + unsigned int dif_apptag;
> + unsigned int dif_guardtag;
> + unsigned long blks = 0;
> + unsigned long i;
> + unsigned long dif_size;
> +
> + tsk->pattern = 0x0123456789abcdef;
> + tsk->opcode = opcode;
> + tsk->test_flags = tflags;
> + tsk->xfer_size = xfer_size;
> +
> + tsk->apptag = 0xFACE;
> + tsk->reftag = 0xABBA;
> +
> + tsk->blk_idx_flg = get_dif_blksz_flg(tsk->xfer_size);
> + blks = tsk->xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + tsk->blks = blks;
> + buf_size = tsk->xfer_size / blks;
> + tsk->xfer_size += 8 * blks;
> + tsk->src1 = aligned_alloc(force_align, tsk->xfer_size);
> + if (!tsk->src1)
> + return -ENOMEM;
> +
> + src = (unsigned char *)tsk->src1;
> + dif_reftag = tsk->reftag;
> + dif_apptag = tsk->apptag;
> +
> + for (i = 1; i <= blks; i++) {
> + dif_size = (buf_size + 8) * (i - 1);
> + memset_pattern((src + dif_size), tsk->pattern, buf_size);
> + dif_guardtag = dsa_calculate_crc_t10dif((src + dif_size), buf_size, 0);
> + src[buf_size + DIF_BLK_GRD_1 + dif_size] = (dif_guardtag >> 8) & 0xFF;
> + src[buf_size + DIF_BLK_GRD_2 + dif_size] = dif_guardtag & 0xFF;
> + src[buf_size + DIF_APP_TAG_1 + dif_size] = (dif_apptag >> 8) & 0xFF;
> + src[buf_size + DIF_APP_TAG_2 + dif_size] = (dif_apptag) & 0xFF;
> + src[buf_size + DIF_REF_TAG_1 + dif_size] = (dif_reftag >> 24) & 0xFF;
> + src[buf_size + DIF_REF_TAG_2 + dif_size] = (dif_reftag >> 16) & 0xFF;
> + src[buf_size + DIF_REF_TAG_3 + dif_size] = (dif_reftag >> 8) & 0xFF;
> + src[buf_size + DIF_REF_TAG_4 + dif_size] = dif_reftag & 0xFF;
> + }
> + tsk->dst1 = aligned_alloc(force_align, tsk->xfer_size);
> + if (!tsk->dst1)
> + return -ENOMEM;
> +
> + return DSA_STATUS_OK;
> +}
> +
> /* this function is re-used by batch task */
> int init_task(struct task *tsk, int tflags, int opcode,
> unsigned long xfer_size)
> @@ -520,6 +741,22 @@ int init_task(struct task *tsk, int tflags, int opcode,
> case DSA_OPCODE_COPY_CRC:
> rc = init_copy_crc(tsk, tflags, opcode, xfer_size);
> break;
> +
> + case DSA_OPCODE_DIF_CHECK:
> + rc = init_dif_check(tsk, tflags, opcode, xfer_size);
> + break;
> +
> + case DSA_OPCODE_DIF_INS:
> + rc = init_dif_ins(tsk, tflags, opcode, xfer_size);
> + break;
> +
> + case DSA_OPCODE_DIF_STRP:
> + rc = init_dif_strp(tsk, tflags, opcode, xfer_size);
> + break;
> +
> + case DSA_OPCODE_DIF_UPDT:
> + rc = init_dif_updt(tsk, tflags, opcode, xfer_size);
> + break;
> }
>
> if (rc != DSA_STATUS_OK) {
> @@ -1441,6 +1678,158 @@ int dsa_crc_copy_multi_task_nodes(struct dsa_context *ctx)
> return ret;
> }
>
> +int dsa_wait_dif(struct dsa_context *ctx, struct task *tsk)
> +{
> + struct dsa_hw_desc *desc = tsk->desc;
> + struct dsa_completion_record *comp = tsk->comp;
> + int rc;
> +
> +again:
> + rc = dsa_wait_on_desc_timeout(comp, ms_timeout);
> + if (rc < 0) {
> + err("DIF desc timeout\n");
> + return DSA_STATUS_TIMEOUT;
> + }
> +
> + /* re-submit if PAGE_FAULT reported by HW && BOF is off */
> + if (stat_val(comp->status) == DSA_COMP_PAGE_FAULT_NOBOF &&
> + !(desc->flags & IDXD_OP_FLAG_BOF)) {
> + task_result_verify(tsk, 0);
> + dsa_reprep_dif(ctx, tsk);
> + goto again;
> + }
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int dsa_dif_check_multi_task_nodes(struct dsa_context *ctx)
> +{
> + struct task_node *tsk_node = ctx->multi_task_node;
> + int ret = DSA_STATUS_OK;
> +
> + while (tsk_node) {
> + tsk_node->tsk->dflags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
> + if ((tsk_node->tsk->test_flags & TEST_FLAGS_BOF) && ctx->bof)
> + tsk_node->tsk->dflags |= IDXD_OP_FLAG_BOF;
> +
> + dsa_prep_dif_check(tsk_node->tsk);
> + tsk_node = tsk_node->next;
> + }
> +
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + dsa_desc_submit(ctx, tsk_node->tsk->desc);
> + tsk_node = tsk_node->next;
> + }
> +
> + info("Submitted all dif check jobs\n");
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + ret = dsa_wait_dif(ctx, tsk_node->tsk);
> + if (ret != DSA_STATUS_OK)
> + info("Desc: %p failed with ret: %d\n", tsk_node->tsk->desc,
> + tsk_node->tsk->comp->status);
> + tsk_node = tsk_node->next;
> + }
> + return ret;
> +}
> +
> +int dsa_dif_ins_multi_task_nodes(struct dsa_context *ctx)
> +{
> + struct task_node *tsk_node = ctx->multi_task_node;
> + int ret = DSA_STATUS_OK;
> +
> + while (tsk_node) {
> + tsk_node->tsk->dflags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
> + if ((tsk_node->tsk->test_flags & TEST_FLAGS_BOF) && ctx->bof)
> + tsk_node->tsk->dflags |= IDXD_OP_FLAG_BOF;
> +
> + dsa_prep_dif_insert(tsk_node->tsk);
> + tsk_node = tsk_node->next;
> + }
> +
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + dsa_desc_submit(ctx, tsk_node->tsk->desc);
> + tsk_node = tsk_node->next;
> + }
> + tsk_node = ctx->multi_task_node;
> + info("Submitted all dif insert jobs\n");
> + while (tsk_node) {
> + ret = dsa_wait_dif(ctx, tsk_node->tsk);
> + if (ret != DSA_STATUS_OK)
> + info("Desc: %p failed with ret: %d\n", tsk_node->tsk->desc,
> + tsk_node->tsk->comp->status);
> + tsk_node = tsk_node->next;
> + }
> + return ret;
> +}
> +
> +int dsa_dif_strp_multi_task_nodes(struct dsa_context *ctx)
> +{
> + struct task_node *tsk_node = ctx->multi_task_node;
> + int ret = DSA_STATUS_OK;
> +
> + while (tsk_node) {
> + tsk_node->tsk->dflags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
> + if ((tsk_node->tsk->test_flags & TEST_FLAGS_BOF) && ctx->bof)
> + tsk_node->tsk->dflags |= IDXD_OP_FLAG_BOF;
> +
> + dsa_prep_dif_strip(tsk_node->tsk);
> + tsk_node = tsk_node->next;
> + }
> +
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + dsa_desc_submit(ctx, tsk_node->tsk->desc);
> + tsk_node = tsk_node->next;
> + }
> +
> + info("Submitted all dif strp jobs\n");
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + ret = dsa_wait_dif(ctx, tsk_node->tsk);
> + if (ret != DSA_STATUS_OK)
> + info("Desc: %p failed with ret: %d\n", tsk_node->tsk->desc,
> + tsk_node->tsk->comp->status);
> + tsk_node = tsk_node->next;
> + }
> +
> + return ret;
> +}
> +
> +int dsa_dif_updt_multi_task_nodes(struct dsa_context *ctx)
> +{
> + struct task_node *tsk_node = ctx->multi_task_node;
> + int ret = DSA_STATUS_OK;
> +
> + while (tsk_node) {
> + tsk_node->tsk->dflags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
> + if ((tsk_node->tsk->test_flags & TEST_FLAGS_BOF) && ctx->bof)
> + tsk_node->tsk->dflags |= IDXD_OP_FLAG_BOF;
> +
> + dsa_prep_dif_update(tsk_node->tsk);
> + tsk_node = tsk_node->next;
> + }
> +
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + dsa_desc_submit(ctx, tsk_node->tsk->desc);
> + tsk_node = tsk_node->next;
> + }
> + tsk_node = ctx->multi_task_node;
> +
> + info("Submitted all dif update jobs\n");
> + while (tsk_node) {
> + ret = dsa_wait_dif(ctx, tsk_node->tsk);
> + if (ret != DSA_STATUS_OK)
> + info("Desc: %p failed with ret: %d\n", tsk_node->tsk->desc,
> + tsk_node->tsk->comp->status);
> + tsk_node = tsk_node->next;
> + }
> + return ret;
> +}
> +
> /* mismatch_expected: expect mismatched buffer with success status 0x1 */
> int task_result_verify(struct task *tsk, int mismatch_expected)
> {
> @@ -1476,6 +1865,19 @@ int task_result_verify(struct task *tsk, int mismatch_expected)
> case DSA_OPCODE_COPY_CRC:
> rc = task_result_verify_crc_copy(tsk, mismatch_expected);
> return rc;
> + case DSA_OPCODE_DIF_INS:
> + rc = task_result_verify_dif(tsk, tsk->xfer_size, mismatch_expected);
> + rc = task_result_verify_dif_tags(tsk, tsk->xfer_size);
> + return rc;
> + case DSA_OPCODE_DIF_STRP:
> + rc = task_result_verify_dif(tsk, tsk->xfer_size - 8 * tsk->blks,
> + mismatch_expected);
> + return rc;
> + case DSA_OPCODE_DIF_UPDT:
> + rc = task_result_verify_dif(tsk, tsk->xfer_size - 8 * tsk->blks,
> + mismatch_expected);
> + rc = task_result_verify_dif_tags(tsk, tsk->xfer_size - 8 * tsk->blks);
> + return rc;
> }
>
> info("test with op %d passed\n", tsk->opcode);
> @@ -1745,6 +2147,333 @@ int task_result_verify_crc_copy(struct task *tsk, int mismatch_expected)
> return DSA_STATUS_OK;
> }
>
> +/**
> + * This function calculates the CRC16 T10 checksum for the DIF descriptors.
> + * @param *buffer pointer to the data buffer.
> + * @param len size of the buffer.
> + *
> + **/
> +uint16_t dsa_calculate_crc_t10dif(unsigned char *buffer, size_t len, int flags)
> +{
> + unsigned short crc;
> + unsigned int i = 0;
> +
> + crc = (flags & DIF_INVERT_CRC_SEED) ? 0xFFFF : 0;
> +
> + for (i = 0; i < len; i++)
> + crc = (crc << 8) ^ t10_dif_crc_table[((crc >> 8) ^ buffer[i]) & 0xff];
> +
> + return (flags & DIF_INVERT_CRC_RESULT) ? ~crc : crc;
> +}
> +
> +static int task_result_verify_dif_page_fault(struct task *tsk, unsigned long xfer_size,
> + int mismatch_expected)
> +{
> + struct dsa_hw_desc *hw = tsk->desc;
> + int rc = 0;
> + unsigned char *src1 = (unsigned char *)hw->src_addr;
> + unsigned char *dst1 = (unsigned char *)hw->dst_addr;
> + unsigned long i, blks;
> +
> + if (tsk->comp->status == 0x16 || xfer_size == 0)
> + /* This check need to be removed for GNR-SP. Its a know bug in SPR-SP
> + * https://hsdes.intel.com/appstore/article/#/22010927356
> + * [SPR][No Fix] For DIF operations, RTL should consider 'computed transfer size'
> + * when determining overlapping buffer conditions
> + */
> + return DSA_STATUS_OK;
> +
> + info("Partial DIF Src and Dest Check Ongoing\n");
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_INS) {
> + blks = xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[dif_blk_arr[tsk->blk_idx_flg] * i],
> + &dst1[(dif_blk_arr[tsk->blk_idx_flg] + 8) * i],
> + dif_blk_arr[tsk->blk_idx_flg]);
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_STRP) {
> + blks = xfer_size / (dif_blk_arr[tsk->blk_idx_flg] + 8);
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[(dif_blk_arr[tsk->blk_idx_flg] + 8) * i],
> + &dst1[dif_blk_arr[tsk->blk_idx_flg] * i],
> + dif_blk_arr[tsk->blk_idx_flg]);
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_UPDT) {
> + blks = xfer_size / (dif_blk_arr[tsk->blk_idx_flg] + 8);
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[(dif_blk_arr[tsk->blk_idx_flg] + 8) * i],
> + &dst1[(dif_blk_arr[tsk->blk_idx_flg] + 8) * i],
> + dif_blk_arr[tsk->blk_idx_flg]);
> + }
> +
> + if (rc) {
> + err("dif mismatch dst1, memcmp rc %d\n", rc);
> + return -ENXIO;
> + }
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int task_result_verify_dif(struct task *tsk, unsigned long xfer_size, int mismatch_expected)
> +{
> + int rc;
> + unsigned long i;
> + unsigned long blks = tsk->blks;
> + unsigned long buf_size = dif_blk_arr[tsk->blk_idx_flg];
> + unsigned char *src1 = (unsigned char *)tsk->src1;
> + unsigned char *dst1 = (unsigned char *)tsk->dst1;
> +
> + if (tsk->comp->status == DSA_COMP_PAGE_FAULT_NOBOF ||
> + tsk->comp->status == DSA_COMP_PAGE_FAULT_IR ||
> + tsk->comp->status == 0x83) {
> + rc = task_result_verify_dif_page_fault(tsk, tsk->comp->bytes_completed, 0);
> + info("Partial DIF Src and Dest Checking Done\n");
> + if (!rc)
> + return DSA_STATUS_OK;
> + }
> +
> + /* This check need to be removed for GNR-SP. Its a know bug in SPR-SP
> + * https://hsdes.intel.com/appstore/article/#/22010927356
> + * [SPR][No Fix] For DIF operations, RTL should consider 'computed transfer size'
> + * when determining overlapping buffer conditions
> + */
> + if (tsk->comp->status == 0x16)
> + return DSA_STATUS_OK;
> +
> + info("Checking Src & Dst buffers\n");
> + if (tsk->opcode == DSA_OPCODE_DIF_INS) {
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[buf_size * i], &dst1[(buf_size + 8) * i], buf_size);
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_STRP) {
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[(buf_size + 8) * i], &dst1[buf_size * i], buf_size);
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_UPDT) {
> + for (i = 0; i < blks; i++)
> + rc = memcmp(&src1[(buf_size + 8) * i], &dst1[(buf_size + 8) * i], buf_size);
> + }
> +
> + if (rc) {
> + err("dif mismatch dst1, memcmp rc %d\n", rc);
> + return -ENXIO;
> + }
> +
> + return DSA_STATUS_OK;
> +}
> +
> +static int task_result_verify_dif_tags_page_fault(struct task *tsk, unsigned long xfer_size)
> +{
> + struct dsa_hw_desc *hw = tsk->desc;
> + unsigned long blks;
> + unsigned long buf_size;
> + unsigned char *dst1 = (uint8_t *)hw->dst_addr;
> + unsigned char *src1 = (uint8_t *)hw->src_addr;
> + unsigned long g_count = 0;
> + unsigned long a_count = 0;
> + unsigned long r_count = 0;
> + unsigned short dif_apptag = 0;
> + unsigned long dif_reftag = 0;
> + unsigned int dif_guardtag = 0;
> + unsigned char tmp_buf;
> + unsigned char dst_tag;
> + unsigned long i;
> +
> + info("Checking Partial DIF Tags\n");
> + /* This check need to be removed for GNR-SP. Its a know bug in SPR-SP
> + * https://hsdes.intel.com/appstore/article/#/22010927356
> + * [SPR][No Fix] For DIF operations, RTL should consider 'computed transfer size'
> + * when determining overlapping buffer conditions
> + */
> + if (tsk->comp->status == 0x16 || xfer_size == 0)
> + return DSA_STATUS_OK;
> +
> + if (tsk->opcode != DSA_OPCODE_DIF_UPDT)
> + blks = xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + else
> + blks = xfer_size / (dif_blk_arr[tsk->blk_idx_flg] + 8);
> +
> + switch (tsk->opcode) {
> + case DSA_OPCODE_DIF_INS:
> + dif_reftag = hw->ins_ref_tag_seed;
> + dif_apptag = hw->ins_app_tag_seed;
> + break;
> +
> + case DSA_OPCODE_DIF_CHECK:
> + case DSA_OPCODE_DIF_STRP:
> + dif_reftag = hw->chk_ref_tag_seed;
> + dif_apptag = hw->chk_app_tag_seed;
> + break;
> +
> + case DSA_OPCODE_DIF_UPDT:
> + dif_reftag = hw->dest_ref_tag_seed;
> + dif_apptag = hw->dest_app_tag_seed;
> + break;
> + }
> +
> + buf_size = dif_blk_arr[tsk->blk_idx_flg];
> + for (i = 0; i < blks; i++) {
> + if (tsk->opcode == DSA_OPCODE_DIF_INS)
> + dif_guardtag = dsa_calculate_crc_t10dif((src1 + buf_size * i),
> + buf_size, 0);
> + else
> + dif_guardtag = dsa_calculate_crc_t10dif((src1 + (buf_size + 8) * i),
> + buf_size, 0);
> +
> + dst_tag = dst1[buf_size + DIF_BLK_GRD_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_guardtag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + g_count++;
> +
> + dst_tag = dst1[buf_size + DIF_BLK_GRD_2 + (buf_size + 8) * i];
> + tmp_buf = dif_guardtag & 0xff;
> + if (tmp_buf != dst_tag)
> + g_count++;
> +
> + dst_tag = dst1[buf_size + DIF_APP_TAG_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_apptag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + a_count++;
> +
> + dst_tag = dst1[buf_size + DIF_APP_TAG_2 + (buf_size + 8) * i];
> + tmp_buf = (dif_apptag) & 0xff;
> + if (tmp_buf != dst_tag)
> + a_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 24) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_2 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 16) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_3 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_4 + (buf_size + 8) * i];
> + tmp_buf = dif_reftag & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + if (tsk->opcode != DSA_OPCODE_DIF_UPDT)
> + dif_reftag++;
> + }
> +
> + if (g_count || a_count || r_count)
> + err("Tag Errors Found g: %ld a: %ld r: %ld\n", g_count, a_count, r_count);
> + else
> + info("All Tags Validated\n", g_count, a_count, r_count);
> +
> + return DSA_STATUS_OK;
> +}
> +
> +int task_result_verify_dif_tags(struct task *tsk, unsigned long xfer_size)
> +{
> + int rc;
> + unsigned long blks;
> + unsigned long buf_size;
> + unsigned char *dst1 = (unsigned char *)tsk->dst1;
> + unsigned char *src1 = (unsigned char *)tsk->src1;
> + unsigned long g_count = 0;
> + unsigned long a_count = 0;
> + unsigned long r_count = 0;
> + unsigned int dif_reftag = tsk->reftag;
> + unsigned int dif_apptag = tsk->apptag;
> + unsigned int dif_guardtag = 0;
> + unsigned char tmp_buf;
> + unsigned char dst_tag;
> + unsigned long i;
> +
> + info("compsts: %x\n", tsk->comp->status);
> + if (tsk->comp->status == 0x83 ||
> + tsk->comp->status == DSA_COMP_PAGE_FAULT_NOBOF ||
> + tsk->comp->status == DSA_COMP_PAGE_FAULT_IR) {
> + rc = task_result_verify_dif_tags_page_fault(tsk, tsk->comp->bytes_completed);
> + info("Partial DIF Tags Checking Done\n");
> + if (!rc)
> + return DSA_STATUS_OK;
> + }
> +
> + info("Checking All Tags\n");
> + if (tsk->opcode != DSA_OPCODE_DIF_UPDT)
> + blks = xfer_size / dif_blk_arr[tsk->blk_idx_flg];
> + else
> + blks = tsk->blks;
> +
> + buf_size = dif_blk_arr[tsk->blk_idx_flg];
> + tsk->reftag = 0xABBA;
> + tsk->apptag = 0xFACE;
> +
> + for (i = 0; i < blks; i++) {
> + if (tsk->opcode == DSA_OPCODE_DIF_INS)
> + dif_guardtag = dsa_calculate_crc_t10dif((src1 + (buf_size) * i),
> + buf_size, 0);
> + else
> + dif_guardtag = dsa_calculate_crc_t10dif((src1 + (buf_size + 8) * i),
> + buf_size, 0);
> +
> + dst_tag = dst1[buf_size + DIF_BLK_GRD_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_guardtag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + g_count++;
> +
> + dst_tag = dst1[buf_size + DIF_BLK_GRD_2 + (buf_size + 8) * i];
> + tmp_buf = dif_guardtag & 0xff;
> + if (tmp_buf != dst_tag)
> + g_count++;
> +
> + dst_tag = dst1[buf_size + DIF_APP_TAG_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_apptag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + a_count++;
> +
> + dst_tag = dst1[buf_size + DIF_APP_TAG_2 + (buf_size + 8) * i];
> + tmp_buf = (dif_apptag) & 0xff;
> + if (tmp_buf != dst_tag)
> + a_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_1 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 24) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_2 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 16) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_3 + (buf_size + 8) * i];
> + tmp_buf = (dif_reftag >> 8) & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + dst_tag = dst1[buf_size + DIF_REF_TAG_4 + (buf_size + 8) * i];
> + tmp_buf = dif_reftag & 0xff;
> + if (tmp_buf != dst_tag)
> + r_count++;
> +
> + if (tsk->opcode != DSA_OPCODE_DIF_UPDT)
> + dif_reftag++;
> + }
> +
> + if (g_count || a_count || r_count)
> + err("Tag Errors Found g: %ld a: %ld r: %ld\n", g_count, a_count, r_count);
> + else
> + info("All Tags Validated\n", g_count, a_count, r_count);
> +
> + return DSA_STATUS_OK;
> +}
> +
> int batch_result_verify(struct batch_task *btsk, int bof)
> {
> uint8_t core_stat, sub_stat;
> diff --git a/test/dsa.h b/test/dsa.h
> index 4bb08ed..9157741 100644
> --- a/test/dsa.h
> +++ b/test/dsa.h
> @@ -5,6 +5,7 @@
> #include <accfg/libaccel_config.h>
> #include <accfg/idxd.h>
> #include "accfg_test.h"
> +#include "crc16_t10_lookup.h"
>
> #define MAX_PATH_LENGTH 1024
>
> @@ -46,6 +47,19 @@
> #define BYPASS_CRC_INV_REF ((unsigned long)(1 << 17))
> #define BYPASS_DATA_REF ((unsigned long)(1 << 18))
>
> +/* DIF index */
> +#define DIF_BLK_GRD_1 0
> +#define DIF_BLK_GRD_2 1
> +#define DIF_APP_TAG_1 2
> +#define DIF_APP_TAG_2 3
> +#define DIF_REF_TAG_1 4
> +#define DIF_REF_TAG_2 5
> +#define DIF_REF_TAG_3 6
> +#define DIF_REF_TAG_4 7
> +
> +#define DIF_INVERT_CRC_SEED ((unsigned long)(1 << 2))
> +#define DIF_INVERT_CRC_RESULT ((unsigned long)(1 << 3))
> +
> #define ADDR_ALIGNMENT 32
>
> #define MIN_DELTA_RECORD_SIZE 80
> @@ -72,6 +86,11 @@ struct task {
> int test_flags;
> int crc_seed;
> unsigned long long *crc_seed_addr;
> + int reftag;
> + int apptag;
> + int guardtag;
> + unsigned long blks;
> + int blk_idx_flg;
> };
>
> struct task_node {
> @@ -247,6 +266,10 @@ int init_dualcast(struct task *tsk, int tflags, int opcode, unsigned long xfer_s
> int init_cr_delta(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> int init_crcgen(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> int init_copy_crc(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> +int init_dif_check(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> +int init_dif_ins(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> +int init_dif_strp(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> +int init_dif_updt(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
> int init_task(struct task *tsk, int tflags, int opcode,
> unsigned long xfer_size);
>
> @@ -283,6 +306,12 @@ int dsa_wait_crcgen(struct dsa_context *ctx, struct task *tsk);
> int dsa_crc_copy_multi_task_nodes(struct dsa_context *ctx);
> int dsa_wait_crc_copy(struct dsa_context *ctx, struct task *tsk);
>
> +int dsa_dif_check_multi_task_nodes(struct dsa_context *ctx);
> +int dsa_dif_ins_multi_task_nodes(struct dsa_context *ctx);
> +int dsa_dif_strp_multi_task_nodes(struct dsa_context *ctx);
> +int dsa_dif_updt_multi_task_nodes(struct dsa_context *ctx);
> +int dsa_wait_dif(struct dsa_context *ctx, struct task *tsk);
> +
> void dsa_prep_noop(struct task *tsk);
> void dsa_prep_drain(struct task *tsk);
> void dsa_prep_memcpy(struct task *tsk);
> @@ -303,6 +332,11 @@ void dsa_prep_crcgen(struct task *tsk);
> void dsa_reprep_crcgen(struct dsa_context *ctx, struct task *tsk);
> void dsa_prep_crc_copy(struct task *tsk);
> void dsa_reprep_crc_copy(struct dsa_context *ctx, struct task *tsk);
> +void dsa_prep_dif_check(struct task *tsk);
> +void dsa_prep_dif_insert(struct task *tsk);
> +void dsa_prep_dif_strip(struct task *tsk);
> +void dsa_prep_dif_update(struct task *tsk);
> +void dsa_reprep_dif(struct dsa_context *ctx, struct task *tsk);
>
> int task_result_verify(struct task *tsk, int mismatch_expected);
> int task_result_verify_task_nodes(struct dsa_context *ctx, int mismatch_expected);
> @@ -314,6 +348,8 @@ int task_result_verify_dualcast(struct task *tsk, int mismatch_expected);
> int task_result_verify_ap_delta(struct task *tsk, int mismatch_expected);
> int task_result_verify_crcgen(struct task *tsk, int mismatch_expected);
> int task_result_verify_crc_copy(struct task *tsk, int mismatch_expected);
> +int task_result_verify_dif(struct task *tsk, unsigned long xfer_size, int mismatch_expected);
> +int task_result_verify_dif_tags(struct task *tsk, unsigned long xfer_size);
> int batch_result_verify(struct batch_task *btsk, int bof);
>
> int alloc_batch_task(struct dsa_context *ctx, unsigned int task_num, int num_itr);
> @@ -331,6 +367,10 @@ void dsa_prep_batch_cr_delta(struct batch_task *btsk);
> void dsa_prep_batch_ap_delta(struct batch_task *btsk);
> void dsa_prep_batch_crcgen(struct batch_task *btsk);
> void dsa_prep_batch_crc_copy(struct batch_task *btsk);
> +void dsa_prep_batch_dif_check(struct batch_task *btsk);
> +void dsa_prep_batch_dif_insert(struct batch_task *btsk);
> +void dsa_prep_batch_dif_strip(struct batch_task *btsk);
> +void dsa_prep_batch_dif_update(struct batch_task *btsk);
> int dsa_wait_batch(struct batch_task *btsk);
>
> void dsa_free(struct dsa_context *ctx);
> @@ -342,4 +382,8 @@ void free_batch_task(struct batch_task *btsk);
> void dsa_prep_desc_common(struct dsa_hw_desc *hw, char opcode,
> uint64_t dest, uint64_t src, size_t len, unsigned long dflags);
> void dsa_desc_submit(struct dsa_context *ctx, struct dsa_hw_desc *hw);
> +
> +uint16_t dsa_calculate_crc_t10dif(unsigned char *buffer, size_t len, int flags);
> +int get_dif_blksz_flg(unsigned long xfer_size);
> +unsigned long get_blks(unsigned long xfer_size);
> #endif
> diff --git a/test/dsa_test.c b/test/dsa_test.c
> index 5a89687..a702f75 100644
> --- a/test/dsa_test.c
> +++ b/test/dsa_test.c
> @@ -111,6 +111,22 @@ static int test_batch(struct dsa_context *ctx, size_t buf_size,
> dsa_prep_batch_crc_copy(btsk_node->btsk);
> break;
>
> + case DSA_OPCODE_DIF_CHECK:
> + dsa_prep_batch_dif_check(btsk_node->btsk);
> + break;
> +
> + case DSA_OPCODE_DIF_INS:
> + dsa_prep_batch_dif_insert(btsk_node->btsk);
> + break;
> +
> + case DSA_OPCODE_DIF_STRP:
> + dsa_prep_batch_dif_strip(btsk_node->btsk);
> + break;
> +
> + case DSA_OPCODE_DIF_UPDT:
> + dsa_prep_batch_dif_update(btsk_node->btsk);
> + break;
> +
> default:
> err("Unsupported op %#x\n", bopcode);
> return -EINVAL;
> @@ -191,6 +207,85 @@ static int test_batch(struct dsa_context *ctx, size_t buf_size,
> return rc;
> }
>
> +static int test_dif(struct dsa_context *ctx, size_t buf_size,
> + int tflags, uint32_t opcode, int num_desc)
> +{
> + struct task_node *tsk_node;
> + int rc = DSA_STATUS_OK;
> + int itr = num_desc, i = 0, range = 0;
> +
> + info("testmemory: opcode %d len %#lx tflags %#x num_desc %ld\n",
> + opcode, buf_size, tflags, num_desc);
> +
> + ctx->is_batch = 0;
> +
> + if (ctx->dedicated == ACCFG_WQ_SHARED)
> + range = ctx->threshold;
> + else
> + range = ctx->wq_size - 1;
> +
> + while (itr > 0 && rc == DSA_STATUS_OK) {
> + i = (itr < range) ? itr : range;
> + /* Allocate memory to all the task nodes, desc, completion record*/
> + rc = alloc_multiple_tasks(ctx, i);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> +
> + /* allocate memory to src and dest buffers and fill in the desc for all the nodes*/
> + tsk_node = ctx->multi_task_node;
> + while (tsk_node) {
> + tsk_node->tsk->xfer_size = buf_size;
> + tsk_node->tsk->blk_idx_flg = get_dif_blksz_flg(tsk_node->tsk->xfer_size);
> +
> + rc = init_task(tsk_node->tsk, tflags, opcode, buf_size);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> +
> + tsk_node = tsk_node->next;
> + }
> +
> + switch (opcode) {
> + case DSA_OPCODE_DIF_CHECK:
> + rc = dsa_dif_check_multi_task_nodes(ctx);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> + break;
> +
> + case DSA_OPCODE_DIF_INS:
> + rc = dsa_dif_ins_multi_task_nodes(ctx);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> + break;
> +
> + case DSA_OPCODE_DIF_STRP:
> + rc = dsa_dif_strp_multi_task_nodes(ctx);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> + break;
> +
> + case DSA_OPCODE_DIF_UPDT:
> + rc = dsa_dif_updt_multi_task_nodes(ctx);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> + break;
> +
> + default:
> + err("Unsupported op %#x\n", opcode);
> + return -EINVAL;
> + }
> +
> + /* Verification of all the nodes*/
> + rc = task_result_verify_task_nodes(ctx, 0);
> + if (rc != DSA_STATUS_OK)
> + return rc;
> +
> + dsa_free_task(ctx);
> + itr = itr - range;
> + }
> +
> + return rc;
> +}
> +
> static int test_noop(struct dsa_context *ctx, int tflags, int num_desc)
> {
> struct task_node *tsk_node;
> @@ -650,6 +745,15 @@ int main(int argc, char *argv[])
> goto error;
> break;
>
> + case DSA_OPCODE_DIF_CHECK:
> + case DSA_OPCODE_DIF_INS:
> + case DSA_OPCODE_DIF_STRP:
> + case DSA_OPCODE_DIF_UPDT:
> + rc = test_dif(dsa, buf_size, tflags, opcode, num_desc);
> + if (rc != DSA_STATUS_OK)
> + goto error;
> + break;
> +
> default:
> rc = -EINVAL;
> break;
> diff --git a/test/prep.c b/test/prep.c
> index daa8db4..5f85b7c 100644
> --- a/test/prep.c
> +++ b/test/prep.c
> @@ -8,6 +8,8 @@
> #include <accfg/idxd.h>
> #include "dsa.h"
>
> +unsigned int dif_arr[] = {512, 520, 4096, 4104};
> +
> void dsa_prep_desc_common(struct dsa_hw_desc *hw, char opcode,
> uint64_t dest, uint64_t src, size_t len, unsigned long dflags)
> {
> @@ -531,6 +533,193 @@ void dsa_prep_batch_crc_copy(struct batch_task *btsk)
> }
> }
>
> +void dsa_prep_dif_check(struct task *tsk)
> +{
> + info("preparing descriptor for dif check\n");
> +
> + dsa_prep_desc_common(tsk->desc, tsk->opcode, (uint64_t)(tsk->dst1),
> + (uint64_t)(tsk->src1), tsk->xfer_size, tsk->dflags);
> + tsk->desc->completion_addr = (uint64_t)(tsk->comp);
> + tsk->comp->status = 0;
> + tsk->desc->chk_app_tag_seed = tsk->apptag;
> + tsk->desc->chk_ref_tag_seed = tsk->reftag;
> + tsk->desc->dif_chk_flags = tsk->blk_idx_flg;
> +}
> +
> +void dsa_prep_dif_insert(struct task *tsk)
> +{
> + info("preparing descriptor for dif insert\n");
> +
> + dsa_prep_desc_common(tsk->desc, tsk->opcode, (uint64_t)(tsk->dst1),
> + (uint64_t)(tsk->src1), tsk->xfer_size, tsk->dflags);
> + tsk->desc->completion_addr = (uint64_t)(tsk->comp);
> + tsk->comp->status = 0;
> + tsk->desc->ins_app_tag_seed = tsk->apptag;
> + tsk->desc->ins_ref_tag_seed = tsk->reftag;
> + tsk->desc->dif_ins_flags = tsk->blk_idx_flg;
> +}
> +
> +void dsa_prep_dif_strip(struct task *tsk)
> +{
> + info("preparing descriptor for dif strip\n");
> +
> + dsa_prep_desc_common(tsk->desc, tsk->opcode, (uint64_t)(tsk->dst1),
> + (uint64_t)(tsk->src1), tsk->xfer_size, tsk->dflags);
> + tsk->desc->completion_addr = (uint64_t)(tsk->comp);
> + tsk->comp->status = 0;
> + tsk->desc->chk_app_tag_seed = tsk->apptag;
> + tsk->desc->chk_ref_tag_seed = tsk->reftag;
> + tsk->desc->dif_chk_flags = tsk->blk_idx_flg;
> +}
> +
> +void dsa_prep_dif_update(struct task *tsk)
> +{
> + info("preparing descriptor for dif update\n");
> +
> + dsa_prep_desc_common(tsk->desc, tsk->opcode, (uint64_t)(tsk->dst1),
> + (uint64_t)(tsk->src1), tsk->xfer_size, tsk->dflags);
> + tsk->desc->completion_addr = (uint64_t)(tsk->comp);
> + tsk->comp->status = 0;
> + tsk->desc->src_app_tag_seed = tsk->apptag;
> + tsk->desc->src_ref_tag_seed = tsk->reftag;
> + tsk->desc->dest_ref_tag_seed = tsk->reftag;
> + tsk->desc->dest_app_tag_seed = tsk->apptag;
> + tsk->desc->src_upd_flags = 0x80;
> + tsk->desc->upd_dest_flags = 0x80;
> + tsk->desc->dif_upd_flags = tsk->blk_idx_flg;
> +}
> +
> +void dsa_reprep_dif(struct dsa_context *ctx, struct task *tsk)
> +{
> + struct dsa_completion_record *compl = tsk->comp;
> + struct dsa_hw_desc *hw = tsk->desc;
> + unsigned long blks_completed = 0;
> +
> + info("PF addr %#lx dir %d bc %#x\n",
> + compl->fault_addr, compl->result,
> + compl->bytes_completed);
> +
> + hw->src_addr += compl->bytes_completed;
> + hw->ins_ref_tag_seed = compl->dif_ins_ref_tag;
> + if (tsk->opcode == DSA_OPCODE_DIF_INS) {
> + blks_completed = compl->bytes_completed / (dif_arr[tsk->blk_idx_flg]);
> + hw->xfer_size -= compl->bytes_completed;
> + hw->dst_addr += compl->bytes_completed + 8 * blks_completed;
> + hw->ins_app_tag_seed = compl->dif_ins_app_tag;
> + hw->ins_ref_tag_seed = compl->dif_ins_ref_tag;
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_STRP) {
> + blks_completed = compl->bytes_completed / (dif_arr[tsk->blk_idx_flg] + 8);
> + hw->xfer_size -= compl->bytes_completed;
> + hw->dst_addr += dif_arr[tsk->blk_idx_flg] * blks_completed;
> + hw->chk_app_tag_seed = compl->dif_chk_app_tag;
> + hw->chk_ref_tag_seed = compl->dif_chk_ref_tag;
> + }
> +
> + if (tsk->opcode == DSA_OPCODE_DIF_UPDT) {
> + blks_completed = compl->bytes_completed / (dif_arr[tsk->blk_idx_flg] + 8);
> + hw->xfer_size -= compl->bytes_completed;
> + hw->dst_addr += (dif_arr[tsk->blk_idx_flg] + 8) * blks_completed;
> + hw->src_app_tag_seed = compl->dif_upd_src_app_tag;
> + hw->dest_app_tag_seed = compl->dif_upd_dest_app_tag;
> + hw->src_ref_tag_seed = compl->dif_upd_dest_ref_tag;
> + hw->dest_ref_tag_seed = compl->dif_upd_dest_ref_tag;
> + }
> + if (tsk->opcode == DSA_OPCODE_DIF_CHECK) {
> + blks_completed = compl->bytes_completed / (dif_arr[tsk->blk_idx_flg] + 8);
> + hw->xfer_size -= compl->bytes_completed;
> + hw->chk_app_tag_seed = compl->dif_chk_app_tag;
> + hw->chk_ref_tag_seed = compl->dif_chk_ref_tag;
> + }
> +
> + resolve_page_fault(compl->fault_addr, compl->status);
> +
> + compl->status = 0;
> +
> + dsa_desc_submit(ctx, hw);
> +}
> +
> +void dsa_prep_batch_dif_check(struct batch_task *btsk)
> +{
> + int i;
> + struct task *sub_task;
> +
> + for (i = 0; i < btsk->task_num; i++) {
> + sub_task = &btsk->sub_tasks[i];
> + sub_task->xfer_size = btsk->sub_tasks[i].xfer_size;
> + sub_task->desc->dif_chk_flags = btsk->sub_tasks[i].blk_idx_flg;
> + dsa_prep_desc_common(sub_task->desc, sub_task->opcode,
> + (uint64_t)(sub_task->dst1), (uint64_t)(sub_task->src1),
> + sub_task->xfer_size, sub_task->dflags);
> + sub_task->desc->completion_addr = (uint64_t)(sub_task->comp);
> + sub_task->comp->status = 0;
> + sub_task->desc->chk_app_tag_seed = sub_task->apptag;
> + sub_task->desc->chk_ref_tag_seed = sub_task->reftag;
> + }
> +}
> +
> +void dsa_prep_batch_dif_insert(struct batch_task *btsk)
> +{
> + int i;
> + struct task *sub_task;
> +
> + for (i = 0; i < btsk->task_num; i++) {
> + sub_task = &btsk->sub_tasks[i];
> + sub_task->xfer_size = btsk->sub_tasks[i].xfer_size;
> + sub_task->desc->dif_chk_flags = btsk->sub_tasks[i].blk_idx_flg;
> + dsa_prep_desc_common(sub_task->desc, sub_task->opcode,
> + (uint64_t)(sub_task->dst1), (uint64_t)(sub_task->src1),
> + sub_task->xfer_size, sub_task->dflags);
> + sub_task->desc->completion_addr = (uint64_t)(sub_task->comp);
> + sub_task->comp->status = 0;
> + sub_task->desc->ins_app_tag_seed = sub_task->apptag;
> + sub_task->desc->ins_ref_tag_seed = sub_task->reftag;
> + }
> +}
> +
> +void dsa_prep_batch_dif_strip(struct batch_task *btsk)
> +{
> + int i;
> + struct task *sub_task;
> +
> + for (i = 0; i < btsk->task_num; i++) {
> + sub_task = &btsk->sub_tasks[i];
> + sub_task->xfer_size = btsk->sub_tasks[i].xfer_size;
> + sub_task->desc->dif_chk_flags = btsk->sub_tasks[i].blk_idx_flg;
> + dsa_prep_desc_common(sub_task->desc, sub_task->opcode,
> + (uint64_t)(sub_task->dst1), (uint64_t)(sub_task->src1),
> + sub_task->xfer_size, sub_task->dflags);
> + sub_task->desc->completion_addr = (uint64_t)(sub_task->comp);
> + sub_task->comp->status = 0;
> + sub_task->desc->chk_app_tag_seed = sub_task->apptag;
> + sub_task->desc->chk_ref_tag_seed = sub_task->reftag;
> + }
> +}
> +
> +void dsa_prep_batch_dif_update(struct batch_task *btsk)
> +{
> + int i;
> + struct task *sub_task;
> +
> + for (i = 0; i < btsk->task_num; i++) {
> + sub_task = &btsk->sub_tasks[i];
> + sub_task->xfer_size = btsk->sub_tasks[i].xfer_size;
> + sub_task->desc->dif_chk_flags = btsk->sub_tasks[i].blk_idx_flg;
> + dsa_prep_desc_common(sub_task->desc, sub_task->opcode,
> + (uint64_t)(sub_task->dst1), (uint64_t)(sub_task->src1),
> + sub_task->xfer_size, sub_task->dflags);
> + sub_task->desc->completion_addr = (uint64_t)(sub_task->comp);
> + sub_task->comp->status = 0;
> + sub_task->desc->src_app_tag_seed = sub_task->apptag;
> + sub_task->desc->src_ref_tag_seed = sub_task->reftag;
> + sub_task->desc->dest_ref_tag_seed = sub_task->reftag;
> + sub_task->desc->dest_app_tag_seed = sub_task->apptag;
> + sub_task->desc->src_upd_flags = 0x80;
> + sub_task->desc->upd_dest_flags = 0x80;
> + }
> +}
> +
> void dsa_prep_batch(struct batch_task *btsk, unsigned long desc_flags)
> {
> struct task *ctsk = btsk->core_task;