From patchwork Sat Aug 20 02:31:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Vargas, Hernan" X-Patchwork-Id: 115272 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1D3F7A034C; Fri, 19 Aug 2022 20:37:47 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7E22D42B9C; Fri, 19 Aug 2022 20:36:27 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id C5227427F6 for ; Fri, 19 Aug 2022 20:36:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1660934178; x=1692470178; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YL3ASxox9duJObNtH6vMgAGzQYnHPrp463ywKGJyrWI=; b=hRMZ+IYUlQeFSUC3gjNu8bwlcRBitJJXRTq8RCEpBhrXJNFpPy+HkG65 sNwB4LceLHv4rTFf6B4DLD9R2wcguv3GL+5Qx43LUdy5NYcar7KykCaoU WkveZs/2iPG2x3wCXDTjFuXfWXiekwc088f3f8PHmLF32pOZslukjtraT T38OvV1j0RKl3MoVkMDOKiTI4U/ey3FReIgKrde+pnwksyWj7rIe4hkyO ARBSpMPN5BvC5GlTaWLUQJVLJ1Kxk7EpPCejDZiRxcWWaBBOd6R71vu5e bzzrHRqPNbw0Z8ApXw3nL65fvctOPXhaVKZCk/ikmb+K8WmQCFWRJbsuN A==; X-IronPort-AV: E=McAfee;i="6500,9779,10444"; a="319107258" X-IronPort-AV: E=Sophos;i="5.93,248,1654585200"; d="scan'208";a="319107258" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2022 11:36:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,248,1654585200"; d="scan'208";a="608296291" Received: from unknown (HELO csl-npg-qt0.la.intel.com) ([10.233.181.103]) by orsmga002.jf.intel.com with ESMTP; 19 Aug 2022 11:36:17 -0700 From: Hernan Vargas To: dev@dpdk.org, gakhil@marvell.com, trix@redhat.com Cc: nicolas.chautru@intel.com, qi.z.zhang@intel.com, Hernan Vargas Subject: [PATCH v2 14/37] baseband/acc100: update validate LDPC enc/dec Date: Fri, 19 Aug 2022 19:31:34 -0700 Message-Id: <20220820023157.189047-15-hernan.vargas@intel.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220820023157.189047-1-hernan.vargas@intel.com> References: <20220820023157.189047-1-hernan.vargas@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Update validate functions to check for valid LDPC parameters to avoid any HW issues. Adding protection for null corner case and for HARQ inbound size out of range. HARQ input size from application may be invalid and causing HW issue. Add checks to ensure that if HARQ is invalid, set to some valid size to ensure HW issues do not occur. Signed-off-by: Hernan Vargas --- drivers/baseband/acc100/rte_acc100_pmd.c | 297 +++++++++++++++++++++-- 1 file changed, 283 insertions(+), 14 deletions(-) diff --git a/drivers/baseband/acc100/rte_acc100_pmd.c b/drivers/baseband/acc100/rte_acc100_pmd.c index e47f7d68c2..1504acfadd 100644 --- a/drivers/baseband/acc100/rte_acc100_pmd.c +++ b/drivers/baseband/acc100/rte_acc100_pmd.c @@ -2404,10 +2404,6 @@ validate_ldpc_enc_op(struct rte_bbdev_enc_op *op, struct acc100_queue *q) if (!validate_op_required(q)) return 0; - if (op->mempool == NULL) { - rte_bbdev_log(ERR, "Invalid mempool pointer"); - return -1; - } if (ldpc_enc->input.data == NULL) { rte_bbdev_log(ERR, "Invalid input pointer"); return -1; @@ -2416,11 +2412,9 @@ validate_ldpc_enc_op(struct rte_bbdev_enc_op *op, struct acc100_queue *q) rte_bbdev_log(ERR, "Invalid output pointer"); return -1; } - if (ldpc_enc->input.length > - RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) { - rte_bbdev_log(ERR, "CB size (%u) is too big, max: %d", - ldpc_enc->input.length, - RTE_BBDEV_LDPC_MAX_CB_SIZE); + if (ldpc_enc->input.length == 0) { + rte_bbdev_log(ERR, "CB size (%u) is null", + ldpc_enc->input.length); return -1; } if ((ldpc_enc->basegraph > 2) || (ldpc_enc->basegraph == 0)) { @@ -2441,13 +2435,107 @@ validate_ldpc_enc_op(struct rte_bbdev_enc_op *op, struct acc100_queue *q) ldpc_enc->code_block_mode); return -1; } + if (ldpc_enc->z_c > 384) { + rte_bbdev_log(ERR, + "Zc (%u) is out of range", + ldpc_enc->z_c); + return -1; + } int K = (ldpc_enc->basegraph == 1 ? 22 : 10) * ldpc_enc->z_c; - if (ldpc_enc->n_filler >= K) { + int N = (ldpc_enc->basegraph == 1 ? ACC100_N_ZC_1 : ACC100_N_ZC_2) + * ldpc_enc->z_c; + int q_m = ldpc_enc->q_m; + int crc24 = 0; + + if (check_bit(op->ldpc_enc.op_flags, + RTE_BBDEV_LDPC_CRC_24A_ATTACH) || + check_bit(op->ldpc_enc.op_flags, + RTE_BBDEV_LDPC_CRC_24B_ATTACH)) + crc24 = 24; + if ((K - ldpc_enc->n_filler) % 8 > 0) { rte_bbdev_log(ERR, - "K and F are not compatible %u %u", + "K - F not byte aligned %u", + K - ldpc_enc->n_filler); + return -1; + } + if (ldpc_enc->n_filler > (K - 2 * ldpc_enc->z_c)) { + rte_bbdev_log(ERR, + "K - F invalid %u %u", K, ldpc_enc->n_filler); return -1; } + if ((ldpc_enc->n_cb > N) || (ldpc_enc->n_cb <= K)) { + rte_bbdev_log(ERR, + "Ncb (%u) is out of range K %d N %d", + ldpc_enc->n_cb, K, N); + return -1; + } + if (!check_bit(op->ldpc_enc.op_flags, + RTE_BBDEV_LDPC_INTERLEAVER_BYPASS) && + ((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1)) + || (q_m > 8))) { + rte_bbdev_log(ERR, + "Qm (%u) is out of range", + ldpc_enc->q_m); + return -1; + } + if (ldpc_enc->code_block_mode == RTE_BBDEV_CODE_BLOCK) { + if (ldpc_enc->cb_params.e == 0) { + rte_bbdev_log(ERR, + "E is null"); + return -1; + } + if (q_m > 0) { + if (ldpc_enc->cb_params.e % q_m > 0) { + rte_bbdev_log(ERR, + "E not multiple of qm %d", q_m); + return -1; + } + } + if ((ldpc_enc->z_c <= 11) && (ldpc_enc->cb_params.e > 3456)) { + rte_bbdev_log(ERR, + "E too large for small block"); + return -1; + } + if (ldpc_enc->input.length > + RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) { + rte_bbdev_log(ERR, "CB size (%u) is too big, max: %d", + ldpc_enc->input.length, + RTE_BBDEV_LDPC_MAX_CB_SIZE); + return -1; + } + if (K < (int) (ldpc_enc->input.length * 8 + + ldpc_enc->n_filler) + crc24) { + rte_bbdev_log(ERR, + "K and F not matching input size %u %u %u", + K, ldpc_enc->n_filler, + ldpc_enc->input.length); + return -1; + } + } else { + if ((ldpc_enc->tb_params.c == 0) || + (ldpc_enc->tb_params.ea == 0) || + (ldpc_enc->tb_params.eb == 0)) { + rte_bbdev_log(ERR, + "TB parameter is null"); + return -1; + } + if (q_m > 0) { + if ((ldpc_enc->tb_params.ea % q_m > 0) || + (ldpc_enc->tb_params.eb % q_m > 0)) { + rte_bbdev_log(ERR, + "E not multiple of qm %d", + q_m); + return -1; + } + } + if ((ldpc_enc->z_c <= 11) && (RTE_MAX(ldpc_enc->tb_params.ea, + ldpc_enc->tb_params.eb) > 3456)) { + rte_bbdev_log(ERR, + "E too large for small block"); + return -1; + } + } return 0; } @@ -2460,8 +2548,16 @@ validate_ldpc_dec_op(struct rte_bbdev_dec_op *op, struct acc100_queue *q) if (!validate_op_required(q)) return 0; - if (op->mempool == NULL) { - rte_bbdev_log(ERR, "Invalid mempool pointer"); + if (ldpc_dec->input.data == NULL) { + rte_bbdev_log(ERR, "Invalid input pointer"); + return -1; + } + if (ldpc_dec->hard_output.data == NULL) { + rte_bbdev_log(ERR, "Invalid output pointer"); + return -1; + } + if (ldpc_dec->input.length == 0) { + rte_bbdev_log(ERR, "input is null"); return -1; } if ((ldpc_dec->basegraph > 2) || (ldpc_dec->basegraph == 0)) { @@ -2488,13 +2584,186 @@ validate_ldpc_dec_op(struct rte_bbdev_dec_op *op, struct acc100_queue *q) ldpc_dec->code_block_mode); return -1; } + /* Check Zc is valid value */ + if ((ldpc_dec->z_c > 384) || (ldpc_dec->z_c < 2)) { + rte_bbdev_log(ERR, + "Zc (%u) is out of range", + ldpc_dec->z_c); + return -1; + } + if (ldpc_dec->z_c > 256) { + if ((ldpc_dec->z_c % 32) != 0) { + rte_bbdev_log(ERR, "Invalid Zc %d", ldpc_dec->z_c); + return -1; + } + } else if (ldpc_dec->z_c > 128) { + if ((ldpc_dec->z_c % 16) != 0) { + rte_bbdev_log(ERR, "Invalid Zc %d", ldpc_dec->z_c); + return -1; + } + } else if (ldpc_dec->z_c > 64) { + if ((ldpc_dec->z_c % 8) != 0) { + rte_bbdev_log(ERR, "Invalid Zc %d", ldpc_dec->z_c); + return -1; + } + } else if (ldpc_dec->z_c > 32) { + if ((ldpc_dec->z_c % 4) != 0) { + rte_bbdev_log(ERR, "Invalid Zc %d", ldpc_dec->z_c); + return -1; + } + } else if (ldpc_dec->z_c > 16) { + if ((ldpc_dec->z_c % 2) != 0) { + rte_bbdev_log(ERR, "Invalid Zc %d", ldpc_dec->z_c); + return -1; + } + } int K = (ldpc_dec->basegraph == 1 ? 22 : 10) * ldpc_dec->z_c; - if (ldpc_dec->n_filler >= K) { + int N = (ldpc_dec->basegraph == 1 ? ACC100_N_ZC_1 : ACC100_N_ZC_2) + * ldpc_dec->z_c; + int q_m = ldpc_dec->q_m; + if (ldpc_dec->n_filler >= K - 2 * ldpc_dec->z_c) { rte_bbdev_log(ERR, "K and F are not compatible %u %u", K, ldpc_dec->n_filler); return -1; } + if ((ldpc_dec->n_cb > N) || (ldpc_dec->n_cb <= K)) { + rte_bbdev_log(ERR, + "Ncb (%u) is out of range K %d N %d", + ldpc_dec->n_cb, K, N); + return -1; + } + + if (((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1)) + || (q_m > 8))) { + rte_bbdev_log(ERR, + "Qm (%u) is out of range", + ldpc_dec->q_m); + return -1; + } + if (ldpc_dec->code_block_mode == RTE_BBDEV_CODE_BLOCK) { + if (ldpc_dec->cb_params.e == 0) { + rte_bbdev_log(ERR, + "E is null"); + return -1; + } + if (ldpc_dec->cb_params.e % q_m > 0) { + rte_bbdev_log(ERR, + "E not multiple of qm %d", q_m); + return -1; + } + if (ldpc_dec->cb_params.e > 512 * ldpc_dec->z_c) { + rte_bbdev_log(ERR, + "E too high"); + return -1; + } + } else { + if ((ldpc_dec->tb_params.c == 0) || + (ldpc_dec->tb_params.ea == 0) || + (ldpc_dec->tb_params.eb == 0)) { + rte_bbdev_log(ERR, + "TB parameter is null"); + return -1; + } + if ((ldpc_dec->tb_params.ea % q_m > 0) || + (ldpc_dec->tb_params.eb % q_m > 0)) { + rte_bbdev_log(ERR, + "E not multiple of qm %d", q_m); + return -1; + } + if ((ldpc_dec->tb_params.ea > 512 * ldpc_dec->z_c) || + (ldpc_dec->tb_params.eb > 512 * ldpc_dec->z_c)) { + rte_bbdev_log(ERR, + "E too high"); + return -1; + } + } + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_DECODE_BYPASS)) { + rte_bbdev_log(ERR, "Avoid LDPC Decode bypass"); + return -1; + } + + /* Avoid HARQ compression for small block size */ + if ((check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION)) + && (K < 2048)) { + op->ldpc_dec.op_flags ^= RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION; + } + uint32_t min_harq_input = check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION) ? 256 : 64; + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) && + ldpc_dec->harq_combined_input.length < + min_harq_input) { + rte_bbdev_log(ERR, "HARQ input size is too small %d < %d", + ldpc_dec->harq_combined_input.length, + min_harq_input); + return -1; + } + + /* Enforce in-range HARQ input size */ + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) { + uint32_t max_harq_input = RTE_ALIGN_CEIL(ldpc_dec->n_cb - + ldpc_dec->n_filler, 64); + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION)) + max_harq_input = max_harq_input * 3 / 4; + if (ldpc_dec->harq_combined_input.length > max_harq_input) { + rte_bbdev_log(ERR, + "HARQ input size out of range %d > %d, Ncb %d F %d K %d N %d", + ldpc_dec->harq_combined_input.length, + max_harq_input, ldpc_dec->n_cb, + ldpc_dec->n_filler, K, N); + /* Fallback to flush HARQ combine */ + ldpc_dec->harq_combined_input.length = 0; + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) { + op->ldpc_dec.op_flags ^= + RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE; + } + } + } + +#ifdef ACC100_EXT_MEM + /* Enforce in-range HARQ offset */ + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) { + if ((op->ldpc_dec.harq_combined_input.offset >> 10) + >= q->d->ddr_size) { + rte_bbdev_log(ERR, + "HARQin offset out of range %d > %d", + op->ldpc_dec.harq_combined_input.offset, + q->d->ddr_size); + return -1; + } + if ((op->ldpc_dec.harq_combined_input.offset & 0x3FF) > 0) { + rte_bbdev_log(ERR, + "HARQin offset not aligned on 1kB %d", + op->ldpc_dec.harq_combined_input.offset); + return -1; + } + } + if (check_bit(op->ldpc_dec.op_flags, + RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) { + if ((op->ldpc_dec.harq_combined_output.offset >> 10) + >= q->d->ddr_size) { + rte_bbdev_log(ERR, + "HARQout offset out of range %d > %d", + op->ldpc_dec.harq_combined_output.offset, + q->d->ddr_size); + return -1; + } + if ((op->ldpc_dec.harq_combined_output.offset & 0x3FF) > 0) { + rte_bbdev_log(ERR, + "HARQout offset not aligned on 1kB %d", + op->ldpc_dec.harq_combined_output.offset); + return -1; + } + } +#endif + return 0; } #endif