// 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_info("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;
		inst->build_deflate_ctx = GET_DC_OPS(accel_dev)->build_deflate_ctx;

		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);
	memset(dc_data->ovf_buff, 0, dc_data->ovf_buff_sz);
	kfree(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);
}
