Commit 9d8f98ad authored by Tom Zanussi's avatar Tom Zanussi Committed by Xiaochen Shen
Browse files

crypto: iaa - Add IAA Compression Accelerator stats

mainline inclusion
from mainline-v6.8-rc1
commit 93382a91632a5d88bb9bb0ff1fea872fe87f5dc2
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I9TA1S
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=93382a91632a5d88bb9bb0ff1fea872fe87f5dc2



--------------------------------

Add support for optional debugfs statistics support for the IAA
Compression Accelerator.  This is enabled by the kernel config item:

  CRYPTO_DEV_IAA_CRYPTO_STATS

When enabled, the IAA crypto driver will generate statistics which can
be accessed at /sys/kernel/debug/iaa-crypto/.

See Documentation/driver-api/crypto/iax/iax-crypto.rst for details.

Intel-SIG: commit 93382a91632a crypto: iaa - Add IAA Compression Accelerator stats.
Backporting patches for Intel IAA crypto driver on Intel Xeon platform.

Signed-off-by: default avatarTom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarXiaochen Shen <xiaochen.shen@intel.com>
parent ad479e26
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -8,3 +8,12 @@ config CRYPTO_DEV_IAA_CRYPTO
	  decompression with the Intel Analytics Accelerator (IAA)
	  hardware using the cryptographic API.  If you choose 'M'
	  here, the module will be called iaa_crypto.

config CRYPTO_DEV_IAA_CRYPTO_STATS
	bool "Enable Intel(R) IAA Compression Accelerator Statistics"
	depends on CRYPTO_DEV_IAA_CRYPTO
	default n
	help
	  Enable statistics for the IAA compression accelerator.
	  These include per-device and per-workqueue statistics in
	  addition to global driver statistics.
+2 −0
Original line number Diff line number Diff line
@@ -8,3 +8,5 @@ ccflags-y += -I $(srctree)/drivers/dma/idxd -DDEFAULT_SYMBOL_NAMESPACE=IDXD
obj-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO) := iaa_crypto.o

iaa_crypto-y := iaa_crypto_main.o iaa_crypto_comp_fixed.o

iaa_crypto-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS) += iaa_crypto_stats.o
+13 −0
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ struct iaa_wq {
	bool			remove;

	struct iaa_device	*iaa_device;

	u64			comp_calls;
	u64			comp_bytes;
	u64			decomp_calls;
	u64			decomp_bytes;
};

struct iaa_device_compression_mode {
@@ -69,6 +74,11 @@ struct iaa_device {

	int				n_wq;
	struct list_head		wqs;

	u64				comp_calls;
	u64				comp_bytes;
	u64				decomp_calls;
	u64				decomp_bytes;
};

struct wq_table_entry {
@@ -157,4 +167,7 @@ struct iaa_compression_ctx {
	bool		use_irq;
};

extern struct list_head iaa_devices;
extern struct mutex iaa_devices_lock;

#endif
+37 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#include "idxd.h"
#include "iaa_crypto.h"
#include "iaa_crypto_stats.h"

#ifdef pr_fmt
#undef pr_fmt
@@ -85,8 +86,8 @@ static void wq_table_clear_entry(int cpu)
	memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *));
}

static LIST_HEAD(iaa_devices);
static DEFINE_MUTEX(iaa_devices_lock);
LIST_HEAD(iaa_devices);
DEFINE_MUTEX(iaa_devices_lock);

/* If enabled, IAA hw crypto algos are registered, unavailable otherwise */
static bool iaa_crypto_enabled;
@@ -1052,6 +1053,7 @@ static inline int check_completion(struct device *dev,
			ret = -ETIMEDOUT;
			dev_dbg(dev, "%s timed out, size=0x%x\n",
				op_str, comp->output_size);
			update_completion_timeout_errs();
			goto out;
		}

@@ -1061,6 +1063,7 @@ static inline int check_completion(struct device *dev,
			dev_dbg(dev, "compressed > uncompressed size,"
				" not compressing, size=0x%x\n",
				comp->output_size);
			update_completion_comp_buf_overflow_errs();
			goto out;
		}

@@ -1073,6 +1076,7 @@ static inline int check_completion(struct device *dev,
		dev_dbg(dev, "iaa %s status=0x%x, error=0x%x, size=0x%x\n",
			op_str, comp->status, comp->error_code, comp->output_size);
		print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, comp, 64, 0);
		update_completion_einval_errs();

		goto out;
	}
@@ -1094,6 +1098,8 @@ static int deflate_generic_decompress(struct acomp_req *req)
	kunmap_local(src);
	kunmap_local(dst);

	update_total_sw_decomp_calls();

	return ret;
}

@@ -1161,6 +1167,15 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc,
		ctx->req->dlen = idxd_desc->iax_completion->output_size;
	}

	/* Update stats */
	if (ctx->compress) {
		update_total_comp_bytes_out(ctx->req->dlen);
		update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen);
	} else {
		update_total_decomp_bytes_in(ctx->req->dlen);
		update_wq_decomp_bytes(iaa_wq->wq, ctx->req->dlen);
	}

	if (ctx->compress && compression_ctx->verify_compress) {
		dma_addr_t src_addr, dst_addr;
		u32 compression_crc;
@@ -1280,6 +1295,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
		goto err;
	}

	/* Update stats */
	update_total_comp_calls();
	update_wq_comp_calls(wq);

	if (ctx->async_mode && !disable_async) {
		ret = -EINPROGRESS;
		dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);
@@ -1294,6 +1313,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,

	*dlen = idxd_desc->iax_completion->output_size;

	/* Update stats */
	update_total_comp_bytes_out(*dlen);
	update_wq_comp_bytes(wq, *dlen);

	*compression_crc = idxd_desc->iax_completion->crc;

	if (!ctx->async_mode)
@@ -1510,6 +1533,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
		goto err;
	}

	/* Update stats */
	update_total_decomp_calls();
	update_wq_decomp_calls(wq);

	if (ctx->async_mode && !disable_async) {
		ret = -EINPROGRESS;
		dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);
@@ -1540,6 +1567,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,

	if (!ctx->async_mode)
		idxd_free_desc(wq, idxd_desc);

	/* Update stats */
	update_total_decomp_bytes_in(slen);
	update_wq_decomp_bytes(wq, slen);
out:
	return ret;
err:
@@ -2104,6 +2135,9 @@ static int __init iaa_crypto_init_module(void)
		goto err_sync_attr_create;
	}

	if (iaa_crypto_debugfs_init())
		pr_warn("debugfs init failed, stats not available\n");

	pr_debug("initialized\n");
out:
	return ret;
@@ -2126,6 +2160,7 @@ static void __exit iaa_crypto_cleanup_module(void)
	if (iaa_unregister_compression_device())
		pr_debug("IAA compression device unregister failed\n");

	iaa_crypto_debugfs_cleanup();
	driver_remove_file(&iaa_crypto_driver.drv,
			   &driver_attr_sync_mode);
	driver_remove_file(&iaa_crypto_driver.drv,
+313 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/smp.h>
#include <uapi/linux/idxd.h>
#include <linux/idxd.h>
#include <linux/dmaengine.h>
#include "../../dma/idxd/idxd.h"
#include <linux/debugfs.h>
#include <crypto/internal/acompress.h>
#include "iaa_crypto.h"
#include "iaa_crypto_stats.h"

static u64 total_comp_calls;
static u64 total_decomp_calls;
static u64 total_sw_decomp_calls;
static u64 max_comp_delay_ns;
static u64 max_decomp_delay_ns;
static u64 max_acomp_delay_ns;
static u64 max_adecomp_delay_ns;
static u64 total_comp_bytes_out;
static u64 total_decomp_bytes_in;
static u64 total_completion_einval_errors;
static u64 total_completion_timeout_errors;
static u64 total_completion_comp_buf_overflow_errors;

static struct dentry *iaa_crypto_debugfs_root;

void update_total_comp_calls(void)
{
	total_comp_calls++;
}

void update_total_comp_bytes_out(int n)
{
	total_comp_bytes_out += n;
}

void update_total_decomp_calls(void)
{
	total_decomp_calls++;
}

void update_total_sw_decomp_calls(void)
{
	total_sw_decomp_calls++;
}

void update_total_decomp_bytes_in(int n)
{
	total_decomp_bytes_in += n;
}

void update_completion_einval_errs(void)
{
	total_completion_einval_errors++;
}

void update_completion_timeout_errs(void)
{
	total_completion_timeout_errors++;
}

void update_completion_comp_buf_overflow_errs(void)
{
	total_completion_comp_buf_overflow_errors++;
}

void update_max_comp_delay_ns(u64 start_time_ns)
{
	u64 time_diff;

	time_diff = ktime_get_ns() - start_time_ns;

	if (time_diff > max_comp_delay_ns)
		max_comp_delay_ns = time_diff;
}

void update_max_decomp_delay_ns(u64 start_time_ns)
{
	u64 time_diff;

	time_diff = ktime_get_ns() - start_time_ns;

	if (time_diff > max_decomp_delay_ns)
		max_decomp_delay_ns = time_diff;
}

void update_max_acomp_delay_ns(u64 start_time_ns)
{
	u64 time_diff;

	time_diff = ktime_get_ns() - start_time_ns;

	if (time_diff > max_acomp_delay_ns)
		max_acomp_delay_ns = time_diff;
}

void update_max_adecomp_delay_ns(u64 start_time_ns)
{
	u64 time_diff;

	time_diff = ktime_get_ns() - start_time_ns;

	if (time_diff > max_adecomp_delay_ns)

		max_adecomp_delay_ns = time_diff;
}

void update_wq_comp_calls(struct idxd_wq *idxd_wq)
{
	struct iaa_wq *wq = idxd_wq_get_private(idxd_wq);

	wq->comp_calls++;
	wq->iaa_device->comp_calls++;
}

void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n)
{
	struct iaa_wq *wq = idxd_wq_get_private(idxd_wq);

	wq->comp_bytes += n;
	wq->iaa_device->comp_bytes += n;
}

void update_wq_decomp_calls(struct idxd_wq *idxd_wq)
{
	struct iaa_wq *wq = idxd_wq_get_private(idxd_wq);

	wq->decomp_calls++;
	wq->iaa_device->decomp_calls++;
}

void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n)
{
	struct iaa_wq *wq = idxd_wq_get_private(idxd_wq);

	wq->decomp_bytes += n;
	wq->iaa_device->decomp_bytes += n;
}

static void reset_iaa_crypto_stats(void)
{
	total_comp_calls = 0;
	total_decomp_calls = 0;
	total_sw_decomp_calls = 0;
	max_comp_delay_ns = 0;
	max_decomp_delay_ns = 0;
	max_acomp_delay_ns = 0;
	max_adecomp_delay_ns = 0;
	total_comp_bytes_out = 0;
	total_decomp_bytes_in = 0;
	total_completion_einval_errors = 0;
	total_completion_timeout_errors = 0;
	total_completion_comp_buf_overflow_errors = 0;
}

static void reset_wq_stats(struct iaa_wq *wq)
{
	wq->comp_calls = 0;
	wq->comp_bytes = 0;
	wq->decomp_calls = 0;
	wq->decomp_bytes = 0;
}

static void reset_device_stats(struct iaa_device *iaa_device)
{
	struct iaa_wq *iaa_wq;

	iaa_device->comp_calls = 0;
	iaa_device->comp_bytes = 0;
	iaa_device->decomp_calls = 0;
	iaa_device->decomp_bytes = 0;

	list_for_each_entry(iaa_wq, &iaa_device->wqs, list)
		reset_wq_stats(iaa_wq);
}

static void wq_show(struct seq_file *m, struct iaa_wq *iaa_wq)
{
	seq_printf(m, "    name: %s\n", iaa_wq->wq->name);
	seq_printf(m, "    comp_calls: %llu\n", iaa_wq->comp_calls);
	seq_printf(m, "    comp_bytes: %llu\n", iaa_wq->comp_bytes);
	seq_printf(m, "    decomp_calls: %llu\n", iaa_wq->decomp_calls);
	seq_printf(m, "    decomp_bytes: %llu\n\n", iaa_wq->decomp_bytes);
}

static void device_stats_show(struct seq_file *m, struct iaa_device *iaa_device)
{
	struct iaa_wq *iaa_wq;

	seq_puts(m, "iaa device:\n");
	seq_printf(m, "  id: %d\n", iaa_device->idxd->id);
	seq_printf(m, "  n_wqs: %d\n", iaa_device->n_wq);
	seq_printf(m, "  comp_calls: %llu\n", iaa_device->comp_calls);
	seq_printf(m, "  comp_bytes: %llu\n", iaa_device->comp_bytes);
	seq_printf(m, "  decomp_calls: %llu\n", iaa_device->decomp_calls);
	seq_printf(m, "  decomp_bytes: %llu\n", iaa_device->decomp_bytes);
	seq_puts(m, "  wqs:\n");

	list_for_each_entry(iaa_wq, &iaa_device->wqs, list)
		wq_show(m, iaa_wq);
}

static void global_stats_show(struct seq_file *m)
{
	seq_puts(m, "global stats:\n");
	seq_printf(m, "  total_comp_calls: %llu\n", total_comp_calls);
	seq_printf(m, "  total_decomp_calls: %llu\n", total_decomp_calls);
	seq_printf(m, "  total_sw_decomp_calls: %llu\n", total_sw_decomp_calls);
	seq_printf(m, "  total_comp_bytes_out: %llu\n", total_comp_bytes_out);
	seq_printf(m, "  total_decomp_bytes_in: %llu\n", total_decomp_bytes_in);
	seq_printf(m, "  total_completion_einval_errors: %llu\n",
		   total_completion_einval_errors);
	seq_printf(m, "  total_completion_timeout_errors: %llu\n",
		   total_completion_timeout_errors);
	seq_printf(m, "  total_completion_comp_buf_overflow_errors: %llu\n\n",
		   total_completion_comp_buf_overflow_errors);
}

static int wq_stats_show(struct seq_file *m, void *v)
{
	struct iaa_device *iaa_device;

	mutex_lock(&iaa_devices_lock);

	global_stats_show(m);

	list_for_each_entry(iaa_device, &iaa_devices, list)
		device_stats_show(m, iaa_device);

	mutex_unlock(&iaa_devices_lock);

	return 0;
}

static int iaa_crypto_stats_reset(void *data, u64 value)
{
	struct iaa_device *iaa_device;

	reset_iaa_crypto_stats();

	mutex_lock(&iaa_devices_lock);

	list_for_each_entry(iaa_device, &iaa_devices, list)
		reset_device_stats(iaa_device);

	mutex_unlock(&iaa_devices_lock);

	return 0;
}

static int wq_stats_open(struct inode *inode, struct file *file)
{
	return single_open(file, wq_stats_show, file);
}

static const struct file_operations wq_stats_fops = {
	.open = wq_stats_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

DEFINE_DEBUGFS_ATTRIBUTE(wq_stats_reset_fops, NULL, iaa_crypto_stats_reset, "%llu\n");

int __init iaa_crypto_debugfs_init(void)
{
	if (!debugfs_initialized())
		return -ENODEV;

	iaa_crypto_debugfs_root = debugfs_create_dir("iaa_crypto", NULL);
	if (!iaa_crypto_debugfs_root)
		return -ENOMEM;

	debugfs_create_u64("max_comp_delay_ns", 0644,
			   iaa_crypto_debugfs_root, &max_comp_delay_ns);
	debugfs_create_u64("max_decomp_delay_ns", 0644,
			   iaa_crypto_debugfs_root, &max_decomp_delay_ns);
	debugfs_create_u64("max_acomp_delay_ns", 0644,
			   iaa_crypto_debugfs_root, &max_comp_delay_ns);
	debugfs_create_u64("max_adecomp_delay_ns", 0644,
			   iaa_crypto_debugfs_root, &max_decomp_delay_ns);
	debugfs_create_u64("total_comp_calls", 0644,
			   iaa_crypto_debugfs_root, &total_comp_calls);
	debugfs_create_u64("total_decomp_calls", 0644,
			   iaa_crypto_debugfs_root, &total_decomp_calls);
	debugfs_create_u64("total_sw_decomp_calls", 0644,
			   iaa_crypto_debugfs_root, &total_sw_decomp_calls);
	debugfs_create_u64("total_comp_bytes_out", 0644,
			   iaa_crypto_debugfs_root, &total_comp_bytes_out);
	debugfs_create_u64("total_decomp_bytes_in", 0644,
			   iaa_crypto_debugfs_root, &total_decomp_bytes_in);
	debugfs_create_file("wq_stats", 0644, iaa_crypto_debugfs_root, NULL,
			    &wq_stats_fops);
	debugfs_create_file("stats_reset", 0644, iaa_crypto_debugfs_root, NULL,
			    &wq_stats_reset_fops);

	return 0;
}

void __exit iaa_crypto_debugfs_cleanup(void)
{
	debugfs_remove_recursive(iaa_crypto_debugfs_root);
}

MODULE_LICENSE("GPL");
Loading