[Accel-config] Re: [PATCH v3 6/7] accel-config/test: add 4 dif operations support
Dave Jiang <dave.jiang at intel.com> Fri, 18 Feb 2022 13:28:53 -0700
| Newsgroups | dev.linux.lists.accel-config |
|---|---|
| Message-ID | <[email protected]> |
On 2/17/2022 6:50 PM, Tony Zhu wrote:
> Add Data Integrity Field (DIF) check, insert, strip, and update
> operation support while transferring data.
I saw several comments where it says it's an issue for SPR but not GNR?
1. Please remove internal links (i.e. HSD) because this is going public.
2. Please refer to external hw errata doc if any.
3. Easiest way to deal with this is check DSA/IAX hw version via
libaccel-config call and only set these changes < version 2.
>
> Signed-off-by: Tony Zhu <tony.zhu(a)intel.com>
> ---
> test/dsa.c | 727 ++++++++++++++++++++++++++++++++++++++++++++++++
> test/dsa.h | 44 +++
> test/dsa_test.c | 104 +++++++
> test/prep.c | 189 +++++++++++++
> 4 files changed, 1064 insertions(+)
>
> diff --git a/test/dsa.c b/test/dsa.c
> index 9a10267..cd9c3d3 100644
> --- a/test/dsa.c
> +++ b/test/dsa.c
> @@ -23,6 +23,35 @@ unsigned int ms_timeout = 5000;
> int debug_logging;
> static int umwait_support;
>
> +unsigned int dif_blk_arr[] = {512, 520, 4096, 4104};
> +
> +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;
> +}
> +
> +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 +506,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 +739,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 +1676,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 +1863,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 +2145,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;