mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
crypto: qat - add support for zstd
Add support for the ZSTD algorithm for QAT GEN4, GEN5 and GEN6 via the acomp API. For GEN4 and GEN5, compression is performed in hardware using LZ4s, a QAT-specific variant of LZ4. The compressed output is post-processed to generate ZSTD sequences, and the ZSTD library is then used to produce the final ZSTD stream via zstd_compress_sequences_and_literals(). Only inputs between 8 KB and 512 KB are offloaded to the device. The minimum size restriction will be relaxed once polling support is added. The maximum size is limited by the use of pre-allocated per-CPU scratch buffers. On these generations, only compression is offloaded to hardware; decompression always falls back to software. For GEN6, both compression and decompression are offloaded to the accelerator, which natively supports the ZSTD algorithm. There is no limit on the input buffer size supported. However, since GEN6 is limited to a history size of 64 KB, decompression of frames compressed with a larger history falls back to software. Since GEN2 devices do not support ZSTD or LZ4s, add a mechanism that prevents selecting GEN2 compression instances for ZSTD or LZ4s when a GEN2 plug-in card is present on a system with an embedded GEN4, GEN5 or GEN6 device. In addition, modify the algorithm registration logic to allow registering the correct implementation, i.e. LZ4s based for GEN4 and GEN5 or native ZSTD for GEN6. Co-developed-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com> Signed-off-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com> Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> Reviewed-by: Laurent M Coquerel <laurent.m.coquerel@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
committed by
Herbert Xu
parent
35ecb77ae0
commit
879a4f78ea
@@ -12,6 +12,7 @@ config CRYPTO_DEV_QAT
|
||||
select CRYPTO_LIB_SHA1
|
||||
select CRYPTO_LIB_SHA256
|
||||
select CRYPTO_LIB_SHA512
|
||||
select CRYPTO_ZSTD
|
||||
select FW_LOADER
|
||||
select CRC8
|
||||
|
||||
|
||||
@@ -488,6 +488,7 @@ void adf_init_hw_data_420xx(struct adf_hw_device_data *hw_data, u32 dev_id)
|
||||
hw_data->clock_frequency = ADF_420XX_AE_FREQ;
|
||||
hw_data->services_supported = adf_gen4_services_supported;
|
||||
hw_data->get_svc_slice_cnt = adf_gen4_get_svc_slice_cnt;
|
||||
hw_data->accel_capabilities_ext_mask = ADF_ACCEL_CAPABILITIES_EXT_ZSTD_LZ4S;
|
||||
|
||||
adf_gen4_set_err_mask(&hw_data->dev_err_mask);
|
||||
adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
|
||||
|
||||
@@ -473,6 +473,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
|
||||
hw_data->clock_frequency = ADF_4XXX_AE_FREQ;
|
||||
hw_data->services_supported = adf_gen4_services_supported;
|
||||
hw_data->get_svc_slice_cnt = adf_gen4_get_svc_slice_cnt;
|
||||
hw_data->accel_capabilities_ext_mask = ADF_ACCEL_CAPABILITIES_EXT_ZSTD_LZ4S;
|
||||
|
||||
adf_gen4_set_err_mask(&hw_data->dev_err_mask);
|
||||
adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define ADF_AE_GROUP_1 GENMASK(7, 4)
|
||||
#define ADF_AE_GROUP_2 BIT(8)
|
||||
|
||||
#define ASB_MULTIPLIER 9
|
||||
|
||||
struct adf_ring_config {
|
||||
u32 ring_mask;
|
||||
enum adf_cfg_service_type ring_type;
|
||||
@@ -509,6 +511,9 @@ static int build_comp_block(void *ctx, enum adf_dc_algo algo)
|
||||
case QAT_DEFLATE:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC;
|
||||
break;
|
||||
case QAT_ZSTD:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_ZSTD_COMPRESS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -519,6 +524,13 @@ static int build_comp_block(void *ctx, enum adf_dc_algo algo)
|
||||
cd_pars->u.sl.comp_slice_cfg_word[0] = lower_val;
|
||||
cd_pars->u.sl.comp_slice_cfg_word[1] = 0;
|
||||
|
||||
/*
|
||||
* Store Auto Select Best (ASB) multiplier in the request template.
|
||||
* This will be used in the data path to set the actual threshold
|
||||
* value based on the input data size.
|
||||
*/
|
||||
req_tmpl->u3.asb_threshold.asb_value = ASB_MULTIPLIER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,12 +544,16 @@ static int build_decomp_block(void *ctx, enum adf_dc_algo algo)
|
||||
case QAT_DEFLATE:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
|
||||
break;
|
||||
case QAT_ZSTD:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_ZSTD_DECOMPRESS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cd_pars->u.sl.comp_slice_cfg_word[0] = 0;
|
||||
cd_pars->u.sl.comp_slice_cfg_word[1] = 0;
|
||||
req_tmpl->u3.asb_threshold.asb_value = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1030,6 +1046,7 @@ void adf_init_hw_data_6xxx(struct adf_hw_device_data *hw_data)
|
||||
hw_data->num_rps = ADF_GEN6_ETR_MAX_BANKS;
|
||||
hw_data->clock_frequency = ADF_6XXX_AE_FREQ;
|
||||
hw_data->get_svc_slice_cnt = adf_gen6_get_svc_slice_cnt;
|
||||
hw_data->accel_capabilities_ext_mask = ADF_ACCEL_CAPABILITIES_EXT_ZSTD;
|
||||
|
||||
adf_gen6_init_services_supported(hw_data);
|
||||
adf_gen6_init_hw_csr_ops(&hw_data->csr_ops);
|
||||
|
||||
@@ -41,6 +41,7 @@ intel_qat-y := adf_accel_engine.o \
|
||||
qat_bl.o \
|
||||
qat_comp_algs.o \
|
||||
qat_compression.o \
|
||||
qat_comp_zstd_utils.o \
|
||||
qat_crypto.o \
|
||||
qat_hal.o \
|
||||
qat_mig_dev.o \
|
||||
|
||||
@@ -59,6 +59,11 @@ enum adf_accel_capabilities {
|
||||
ADF_ACCEL_CAPABILITIES_RANDOM_NUMBER = 128
|
||||
};
|
||||
|
||||
enum adf_accel_capabilities_ext {
|
||||
ADF_ACCEL_CAPABILITIES_EXT_ZSTD_LZ4S = BIT(0),
|
||||
ADF_ACCEL_CAPABILITIES_EXT_ZSTD = BIT(1),
|
||||
};
|
||||
|
||||
enum adf_fuses {
|
||||
ADF_FUSECTL0,
|
||||
ADF_FUSECTL1,
|
||||
@@ -336,6 +341,7 @@ struct adf_hw_device_data {
|
||||
u32 fuses[ADF_MAX_FUSES];
|
||||
u32 straps;
|
||||
u32 accel_capabilities_mask;
|
||||
u32 accel_capabilities_ext_mask;
|
||||
u32 extended_dc_capabilities;
|
||||
u16 fw_capabilities;
|
||||
u32 clock_frequency;
|
||||
|
||||
@@ -111,12 +111,12 @@ void qat_algs_unregister(void);
|
||||
int qat_asym_algs_register(void);
|
||||
void qat_asym_algs_unregister(void);
|
||||
|
||||
struct qat_compression_instance *qat_compression_get_instance_node(int node);
|
||||
struct qat_compression_instance *qat_compression_get_instance_node(int node, int alg);
|
||||
void qat_compression_put_instance(struct qat_compression_instance *inst);
|
||||
int qat_compression_register(void);
|
||||
int qat_compression_unregister(void);
|
||||
int qat_comp_algs_register(void);
|
||||
void qat_comp_algs_unregister(void);
|
||||
int qat_comp_algs_register(u32 caps);
|
||||
void qat_comp_algs_unregister(u32 caps);
|
||||
void qat_comp_alg_callback(void *resp);
|
||||
|
||||
int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev);
|
||||
|
||||
@@ -504,14 +504,20 @@ static int adf_gen4_build_comp_block(void *ctx, enum adf_dc_algo algo)
|
||||
switch (algo) {
|
||||
case QAT_DEFLATE:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC;
|
||||
hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_ILZ77;
|
||||
hw_comp_lower_csr.lllbd = ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED;
|
||||
hw_comp_lower_csr.skip_ctrl = ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_LITERAL;
|
||||
break;
|
||||
case QAT_LZ4S:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_20_CMD_LZ4S_COMPRESS;
|
||||
hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4S;
|
||||
hw_comp_lower_csr.lllbd = ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_DISABLED;
|
||||
hw_comp_lower_csr.abd = ICP_QAT_HW_COMP_20_ABD_ABD_DISABLED;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_comp_lower_csr.skip_ctrl = ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_LITERAL;
|
||||
hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_ILZ77;
|
||||
hw_comp_lower_csr.lllbd = ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED;
|
||||
hw_comp_lower_csr.sd = ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_1;
|
||||
hw_comp_lower_csr.hash_update = ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_DONT_ALLOW;
|
||||
hw_comp_lower_csr.edmm = ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_ENABLED;
|
||||
@@ -538,12 +544,16 @@ static int adf_gen4_build_decomp_block(void *ctx, enum adf_dc_algo algo)
|
||||
switch (algo) {
|
||||
case QAT_DEFLATE:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
|
||||
hw_decomp_lower_csr.algo = ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE;
|
||||
break;
|
||||
case QAT_LZ4S:
|
||||
header->service_cmd_id = ICP_QAT_FW_COMP_20_CMD_LZ4S_DECOMPRESS;
|
||||
hw_decomp_lower_csr.algo = ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_LZ4S;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_decomp_lower_csr.algo = ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE;
|
||||
lower_val = ICP_QAT_FW_DECOMP_20_BUILD_CONFIG_LOWER(hw_decomp_lower_csr);
|
||||
|
||||
cd_pars->u.sl.comp_slice_cfg_word[0] = lower_val;
|
||||
|
||||
@@ -180,6 +180,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
|
||||
{
|
||||
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
|
||||
struct service_hndl *service;
|
||||
u32 caps;
|
||||
int ret;
|
||||
|
||||
set_bit(ADF_STATUS_STARTING, &accel_dev->status);
|
||||
@@ -253,7 +254,8 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
|
||||
}
|
||||
set_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status);
|
||||
|
||||
if (!list_empty(&accel_dev->compression_list) && qat_comp_algs_register()) {
|
||||
caps = hw_data->accel_capabilities_ext_mask;
|
||||
if (!list_empty(&accel_dev->compression_list) && qat_comp_algs_register(caps)) {
|
||||
dev_err(&GET_DEV(accel_dev),
|
||||
"Failed to register compression algs\n");
|
||||
set_bit(ADF_STATUS_STARTING, &accel_dev->status);
|
||||
@@ -308,7 +310,7 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
|
||||
|
||||
if (!list_empty(&accel_dev->compression_list) &&
|
||||
test_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status))
|
||||
qat_comp_algs_unregister();
|
||||
qat_comp_algs_unregister(hw_data->accel_capabilities_ext_mask);
|
||||
clear_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status);
|
||||
|
||||
list_for_each_entry(service, &service_table, list) {
|
||||
|
||||
@@ -151,6 +151,13 @@ struct icp_qat_fw_comn_resp {
|
||||
ICP_QAT_FW_COMN_CNV_FLAG_BITPOS, \
|
||||
ICP_QAT_FW_COMN_CNV_FLAG_MASK)
|
||||
|
||||
#define ICP_QAT_FW_COMN_ST_BLK_FLAG_BITPOS 4
|
||||
#define ICP_QAT_FW_COMN_ST_BLK_FLAG_MASK 0x1
|
||||
#define ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(hdr_flags) \
|
||||
QAT_FIELD_GET(hdr_flags, \
|
||||
ICP_QAT_FW_COMN_ST_BLK_FLAG_BITPOS, \
|
||||
ICP_QAT_FW_COMN_ST_BLK_FLAG_MASK)
|
||||
|
||||
#define ICP_QAT_FW_COMN_HDR_CNV_FLAG_SET(hdr_t, val) \
|
||||
QAT_FIELD_SET((hdr_t.hdr_flags), (val), \
|
||||
ICP_QAT_FW_COMN_CNV_FLAG_BITPOS, \
|
||||
|
||||
@@ -8,6 +8,8 @@ enum icp_qat_fw_comp_cmd_id {
|
||||
ICP_QAT_FW_COMP_CMD_STATIC = 0,
|
||||
ICP_QAT_FW_COMP_CMD_DYNAMIC = 1,
|
||||
ICP_QAT_FW_COMP_CMD_DECOMPRESS = 2,
|
||||
ICP_QAT_FW_COMP_CMD_ZSTD_COMPRESS = 10,
|
||||
ICP_QAT_FW_COMP_CMD_ZSTD_DECOMPRESS = 11,
|
||||
ICP_QAT_FW_COMP_CMD_DELIMITER
|
||||
};
|
||||
|
||||
|
||||
@@ -336,7 +336,8 @@ enum icp_qat_hw_compression_delayed_match {
|
||||
enum icp_qat_hw_compression_algo {
|
||||
ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE = 0,
|
||||
ICP_QAT_HW_COMPRESSION_ALGO_LZS = 1,
|
||||
ICP_QAT_HW_COMPRESSION_ALGO_DELIMITER = 2
|
||||
ICP_QAT_HW_COMPRESSION_ALGO_ZSTD = 2,
|
||||
ICP_QAT_HW_COMPRESSION_ALGO_DELIMITER
|
||||
};
|
||||
|
||||
enum icp_qat_hw_compression_depth {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ static inline void qat_comp_create_req(void *ctx, void *req, u64 src, u32 slen,
|
||||
fw_req->comn_mid.opaque_data = opaque;
|
||||
req_pars->comp_len = slen;
|
||||
req_pars->out_buffer_sz = dlen;
|
||||
fw_req->u3.asb_threshold.asb_value *= slen >> 4;
|
||||
}
|
||||
|
||||
static inline void qat_comp_create_compression_req(void *ctx, void *req,
|
||||
@@ -110,4 +111,12 @@ static inline u8 qat_comp_get_cmp_cnv_flag(void *resp)
|
||||
return ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(flags);
|
||||
}
|
||||
|
||||
static inline u8 qat_comp_get_cmp_uncomp_flag(void *resp)
|
||||
{
|
||||
struct icp_qat_fw_comp_resp *qat_resp = resp;
|
||||
u8 flags = qat_resp->comn_resp.hdr_flags;
|
||||
|
||||
return ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright(c) 2026 Intel Corporation */
|
||||
#include <linux/errno.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <linux/zstd.h>
|
||||
|
||||
#include "qat_comp_zstd_utils.h"
|
||||
|
||||
#define ML_BITS 4
|
||||
#define ML_MASK ((1U << ML_BITS) - 1)
|
||||
#define RUN_BITS (8 - ML_BITS)
|
||||
#define RUN_MASK ((1U << RUN_BITS) - 1)
|
||||
#define LZ4S_MINMATCH 2
|
||||
|
||||
/*
|
||||
* ZSTD blocks can decompress to at most min(windowSize, 128KB) bytes.
|
||||
* Insert explicit block delimiters to keep blocks within this limit.
|
||||
*/
|
||||
#define QAT_ZSTD_BLOCK_MAX ZSTD_BLOCKSIZE_MAX
|
||||
|
||||
static int emit_delimiter(ZSTD_Sequence *out_seqs, size_t *seqs_idx,
|
||||
size_t out_seqs_capacity, unsigned int lz4s_buff_size)
|
||||
{
|
||||
if (*seqs_idx >= out_seqs_capacity - 1) {
|
||||
pr_debug("QAT ZSTD: sequence overflow (seqs_idx:%zu, capacity:%zu, lz4s_size:%u)\n",
|
||||
*seqs_idx, out_seqs_capacity, lz4s_buff_size);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
out_seqs[*seqs_idx].offset = 0;
|
||||
out_seqs[*seqs_idx].litLength = 0;
|
||||
out_seqs[*seqs_idx].matchLength = 0;
|
||||
(*seqs_idx)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qat_alg_dec_lz4s(ZSTD_Sequence *out_seqs, size_t out_seqs_capacity,
|
||||
unsigned char *lz4s_buff, unsigned int lz4s_buff_size,
|
||||
unsigned char *literals, unsigned int *lit_len)
|
||||
{
|
||||
unsigned char *end_ip = lz4s_buff + lz4s_buff_size;
|
||||
unsigned char *start, *dest, *dest_end;
|
||||
unsigned int hist_literal_len = 0;
|
||||
unsigned char *ip = lz4s_buff;
|
||||
size_t block_decomp_size = 0;
|
||||
size_t seqs_idx = 0;
|
||||
int ret;
|
||||
|
||||
*lit_len = 0;
|
||||
|
||||
if (!lz4s_buff_size)
|
||||
return 0;
|
||||
|
||||
while (ip < end_ip) {
|
||||
size_t literal_len = 0, match_len = 0;
|
||||
const unsigned int token = *ip++;
|
||||
size_t length = 0;
|
||||
size_t offset = 0;
|
||||
|
||||
/* Get literal length */
|
||||
length = token >> ML_BITS;
|
||||
if (length == RUN_MASK) {
|
||||
unsigned int s;
|
||||
|
||||
do {
|
||||
s = *ip++;
|
||||
length += s;
|
||||
} while (s == 255);
|
||||
}
|
||||
|
||||
literal_len = length;
|
||||
|
||||
start = ip;
|
||||
dest = literals;
|
||||
dest_end = literals + length;
|
||||
|
||||
do {
|
||||
memcpy(dest, start, QAT_ZSTD_LIT_COPY_LEN);
|
||||
dest += QAT_ZSTD_LIT_COPY_LEN;
|
||||
start += QAT_ZSTD_LIT_COPY_LEN;
|
||||
} while (dest < dest_end);
|
||||
|
||||
literals += length;
|
||||
*lit_len += length;
|
||||
|
||||
ip += length;
|
||||
if (ip == end_ip) {
|
||||
literal_len += hist_literal_len;
|
||||
/*
|
||||
* If adding trailing literals would overflow the
|
||||
* current block, close it first.
|
||||
*/
|
||||
if (block_decomp_size + literal_len > QAT_ZSTD_BLOCK_MAX) {
|
||||
ret = emit_delimiter(out_seqs, &seqs_idx,
|
||||
out_seqs_capacity,
|
||||
lz4s_buff_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
out_seqs[seqs_idx].litLength = literal_len;
|
||||
out_seqs[seqs_idx].offset = offset;
|
||||
out_seqs[seqs_idx].matchLength = match_len;
|
||||
break;
|
||||
}
|
||||
|
||||
offset = get_unaligned_le16(ip);
|
||||
ip += 2;
|
||||
|
||||
length = token & ML_MASK;
|
||||
if (length == ML_MASK) {
|
||||
unsigned int s;
|
||||
|
||||
do {
|
||||
s = *ip++;
|
||||
length += s;
|
||||
} while (s == 255);
|
||||
}
|
||||
if (length != 0) {
|
||||
length += LZ4S_MINMATCH;
|
||||
match_len = (unsigned short)length;
|
||||
literal_len += hist_literal_len;
|
||||
|
||||
/*
|
||||
* If this sequence would push the current block past
|
||||
* the ZSTD maximum, close the block first.
|
||||
*/
|
||||
if (block_decomp_size + literal_len + match_len > QAT_ZSTD_BLOCK_MAX) {
|
||||
ret = emit_delimiter(out_seqs, &seqs_idx,
|
||||
out_seqs_capacity,
|
||||
lz4s_buff_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
block_decomp_size = 0;
|
||||
}
|
||||
|
||||
out_seqs[seqs_idx].offset = offset;
|
||||
out_seqs[seqs_idx].litLength = literal_len;
|
||||
out_seqs[seqs_idx].matchLength = match_len;
|
||||
hist_literal_len = 0;
|
||||
seqs_idx++;
|
||||
if (seqs_idx >= out_seqs_capacity - 1) {
|
||||
pr_debug("QAT ZSTD: sequence overflow (seqs_idx:%zu, capacity:%zu, lz4s_size:%u)\n",
|
||||
seqs_idx, out_seqs_capacity, lz4s_buff_size);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
block_decomp_size += literal_len + match_len;
|
||||
} else {
|
||||
if (literal_len > 0) {
|
||||
/*
|
||||
* When match length is 0, the literal length needs
|
||||
* to be temporarily stored and processed together
|
||||
* with the next data block.
|
||||
*/
|
||||
hist_literal_len += literal_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return seqs_idx + 1;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright(c) 2026 Intel Corporation */
|
||||
#ifndef QAT_COMP_ZSTD_UTILS_H_
|
||||
#define QAT_COMP_ZSTD_UTILS_H_
|
||||
#include <linux/zstd_lib.h>
|
||||
|
||||
#define QAT_ZSTD_LIT_COPY_LEN 8
|
||||
|
||||
int qat_alg_dec_lz4s(ZSTD_Sequence *out_seqs, size_t out_seqs_capacity,
|
||||
unsigned char *lz4s_buff, unsigned int lz4s_buff_size,
|
||||
unsigned char *literals, unsigned int *lit_len);
|
||||
|
||||
#endif
|
||||
@@ -46,12 +46,14 @@ static int qat_compression_free_instances(struct adf_accel_dev *accel_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct qat_compression_instance *qat_compression_get_instance_node(int node)
|
||||
struct qat_compression_instance *qat_compression_get_instance_node(int node, int alg)
|
||||
{
|
||||
struct qat_compression_instance *inst = NULL;
|
||||
struct adf_hw_device_data *hw_data = NULL;
|
||||
struct adf_accel_dev *accel_dev = NULL;
|
||||
unsigned long best = ~0;
|
||||
struct list_head *itr;
|
||||
u32 caps, mask;
|
||||
|
||||
list_for_each(itr, adf_devmgr_get_head()) {
|
||||
struct adf_accel_dev *tmp_dev;
|
||||
@@ -61,6 +63,15 @@ struct qat_compression_instance *qat_compression_get_instance_node(int node)
|
||||
tmp_dev = list_entry(itr, struct adf_accel_dev, list);
|
||||
tmp_dev_node = dev_to_node(&GET_DEV(tmp_dev));
|
||||
|
||||
if (alg == QAT_ZSTD || alg == QAT_LZ4S) {
|
||||
hw_data = tmp_dev->hw_device;
|
||||
caps = hw_data->accel_capabilities_ext_mask;
|
||||
mask = ADF_ACCEL_CAPABILITIES_EXT_ZSTD |
|
||||
ADF_ACCEL_CAPABILITIES_EXT_ZSTD_LZ4S;
|
||||
if (!(caps & mask))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((node == tmp_dev_node || tmp_dev_node < 0) &&
|
||||
adf_dev_started(tmp_dev) && !list_empty(&tmp_dev->compression_list)) {
|
||||
ctr = atomic_read(&tmp_dev->ref_count);
|
||||
@@ -78,6 +89,16 @@ struct qat_compression_instance *qat_compression_get_instance_node(int node)
|
||||
struct adf_accel_dev *tmp_dev;
|
||||
|
||||
tmp_dev = list_entry(itr, struct adf_accel_dev, list);
|
||||
|
||||
if (alg == QAT_ZSTD || alg == QAT_LZ4S) {
|
||||
hw_data = tmp_dev->hw_device;
|
||||
caps = hw_data->accel_capabilities_ext_mask;
|
||||
mask = ADF_ACCEL_CAPABILITIES_EXT_ZSTD |
|
||||
ADF_ACCEL_CAPABILITIES_EXT_ZSTD_LZ4S;
|
||||
if (!(caps & mask))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (adf_dev_started(tmp_dev) &&
|
||||
!list_empty(&tmp_dev->compression_list)) {
|
||||
accel_dev = tmp_dev;
|
||||
|
||||
Reference in New Issue
Block a user