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 ...@@ -8,3 +8,12 @@ config CRYPTO_DEV_IAA_CRYPTO
decompression with the Intel Analytics Accelerator (IAA) decompression with the Intel Analytics Accelerator (IAA)
hardware using the cryptographic API. If you choose 'M' hardware using the cryptographic API. If you choose 'M'
here, the module will be called iaa_crypto. 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 ...@@ -8,3 +8,5 @@ ccflags-y += -I $(srctree)/drivers/dma/idxd -DDEFAULT_SYMBOL_NAMESPACE=IDXD
obj-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO) := iaa_crypto.o obj-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO) := iaa_crypto.o
iaa_crypto-y := iaa_crypto_main.o iaa_crypto_comp_fixed.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 { ...@@ -48,6 +48,11 @@ struct iaa_wq {
bool remove; bool remove;
struct iaa_device *iaa_device; struct iaa_device *iaa_device;
u64 comp_calls;
u64 comp_bytes;
u64 decomp_calls;
u64 decomp_bytes;
}; };
struct iaa_device_compression_mode { struct iaa_device_compression_mode {
...@@ -69,6 +74,11 @@ struct iaa_device { ...@@ -69,6 +74,11 @@ struct iaa_device {
int n_wq; int n_wq;
struct list_head wqs; struct list_head wqs;
u64 comp_calls;
u64 comp_bytes;
u64 decomp_calls;
u64 decomp_bytes;
}; };
struct wq_table_entry { struct wq_table_entry {
...@@ -157,4 +167,7 @@ struct iaa_compression_ctx { ...@@ -157,4 +167,7 @@ struct iaa_compression_ctx {
bool use_irq; bool use_irq;
}; };
extern struct list_head iaa_devices;
extern struct mutex iaa_devices_lock;
#endif #endif
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "idxd.h" #include "idxd.h"
#include "iaa_crypto.h" #include "iaa_crypto.h"
#include "iaa_crypto_stats.h"
#ifdef pr_fmt #ifdef pr_fmt
#undef pr_fmt #undef pr_fmt
...@@ -85,8 +86,8 @@ static void wq_table_clear_entry(int cpu) ...@@ -85,8 +86,8 @@ static void wq_table_clear_entry(int cpu)
memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *)); memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *));
} }
static LIST_HEAD(iaa_devices); LIST_HEAD(iaa_devices);
static DEFINE_MUTEX(iaa_devices_lock); DEFINE_MUTEX(iaa_devices_lock);
/* If enabled, IAA hw crypto algos are registered, unavailable otherwise */ /* If enabled, IAA hw crypto algos are registered, unavailable otherwise */
static bool iaa_crypto_enabled; static bool iaa_crypto_enabled;
...@@ -1052,6 +1053,7 @@ static inline int check_completion(struct device *dev, ...@@ -1052,6 +1053,7 @@ static inline int check_completion(struct device *dev,
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
dev_dbg(dev, "%s timed out, size=0x%x\n", dev_dbg(dev, "%s timed out, size=0x%x\n",
op_str, comp->output_size); op_str, comp->output_size);
update_completion_timeout_errs();
goto out; goto out;
} }
...@@ -1061,6 +1063,7 @@ static inline int check_completion(struct device *dev, ...@@ -1061,6 +1063,7 @@ static inline int check_completion(struct device *dev,
dev_dbg(dev, "compressed > uncompressed size," dev_dbg(dev, "compressed > uncompressed size,"
" not compressing, size=0x%x\n", " not compressing, size=0x%x\n",
comp->output_size); comp->output_size);
update_completion_comp_buf_overflow_errs();
goto out; goto out;
} }
...@@ -1073,6 +1076,7 @@ static inline int check_completion(struct device *dev, ...@@ -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", 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); 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); print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, comp, 64, 0);
update_completion_einval_errs();
goto out; goto out;
} }
...@@ -1094,6 +1098,8 @@ static int deflate_generic_decompress(struct acomp_req *req) ...@@ -1094,6 +1098,8 @@ static int deflate_generic_decompress(struct acomp_req *req)
kunmap_local(src); kunmap_local(src);
kunmap_local(dst); kunmap_local(dst);
update_total_sw_decomp_calls();
return ret; return ret;
} }
...@@ -1161,6 +1167,15 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, ...@@ -1161,6 +1167,15 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc,
ctx->req->dlen = idxd_desc->iax_completion->output_size; 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) { if (ctx->compress && compression_ctx->verify_compress) {
dma_addr_t src_addr, dst_addr; dma_addr_t src_addr, dst_addr;
u32 compression_crc; u32 compression_crc;
...@@ -1280,6 +1295,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req, ...@@ -1280,6 +1295,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
goto err; goto err;
} }
/* Update stats */
update_total_comp_calls();
update_wq_comp_calls(wq);
if (ctx->async_mode && !disable_async) { if (ctx->async_mode && !disable_async) {
ret = -EINPROGRESS; ret = -EINPROGRESS;
dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__); dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);
...@@ -1294,6 +1313,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req, ...@@ -1294,6 +1313,10 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
*dlen = idxd_desc->iax_completion->output_size; *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; *compression_crc = idxd_desc->iax_completion->crc;
if (!ctx->async_mode) if (!ctx->async_mode)
...@@ -1510,6 +1533,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req, ...@@ -1510,6 +1533,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
goto err; goto err;
} }
/* Update stats */
update_total_decomp_calls();
update_wq_decomp_calls(wq);
if (ctx->async_mode && !disable_async) { if (ctx->async_mode && !disable_async) {
ret = -EINPROGRESS; ret = -EINPROGRESS;
dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__); dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);
...@@ -1540,6 +1567,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req, ...@@ -1540,6 +1567,10 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
if (!ctx->async_mode) if (!ctx->async_mode)
idxd_free_desc(wq, idxd_desc); idxd_free_desc(wq, idxd_desc);
/* Update stats */
update_total_decomp_bytes_in(slen);
update_wq_decomp_bytes(wq, slen);
out: out:
return ret; return ret;
err: err:
...@@ -2104,6 +2135,9 @@ static int __init iaa_crypto_init_module(void) ...@@ -2104,6 +2135,9 @@ static int __init iaa_crypto_init_module(void)
goto err_sync_attr_create; goto err_sync_attr_create;
} }
if (iaa_crypto_debugfs_init())
pr_warn("debugfs init failed, stats not available\n");
pr_debug("initialized\n"); pr_debug("initialized\n");
out: out:
return ret; return ret;
...@@ -2126,6 +2160,7 @@ static void __exit iaa_crypto_cleanup_module(void) ...@@ -2126,6 +2160,7 @@ static void __exit iaa_crypto_cleanup_module(void)
if (iaa_unregister_compression_device()) if (iaa_unregister_compression_device())
pr_debug("IAA compression device unregister failed\n"); pr_debug("IAA compression device unregister failed\n");
iaa_crypto_debugfs_cleanup();
driver_remove_file(&iaa_crypto_driver.drv, driver_remove_file(&iaa_crypto_driver.drv,
&driver_attr_sync_mode); &driver_attr_sync_mode);
driver_remove_file(&iaa_crypto_driver.drv, 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