Commit 93382a91 authored by Tom Zanussi's avatar Tom Zanussi Committed by Herbert Xu

crypto: iaa - Add IAA Compression Accelerator stats

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.
Signed-off-by: default avatarTom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 09646c98
......@@ -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.
......@@ -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
......@@ -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
......@@ -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,
......
// 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");
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */
#ifndef __CRYPTO_DEV_IAA_CRYPTO_STATS_H__
#define __CRYPTO_DEV_IAA_CRYPTO_STATS_H__
#if defined(CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS)
int iaa_crypto_debugfs_init(void);
void iaa_crypto_debugfs_cleanup(void);
void update_total_comp_calls(void);
void update_total_comp_bytes_out(int n);
void update_total_decomp_calls(void);
void update_total_sw_decomp_calls(void);
void update_total_decomp_bytes_in(int n);
void update_max_comp_delay_ns(u64 start_time_ns);
void update_max_decomp_delay_ns(u64 start_time_ns);
void update_max_acomp_delay_ns(u64 start_time_ns);
void update_max_adecomp_delay_ns(u64 start_time_ns);
void update_completion_einval_errs(void);
void update_completion_timeout_errs(void);
void update_completion_comp_buf_overflow_errs(void);
void update_wq_comp_calls(struct idxd_wq *idxd_wq);
void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n);
void update_wq_decomp_calls(struct idxd_wq *idxd_wq);
void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n);
#else
static inline int iaa_crypto_debugfs_init(void) { return 0; }
static inline void iaa_crypto_debugfs_cleanup(void) {}
static inline void update_total_comp_calls(void) {}
static inline void update_total_comp_bytes_out(int n) {}
static inline void update_total_decomp_calls(void) {}
static inline void update_total_sw_decomp_calls(void) {}
static inline void update_total_decomp_bytes_in(int n) {}
static inline void update_max_comp_delay_ns(u64 start_time_ns) {}
static inline void update_max_decomp_delay_ns(u64 start_time_ns) {}
static inline void update_max_acomp_delay_ns(u64 start_time_ns) {}
static inline void update_max_adecomp_delay_ns(u64 start_time_ns) {}
static inline void update_completion_einval_errs(void) {}
static inline void update_completion_timeout_errs(void) {}
static inline void update_completion_comp_buf_overflow_errs(void) {}
static inline void update_wq_comp_calls(struct idxd_wq *idxd_wq) {}
static inline void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n) {}
static inline void update_wq_decomp_calls(struct idxd_wq *idxd_wq) {}
static inline void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n) {}
#endif // CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment