root/sys/dev/qat/qat_api/common/compression/dc_buffers.c
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright(c) 2007-2022 Intel Corporation */
/**
 *****************************************************************************
 * @file dc_buffers.c
 *
 * @defgroup Dc_DataCompression DC Data Compression
 *
 * @ingroup Dc_DataCompression
 *
 * @description
 *      Implementation of the buffer management operations for
 *      Data Compression service.
 *
 *****************************************************************************/

/*
*******************************************************************************
* Include public/global header files
*******************************************************************************
*/
#include "cpa.h"
#include "cpa_dc.h"
#include "cpa_dc_bp.h"

#include "sal_types_compression.h"
#include "icp_qat_fw_comp.h"
#include "sal_hw_gen.h"

#define CPA_DC_CEIL_DIV(x, y) (((x) + (y)-1) / (y))
#define DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 (55)
#define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC (1029)
#define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN (512)
#define DC_DEST_BUFF_MIN_EXTRA_BYTES(x) ((x < 8) ? (8 - x) : 0)
#define DC_BUF_MAX_SIZE (0xFFFFFFFF)

CpaStatus
cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle,
                           Cpa32U numBuffers,
                           Cpa32U *pSizeInBytes)
{
        CpaInstanceHandle insHandle = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) {
                insHandle = dcGetFirstHandle();
        } else {
                insHandle = instanceHandle;
        }

        LAC_CHECK_INSTANCE_HANDLE(insHandle);
        LAC_CHECK_NULL_PARAM(pSizeInBytes);

        /* Ensure this is a compression instance */
        SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);

        if (0 == numBuffers) {
                QAT_UTILS_LOG("Number of buffers is 0.\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        *pSizeInBytes = (sizeof(icp_buffer_list_desc_t) +
                         (sizeof(icp_flat_buffer_desc_t) * (numBuffers + 1)) +
                         ICP_DESCRIPTOR_ALIGNMENT_BYTES);

        return CPA_STATUS_SUCCESS;
}

CpaStatus
cpaDcBnpBufferListGetMetaSize(const CpaInstanceHandle instanceHandle,
                              Cpa32U numJobs,
                              Cpa32U *pSizeInBytes)
{
        return CPA_STATUS_UNSUPPORTED;
}

static inline CpaStatus
dcDeflateBoundGen2(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize)
{
        Cpa64U inBufferSize = inputSize;
        Cpa64U outBufferSize = 0;

        /* Formula for GEN2 deflate:
         * ceil(9 * Total input bytes / 8) + 55 bytes.
         * 55 bytes is the skid pad value for GEN2 devices.
         * Adding extra bytes = `DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize)`
         * when calculated value from `CPA_DC_CEIL_DIV(9 * inputSize, 8) +
         * DC_DEST_BUFF_EXTRA_DEFLATE_GEN2` is less than 64 bytes to
         * achieve a safer output buffer size of 64 bytes.
         */
        outBufferSize = CPA_DC_CEIL_DIV(9 * inBufferSize, 8) +
            DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 +
            DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize);

        if (outBufferSize > DC_BUF_MAX_SIZE)
                *outputSize = DC_BUF_MAX_SIZE;
        else
                *outputSize = (Cpa32U)outBufferSize;

        return CPA_STATUS_SUCCESS;
}

static inline CpaStatus
dcDeflateBoundGen4(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize)
{
        Cpa64U outputSizeLong;
        Cpa64U inputSizeLong = (Cpa64U)inputSize;

        switch (huffType) {
        case CPA_DC_HT_STATIC:
                /* Formula for GEN4 static deflate:
                 * ceil((9*sourceLen)/8) + 5 + 1024. */
                outputSizeLong = CPA_DC_CEIL_DIV(9 * inputSizeLong, 8) +
                    DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC;
                break;
        case CPA_DC_HT_FULL_DYNAMIC:
                /* Formula for GEN4 dynamic deflate:
                 * Ceil ((9*sourceLen)/8)▒| +
                 * ((((8/7) * sourceLen)/ 16KB) * (150+5)) + 512
                 */
                outputSizeLong = DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN;
                outputSizeLong += CPA_DC_CEIL_DIV(9 * inputSizeLong, 8);
                outputSizeLong += ((8 * inputSizeLong * 155) / 7) / (16 * 1024);
                break;
        default:
                return CPA_STATUS_INVALID_PARAM;
        }

        /* Avoid output size overflow */
        if (outputSizeLong & 0xffffffff00000000UL)
                return CPA_STATUS_INVALID_PARAM;

        *outputSize = (Cpa32U)outputSizeLong;
        return CPA_STATUS_SUCCESS;
}

CpaStatus
cpaDcDeflateCompressBound(const CpaInstanceHandle dcInstance,
                          CpaDcHuffType huffType,
                          Cpa32U inputSize,
                          Cpa32U *outputSize)
{
        sal_compression_service_t *pService = NULL;
        CpaInstanceHandle insHandle = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                insHandle = dcGetFirstHandle();
        } else {
                insHandle = dcInstance;
        }

        LAC_CHECK_INSTANCE_HANDLE(insHandle);
        LAC_CHECK_NULL_PARAM(outputSize);
        /* Ensure this is a compression instance */
        SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
        if (!inputSize) {
                QAT_UTILS_LOG(
                    "The input size needs to be greater than zero.\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((CPA_DC_HT_STATIC != huffType) &&
            (CPA_DC_HT_FULL_DYNAMIC != huffType)) {
                QAT_UTILS_LOG("Invalid huffType value.\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        pService = (sal_compression_service_t *)insHandle;
        if (isDcGen4x(pService)) {
                return dcDeflateBoundGen4(huffType, inputSize, outputSize);
        } else {
                return dcDeflateBoundGen2(huffType, inputSize, outputSize);
        }
}

CpaStatus
cpaDcLZ4CompressBound(const CpaInstanceHandle dcInstance,
                      Cpa32U inputSize,
                      Cpa32U *outputSize)
{
        return CPA_STATUS_UNSUPPORTED;
}

CpaStatus
cpaDcLZ4SCompressBound(const CpaInstanceHandle dcInstance,
                       Cpa32U inputSize,
                       Cpa32U *outputSize)
{
        return CPA_STATUS_UNSUPPORTED;
}