Fiona Trahe 4e8f2d6a6a compress/qat: add log for IM buffer too small
Display trace if error returned from firmware is likely due
to intermediate buffers being too small for the compressed
output. Update documentation to explain this error case
and to clarify intermediate buffer memory usage.

Signed-off-by: Fiona Trahe <fiona.trahe@intel.com>
Acked-by: Tomasz Jozwiak <tomaszx.jozwiak@intel.com>
2018-11-02 12:26:06 +01:00

419 lines
12 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2018 Intel Corporation
*/
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_hexdump.h>
#include <rte_comp.h>
#include <rte_bus_pci.h>
#include <rte_byteorder.h>
#include <rte_memcpy.h>
#include <rte_common.h>
#include <rte_spinlock.h>
#include <rte_log.h>
#include <rte_malloc.h>
#include "qat_logs.h"
#include "qat_comp.h"
#include "qat_comp_pmd.h"
int
qat_comp_build_request(void *in_op, uint8_t *out_msg,
void *op_cookie,
enum qat_device_gen qat_dev_gen __rte_unused)
{
struct rte_comp_op *op = in_op;
struct qat_comp_op_cookie *cookie =
(struct qat_comp_op_cookie *)op_cookie;
struct qat_comp_xform *qat_xform = op->private_xform;
const uint8_t *tmpl = (uint8_t *)&qat_xform->qat_comp_req_tmpl;
struct icp_qat_fw_comp_req *comp_req =
(struct icp_qat_fw_comp_req *)out_msg;
if (unlikely(op->op_type != RTE_COMP_OP_STATELESS)) {
QAT_DP_LOG(ERR, "QAT PMD only supports stateless compression "
"operation requests, op (%p) is not a "
"stateless operation.", op);
return -EINVAL;
}
rte_mov128(out_msg, tmpl);
comp_req->comn_mid.opaque_data = (uint64_t)(uintptr_t)op;
/* common for sgl and flat buffers */
comp_req->comp_pars.comp_len = op->src.length;
comp_req->comp_pars.out_buffer_sz = rte_pktmbuf_pkt_len(op->m_dst) -
op->dst.offset;
if (op->m_src->next != NULL || op->m_dst->next != NULL) {
/* sgl */
int ret = 0;
ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
QAT_COMN_PTR_TYPE_SGL);
ret = qat_sgl_fill_array(op->m_src,
op->src.offset,
&cookie->qat_sgl_src,
op->src.length,
RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS);
if (ret) {
QAT_DP_LOG(ERR, "QAT PMD Cannot fill source sgl array");
return ret;
}
ret = qat_sgl_fill_array(op->m_dst,
op->dst.offset,
&cookie->qat_sgl_dst,
comp_req->comp_pars.out_buffer_sz,
RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS);
if (ret) {
QAT_DP_LOG(ERR, "QAT PMD Cannot fill dest. sgl array");
return ret;
}
comp_req->comn_mid.src_data_addr =
cookie->qat_sgl_src_phys_addr;
comp_req->comn_mid.dest_data_addr =
cookie->qat_sgl_dst_phys_addr;
comp_req->comn_mid.src_length = 0;
comp_req->comn_mid.dst_length = 0;
} else {
/* flat aka linear buffer */
ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
QAT_COMN_PTR_TYPE_FLAT);
comp_req->comn_mid.src_length = op->src.length;
comp_req->comn_mid.dst_length =
comp_req->comp_pars.out_buffer_sz;
comp_req->comn_mid.src_data_addr =
rte_pktmbuf_mtophys_offset(op->m_src, op->src.offset);
comp_req->comn_mid.dest_data_addr =
rte_pktmbuf_mtophys_offset(op->m_dst, op->dst.offset);
}
#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
QAT_DP_LOG(DEBUG, "Direction: %s",
qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS ?
"decompression" : "compression");
QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message:", comp_req,
sizeof(struct icp_qat_fw_comp_req));
#endif
return 0;
}
int
qat_comp_process_response(void **op, uint8_t *resp)
{
struct icp_qat_fw_comp_resp *resp_msg =
(struct icp_qat_fw_comp_resp *)resp;
struct rte_comp_op *rx_op = (struct rte_comp_op *)(uintptr_t)
(resp_msg->opaque_data);
struct qat_comp_xform *qat_xform = (struct qat_comp_xform *)
(rx_op->private_xform);
#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
QAT_DP_LOG(DEBUG, "Direction: %s",
qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS ?
"decompression" : "compression");
QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
sizeof(struct icp_qat_fw_comp_resp));
#endif
if (likely(qat_xform->qat_comp_request_type
!= QAT_COMP_REQUEST_DECOMPRESS)) {
if (unlikely(ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(
resp_msg->comn_resp.hdr_flags)
== ICP_QAT_FW_COMP_NO_CNV)) {
rx_op->status = RTE_COMP_OP_STATUS_ERROR;
rx_op->debug_status = ERR_CODE_QAT_COMP_WRONG_FW;
*op = (void *)rx_op;
QAT_DP_LOG(ERR, "QAT has wrong firmware");
return 0;
}
}
if ((ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(resp_msg->comn_resp.comn_status)
| ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(
resp_msg->comn_resp.comn_status)) !=
ICP_QAT_FW_COMN_STATUS_FLAG_OK) {
if (unlikely((ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(
resp_msg->comn_resp.comn_status) !=
ICP_QAT_FW_COMN_STATUS_FLAG_OK) &&
(qat_xform->qat_comp_request_type
== QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)))
QAT_DP_LOG(ERR, "QAT intermediate buffer may be too "
"small for output, try configuring a larger size");
rx_op->status = RTE_COMP_OP_STATUS_ERROR;
rx_op->debug_status =
*((uint16_t *)(&resp_msg->comn_resp.comn_error));
} else {
struct icp_qat_fw_resp_comp_pars *comp_resp =
(struct icp_qat_fw_resp_comp_pars *)&resp_msg->comp_resp_pars;
rx_op->status = RTE_COMP_OP_STATUS_SUCCESS;
rx_op->consumed = comp_resp->input_byte_counter;
rx_op->produced = comp_resp->output_byte_counter;
if (qat_xform->checksum_type != RTE_COMP_CHECKSUM_NONE) {
if (qat_xform->checksum_type == RTE_COMP_CHECKSUM_CRC32)
rx_op->output_chksum = comp_resp->curr_crc32;
else if (qat_xform->checksum_type ==
RTE_COMP_CHECKSUM_ADLER32)
rx_op->output_chksum = comp_resp->curr_adler_32;
else
rx_op->output_chksum = comp_resp->curr_chksum;
}
}
*op = (void *)rx_op;
return 0;
}
unsigned int
qat_comp_xform_size(void)
{
return RTE_ALIGN_CEIL(sizeof(struct qat_comp_xform), 8);
}
static void qat_comp_create_req_hdr(struct icp_qat_fw_comn_req_hdr *header,
enum qat_comp_request_type request)
{
if (request == QAT_COMP_REQUEST_FIXED_COMP_STATELESS)
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_STATIC;
else if (request == QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC;
else if (request == QAT_COMP_REQUEST_DECOMPRESS)
header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
header->service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_COMP;
header->hdr_flags =
ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
header->comn_req_flags = ICP_QAT_FW_COMN_FLAGS_BUILD(
QAT_COMN_CD_FLD_TYPE_16BYTE_DATA, QAT_COMN_PTR_TYPE_FLAT);
}
static int qat_comp_create_templates(struct qat_comp_xform *qat_xform,
const struct rte_memzone *interm_buff_mz,
const struct rte_comp_xform *xform)
{
struct icp_qat_fw_comp_req *comp_req;
int comp_level, algo;
uint32_t req_par_flags;
int direction = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
if (unlikely(qat_xform == NULL)) {
QAT_LOG(ERR, "Session was not created for this device");
return -EINVAL;
}
if (qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS) {
direction = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS;
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_1;
req_par_flags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP,
ICP_QAT_FW_COMP_BFINAL, ICP_QAT_FW_COMP_NO_CNV,
ICP_QAT_FW_COMP_NO_CNV_RECOVERY);
} else {
if (xform->compress.level == RTE_COMP_LEVEL_PMD_DEFAULT)
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_8;
else if (xform->compress.level == 1)
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_1;
else if (xform->compress.level == 2)
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_4;
else if (xform->compress.level == 3)
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_8;
else if (xform->compress.level >= 4 &&
xform->compress.level <= 9)
comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_16;
else {
QAT_LOG(ERR, "compression level not supported");
return -EINVAL;
}
req_par_flags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP,
ICP_QAT_FW_COMP_BFINAL, ICP_QAT_FW_COMP_CNV,
ICP_QAT_FW_COMP_CNV_RECOVERY);
}
switch (xform->compress.algo) {
case RTE_COMP_ALGO_DEFLATE:
algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
break;
case RTE_COMP_ALGO_LZS:
default:
/* RTE_COMP_NULL */
QAT_LOG(ERR, "compression algorithm not supported");
return -EINVAL;
}
comp_req = &qat_xform->qat_comp_req_tmpl;
/* Initialize header */
qat_comp_create_req_hdr(&comp_req->comn_hdr,
qat_xform->qat_comp_request_type);
comp_req->comn_hdr.serv_specif_flags = ICP_QAT_FW_COMP_FLAGS_BUILD(
ICP_QAT_FW_COMP_STATELESS_SESSION,
ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST,
ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST,
ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST,
ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF);
comp_req->cd_pars.sl.comp_slice_cfg_word[0] =
ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(
direction,
/* In CPM 1.6 only valid mode ! */
ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED, algo,
/* Translate level to depth */
comp_level, ICP_QAT_HW_COMPRESSION_FILE_TYPE_0);
comp_req->comp_pars.initial_adler = 1;
comp_req->comp_pars.initial_crc32 = 0;
comp_req->comp_pars.req_par_flags = req_par_flags;
if (qat_xform->qat_comp_request_type ==
QAT_COMP_REQUEST_FIXED_COMP_STATELESS ||
qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS) {
ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
ICP_QAT_FW_SLICE_DRAM_WR);
ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
ICP_QAT_FW_SLICE_COMP);
} else if (qat_xform->qat_comp_request_type ==
QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS) {
ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
ICP_QAT_FW_SLICE_XLAT);
ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
ICP_QAT_FW_SLICE_COMP);
ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->u2.xlt_cd_ctrl,
ICP_QAT_FW_SLICE_DRAM_WR);
ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->u2.xlt_cd_ctrl,
ICP_QAT_FW_SLICE_XLAT);
comp_req->u1.xlt_pars.inter_buff_ptr =
interm_buff_mz->phys_addr;
}
#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message template:", comp_req,
sizeof(struct icp_qat_fw_comp_req));
#endif
return 0;
}
/**
* Create driver private_xform data.
*
* @param dev
* Compressdev device
* @param xform
* xform data from application
* @param private_xform
* ptr where handle of pmd's private_xform data should be stored
* @return
* - if successful returns 0
* and valid private_xform handle
* - <0 in error cases
* - Returns -EINVAL if input parameters are invalid.
* - Returns -ENOTSUP if comp device does not support the comp transform.
* - Returns -ENOMEM if the private_xform could not be allocated.
*/
int
qat_comp_private_xform_create(struct rte_compressdev *dev,
const struct rte_comp_xform *xform,
void **private_xform)
{
struct qat_comp_dev_private *qat = dev->data->dev_private;
if (unlikely(private_xform == NULL)) {
QAT_LOG(ERR, "QAT: private_xform parameter is NULL");
return -EINVAL;
}
if (unlikely(qat->xformpool == NULL)) {
QAT_LOG(ERR, "QAT device has no private_xform mempool");
return -ENOMEM;
}
if (rte_mempool_get(qat->xformpool, private_xform)) {
QAT_LOG(ERR, "Couldn't get object from qat xform mempool");
return -ENOMEM;
}
struct qat_comp_xform *qat_xform =
(struct qat_comp_xform *)*private_xform;
if (xform->type == RTE_COMP_COMPRESS) {
if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED ||
((xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_DEFAULT)
&& qat->interm_buff_mz == NULL))
qat_xform->qat_comp_request_type =
QAT_COMP_REQUEST_FIXED_COMP_STATELESS;
else if ((xform->compress.deflate.huffman ==
RTE_COMP_HUFFMAN_DYNAMIC ||
xform->compress.deflate.huffman ==
RTE_COMP_HUFFMAN_DEFAULT) &&
qat->interm_buff_mz != NULL)
qat_xform->qat_comp_request_type =
QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS;
else {
QAT_LOG(ERR,
"IM buffers needed for dynamic deflate. Set size in config file");
return -EINVAL;
}
qat_xform->checksum_type = xform->compress.chksum;
} else {
qat_xform->qat_comp_request_type = QAT_COMP_REQUEST_DECOMPRESS;
qat_xform->checksum_type = xform->decompress.chksum;
}
if (qat_comp_create_templates(qat_xform, qat->interm_buff_mz, xform)) {
QAT_LOG(ERR, "QAT: Problem with setting compression");
return -EINVAL;
}
return 0;
}
/**
* Free driver private_xform data.
*
* @param dev
* Compressdev device
* @param private_xform
* handle of pmd's private_xform data
* @return
* - 0 if successful
* - <0 in error cases
* - Returns -EINVAL if input parameters are invalid.
*/
int
qat_comp_private_xform_free(struct rte_compressdev *dev __rte_unused,
void *private_xform)
{
struct qat_comp_xform *qat_xform =
(struct qat_comp_xform *)private_xform;
if (qat_xform) {
memset(qat_xform, 0, qat_comp_xform_size());
struct rte_mempool *mp = rte_mempool_from_obj(qat_xform);
rte_mempool_put(mp, qat_xform);
return 0;
}
return -EINVAL;
}