Files
linux/drivers/crypto/intel/qat/qat_common/qat_compression.c
Suman Kumar Chakraborty cd0e7160f8 crypto: qat - refactor compression template logic
The logic that generates the compression templates, which are used by to
submit compression requests to the QAT device, is very similar between
QAT devices and diverges mainly on the HW generation-specific
configuration word.

This makes the logic that generates the compression and decompression
templates common between GEN2 and GEN4 devices and abstracts the
generation-specific logic to the generation-specific implementations.

The adf_gen2_dc.c and adf_gen4_dc.c have been replaced by adf_dc.c, and
the generation-specific logic has been reduced and moved to
adf_gen2_hw_data.c and adf_gen4_hw_data.c.

This does not introduce any functional change.

Co-developed-by: Vijay Sundar Selvamani <vijay.sundar.selvamani@intel.com>
Signed-off-by: Vijay Sundar Selvamani <vijay.sundar.selvamani@intel.com>
Signed-off-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-05-05 18:20:44 +08:00

296 lines
6.9 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation */
#include <linux/module.h>
#include <linux/slab.h>
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_transport.h"
#include "adf_transport_access_macros.h"
#include "adf_cfg.h"
#include "adf_cfg_strings.h"
#include "qat_compression.h"
#include "icp_qat_fw.h"
#define SEC ADF_KERNEL_SEC
static struct service_hndl qat_compression;
void qat_compression_put_instance(struct qat_compression_instance *inst)
{
atomic_dec(&inst->refctr);
adf_dev_put(inst->accel_dev);
}
static int qat_compression_free_instances(struct adf_accel_dev *accel_dev)
{
struct qat_compression_instance *inst;
struct list_head *list_ptr, *tmp;
int i;
list_for_each_safe(list_ptr, tmp, &accel_dev->compression_list) {
inst = list_entry(list_ptr,
struct qat_compression_instance, list);
for (i = 0; i < atomic_read(&inst->refctr); i++)
qat_compression_put_instance(inst);
if (inst->dc_tx)
adf_remove_ring(inst->dc_tx);
if (inst->dc_rx)
adf_remove_ring(inst->dc_rx);
list_del(list_ptr);
kfree(inst);
}
return 0;
}
struct qat_compression_instance *qat_compression_get_instance_node(int node)
{
struct qat_compression_instance *inst = NULL;
struct adf_accel_dev *accel_dev = NULL;
unsigned long best = ~0;
struct list_head *itr;
list_for_each(itr, adf_devmgr_get_head()) {
struct adf_accel_dev *tmp_dev;
unsigned long ctr;
int tmp_dev_node;
tmp_dev = list_entry(itr, struct adf_accel_dev, list);
tmp_dev_node = dev_to_node(&GET_DEV(tmp_dev));
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);
if (best > ctr) {
accel_dev = tmp_dev;
best = ctr;
}
}
}
if (!accel_dev) {
pr_debug_ratelimited("QAT: Could not find a device on node %d\n", node);
/* Get any started device */
list_for_each(itr, adf_devmgr_get_head()) {
struct adf_accel_dev *tmp_dev;
tmp_dev = list_entry(itr, struct adf_accel_dev, list);
if (adf_dev_started(tmp_dev) &&
!list_empty(&tmp_dev->compression_list)) {
accel_dev = tmp_dev;
break;
}
}
}
if (!accel_dev)
return NULL;
best = ~0;
list_for_each(itr, &accel_dev->compression_list) {
struct qat_compression_instance *tmp_inst;
unsigned long ctr;
tmp_inst = list_entry(itr, struct qat_compression_instance, list);
ctr = atomic_read(&tmp_inst->refctr);
if (best > ctr) {
inst = tmp_inst;
best = ctr;
}
}
if (inst) {
if (adf_dev_get(accel_dev)) {
dev_err(&GET_DEV(accel_dev), "Could not increment dev refctr\n");
return NULL;
}
atomic_inc(&inst->refctr);
}
return inst;
}
static int qat_compression_create_instances(struct adf_accel_dev *accel_dev)
{
struct qat_compression_instance *inst;
char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
unsigned long num_inst, num_msg_dc;
unsigned long bank;
int msg_size;
int ret;
int i;
INIT_LIST_HEAD(&accel_dev->compression_list);
strscpy(key, ADF_NUM_DC, sizeof(key));
ret = adf_cfg_get_param_value(accel_dev, SEC, key, val);
if (ret)
return ret;
ret = kstrtoul(val, 10, &num_inst);
if (ret)
return ret;
for (i = 0; i < num_inst; i++) {
inst = kzalloc_node(sizeof(*inst), GFP_KERNEL,
dev_to_node(&GET_DEV(accel_dev)));
if (!inst) {
ret = -ENOMEM;
goto err;
}
list_add_tail(&inst->list, &accel_dev->compression_list);
inst->id = i;
atomic_set(&inst->refctr, 0);
inst->accel_dev = accel_dev;
snprintf(key, sizeof(key), ADF_DC "%d" ADF_RING_DC_BANK_NUM, i);
ret = adf_cfg_get_param_value(accel_dev, SEC, key, val);
if (ret)
return ret;
ret = kstrtoul(val, 10, &bank);
if (ret)
return ret;
snprintf(key, sizeof(key), ADF_DC "%d" ADF_RING_DC_SIZE, i);
ret = adf_cfg_get_param_value(accel_dev, SEC, key, val);
if (ret)
return ret;
ret = kstrtoul(val, 10, &num_msg_dc);
if (ret)
return ret;
msg_size = ICP_QAT_FW_REQ_DEFAULT_SZ;
snprintf(key, sizeof(key), ADF_DC "%d" ADF_RING_DC_TX, i);
ret = adf_create_ring(accel_dev, SEC, bank, num_msg_dc,
msg_size, key, NULL, 0, &inst->dc_tx);
if (ret)
return ret;
msg_size = ICP_QAT_FW_RESP_DEFAULT_SZ;
snprintf(key, sizeof(key), ADF_DC "%d" ADF_RING_DC_RX, i);
ret = adf_create_ring(accel_dev, SEC, bank, num_msg_dc,
msg_size, key, qat_comp_alg_callback, 0,
&inst->dc_rx);
if (ret)
return ret;
inst->dc_data = accel_dev->dc_data;
INIT_LIST_HEAD(&inst->backlog.list);
spin_lock_init(&inst->backlog.lock);
}
return 0;
err:
qat_compression_free_instances(accel_dev);
return ret;
}
static int qat_compression_alloc_dc_data(struct adf_accel_dev *accel_dev)
{
struct device *dev = &GET_DEV(accel_dev);
dma_addr_t obuff_p = DMA_MAPPING_ERROR;
size_t ovf_buff_sz = QAT_COMP_MAX_SKID;
struct adf_dc_data *dc_data = NULL;
u8 *obuff = NULL;
dc_data = devm_kzalloc(dev, sizeof(*dc_data), GFP_KERNEL);
if (!dc_data)
goto err;
obuff = kzalloc_node(ovf_buff_sz, GFP_KERNEL, dev_to_node(dev));
if (!obuff)
goto err;
obuff_p = dma_map_single(dev, obuff, ovf_buff_sz, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(dev, obuff_p)))
goto err;
dc_data->ovf_buff = obuff;
dc_data->ovf_buff_p = obuff_p;
dc_data->ovf_buff_sz = ovf_buff_sz;
accel_dev->dc_data = dc_data;
return 0;
err:
accel_dev->dc_data = NULL;
kfree(obuff);
devm_kfree(dev, dc_data);
return -ENOMEM;
}
static void qat_free_dc_data(struct adf_accel_dev *accel_dev)
{
struct adf_dc_data *dc_data = accel_dev->dc_data;
struct device *dev = &GET_DEV(accel_dev);
if (!dc_data)
return;
dma_unmap_single(dev, dc_data->ovf_buff_p, dc_data->ovf_buff_sz,
DMA_FROM_DEVICE);
kfree_sensitive(dc_data->ovf_buff);
devm_kfree(dev, dc_data);
accel_dev->dc_data = NULL;
}
static int qat_compression_init(struct adf_accel_dev *accel_dev)
{
int ret;
ret = qat_compression_alloc_dc_data(accel_dev);
if (ret)
return ret;
ret = qat_compression_create_instances(accel_dev);
if (ret)
qat_free_dc_data(accel_dev);
return ret;
}
static int qat_compression_shutdown(struct adf_accel_dev *accel_dev)
{
qat_free_dc_data(accel_dev);
return qat_compression_free_instances(accel_dev);
}
static int qat_compression_event_handler(struct adf_accel_dev *accel_dev,
enum adf_event event)
{
int ret;
switch (event) {
case ADF_EVENT_INIT:
ret = qat_compression_init(accel_dev);
break;
case ADF_EVENT_SHUTDOWN:
ret = qat_compression_shutdown(accel_dev);
break;
case ADF_EVENT_RESTARTING:
case ADF_EVENT_RESTARTED:
case ADF_EVENT_START:
case ADF_EVENT_STOP:
default:
ret = 0;
}
return ret;
}
int qat_compression_register(void)
{
memset(&qat_compression, 0, sizeof(qat_compression));
qat_compression.event_hld = qat_compression_event_handler;
qat_compression.name = "qat_compression";
return adf_service_register(&qat_compression);
}
int qat_compression_unregister(void)
{
return adf_service_unregister(&qat_compression);
}