Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Tom Zanussi and committed by
Herbert Xu
93382a91 09646c98

+427 -2
+9
drivers/crypto/intel/iaa/Kconfig
··· 8 8 decompression with the Intel Analytics Accelerator (IAA) 9 9 hardware using the cryptographic API. If you choose 'M' 10 10 here, the module will be called iaa_crypto. 11 + 12 + config CRYPTO_DEV_IAA_CRYPTO_STATS 13 + bool "Enable Intel(R) IAA Compression Accelerator Statistics" 14 + depends on CRYPTO_DEV_IAA_CRYPTO 15 + default n 16 + help 17 + Enable statistics for the IAA compression accelerator. 18 + These include per-device and per-workqueue statistics in 19 + addition to global driver statistics.
+2
drivers/crypto/intel/iaa/Makefile
··· 8 8 obj-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO) := iaa_crypto.o 9 9 10 10 iaa_crypto-y := iaa_crypto_main.o iaa_crypto_comp_fixed.o 11 + 12 + iaa_crypto-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS) += iaa_crypto_stats.o
+13
drivers/crypto/intel/iaa/iaa_crypto.h
··· 48 48 bool remove; 49 49 50 50 struct iaa_device *iaa_device; 51 + 52 + u64 comp_calls; 53 + u64 comp_bytes; 54 + u64 decomp_calls; 55 + u64 decomp_bytes; 51 56 }; 52 57 53 58 struct iaa_device_compression_mode { ··· 74 69 75 70 int n_wq; 76 71 struct list_head wqs; 72 + 73 + u64 comp_calls; 74 + u64 comp_bytes; 75 + u64 decomp_calls; 76 + u64 decomp_bytes; 77 77 }; 78 78 79 79 struct wq_table_entry { ··· 166 156 bool async_mode; 167 157 bool use_irq; 168 158 }; 159 + 160 + extern struct list_head iaa_devices; 161 + extern struct mutex iaa_devices_lock; 169 162 170 163 #endif
+37 -2
drivers/crypto/intel/iaa/iaa_crypto_main.c
··· 14 14 15 15 #include "idxd.h" 16 16 #include "iaa_crypto.h" 17 + #include "iaa_crypto_stats.h" 17 18 18 19 #ifdef pr_fmt 19 20 #undef pr_fmt ··· 86 85 memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *)); 87 86 } 88 87 89 - static LIST_HEAD(iaa_devices); 90 - static DEFINE_MUTEX(iaa_devices_lock); 88 + LIST_HEAD(iaa_devices); 89 + DEFINE_MUTEX(iaa_devices_lock); 91 90 92 91 /* If enabled, IAA hw crypto algos are registered, unavailable otherwise */ 93 92 static bool iaa_crypto_enabled; ··· 1053 1052 ret = -ETIMEDOUT; 1054 1053 dev_dbg(dev, "%s timed out, size=0x%x\n", 1055 1054 op_str, comp->output_size); 1055 + update_completion_timeout_errs(); 1056 1056 goto out; 1057 1057 } 1058 1058 ··· 1063 1061 dev_dbg(dev, "compressed > uncompressed size," 1064 1062 " not compressing, size=0x%x\n", 1065 1063 comp->output_size); 1064 + update_completion_comp_buf_overflow_errs(); 1066 1065 goto out; 1067 1066 } 1068 1067 ··· 1076 1073 dev_dbg(dev, "iaa %s status=0x%x, error=0x%x, size=0x%x\n", 1077 1074 op_str, comp->status, comp->error_code, comp->output_size); 1078 1075 print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, comp, 64, 0); 1076 + update_completion_einval_errs(); 1079 1077 1080 1078 goto out; 1081 1079 } ··· 1097 1093 1098 1094 kunmap_local(src); 1099 1095 kunmap_local(dst); 1096 + 1097 + update_total_sw_decomp_calls(); 1100 1098 1101 1099 return ret; 1102 1100 } ··· 1165 1159 } 1166 1160 } else { 1167 1161 ctx->req->dlen = idxd_desc->iax_completion->output_size; 1162 + } 1163 + 1164 + /* Update stats */ 1165 + if (ctx->compress) { 1166 + update_total_comp_bytes_out(ctx->req->dlen); 1167 + update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen); 1168 + } else { 1169 + update_total_decomp_bytes_in(ctx->req->dlen); 1170 + update_wq_decomp_bytes(iaa_wq->wq, ctx->req->dlen); 1168 1171 } 1169 1172 1170 1173 if (ctx->compress && compression_ctx->verify_compress) { ··· 1295 1280 goto err; 1296 1281 } 1297 1282 1283 + /* Update stats */ 1284 + update_total_comp_calls(); 1285 + update_wq_comp_calls(wq); 1286 + 1298 1287 if (ctx->async_mode && !disable_async) { 1299 1288 ret = -EINPROGRESS; 1300 1289 dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__); ··· 1312 1293 } 1313 1294 1314 1295 *dlen = idxd_desc->iax_completion->output_size; 1296 + 1297 + /* Update stats */ 1298 + update_total_comp_bytes_out(*dlen); 1299 + update_wq_comp_bytes(wq, *dlen); 1315 1300 1316 1301 *compression_crc = idxd_desc->iax_completion->crc; 1317 1302 ··· 1533 1510 goto err; 1534 1511 } 1535 1512 1513 + /* Update stats */ 1514 + update_total_decomp_calls(); 1515 + update_wq_decomp_calls(wq); 1516 + 1536 1517 if (ctx->async_mode && !disable_async) { 1537 1518 ret = -EINPROGRESS; 1538 1519 dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__); ··· 1567 1540 1568 1541 if (!ctx->async_mode) 1569 1542 idxd_free_desc(wq, idxd_desc); 1543 + 1544 + /* Update stats */ 1545 + update_total_decomp_bytes_in(slen); 1546 + update_wq_decomp_bytes(wq, slen); 1570 1547 out: 1571 1548 return ret; 1572 1549 err: ··· 2135 2104 goto err_sync_attr_create; 2136 2105 } 2137 2106 2107 + if (iaa_crypto_debugfs_init()) 2108 + pr_warn("debugfs init failed, stats not available\n"); 2109 + 2138 2110 pr_debug("initialized\n"); 2139 2111 out: 2140 2112 return ret; ··· 2160 2126 if (iaa_unregister_compression_device()) 2161 2127 pr_debug("IAA compression device unregister failed\n"); 2162 2128 2129 + iaa_crypto_debugfs_cleanup(); 2163 2130 driver_remove_file(&iaa_crypto_driver.drv, 2164 2131 &driver_attr_sync_mode); 2165 2132 driver_remove_file(&iaa_crypto_driver.drv,
+313
drivers/crypto/intel/iaa/iaa_crypto_stats.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2021 Intel Corporation. All rights rsvd. */ 3 + 4 + #include <linux/module.h> 5 + #include <linux/kernel.h> 6 + #include <linux/highmem.h> 7 + #include <linux/mm.h> 8 + #include <linux/slab.h> 9 + #include <linux/delay.h> 10 + #include <linux/smp.h> 11 + #include <uapi/linux/idxd.h> 12 + #include <linux/idxd.h> 13 + #include <linux/dmaengine.h> 14 + #include "../../dma/idxd/idxd.h" 15 + #include <linux/debugfs.h> 16 + #include <crypto/internal/acompress.h> 17 + #include "iaa_crypto.h" 18 + #include "iaa_crypto_stats.h" 19 + 20 + static u64 total_comp_calls; 21 + static u64 total_decomp_calls; 22 + static u64 total_sw_decomp_calls; 23 + static u64 max_comp_delay_ns; 24 + static u64 max_decomp_delay_ns; 25 + static u64 max_acomp_delay_ns; 26 + static u64 max_adecomp_delay_ns; 27 + static u64 total_comp_bytes_out; 28 + static u64 total_decomp_bytes_in; 29 + static u64 total_completion_einval_errors; 30 + static u64 total_completion_timeout_errors; 31 + static u64 total_completion_comp_buf_overflow_errors; 32 + 33 + static struct dentry *iaa_crypto_debugfs_root; 34 + 35 + void update_total_comp_calls(void) 36 + { 37 + total_comp_calls++; 38 + } 39 + 40 + void update_total_comp_bytes_out(int n) 41 + { 42 + total_comp_bytes_out += n; 43 + } 44 + 45 + void update_total_decomp_calls(void) 46 + { 47 + total_decomp_calls++; 48 + } 49 + 50 + void update_total_sw_decomp_calls(void) 51 + { 52 + total_sw_decomp_calls++; 53 + } 54 + 55 + void update_total_decomp_bytes_in(int n) 56 + { 57 + total_decomp_bytes_in += n; 58 + } 59 + 60 + void update_completion_einval_errs(void) 61 + { 62 + total_completion_einval_errors++; 63 + } 64 + 65 + void update_completion_timeout_errs(void) 66 + { 67 + total_completion_timeout_errors++; 68 + } 69 + 70 + void update_completion_comp_buf_overflow_errs(void) 71 + { 72 + total_completion_comp_buf_overflow_errors++; 73 + } 74 + 75 + void update_max_comp_delay_ns(u64 start_time_ns) 76 + { 77 + u64 time_diff; 78 + 79 + time_diff = ktime_get_ns() - start_time_ns; 80 + 81 + if (time_diff > max_comp_delay_ns) 82 + max_comp_delay_ns = time_diff; 83 + } 84 + 85 + void update_max_decomp_delay_ns(u64 start_time_ns) 86 + { 87 + u64 time_diff; 88 + 89 + time_diff = ktime_get_ns() - start_time_ns; 90 + 91 + if (time_diff > max_decomp_delay_ns) 92 + max_decomp_delay_ns = time_diff; 93 + } 94 + 95 + void update_max_acomp_delay_ns(u64 start_time_ns) 96 + { 97 + u64 time_diff; 98 + 99 + time_diff = ktime_get_ns() - start_time_ns; 100 + 101 + if (time_diff > max_acomp_delay_ns) 102 + max_acomp_delay_ns = time_diff; 103 + } 104 + 105 + void update_max_adecomp_delay_ns(u64 start_time_ns) 106 + { 107 + u64 time_diff; 108 + 109 + time_diff = ktime_get_ns() - start_time_ns; 110 + 111 + if (time_diff > max_adecomp_delay_ns) 112 + 113 + max_adecomp_delay_ns = time_diff; 114 + } 115 + 116 + void update_wq_comp_calls(struct idxd_wq *idxd_wq) 117 + { 118 + struct iaa_wq *wq = idxd_wq_get_private(idxd_wq); 119 + 120 + wq->comp_calls++; 121 + wq->iaa_device->comp_calls++; 122 + } 123 + 124 + void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n) 125 + { 126 + struct iaa_wq *wq = idxd_wq_get_private(idxd_wq); 127 + 128 + wq->comp_bytes += n; 129 + wq->iaa_device->comp_bytes += n; 130 + } 131 + 132 + void update_wq_decomp_calls(struct idxd_wq *idxd_wq) 133 + { 134 + struct iaa_wq *wq = idxd_wq_get_private(idxd_wq); 135 + 136 + wq->decomp_calls++; 137 + wq->iaa_device->decomp_calls++; 138 + } 139 + 140 + void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n) 141 + { 142 + struct iaa_wq *wq = idxd_wq_get_private(idxd_wq); 143 + 144 + wq->decomp_bytes += n; 145 + wq->iaa_device->decomp_bytes += n; 146 + } 147 + 148 + static void reset_iaa_crypto_stats(void) 149 + { 150 + total_comp_calls = 0; 151 + total_decomp_calls = 0; 152 + total_sw_decomp_calls = 0; 153 + max_comp_delay_ns = 0; 154 + max_decomp_delay_ns = 0; 155 + max_acomp_delay_ns = 0; 156 + max_adecomp_delay_ns = 0; 157 + total_comp_bytes_out = 0; 158 + total_decomp_bytes_in = 0; 159 + total_completion_einval_errors = 0; 160 + total_completion_timeout_errors = 0; 161 + total_completion_comp_buf_overflow_errors = 0; 162 + } 163 + 164 + static void reset_wq_stats(struct iaa_wq *wq) 165 + { 166 + wq->comp_calls = 0; 167 + wq->comp_bytes = 0; 168 + wq->decomp_calls = 0; 169 + wq->decomp_bytes = 0; 170 + } 171 + 172 + static void reset_device_stats(struct iaa_device *iaa_device) 173 + { 174 + struct iaa_wq *iaa_wq; 175 + 176 + iaa_device->comp_calls = 0; 177 + iaa_device->comp_bytes = 0; 178 + iaa_device->decomp_calls = 0; 179 + iaa_device->decomp_bytes = 0; 180 + 181 + list_for_each_entry(iaa_wq, &iaa_device->wqs, list) 182 + reset_wq_stats(iaa_wq); 183 + } 184 + 185 + static void wq_show(struct seq_file *m, struct iaa_wq *iaa_wq) 186 + { 187 + seq_printf(m, " name: %s\n", iaa_wq->wq->name); 188 + seq_printf(m, " comp_calls: %llu\n", iaa_wq->comp_calls); 189 + seq_printf(m, " comp_bytes: %llu\n", iaa_wq->comp_bytes); 190 + seq_printf(m, " decomp_calls: %llu\n", iaa_wq->decomp_calls); 191 + seq_printf(m, " decomp_bytes: %llu\n\n", iaa_wq->decomp_bytes); 192 + } 193 + 194 + static void device_stats_show(struct seq_file *m, struct iaa_device *iaa_device) 195 + { 196 + struct iaa_wq *iaa_wq; 197 + 198 + seq_puts(m, "iaa device:\n"); 199 + seq_printf(m, " id: %d\n", iaa_device->idxd->id); 200 + seq_printf(m, " n_wqs: %d\n", iaa_device->n_wq); 201 + seq_printf(m, " comp_calls: %llu\n", iaa_device->comp_calls); 202 + seq_printf(m, " comp_bytes: %llu\n", iaa_device->comp_bytes); 203 + seq_printf(m, " decomp_calls: %llu\n", iaa_device->decomp_calls); 204 + seq_printf(m, " decomp_bytes: %llu\n", iaa_device->decomp_bytes); 205 + seq_puts(m, " wqs:\n"); 206 + 207 + list_for_each_entry(iaa_wq, &iaa_device->wqs, list) 208 + wq_show(m, iaa_wq); 209 + } 210 + 211 + static void global_stats_show(struct seq_file *m) 212 + { 213 + seq_puts(m, "global stats:\n"); 214 + seq_printf(m, " total_comp_calls: %llu\n", total_comp_calls); 215 + seq_printf(m, " total_decomp_calls: %llu\n", total_decomp_calls); 216 + seq_printf(m, " total_sw_decomp_calls: %llu\n", total_sw_decomp_calls); 217 + seq_printf(m, " total_comp_bytes_out: %llu\n", total_comp_bytes_out); 218 + seq_printf(m, " total_decomp_bytes_in: %llu\n", total_decomp_bytes_in); 219 + seq_printf(m, " total_completion_einval_errors: %llu\n", 220 + total_completion_einval_errors); 221 + seq_printf(m, " total_completion_timeout_errors: %llu\n", 222 + total_completion_timeout_errors); 223 + seq_printf(m, " total_completion_comp_buf_overflow_errors: %llu\n\n", 224 + total_completion_comp_buf_overflow_errors); 225 + } 226 + 227 + static int wq_stats_show(struct seq_file *m, void *v) 228 + { 229 + struct iaa_device *iaa_device; 230 + 231 + mutex_lock(&iaa_devices_lock); 232 + 233 + global_stats_show(m); 234 + 235 + list_for_each_entry(iaa_device, &iaa_devices, list) 236 + device_stats_show(m, iaa_device); 237 + 238 + mutex_unlock(&iaa_devices_lock); 239 + 240 + return 0; 241 + } 242 + 243 + static int iaa_crypto_stats_reset(void *data, u64 value) 244 + { 245 + struct iaa_device *iaa_device; 246 + 247 + reset_iaa_crypto_stats(); 248 + 249 + mutex_lock(&iaa_devices_lock); 250 + 251 + list_for_each_entry(iaa_device, &iaa_devices, list) 252 + reset_device_stats(iaa_device); 253 + 254 + mutex_unlock(&iaa_devices_lock); 255 + 256 + return 0; 257 + } 258 + 259 + static int wq_stats_open(struct inode *inode, struct file *file) 260 + { 261 + return single_open(file, wq_stats_show, file); 262 + } 263 + 264 + static const struct file_operations wq_stats_fops = { 265 + .open = wq_stats_open, 266 + .read = seq_read, 267 + .llseek = seq_lseek, 268 + .release = single_release, 269 + }; 270 + 271 + DEFINE_DEBUGFS_ATTRIBUTE(wq_stats_reset_fops, NULL, iaa_crypto_stats_reset, "%llu\n"); 272 + 273 + int __init iaa_crypto_debugfs_init(void) 274 + { 275 + if (!debugfs_initialized()) 276 + return -ENODEV; 277 + 278 + iaa_crypto_debugfs_root = debugfs_create_dir("iaa_crypto", NULL); 279 + if (!iaa_crypto_debugfs_root) 280 + return -ENOMEM; 281 + 282 + debugfs_create_u64("max_comp_delay_ns", 0644, 283 + iaa_crypto_debugfs_root, &max_comp_delay_ns); 284 + debugfs_create_u64("max_decomp_delay_ns", 0644, 285 + iaa_crypto_debugfs_root, &max_decomp_delay_ns); 286 + debugfs_create_u64("max_acomp_delay_ns", 0644, 287 + iaa_crypto_debugfs_root, &max_comp_delay_ns); 288 + debugfs_create_u64("max_adecomp_delay_ns", 0644, 289 + iaa_crypto_debugfs_root, &max_decomp_delay_ns); 290 + debugfs_create_u64("total_comp_calls", 0644, 291 + iaa_crypto_debugfs_root, &total_comp_calls); 292 + debugfs_create_u64("total_decomp_calls", 0644, 293 + iaa_crypto_debugfs_root, &total_decomp_calls); 294 + debugfs_create_u64("total_sw_decomp_calls", 0644, 295 + iaa_crypto_debugfs_root, &total_sw_decomp_calls); 296 + debugfs_create_u64("total_comp_bytes_out", 0644, 297 + iaa_crypto_debugfs_root, &total_comp_bytes_out); 298 + debugfs_create_u64("total_decomp_bytes_in", 0644, 299 + iaa_crypto_debugfs_root, &total_decomp_bytes_in); 300 + debugfs_create_file("wq_stats", 0644, iaa_crypto_debugfs_root, NULL, 301 + &wq_stats_fops); 302 + debugfs_create_file("stats_reset", 0644, iaa_crypto_debugfs_root, NULL, 303 + &wq_stats_reset_fops); 304 + 305 + return 0; 306 + } 307 + 308 + void __exit iaa_crypto_debugfs_cleanup(void) 309 + { 310 + debugfs_remove_recursive(iaa_crypto_debugfs_root); 311 + } 312 + 313 + MODULE_LICENSE("GPL");
+53
drivers/crypto/intel/iaa/iaa_crypto_stats.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2021 Intel Corporation. All rights rsvd. */ 3 + 4 + #ifndef __CRYPTO_DEV_IAA_CRYPTO_STATS_H__ 5 + #define __CRYPTO_DEV_IAA_CRYPTO_STATS_H__ 6 + 7 + #if defined(CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS) 8 + int iaa_crypto_debugfs_init(void); 9 + void iaa_crypto_debugfs_cleanup(void); 10 + 11 + void update_total_comp_calls(void); 12 + void update_total_comp_bytes_out(int n); 13 + void update_total_decomp_calls(void); 14 + void update_total_sw_decomp_calls(void); 15 + void update_total_decomp_bytes_in(int n); 16 + void update_max_comp_delay_ns(u64 start_time_ns); 17 + void update_max_decomp_delay_ns(u64 start_time_ns); 18 + void update_max_acomp_delay_ns(u64 start_time_ns); 19 + void update_max_adecomp_delay_ns(u64 start_time_ns); 20 + void update_completion_einval_errs(void); 21 + void update_completion_timeout_errs(void); 22 + void update_completion_comp_buf_overflow_errs(void); 23 + 24 + void update_wq_comp_calls(struct idxd_wq *idxd_wq); 25 + void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n); 26 + void update_wq_decomp_calls(struct idxd_wq *idxd_wq); 27 + void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n); 28 + 29 + #else 30 + static inline int iaa_crypto_debugfs_init(void) { return 0; } 31 + static inline void iaa_crypto_debugfs_cleanup(void) {} 32 + 33 + static inline void update_total_comp_calls(void) {} 34 + static inline void update_total_comp_bytes_out(int n) {} 35 + static inline void update_total_decomp_calls(void) {} 36 + static inline void update_total_sw_decomp_calls(void) {} 37 + static inline void update_total_decomp_bytes_in(int n) {} 38 + static inline void update_max_comp_delay_ns(u64 start_time_ns) {} 39 + static inline void update_max_decomp_delay_ns(u64 start_time_ns) {} 40 + static inline void update_max_acomp_delay_ns(u64 start_time_ns) {} 41 + static inline void update_max_adecomp_delay_ns(u64 start_time_ns) {} 42 + static inline void update_completion_einval_errs(void) {} 43 + static inline void update_completion_timeout_errs(void) {} 44 + static inline void update_completion_comp_buf_overflow_errs(void) {} 45 + 46 + static inline void update_wq_comp_calls(struct idxd_wq *idxd_wq) {} 47 + static inline void update_wq_comp_bytes(struct idxd_wq *idxd_wq, int n) {} 48 + static inline void update_wq_decomp_calls(struct idxd_wq *idxd_wq) {} 49 + static inline void update_wq_decomp_bytes(struct idxd_wq *idxd_wq, int n) {} 50 + 51 + #endif // CONFIG_CRYPTO_DEV_IAA_CRYPTO_STATS 52 + 53 + #endif