1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2020 Intel Corporation. 3*975c1df9SAlexey Marchuk * Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. 49f51cf32Spaul luse * All rights reserved. 59f51cf32Spaul luse */ 69f51cf32Spaul luse 79f51cf32Spaul luse #include "spdk/stdinc.h" 89f51cf32Spaul luse #include "spdk/thread.h" 99f51cf32Spaul luse #include "spdk/env.h" 109f51cf32Spaul luse #include "spdk/event.h" 119f51cf32Spaul luse #include "spdk/log.h" 129f51cf32Spaul luse #include "spdk/string.h" 13081f080aSBen Walker #include "spdk/accel.h" 14e69375bfSpaul luse #include "spdk/crc32.h" 150cecfcb1Spaul luse #include "spdk/util.h" 16a5d5ab27SArtur Paszkiewicz #include "spdk/xor.h" 1744bf79a8SKrzysztof Sprzaczkowski #include "spdk/dif.h" 189f51cf32Spaul luse 19b9218b7aSpaul luse #define DATA_PATTERN 0x5a 200ef079c6Spaul luse #define ALIGN_4K 0x1000 216afbf3dbSpaul luse #define COMP_BUF_PAD_PERCENTAGE 1.1L 22b9218b7aSpaul luse 239f51cf32Spaul luse static uint64_t g_tsc_rate; 249f51cf32Spaul luse static uint64_t g_tsc_end; 259b189667Spaul luse static int g_rc; 269f51cf32Spaul luse static int g_xfer_size_bytes = 4096; 2744bf79a8SKrzysztof Sprzaczkowski static int g_block_size_bytes = 512; 2844bf79a8SKrzysztof Sprzaczkowski static int g_md_size_bytes = 8; 299f51cf32Spaul luse static int g_queue_depth = 32; 30e1bf63afSJim Harris /* g_allocate_depth indicates how many tasks we allocate per worker. It will 31e1bf63afSJim Harris * be at least as much as the queue depth. 32e1bf63afSJim Harris */ 33e1bf63afSJim Harris static int g_allocate_depth = 0; 34445fe74eSpaul luse static int g_threads_per_core = 1; 359f51cf32Spaul luse static int g_time_in_sec = 5; 36e69375bfSpaul luse static uint32_t g_crc32c_seed = 0; 37850cd900Spaul luse static uint32_t g_chained_count = 1; 38b9218b7aSpaul luse static int g_fail_percent_goal = 0; 3989495464Spaul luse static uint8_t g_fill_pattern = 255; 40a5d5ab27SArtur Paszkiewicz static uint32_t g_xor_src_count = 2; 419f51cf32Spaul luse static bool g_verify = false; 422a0c66d0Spaul luse static const char *g_workload_type = NULL; 4384dbdf08STomasz Zawadzki static enum spdk_accel_opcode g_workload_selection = SPDK_ACCEL_OPC_LAST; 440a6b7098STomasz Zawadzki static const char *g_module_name = NULL; 459f51cf32Spaul luse static struct worker_thread *g_workers = NULL; 469f51cf32Spaul luse static int g_num_workers = 0; 4727e85f52SBen Walker static char *g_cd_file_in_name = NULL; 489f51cf32Spaul luse static pthread_mutex_t g_workers_lock = PTHREAD_MUTEX_INITIALIZER; 499260fa0cSpaul luse static struct spdk_app_opts g_opts = {}; 50cdefd3d3Spaul luse 5127e85f52SBen Walker struct ap_compress_seg { 5227e85f52SBen Walker void *uncompressed_data; 5327e85f52SBen Walker uint32_t uncompressed_len; 5427e85f52SBen Walker struct iovec *uncompressed_iovs; 5527e85f52SBen Walker uint32_t uncompressed_iovcnt; 5627e85f52SBen Walker 5727e85f52SBen Walker void *compressed_data; 5827e85f52SBen Walker uint32_t compressed_len; 596afbf3dbSpaul luse uint32_t compressed_len_padded; 6027e85f52SBen Walker struct iovec *compressed_iovs; 6127e85f52SBen Walker uint32_t compressed_iovcnt; 6227e85f52SBen Walker 6327e85f52SBen Walker STAILQ_ENTRY(ap_compress_seg) link; 6427e85f52SBen Walker }; 6527e85f52SBen Walker 6627e85f52SBen Walker static STAILQ_HEAD(, ap_compress_seg) g_compress_segs = STAILQ_HEAD_INITIALIZER(g_compress_segs); 6727e85f52SBen Walker 68cdefd3d3Spaul luse struct worker_thread; 69cdefd3d3Spaul luse static void accel_done(void *ref, int status); 70cdefd3d3Spaul luse 71445fe74eSpaul luse struct display_info { 72445fe74eSpaul luse int core; 73445fe74eSpaul luse int thread; 74445fe74eSpaul luse }; 75445fe74eSpaul luse 76cdefd3d3Spaul luse struct ap_task { 77cdefd3d3Spaul luse void *src; 7828886ac3Spaul luse struct iovec *src_iovs; 7928886ac3Spaul luse uint32_t src_iovcnt; 80a5d5ab27SArtur Paszkiewicz void **sources; 81850cd900Spaul luse struct iovec *dst_iovs; 82850cd900Spaul luse uint32_t dst_iovcnt; 8380dfab0aSKrzysztof Karas struct iovec md_iov; 84cdefd3d3Spaul luse void *dst; 85cdefd3d3Spaul luse void *dst2; 8681beca34SMoshe Shahar uint32_t *crc_dst; 8727e85f52SBen Walker uint32_t compressed_sz; 8827e85f52SBen Walker struct ap_compress_seg *cur_seg; 89cdefd3d3Spaul luse struct worker_thread *worker; 90cdefd3d3Spaul luse int expected_status; /* used for the compare operation */ 9144bf79a8SKrzysztof Sprzaczkowski uint32_t num_blocks; /* used for the DIF related operations */ 9244bf79a8SKrzysztof Sprzaczkowski struct spdk_dif_ctx dif_ctx; 9344bf79a8SKrzysztof Sprzaczkowski struct spdk_dif_error dif_err; 94cdefd3d3Spaul luse TAILQ_ENTRY(ap_task) link; 95cdefd3d3Spaul luse }; 969f51cf32Spaul luse 979f51cf32Spaul luse struct worker_thread { 989f51cf32Spaul luse struct spdk_io_channel *ch; 99e3babb2bSKonrad Sztyber struct spdk_accel_opcode_stats stats; 1009f51cf32Spaul luse uint64_t xfer_failed; 101b9218b7aSpaul luse uint64_t injected_miscompares; 1029f51cf32Spaul luse uint64_t current_queue_depth; 103ac9a1a83Spaul luse TAILQ_HEAD(, ap_task) tasks_pool; 1049f51cf32Spaul luse struct worker_thread *next; 1059f51cf32Spaul luse unsigned core; 1069f51cf32Spaul luse struct spdk_thread *thread; 1079f51cf32Spaul luse bool is_draining; 1089f51cf32Spaul luse struct spdk_poller *is_draining_poller; 1099f51cf32Spaul luse struct spdk_poller *stop_poller; 110ac9a1a83Spaul luse void *task_base; 111445fe74eSpaul luse struct display_info display; 1125105dc5dSKonrad Sztyber enum spdk_accel_opcode workload; 1139f51cf32Spaul luse }; 1149f51cf32Spaul luse 1159f51cf32Spaul luse static void 1169260fa0cSpaul luse dump_user_config(void) 1179f51cf32Spaul luse { 118712e8cb7SBen Walker const char *module_name = NULL; 1199260fa0cSpaul luse int rc; 1209260fa0cSpaul luse 121712e8cb7SBen Walker rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name); 1229260fa0cSpaul luse if (rc) { 123712e8cb7SBen Walker printf("error getting module name (%d)\n", rc); 1249260fa0cSpaul luse } 1259260fa0cSpaul luse 1269260fa0cSpaul luse printf("\nSPDK Configuration:\n"); 1279260fa0cSpaul luse printf("Core mask: %s\n\n", g_opts.reactor_mask); 1289f51cf32Spaul luse printf("Accel Perf Configuration:\n"); 1292a0c66d0Spaul luse printf("Workload Type: %s\n", g_workload_type); 1305105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 1315105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 132b9218b7aSpaul luse printf("CRC-32C seed: %u\n", g_crc32c_seed); 1335105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_FILL) { 13489495464Spaul luse printf("Fill pattern: 0x%x\n", g_fill_pattern); 1355105dc5dSKonrad Sztyber } else if ((g_workload_selection == SPDK_ACCEL_OPC_COMPARE) && g_fail_percent_goal > 0) { 13689495464Spaul luse printf("Failure inject: %u percent\n", g_fail_percent_goal); 1375105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 138a5d5ab27SArtur Paszkiewicz printf("Source buffers: %u\n", g_xor_src_count); 139e69375bfSpaul luse } 14044bf79a8SKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C || 141fbe2860eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 142ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 14380dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY || 14480dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE || 145fbe2860eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) { 146221eb3f4Spaul luse printf("Vector size: %u bytes\n", g_xfer_size_bytes); 147850cd900Spaul luse printf("Transfer size: %u bytes\n", g_xfer_size_bytes * g_chained_count); 148221eb3f4Spaul luse } else { 1499f51cf32Spaul luse printf("Transfer size: %u bytes\n", g_xfer_size_bytes); 150221eb3f4Spaul luse } 151ee2adf2eSKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 15280dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 15380dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE || 15480dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY) { 15544bf79a8SKrzysztof Sprzaczkowski printf("Block size: %u bytes\n", g_block_size_bytes); 15644bf79a8SKrzysztof Sprzaczkowski printf("Metadata size: %u bytes\n", g_md_size_bytes); 15744bf79a8SKrzysztof Sprzaczkowski } 15844bf79a8SKrzysztof Sprzaczkowski printf("Vector count %u\n", g_chained_count); 159712e8cb7SBen Walker printf("Module: %s\n", module_name); 1605105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS || 1615105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 16227e85f52SBen Walker printf("File Name: %s\n", g_cd_file_in_name); 16327e85f52SBen Walker } 1649f51cf32Spaul luse printf("Queue depth: %u\n", g_queue_depth); 165e1bf63afSJim Harris printf("Allocate depth: %u\n", g_allocate_depth); 166445fe74eSpaul luse printf("# threads/core: %u\n", g_threads_per_core); 1679f51cf32Spaul luse printf("Run time: %u seconds\n", g_time_in_sec); 1689f51cf32Spaul luse printf("Verify: %s\n\n", g_verify ? "Yes" : "No"); 1699f51cf32Spaul luse } 1709f51cf32Spaul luse 1719f51cf32Spaul luse static void 1729f51cf32Spaul luse usage(void) 1739f51cf32Spaul luse { 1749f51cf32Spaul luse printf("accel_perf options:\n"); 1759f51cf32Spaul luse printf("\t[-h help message]\n"); 176f17e6705Spaul luse printf("\t[-q queue depth per core]\n"); 177850cd900Spaul luse printf("\t[-C for supported workloads, use this value to configure the io vector size to test (default 1)\n"); 178445fe74eSpaul luse printf("\t[-T number of threads per core\n"); 17927e85f52SBen Walker printf("\t[-o transfer size in bytes (default: 4KiB. For compress/decompress, 0 means the input file size)]\n"); 1809f51cf32Spaul luse printf("\t[-t time in seconds]\n"); 181ee2adf2eSKrzysztof Sprzaczkowski printf("\t[-w workload type must be one of these: copy, fill, crc32c, copy_crc32c, compare, compress, decompress, dualcast, xor,\n"); 18280dfab0aSKrzysztof Karas printf("\t[ dif_verify, dif_verify_copy, dif_generate, dif_generate_copy, dix_generate, dix_verify\n"); 1830a6b7098STomasz Zawadzki printf("\t[-M assign module to the operation, not compatible with accel_assign_opc RPC\n"); 18427e85f52SBen Walker printf("\t[-l for compress/decompress workloads, name of uncompressed input file\n"); 185436877a4SKonrad Sztyber printf("\t[-S for crc32c workload, use this seed value (default 0)\n"); 186b9218b7aSpaul luse printf("\t[-P for compare workload, percentage of operations that should miscompare (percent, default 0)\n"); 18789495464Spaul luse printf("\t[-f for fill workload, use this BYTE value (default 255)\n"); 188a5d5ab27SArtur Paszkiewicz printf("\t[-x for xor workload, use this number of source buffers (default, minimum: 2)]\n"); 1892a0c66d0Spaul luse printf("\t[-y verify result if this switch is on]\n"); 190e1bf63afSJim Harris printf("\t[-a tasks to allocate per core (default: same value as -q)]\n"); 191e1bf63afSJim Harris printf("\t\tCan be used to spread operations across a wider range of memory.\n"); 1929f51cf32Spaul luse } 1939f51cf32Spaul luse 1949f51cf32Spaul luse static int 195436877a4SKonrad Sztyber parse_args(int ch, char *arg) 1969f51cf32Spaul luse { 197358b84b4SZiye Yang int argval = 0; 198c82d5789SJim Harris 199436877a4SKonrad Sztyber switch (ch) { 200e1bf63afSJim Harris case 'a': 201c82d5789SJim Harris case 'C': 202c82d5789SJim Harris case 'f': 203c82d5789SJim Harris case 'T': 204c82d5789SJim Harris case 'o': 205c82d5789SJim Harris case 'P': 206c82d5789SJim Harris case 'q': 207436877a4SKonrad Sztyber case 'S': 208c82d5789SJim Harris case 't': 209a5d5ab27SArtur Paszkiewicz case 'x': 210c82d5789SJim Harris argval = spdk_strtol(optarg, 10); 211c82d5789SJim Harris if (argval < 0) { 212436877a4SKonrad Sztyber fprintf(stderr, "-%c option must be non-negative.\n", ch); 213c82d5789SJim Harris usage(); 214c82d5789SJim Harris return 1; 215c82d5789SJim Harris } 216c82d5789SJim Harris break; 217c82d5789SJim Harris default: 218c82d5789SJim Harris break; 219c82d5789SJim Harris }; 220c82d5789SJim Harris 221436877a4SKonrad Sztyber switch (ch) { 222e1bf63afSJim Harris case 'a': 223e1bf63afSJim Harris g_allocate_depth = argval; 224e1bf63afSJim Harris break; 22588754353SZiye Yang case 'C': 226850cd900Spaul luse g_chained_count = argval; 22788754353SZiye Yang break; 22827e85f52SBen Walker case 'l': 22927e85f52SBen Walker g_cd_file_in_name = optarg; 23027e85f52SBen Walker break; 23189495464Spaul luse case 'f': 232c82d5789SJim Harris g_fill_pattern = (uint8_t)argval; 23389495464Spaul luse break; 234445fe74eSpaul luse case 'T': 235c82d5789SJim Harris g_threads_per_core = argval; 236445fe74eSpaul luse break; 2379f51cf32Spaul luse case 'o': 238c82d5789SJim Harris g_xfer_size_bytes = argval; 2399f51cf32Spaul luse break; 240b9218b7aSpaul luse case 'P': 241c82d5789SJim Harris g_fail_percent_goal = argval; 242b9218b7aSpaul luse break; 2439f51cf32Spaul luse case 'q': 244c82d5789SJim Harris g_queue_depth = argval; 2459f51cf32Spaul luse break; 246436877a4SKonrad Sztyber case 'S': 247c82d5789SJim Harris g_crc32c_seed = argval; 248e69375bfSpaul luse break; 2499f51cf32Spaul luse case 't': 250c82d5789SJim Harris g_time_in_sec = argval; 2519f51cf32Spaul luse break; 252a5d5ab27SArtur Paszkiewicz case 'x': 253a5d5ab27SArtur Paszkiewicz g_xor_src_count = argval; 254a5d5ab27SArtur Paszkiewicz break; 2559f51cf32Spaul luse case 'y': 2569f51cf32Spaul luse g_verify = true; 2579f51cf32Spaul luse break; 2582a0c66d0Spaul luse case 'w': 2592a0c66d0Spaul luse g_workload_type = optarg; 260514be889Spaul luse if (!strcmp(g_workload_type, "copy")) { 2615105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COPY; 262514be889Spaul luse } else if (!strcmp(g_workload_type, "fill")) { 2635105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_FILL; 264e69375bfSpaul luse } else if (!strcmp(g_workload_type, "crc32c")) { 2655105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_CRC32C; 266221eb3f4Spaul luse } else if (!strcmp(g_workload_type, "copy_crc32c")) { 2675105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COPY_CRC32C; 268b9218b7aSpaul luse } else if (!strcmp(g_workload_type, "compare")) { 2695105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COMPARE; 2700ef079c6Spaul luse } else if (!strcmp(g_workload_type, "dualcast")) { 2715105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_DUALCAST; 27227e85f52SBen Walker } else if (!strcmp(g_workload_type, "compress")) { 2735105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COMPRESS; 27427e85f52SBen Walker } else if (!strcmp(g_workload_type, "decompress")) { 2755105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_DECOMPRESS; 276a5d5ab27SArtur Paszkiewicz } else if (!strcmp(g_workload_type, "xor")) { 2775105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_XOR; 27844bf79a8SKrzysztof Sprzaczkowski } else if (!strcmp(g_workload_type, "dif_verify")) { 27944bf79a8SKrzysztof Sprzaczkowski g_workload_selection = SPDK_ACCEL_OPC_DIF_VERIFY; 28097457e44SKrzysztof Sprzaczkowski } else if (!strcmp(g_workload_type, "dif_verify_copy")) { 28197457e44SKrzysztof Sprzaczkowski g_workload_selection = SPDK_ACCEL_OPC_DIF_VERIFY_COPY; 282ee2adf2eSKrzysztof Sprzaczkowski } else if (!strcmp(g_workload_type, "dif_generate")) { 283ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection = SPDK_ACCEL_OPC_DIF_GENERATE; 284fbe2860eSKrzysztof Sprzaczkowski } else if (!strcmp(g_workload_type, "dif_generate_copy")) { 285fbe2860eSKrzysztof Sprzaczkowski g_workload_selection = SPDK_ACCEL_OPC_DIF_GENERATE_COPY; 28680dfab0aSKrzysztof Karas } else if (!strcmp(g_workload_type, "dix_verify")) { 28780dfab0aSKrzysztof Karas g_workload_selection = SPDK_ACCEL_OPC_DIX_VERIFY; 28880dfab0aSKrzysztof Karas } else if (!strcmp(g_workload_type, "dix_generate")) { 28980dfab0aSKrzysztof Karas g_workload_selection = SPDK_ACCEL_OPC_DIX_GENERATE; 290b21221e1Spaul luse } else { 29184dbdf08STomasz Zawadzki fprintf(stderr, "Unsupported workload type: %s\n", optarg); 292b21221e1Spaul luse usage(); 293b21221e1Spaul luse return 1; 294514be889Spaul luse } 2952a0c66d0Spaul luse break; 2960a6b7098STomasz Zawadzki case 'M': 2970a6b7098STomasz Zawadzki g_module_name = optarg; 2980a6b7098STomasz Zawadzki break; 2990a6b7098STomasz Zawadzki 3009f51cf32Spaul luse default: 3019f51cf32Spaul luse usage(); 3029f51cf32Spaul luse return 1; 3039f51cf32Spaul luse } 30488754353SZiye Yang 3059f51cf32Spaul luse return 0; 3069f51cf32Spaul luse } 3079f51cf32Spaul luse 308eea826a2Spaul luse static int dump_result(void); 3099f51cf32Spaul luse static void 3109f51cf32Spaul luse unregister_worker(void *arg1) 3119f51cf32Spaul luse { 3129f51cf32Spaul luse struct worker_thread *worker = arg1; 3139f51cf32Spaul luse 31420b5c460STomasz Zawadzki if (worker->ch) { 315e3babb2bSKonrad Sztyber spdk_accel_get_opcode_stats(worker->ch, worker->workload, 316e3babb2bSKonrad Sztyber &worker->stats, sizeof(worker->stats)); 3179f51cf32Spaul luse spdk_put_io_channel(worker->ch); 31820b5c460STomasz Zawadzki worker->ch = NULL; 31920b5c460STomasz Zawadzki } 32020b5c460STomasz Zawadzki free(worker->task_base); 3210e7821e9SJim Harris spdk_thread_exit(spdk_get_thread()); 3229f51cf32Spaul luse pthread_mutex_lock(&g_workers_lock); 3239f51cf32Spaul luse assert(g_num_workers >= 1); 3249f51cf32Spaul luse if (--g_num_workers == 0) { 3259f51cf32Spaul luse pthread_mutex_unlock(&g_workers_lock); 32620b5c460STomasz Zawadzki /* Only dump results on successful runs */ 32720b5c460STomasz Zawadzki if (g_rc == 0) { 3289b189667Spaul luse g_rc = dump_result(); 32920b5c460STomasz Zawadzki } 33020b5c460STomasz Zawadzki spdk_app_stop(g_rc); 331f042d6baSGangCao } else { 3329f51cf32Spaul luse pthread_mutex_unlock(&g_workers_lock); 3339f51cf32Spaul luse } 334f042d6baSGangCao } 3359f51cf32Spaul luse 33627e85f52SBen Walker static void 33727e85f52SBen Walker accel_perf_construct_iovs(void *buf, uint64_t sz, struct iovec *iovs, uint32_t iovcnt) 33827e85f52SBen Walker { 33927e85f52SBen Walker uint64_t ele_size; 34027e85f52SBen Walker uint8_t *data; 34127e85f52SBen Walker uint32_t i; 34227e85f52SBen Walker 34327e85f52SBen Walker ele_size = spdk_divide_round_up(sz, iovcnt); 34427e85f52SBen Walker 34527e85f52SBen Walker data = buf; 34627e85f52SBen Walker for (i = 0; i < iovcnt; i++) { 34727e85f52SBen Walker ele_size = spdk_min(ele_size, sz); 34827e85f52SBen Walker assert(ele_size > 0); 34927e85f52SBen Walker 35027e85f52SBen Walker iovs[i].iov_base = data; 35127e85f52SBen Walker iovs[i].iov_len = ele_size; 35227e85f52SBen Walker 35327e85f52SBen Walker data += ele_size; 35427e85f52SBen Walker sz -= ele_size; 35527e85f52SBen Walker } 35627e85f52SBen Walker assert(sz == 0); 35727e85f52SBen Walker } 35827e85f52SBen Walker 3598da995c4Spaul luse static int 3608da995c4Spaul luse _get_task_data_bufs(struct ap_task *task) 3618da995c4Spaul luse { 3628da995c4Spaul luse uint32_t align = 0; 36388754353SZiye Yang uint32_t i = 0; 36444bf79a8SKrzysztof Sprzaczkowski int src_buff_len = g_xfer_size_bytes; 365221eb3f4Spaul luse int dst_buff_len = g_xfer_size_bytes; 36680dfab0aSKrzysztof Karas int md_buff_len; 36744bf79a8SKrzysztof Sprzaczkowski struct spdk_dif_ctx_init_ext_opts dif_opts; 368fbe2860eSKrzysztof Sprzaczkowski uint32_t num_blocks, transfer_size_with_md; 36944bf79a8SKrzysztof Sprzaczkowski int rc; 3708da995c4Spaul luse 3718da995c4Spaul luse /* For dualcast, the DSA HW requires 4K alignment on destination addresses but 372712e8cb7SBen Walker * we do this for all modules to keep it simple. 3738da995c4Spaul luse */ 3745105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST) { 3758da995c4Spaul luse align = ALIGN_4K; 3768da995c4Spaul luse } 3778da995c4Spaul luse 3785105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS || 3795105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 38027e85f52SBen Walker task->cur_seg = STAILQ_FIRST(&g_compress_segs); 3816afbf3dbSpaul luse 3825105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 3836afbf3dbSpaul luse dst_buff_len = task->cur_seg->compressed_len_padded; 3846afbf3dbSpaul luse } 3856afbf3dbSpaul luse 3866afbf3dbSpaul luse task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL); 3876afbf3dbSpaul luse if (task->dst == NULL) { 3886afbf3dbSpaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 3896afbf3dbSpaul luse return -ENOMEM; 3906afbf3dbSpaul luse } 3916afbf3dbSpaul luse 3926afbf3dbSpaul luse task->dst_iovs = calloc(g_chained_count, sizeof(struct iovec)); 3936afbf3dbSpaul luse if (!task->dst_iovs) { 3946afbf3dbSpaul luse fprintf(stderr, "cannot allocate task->dst_iovs for task=%p\n", task); 3956afbf3dbSpaul luse return -ENOMEM; 3966afbf3dbSpaul luse } 3976afbf3dbSpaul luse task->dst_iovcnt = g_chained_count; 3986afbf3dbSpaul luse accel_perf_construct_iovs(task->dst, dst_buff_len, task->dst_iovs, task->dst_iovcnt); 3996afbf3dbSpaul luse 4006afbf3dbSpaul luse return 0; 4016afbf3dbSpaul luse } 4026afbf3dbSpaul luse 403fbe2860eSKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) { 404fbe2860eSKrzysztof Sprzaczkowski task->dst_iovcnt = g_chained_count; 405fbe2860eSKrzysztof Sprzaczkowski task->dst_iovs = calloc(task->dst_iovcnt, sizeof(struct iovec)); 406fbe2860eSKrzysztof Sprzaczkowski if (!task->dst_iovs) { 407fbe2860eSKrzysztof Sprzaczkowski fprintf(stderr, "cannot allocate task->dst_iovs for task=%p\n", task); 408fbe2860eSKrzysztof Sprzaczkowski return -ENOMEM; 409fbe2860eSKrzysztof Sprzaczkowski } 410fbe2860eSKrzysztof Sprzaczkowski 411fbe2860eSKrzysztof Sprzaczkowski num_blocks = g_xfer_size_bytes / g_block_size_bytes; 412fbe2860eSKrzysztof Sprzaczkowski /* Add bytes for each block for metadata */ 413fbe2860eSKrzysztof Sprzaczkowski transfer_size_with_md = g_xfer_size_bytes + (num_blocks * g_md_size_bytes); 414fbe2860eSKrzysztof Sprzaczkowski task->num_blocks = num_blocks; 415fbe2860eSKrzysztof Sprzaczkowski 416fbe2860eSKrzysztof Sprzaczkowski for (i = 0; i < task->dst_iovcnt; i++) { 417fbe2860eSKrzysztof Sprzaczkowski task->dst_iovs[i].iov_base = spdk_dma_zmalloc(transfer_size_with_md, 0, NULL); 418fbe2860eSKrzysztof Sprzaczkowski if (task->dst_iovs[i].iov_base == NULL) { 419fbe2860eSKrzysztof Sprzaczkowski return -ENOMEM; 420fbe2860eSKrzysztof Sprzaczkowski } 421fbe2860eSKrzysztof Sprzaczkowski task->dst_iovs[i].iov_len = transfer_size_with_md; 422fbe2860eSKrzysztof Sprzaczkowski } 423fbe2860eSKrzysztof Sprzaczkowski 424fbe2860eSKrzysztof Sprzaczkowski dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format); 425fbe2860eSKrzysztof Sprzaczkowski dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16; 426fbe2860eSKrzysztof Sprzaczkowski 427fbe2860eSKrzysztof Sprzaczkowski rc = spdk_dif_ctx_init(&task->dif_ctx, 428fbe2860eSKrzysztof Sprzaczkowski g_block_size_bytes + g_md_size_bytes, 429fbe2860eSKrzysztof Sprzaczkowski g_md_size_bytes, true, true, 430fbe2860eSKrzysztof Sprzaczkowski SPDK_DIF_TYPE1, 431fbe2860eSKrzysztof Sprzaczkowski SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK, 432fbe2860eSKrzysztof Sprzaczkowski 0x123, 0xFFFF, 0x234, 0, 0, &dif_opts); 433fbe2860eSKrzysztof Sprzaczkowski if (rc != 0) { 4341940e7e4SKrzysztof Sprzaczkowski fprintf(stderr, "Initialization of DIF context failed, error (%d)\n", rc); 435fbe2860eSKrzysztof Sprzaczkowski return rc; 436fbe2860eSKrzysztof Sprzaczkowski } 437fbe2860eSKrzysztof Sprzaczkowski } 438fbe2860eSKrzysztof Sprzaczkowski 43997457e44SKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY_COPY) { 44097457e44SKrzysztof Sprzaczkowski /* Allocate source buffers */ 44197457e44SKrzysztof Sprzaczkowski task->src_iovcnt = g_chained_count; 44297457e44SKrzysztof Sprzaczkowski task->src_iovs = calloc(task->src_iovcnt, sizeof(struct iovec)); 44397457e44SKrzysztof Sprzaczkowski if (!task->src_iovs) { 44497457e44SKrzysztof Sprzaczkowski fprintf(stderr, "cannot allocate task->src_iovs for task=%p\n", task); 44597457e44SKrzysztof Sprzaczkowski return -ENOMEM; 44697457e44SKrzysztof Sprzaczkowski } 44797457e44SKrzysztof Sprzaczkowski 44897457e44SKrzysztof Sprzaczkowski num_blocks = g_xfer_size_bytes / g_block_size_bytes; 44997457e44SKrzysztof Sprzaczkowski /* Add bytes for each block for metadata */ 45097457e44SKrzysztof Sprzaczkowski transfer_size_with_md = g_xfer_size_bytes + (num_blocks * g_md_size_bytes); 45197457e44SKrzysztof Sprzaczkowski task->num_blocks = num_blocks; 45297457e44SKrzysztof Sprzaczkowski 45397457e44SKrzysztof Sprzaczkowski for (i = 0; i < task->src_iovcnt; i++) { 45497457e44SKrzysztof Sprzaczkowski task->src_iovs[i].iov_base = spdk_dma_zmalloc(transfer_size_with_md, 0, NULL); 45597457e44SKrzysztof Sprzaczkowski if (task->src_iovs[i].iov_base == NULL) { 45697457e44SKrzysztof Sprzaczkowski return -ENOMEM; 45797457e44SKrzysztof Sprzaczkowski } 45897457e44SKrzysztof Sprzaczkowski memset(task->src_iovs[i].iov_base, DATA_PATTERN, transfer_size_with_md); 45997457e44SKrzysztof Sprzaczkowski task->src_iovs[i].iov_len = transfer_size_with_md; 46097457e44SKrzysztof Sprzaczkowski } 46197457e44SKrzysztof Sprzaczkowski 46297457e44SKrzysztof Sprzaczkowski /* Allocate destination buffers */ 46397457e44SKrzysztof Sprzaczkowski task->dst_iovcnt = g_chained_count; 46497457e44SKrzysztof Sprzaczkowski task->dst_iovs = calloc(task->dst_iovcnt, sizeof(struct iovec)); 46597457e44SKrzysztof Sprzaczkowski if (!task->dst_iovs) { 46697457e44SKrzysztof Sprzaczkowski fprintf(stderr, "cannot allocated task->dst_iovs fot task=%p\n", task); 46797457e44SKrzysztof Sprzaczkowski return -ENOMEM; 46897457e44SKrzysztof Sprzaczkowski } 46997457e44SKrzysztof Sprzaczkowski 47097457e44SKrzysztof Sprzaczkowski for (i = 0; i < task->dst_iovcnt; i++) { 47197457e44SKrzysztof Sprzaczkowski task->dst_iovs[i].iov_base = spdk_dma_zmalloc(dst_buff_len, 0, NULL); 47297457e44SKrzysztof Sprzaczkowski if (task->dst_iovs[i].iov_base == NULL) { 47397457e44SKrzysztof Sprzaczkowski return -ENOMEM; 47497457e44SKrzysztof Sprzaczkowski } 47597457e44SKrzysztof Sprzaczkowski task->dst_iovs[i].iov_len = dst_buff_len; 47697457e44SKrzysztof Sprzaczkowski } 47797457e44SKrzysztof Sprzaczkowski 47897457e44SKrzysztof Sprzaczkowski dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format); 47997457e44SKrzysztof Sprzaczkowski dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16; 48097457e44SKrzysztof Sprzaczkowski 48197457e44SKrzysztof Sprzaczkowski /* Init DIF ctx */ 48297457e44SKrzysztof Sprzaczkowski rc = spdk_dif_ctx_init(&task->dif_ctx, 48397457e44SKrzysztof Sprzaczkowski g_block_size_bytes + g_md_size_bytes, 48497457e44SKrzysztof Sprzaczkowski g_md_size_bytes, true, true, 48597457e44SKrzysztof Sprzaczkowski SPDK_DIF_TYPE1, 48697457e44SKrzysztof Sprzaczkowski SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK, 48797457e44SKrzysztof Sprzaczkowski 0x123, 0xFFFF, 0x234, 0, 0, &dif_opts); 48897457e44SKrzysztof Sprzaczkowski if (rc != 0) { 48997457e44SKrzysztof Sprzaczkowski fprintf(stderr, "Initialization of DIF context failed, error (%d)\n", rc); 49097457e44SKrzysztof Sprzaczkowski return rc; 49197457e44SKrzysztof Sprzaczkowski } 49297457e44SKrzysztof Sprzaczkowski 49397457e44SKrzysztof Sprzaczkowski rc = spdk_dif_generate(task->src_iovs, task->src_iovcnt, task->num_blocks, &task->dif_ctx); 49497457e44SKrzysztof Sprzaczkowski if (rc != 0) { 49597457e44SKrzysztof Sprzaczkowski fprintf(stderr, "Generation of DIF failed, error (%d)\n", rc); 49697457e44SKrzysztof Sprzaczkowski return rc; 49797457e44SKrzysztof Sprzaczkowski } 49897457e44SKrzysztof Sprzaczkowski } 49997457e44SKrzysztof Sprzaczkowski 5005105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 50181beca34SMoshe Shahar g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 50281beca34SMoshe Shahar task->crc_dst = spdk_dma_zmalloc(sizeof(*task->crc_dst), 0, NULL); 50381beca34SMoshe Shahar } 50481beca34SMoshe Shahar 50581beca34SMoshe Shahar if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 50644bf79a8SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C || 507fbe2860eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 508ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 50980dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY || 51080dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY || 51180dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE) { 512850cd900Spaul luse assert(g_chained_count > 0); 513850cd900Spaul luse task->src_iovcnt = g_chained_count; 51428886ac3Spaul luse task->src_iovs = calloc(task->src_iovcnt, sizeof(struct iovec)); 51528886ac3Spaul luse if (!task->src_iovs) { 51628886ac3Spaul luse fprintf(stderr, "cannot allocated task->src_iovs fot task=%p\n", task); 51788754353SZiye Yang return -ENOMEM; 51888754353SZiye Yang } 51988754353SZiye Yang 5205105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 521850cd900Spaul luse dst_buff_len = g_xfer_size_bytes * g_chained_count; 522221eb3f4Spaul luse } 523221eb3f4Spaul luse 524ee2adf2eSKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 525ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) { 52644bf79a8SKrzysztof Sprzaczkowski src_buff_len += (g_xfer_size_bytes / g_block_size_bytes) * g_md_size_bytes; 52744bf79a8SKrzysztof Sprzaczkowski } 52844bf79a8SKrzysztof Sprzaczkowski 52928886ac3Spaul luse for (i = 0; i < task->src_iovcnt; i++) { 53044bf79a8SKrzysztof Sprzaczkowski task->src_iovs[i].iov_base = spdk_dma_zmalloc(src_buff_len, 0, NULL); 53128886ac3Spaul luse if (task->src_iovs[i].iov_base == NULL) { 53288754353SZiye Yang return -ENOMEM; 53388754353SZiye Yang } 53444bf79a8SKrzysztof Sprzaczkowski memset(task->src_iovs[i].iov_base, DATA_PATTERN, src_buff_len); 53544bf79a8SKrzysztof Sprzaczkowski task->src_iovs[i].iov_len = src_buff_len; 53688754353SZiye Yang } 53780dfab0aSKrzysztof Karas if (g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE || 53880dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY) { 53980dfab0aSKrzysztof Karas md_buff_len = (g_xfer_size_bytes / g_block_size_bytes) * g_md_size_bytes * 54080dfab0aSKrzysztof Karas g_chained_count; 54180dfab0aSKrzysztof Karas task->md_iov.iov_base = spdk_dma_zmalloc(md_buff_len, 0, NULL); 54280dfab0aSKrzysztof Karas if (task->md_iov.iov_base == NULL) { 54380dfab0aSKrzysztof Karas return -ENOMEM; 54480dfab0aSKrzysztof Karas } 54580dfab0aSKrzysztof Karas task->md_iov.iov_len = md_buff_len; 54680dfab0aSKrzysztof Karas } 5475105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 548a5d5ab27SArtur Paszkiewicz assert(g_xor_src_count > 1); 549a5d5ab27SArtur Paszkiewicz task->sources = calloc(g_xor_src_count, sizeof(*task->sources)); 550a5d5ab27SArtur Paszkiewicz if (!task->sources) { 551a5d5ab27SArtur Paszkiewicz return -ENOMEM; 552a5d5ab27SArtur Paszkiewicz } 55388754353SZiye Yang 554a5d5ab27SArtur Paszkiewicz for (i = 0; i < g_xor_src_count; i++) { 555a5d5ab27SArtur Paszkiewicz task->sources[i] = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL); 556a5d5ab27SArtur Paszkiewicz if (!task->sources[i]) { 557a5d5ab27SArtur Paszkiewicz return -ENOMEM; 558a5d5ab27SArtur Paszkiewicz } 559a5d5ab27SArtur Paszkiewicz memset(task->sources[i], DATA_PATTERN, g_xfer_size_bytes); 560a5d5ab27SArtur Paszkiewicz } 56188754353SZiye Yang } else { 5628da995c4Spaul luse task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL); 5638da995c4Spaul luse if (task->src == NULL) { 5648da995c4Spaul luse fprintf(stderr, "Unable to alloc src buffer\n"); 5658da995c4Spaul luse return -ENOMEM; 5668da995c4Spaul luse } 56788754353SZiye Yang 56888754353SZiye Yang /* For fill, set the entire src buffer so we can check if verify is enabled. */ 5695105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_FILL) { 57088754353SZiye Yang memset(task->src, g_fill_pattern, g_xfer_size_bytes); 57188754353SZiye Yang } else { 5728da995c4Spaul luse memset(task->src, DATA_PATTERN, g_xfer_size_bytes); 57388754353SZiye Yang } 57488754353SZiye Yang } 5758da995c4Spaul luse 57644bf79a8SKrzysztof Sprzaczkowski if (g_workload_selection != SPDK_ACCEL_OPC_CRC32C && 577fbe2860eSKrzysztof Sprzaczkowski g_workload_selection != SPDK_ACCEL_OPC_DIF_VERIFY && 578ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection != SPDK_ACCEL_OPC_DIF_GENERATE && 57997457e44SKrzysztof Sprzaczkowski g_workload_selection != SPDK_ACCEL_OPC_DIF_GENERATE_COPY && 58080dfab0aSKrzysztof Karas g_workload_selection != SPDK_ACCEL_OPC_DIF_VERIFY_COPY && 58180dfab0aSKrzysztof Karas g_workload_selection != SPDK_ACCEL_OPC_DIX_VERIFY && 58280dfab0aSKrzysztof Karas g_workload_selection != SPDK_ACCEL_OPC_DIX_GENERATE) { 583221eb3f4Spaul luse task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL); 5848da995c4Spaul luse if (task->dst == NULL) { 5858da995c4Spaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 5868da995c4Spaul luse return -ENOMEM; 5878da995c4Spaul luse } 5888da995c4Spaul luse 5898da995c4Spaul luse /* For compare we want the buffers to match, otherwise not. */ 5905105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPARE) { 591221eb3f4Spaul luse memset(task->dst, DATA_PATTERN, dst_buff_len); 5928da995c4Spaul luse } else { 593221eb3f4Spaul luse memset(task->dst, ~DATA_PATTERN, dst_buff_len); 594221eb3f4Spaul luse } 5958da995c4Spaul luse } 5968da995c4Spaul luse 59784162738Spaul luse /* For dualcast 2 buffers are needed for the operation. */ 5985105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST || 5995105dc5dSKonrad Sztyber (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_verify)) { 6008da995c4Spaul luse task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL); 6018da995c4Spaul luse if (task->dst2 == NULL) { 6028da995c4Spaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 6038da995c4Spaul luse return -ENOMEM; 6048da995c4Spaul luse } 6058da995c4Spaul luse memset(task->dst2, ~DATA_PATTERN, g_xfer_size_bytes); 6068da995c4Spaul luse } 6078da995c4Spaul luse 608ee2adf2eSKrzysztof Sprzaczkowski if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 60997457e44SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 61097457e44SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY_COPY) { 61144bf79a8SKrzysztof Sprzaczkowski dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format); 61244bf79a8SKrzysztof Sprzaczkowski dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16; 61344bf79a8SKrzysztof Sprzaczkowski 61444bf79a8SKrzysztof Sprzaczkowski task->num_blocks = (g_xfer_size_bytes * g_chained_count) / g_block_size_bytes; 61544bf79a8SKrzysztof Sprzaczkowski 61644bf79a8SKrzysztof Sprzaczkowski rc = spdk_dif_ctx_init(&task->dif_ctx, 61744bf79a8SKrzysztof Sprzaczkowski g_block_size_bytes + g_md_size_bytes, 61844bf79a8SKrzysztof Sprzaczkowski g_md_size_bytes, true, true, 61944bf79a8SKrzysztof Sprzaczkowski SPDK_DIF_TYPE1, 62044bf79a8SKrzysztof Sprzaczkowski SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK, 62144bf79a8SKrzysztof Sprzaczkowski 16, 0xFFFF, 10, 0, 0, &dif_opts); 62244bf79a8SKrzysztof Sprzaczkowski if (rc != 0) { 62344bf79a8SKrzysztof Sprzaczkowski fprintf(stderr, "Initialization of DIF context failed, error (%d)\n", rc); 62444bf79a8SKrzysztof Sprzaczkowski return rc; 62544bf79a8SKrzysztof Sprzaczkowski } 62644bf79a8SKrzysztof Sprzaczkowski 62797457e44SKrzysztof Sprzaczkowski if ((g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) || 62897457e44SKrzysztof Sprzaczkowski (g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY_COPY)) { 62944bf79a8SKrzysztof Sprzaczkowski rc = spdk_dif_generate(task->src_iovs, task->src_iovcnt, task->num_blocks, &task->dif_ctx); 63044bf79a8SKrzysztof Sprzaczkowski if (rc != 0) { 63144bf79a8SKrzysztof Sprzaczkowski fprintf(stderr, "Generation of DIF failed, error (%d)\n", rc); 63244bf79a8SKrzysztof Sprzaczkowski return rc; 63344bf79a8SKrzysztof Sprzaczkowski } 63444bf79a8SKrzysztof Sprzaczkowski } 635ee2adf2eSKrzysztof Sprzaczkowski } 63680dfab0aSKrzysztof Karas if (g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE || 63780dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY) { 63880dfab0aSKrzysztof Karas dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format); 63980dfab0aSKrzysztof Karas dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16; 64080dfab0aSKrzysztof Karas 64180dfab0aSKrzysztof Karas task->num_blocks = (g_xfer_size_bytes * g_chained_count) / g_block_size_bytes; 64280dfab0aSKrzysztof Karas 64380dfab0aSKrzysztof Karas rc = spdk_dif_ctx_init(&task->dif_ctx, 64480dfab0aSKrzysztof Karas g_block_size_bytes, 64580dfab0aSKrzysztof Karas g_md_size_bytes, false, true, 64680dfab0aSKrzysztof Karas SPDK_DIF_TYPE1, 64780dfab0aSKrzysztof Karas SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 64880dfab0aSKrzysztof Karas SPDK_DIF_FLAGS_REFTAG_CHECK, 64980dfab0aSKrzysztof Karas 0x123, 0xFFFF, 0x234, 0, 0, &dif_opts); 65080dfab0aSKrzysztof Karas if (rc != 0) { 65180dfab0aSKrzysztof Karas fprintf(stderr, "Initialization of DIX context failed, error (%d)\n", rc); 65280dfab0aSKrzysztof Karas return rc; 65380dfab0aSKrzysztof Karas } 65480dfab0aSKrzysztof Karas if (g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY) { 65580dfab0aSKrzysztof Karas rc = spdk_dix_generate(task->src_iovs, task->src_iovcnt, &task->md_iov, 65680dfab0aSKrzysztof Karas task->num_blocks, &task->dif_ctx); 65780dfab0aSKrzysztof Karas if (rc != 0) { 65880dfab0aSKrzysztof Karas fprintf(stderr, "Generation of DIX failed, error (%d)\n", rc); 65980dfab0aSKrzysztof Karas return rc; 66080dfab0aSKrzysztof Karas } 66180dfab0aSKrzysztof Karas } 66280dfab0aSKrzysztof Karas 66380dfab0aSKrzysztof Karas } 66444bf79a8SKrzysztof Sprzaczkowski 6658da995c4Spaul luse return 0; 6668da995c4Spaul luse } 6678da995c4Spaul luse 668ac9a1a83Spaul luse inline static struct ap_task * 669ac9a1a83Spaul luse _get_task(struct worker_thread *worker) 670ac9a1a83Spaul luse { 671ac9a1a83Spaul luse struct ap_task *task; 672ac9a1a83Spaul luse 673ac9a1a83Spaul luse if (!TAILQ_EMPTY(&worker->tasks_pool)) { 674ac9a1a83Spaul luse task = TAILQ_FIRST(&worker->tasks_pool); 675ac9a1a83Spaul luse TAILQ_REMOVE(&worker->tasks_pool, task, link); 676ac9a1a83Spaul luse } else { 677ac9a1a83Spaul luse fprintf(stderr, "Unable to get ap_task\n"); 678ac9a1a83Spaul luse return NULL; 679ac9a1a83Spaul luse } 680ac9a1a83Spaul luse 681ac9a1a83Spaul luse return task; 682ac9a1a83Spaul luse } 683ac9a1a83Spaul luse 684f17e6705Spaul luse /* Submit one operation using the same ap task that just completed. */ 6859f51cf32Spaul luse static void 686ac9a1a83Spaul luse _submit_single(struct worker_thread *worker, struct ap_task *task) 6879f51cf32Spaul luse { 688b9218b7aSpaul luse int random_num; 68940ec8e97Spaul luse int rc = 0; 6909f51cf32Spaul luse 6919f51cf32Spaul luse assert(worker); 6929f51cf32Spaul luse 69313067997Spaul luse switch (worker->workload) { 6945105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY: 695e8463f87Spaul luse rc = spdk_accel_submit_copy(worker->ch, task->dst, task->src, 69679e2a56fSKonrad Sztyber g_xfer_size_bytes, accel_done, task); 697e69375bfSpaul luse break; 6985105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_FILL: 6992a0c66d0Spaul luse /* For fill use the first byte of the task->dst buffer */ 700ee7e31f9Spaul luse rc = spdk_accel_submit_fill(worker->ch, task->dst, *(uint8_t *)task->src, 70179e2a56fSKonrad Sztyber g_xfer_size_bytes, accel_done, task); 702e69375bfSpaul luse break; 7035105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_CRC32C: 70481beca34SMoshe Shahar rc = spdk_accel_submit_crc32cv(worker->ch, task->crc_dst, 70528886ac3Spaul luse task->src_iovs, task->src_iovcnt, g_crc32c_seed, 70690c56d96SZiye Yang accel_done, task); 707e69375bfSpaul luse break; 7085105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY_CRC32C: 70928886ac3Spaul luse rc = spdk_accel_submit_copy_crc32cv(worker->ch, task->dst, task->src_iovs, task->src_iovcnt, 71079e2a56fSKonrad Sztyber task->crc_dst, g_crc32c_seed, accel_done, task); 711221eb3f4Spaul luse break; 7125105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPARE: 713b9218b7aSpaul luse random_num = rand() % 100; 714b9218b7aSpaul luse if (random_num < g_fail_percent_goal) { 715b9218b7aSpaul luse task->expected_status = -EILSEQ; 716b9218b7aSpaul luse *(uint8_t *)task->dst = ~DATA_PATTERN; 717b9218b7aSpaul luse } else { 718b9218b7aSpaul luse task->expected_status = 0; 719b9218b7aSpaul luse *(uint8_t *)task->dst = DATA_PATTERN; 720b9218b7aSpaul luse } 721ee7e31f9Spaul luse rc = spdk_accel_submit_compare(worker->ch, task->dst, task->src, 722e8463f87Spaul luse g_xfer_size_bytes, accel_done, task); 723b9218b7aSpaul luse break; 7245105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DUALCAST: 725ee7e31f9Spaul luse rc = spdk_accel_submit_dualcast(worker->ch, task->dst, task->dst2, 72679e2a56fSKonrad Sztyber task->src, g_xfer_size_bytes, accel_done, task); 7270ef079c6Spaul luse break; 7285105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPRESS: 72927e85f52SBen Walker task->src_iovs = task->cur_seg->uncompressed_iovs; 73027e85f52SBen Walker task->src_iovcnt = task->cur_seg->uncompressed_iovcnt; 7316afbf3dbSpaul luse rc = spdk_accel_submit_compress(worker->ch, task->dst, task->cur_seg->compressed_len_padded, 7326afbf3dbSpaul luse task->src_iovs, 73379e2a56fSKonrad Sztyber task->src_iovcnt, &task->compressed_sz, accel_done, task); 73427e85f52SBen Walker break; 7355105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DECOMPRESS: 73627e85f52SBen Walker task->src_iovs = task->cur_seg->compressed_iovs; 73727e85f52SBen Walker task->src_iovcnt = task->cur_seg->compressed_iovcnt; 73827e85f52SBen Walker rc = spdk_accel_submit_decompress(worker->ch, task->dst_iovs, task->dst_iovcnt, task->src_iovs, 73979e2a56fSKonrad Sztyber task->src_iovcnt, NULL, accel_done, task); 74027e85f52SBen Walker break; 7415105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_XOR: 742a5d5ab27SArtur Paszkiewicz rc = spdk_accel_submit_xor(worker->ch, task->dst, task->sources, g_xor_src_count, 743a5d5ab27SArtur Paszkiewicz g_xfer_size_bytes, accel_done, task); 744a5d5ab27SArtur Paszkiewicz break; 74544bf79a8SKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_VERIFY: 74644bf79a8SKrzysztof Sprzaczkowski rc = spdk_accel_submit_dif_verify(worker->ch, task->src_iovs, task->src_iovcnt, task->num_blocks, 74744bf79a8SKrzysztof Sprzaczkowski &task->dif_ctx, &task->dif_err, accel_done, task); 74844bf79a8SKrzysztof Sprzaczkowski break; 749ee2adf2eSKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_GENERATE: 750ee2adf2eSKrzysztof Sprzaczkowski rc = spdk_accel_submit_dif_generate(worker->ch, task->src_iovs, task->src_iovcnt, task->num_blocks, 751ee2adf2eSKrzysztof Sprzaczkowski &task->dif_ctx, accel_done, task); 752ee2adf2eSKrzysztof Sprzaczkowski break; 753fbe2860eSKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_GENERATE_COPY: 754fbe2860eSKrzysztof Sprzaczkowski rc = spdk_accel_submit_dif_generate_copy(worker->ch, task->dst_iovs, task->dst_iovcnt, 755fbe2860eSKrzysztof Sprzaczkowski task->src_iovs, task->src_iovcnt, 756fbe2860eSKrzysztof Sprzaczkowski task->num_blocks, &task->dif_ctx, accel_done, task); 757fbe2860eSKrzysztof Sprzaczkowski break; 75897457e44SKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_VERIFY_COPY: 75997457e44SKrzysztof Sprzaczkowski rc = spdk_accel_submit_dif_verify_copy(worker->ch, task->dst_iovs, task->dst_iovcnt, 76097457e44SKrzysztof Sprzaczkowski task->src_iovs, task->src_iovcnt, task->num_blocks, 76197457e44SKrzysztof Sprzaczkowski &task->dif_ctx, &task->dif_err, accel_done, task); 76297457e44SKrzysztof Sprzaczkowski break; 76380dfab0aSKrzysztof Karas case SPDK_ACCEL_OPC_DIX_GENERATE: 76480dfab0aSKrzysztof Karas rc = spdk_accel_submit_dix_generate(worker->ch, task->src_iovs, task->src_iovcnt, 76580dfab0aSKrzysztof Karas &task->md_iov, task->num_blocks, 76680dfab0aSKrzysztof Karas &task->dif_ctx, accel_done, task); 76780dfab0aSKrzysztof Karas break; 76880dfab0aSKrzysztof Karas case SPDK_ACCEL_OPC_DIX_VERIFY: 76980dfab0aSKrzysztof Karas rc = spdk_accel_submit_dix_verify(worker->ch, task->src_iovs, task->src_iovcnt, 77080dfab0aSKrzysztof Karas &task->md_iov, task->num_blocks, 77180dfab0aSKrzysztof Karas &task->dif_ctx, &task->dif_err, accel_done, task); 77280dfab0aSKrzysztof Karas break; 773e69375bfSpaul luse default: 7742a0c66d0Spaul luse assert(false); 775e69375bfSpaul luse break; 776e69375bfSpaul luse 7772a0c66d0Spaul luse } 77840ec8e97Spaul luse 7796799d46aSpaul luse worker->current_queue_depth++; 78040ec8e97Spaul luse if (rc) { 781e8463f87Spaul luse accel_done(task, rc); 78240ec8e97Spaul luse } 7839f51cf32Spaul luse } 7849f51cf32Spaul luse 7859f51cf32Spaul luse static void 786e150f6b8SZiye Yang _free_task_buffers(struct ap_task *task) 787ac9a1a83Spaul luse { 78888754353SZiye Yang uint32_t i; 78988754353SZiye Yang 7905105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS || 7915105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 79227e85f52SBen Walker free(task->dst_iovs); 7935105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 79444bf79a8SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C || 795fbe2860eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 796ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 79797457e44SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY || 79880dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY_COPY || 79980dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY || 80080dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE) { 80181beca34SMoshe Shahar if (task->crc_dst) { 80281beca34SMoshe Shahar spdk_dma_free(task->crc_dst); 80381beca34SMoshe Shahar } 80428886ac3Spaul luse if (task->src_iovs) { 80528886ac3Spaul luse for (i = 0; i < task->src_iovcnt; i++) { 80628886ac3Spaul luse if (task->src_iovs[i].iov_base) { 80728886ac3Spaul luse spdk_dma_free(task->src_iovs[i].iov_base); 80888754353SZiye Yang } 80988754353SZiye Yang } 81028886ac3Spaul luse free(task->src_iovs); 81188754353SZiye Yang } 81297457e44SKrzysztof Sprzaczkowski if (task->dst_iovs) { 81397457e44SKrzysztof Sprzaczkowski for (i = 0; i < task->dst_iovcnt; i++) { 81497457e44SKrzysztof Sprzaczkowski if (task->dst_iovs[i].iov_base) { 81597457e44SKrzysztof Sprzaczkowski spdk_dma_free(task->dst_iovs[i].iov_base); 81697457e44SKrzysztof Sprzaczkowski } 81797457e44SKrzysztof Sprzaczkowski } 81897457e44SKrzysztof Sprzaczkowski free(task->dst_iovs); 81997457e44SKrzysztof Sprzaczkowski } 82080dfab0aSKrzysztof Karas if (task->md_iov.iov_base) { 82180dfab0aSKrzysztof Karas spdk_dma_free(task->md_iov.iov_base); 82280dfab0aSKrzysztof Karas } 8235105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 824a5d5ab27SArtur Paszkiewicz if (task->sources) { 825a5d5ab27SArtur Paszkiewicz for (i = 0; i < g_xor_src_count; i++) { 826a5d5ab27SArtur Paszkiewicz spdk_dma_free(task->sources[i]); 827a5d5ab27SArtur Paszkiewicz } 828a5d5ab27SArtur Paszkiewicz free(task->sources); 829a5d5ab27SArtur Paszkiewicz } 83088754353SZiye Yang } else { 831ac9a1a83Spaul luse spdk_dma_free(task->src); 83288754353SZiye Yang } 83388754353SZiye Yang 834ac9a1a83Spaul luse spdk_dma_free(task->dst); 8355105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST || g_workload_selection == SPDK_ACCEL_OPC_XOR) { 836ac9a1a83Spaul luse spdk_dma_free(task->dst2); 837ac9a1a83Spaul luse } 838ac9a1a83Spaul luse } 839ac9a1a83Spaul luse 840221eb3f4Spaul luse static int 84128886ac3Spaul luse _vector_memcmp(void *_dst, struct iovec *src_src_iovs, uint32_t iovcnt) 842221eb3f4Spaul luse { 843221eb3f4Spaul luse uint32_t i; 844221eb3f4Spaul luse uint32_t ttl_len = 0; 845221eb3f4Spaul luse uint8_t *dst = (uint8_t *)_dst; 846221eb3f4Spaul luse 847221eb3f4Spaul luse for (i = 0; i < iovcnt; i++) { 84828886ac3Spaul luse if (memcmp(dst, src_src_iovs[i].iov_base, src_src_iovs[i].iov_len)) { 849221eb3f4Spaul luse return -1; 850221eb3f4Spaul luse } 85128886ac3Spaul luse dst += src_src_iovs[i].iov_len; 85228886ac3Spaul luse ttl_len += src_src_iovs[i].iov_len; 853221eb3f4Spaul luse } 854221eb3f4Spaul luse 855221eb3f4Spaul luse if (ttl_len != iovcnt * g_xfer_size_bytes) { 856221eb3f4Spaul luse return -1; 857221eb3f4Spaul luse } 858221eb3f4Spaul luse 859221eb3f4Spaul luse return 0; 860221eb3f4Spaul luse } 861221eb3f4Spaul luse 86213067997Spaul luse static int _worker_stop(void *arg); 86313067997Spaul luse 864fab40895Spaul luse static void 865df42f358Spaul luse accel_done(void *arg1, int status) 8669f51cf32Spaul luse { 8679f51cf32Spaul luse struct ap_task *task = arg1; 8689f51cf32Spaul luse struct worker_thread *worker = task->worker; 869e69375bfSpaul luse uint32_t sw_crc32c; 870fbe2860eSKrzysztof Sprzaczkowski struct spdk_dif_error err_blk; 8719f51cf32Spaul luse 8729f51cf32Spaul luse assert(worker); 8739f51cf32Spaul luse assert(worker->current_queue_depth > 0); 8749f51cf32Spaul luse 875df42f358Spaul luse if (g_verify && status == 0) { 87613067997Spaul luse switch (worker->workload) { 8775105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY_CRC32C: 87828886ac3Spaul luse sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed); 87981beca34SMoshe Shahar if (*task->crc_dst != sw_crc32c) { 880221eb3f4Spaul luse SPDK_NOTICELOG("CRC-32C miscompare\n"); 881221eb3f4Spaul luse worker->xfer_failed++; 882221eb3f4Spaul luse } 88328886ac3Spaul luse if (_vector_memcmp(task->dst, task->src_iovs, task->src_iovcnt)) { 884221eb3f4Spaul luse SPDK_NOTICELOG("Data miscompare\n"); 885221eb3f4Spaul luse worker->xfer_failed++; 886221eb3f4Spaul luse } 887221eb3f4Spaul luse break; 8885105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_CRC32C: 88928886ac3Spaul luse sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed); 89081beca34SMoshe Shahar if (*task->crc_dst != sw_crc32c) { 891e69375bfSpaul luse SPDK_NOTICELOG("CRC-32C miscompare\n"); 892e69375bfSpaul luse worker->xfer_failed++; 893e69375bfSpaul luse } 894b9218b7aSpaul luse break; 8955105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY: 896b9218b7aSpaul luse if (memcmp(task->src, task->dst, g_xfer_size_bytes)) { 8979f51cf32Spaul luse SPDK_NOTICELOG("Data miscompare\n"); 8989f51cf32Spaul luse worker->xfer_failed++; 899b9218b7aSpaul luse } 900b9218b7aSpaul luse break; 9015105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DUALCAST: 9020ef079c6Spaul luse if (memcmp(task->src, task->dst, g_xfer_size_bytes)) { 9030ef079c6Spaul luse SPDK_NOTICELOG("Data miscompare, first destination\n"); 9040ef079c6Spaul luse worker->xfer_failed++; 9050ef079c6Spaul luse } 9060ef079c6Spaul luse if (memcmp(task->src, task->dst2, g_xfer_size_bytes)) { 9070ef079c6Spaul luse SPDK_NOTICELOG("Data miscompare, second destination\n"); 9080ef079c6Spaul luse worker->xfer_failed++; 9090ef079c6Spaul luse } 9100ef079c6Spaul luse break; 9115105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_FILL: 912d207237fSpaul luse if (memcmp(task->dst, task->src, g_xfer_size_bytes)) { 913d207237fSpaul luse SPDK_NOTICELOG("Data miscompare\n"); 914d207237fSpaul luse worker->xfer_failed++; 915d207237fSpaul luse } 916d207237fSpaul luse break; 9175105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPARE: 9188cee297cSpaul luse break; 9195105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPRESS: 92027e85f52SBen Walker break; 9215105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DECOMPRESS: 92227e85f52SBen Walker if (memcmp(task->dst, task->cur_seg->uncompressed_data, task->cur_seg->uncompressed_len)) { 92327e85f52SBen Walker SPDK_NOTICELOG("Data miscompare on decompression\n"); 92427e85f52SBen Walker worker->xfer_failed++; 92527e85f52SBen Walker } 92627e85f52SBen Walker break; 9275105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_XOR: 928a5d5ab27SArtur Paszkiewicz if (spdk_xor_gen(task->dst2, task->sources, g_xor_src_count, 929a5d5ab27SArtur Paszkiewicz g_xfer_size_bytes) != 0) { 930a5d5ab27SArtur Paszkiewicz SPDK_ERRLOG("Failed to generate xor for verification\n"); 931a5d5ab27SArtur Paszkiewicz } else if (memcmp(task->dst, task->dst2, g_xfer_size_bytes)) { 932a5d5ab27SArtur Paszkiewicz SPDK_NOTICELOG("Data miscompare\n"); 933a5d5ab27SArtur Paszkiewicz worker->xfer_failed++; 934a5d5ab27SArtur Paszkiewicz } 935a5d5ab27SArtur Paszkiewicz break; 93644bf79a8SKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_VERIFY: 93744bf79a8SKrzysztof Sprzaczkowski break; 938ee2adf2eSKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_GENERATE: 939ee2adf2eSKrzysztof Sprzaczkowski if (spdk_dif_verify(task->src_iovs, task->src_iovcnt, task->num_blocks, 940ee2adf2eSKrzysztof Sprzaczkowski &task->dif_ctx, &err_blk) != 0) { 941ee2adf2eSKrzysztof Sprzaczkowski SPDK_NOTICELOG("Data miscompare, " 942ee2adf2eSKrzysztof Sprzaczkowski "err_type %u, expected %lu, actual %lu, err_offset %u\n", 943ee2adf2eSKrzysztof Sprzaczkowski err_blk.err_type, err_blk.expected, 944ee2adf2eSKrzysztof Sprzaczkowski err_blk.actual, err_blk.err_offset); 945ee2adf2eSKrzysztof Sprzaczkowski worker->xfer_failed++; 946ee2adf2eSKrzysztof Sprzaczkowski } 947ee2adf2eSKrzysztof Sprzaczkowski break; 948fbe2860eSKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_GENERATE_COPY: 949fbe2860eSKrzysztof Sprzaczkowski if (spdk_dif_verify(task->dst_iovs, task->dst_iovcnt, task->num_blocks, 950fbe2860eSKrzysztof Sprzaczkowski &task->dif_ctx, &err_blk) != 0) { 951fbe2860eSKrzysztof Sprzaczkowski SPDK_NOTICELOG("Data miscompare, " 952fbe2860eSKrzysztof Sprzaczkowski "err_type %u, expected %lu, actual %lu, err_offset %u\n", 953fbe2860eSKrzysztof Sprzaczkowski err_blk.err_type, err_blk.expected, 954fbe2860eSKrzysztof Sprzaczkowski err_blk.actual, err_blk.err_offset); 955fbe2860eSKrzysztof Sprzaczkowski worker->xfer_failed++; 956fbe2860eSKrzysztof Sprzaczkowski } 957fbe2860eSKrzysztof Sprzaczkowski break; 95897457e44SKrzysztof Sprzaczkowski case SPDK_ACCEL_OPC_DIF_VERIFY_COPY: 95997457e44SKrzysztof Sprzaczkowski break; 96080dfab0aSKrzysztof Karas case SPDK_ACCEL_OPC_DIX_GENERATE: 96180dfab0aSKrzysztof Karas if (spdk_dix_verify(task->src_iovs, task->src_iovcnt, &task->md_iov, 96280dfab0aSKrzysztof Karas task->num_blocks, &task->dif_ctx, &err_blk) != 0) { 96380dfab0aSKrzysztof Karas SPDK_NOTICELOG("Data miscompare, " 96480dfab0aSKrzysztof Karas "err_type %u, expected %lu, actual %lu, err_offset %u\n", 96580dfab0aSKrzysztof Karas err_blk.err_type, err_blk.expected, 96680dfab0aSKrzysztof Karas err_blk.actual, err_blk.err_offset); 96780dfab0aSKrzysztof Karas worker->xfer_failed++; 96880dfab0aSKrzysztof Karas } 96980dfab0aSKrzysztof Karas break; 97080dfab0aSKrzysztof Karas case SPDK_ACCEL_OPC_DIX_VERIFY: 97180dfab0aSKrzysztof Karas break; 972b9218b7aSpaul luse default: 973b9218b7aSpaul luse assert(false); 974b9218b7aSpaul luse break; 9759f51cf32Spaul luse } 9769f51cf32Spaul luse } 977b9218b7aSpaul luse 9785105dc5dSKonrad Sztyber if (worker->workload == SPDK_ACCEL_OPC_COMPRESS || 9795105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 98027e85f52SBen Walker /* Advance the task to the next segment */ 98127e85f52SBen Walker task->cur_seg = STAILQ_NEXT(task->cur_seg, link); 98227e85f52SBen Walker if (task->cur_seg == NULL) { 98327e85f52SBen Walker task->cur_seg = STAILQ_FIRST(&g_compress_segs); 98427e85f52SBen Walker } 98527e85f52SBen Walker } 98627e85f52SBen Walker 987b9218b7aSpaul luse if (task->expected_status == -EILSEQ) { 988df42f358Spaul luse assert(status != 0); 989b9218b7aSpaul luse worker->injected_miscompares++; 99013067997Spaul luse status = 0; 991df42f358Spaul luse } else if (status) { 992712e8cb7SBen Walker /* Expected to pass but the accel module reported an error (ex: COMPARE operation). */ 993b9218b7aSpaul luse worker->xfer_failed++; 994b9218b7aSpaul luse } 995b9218b7aSpaul luse 9969f51cf32Spaul luse worker->current_queue_depth--; 9979f51cf32Spaul luse 99813067997Spaul luse if (!worker->is_draining && status == 0) { 999451462f6SJim Harris TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 1000451462f6SJim Harris task = _get_task(worker); 10019f51cf32Spaul luse _submit_single(worker, task); 1002f17e6705Spaul luse } else { 1003b34883e0SZiye Yang TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 1004f17e6705Spaul luse } 10059f51cf32Spaul luse } 10069f51cf32Spaul luse 10079f51cf32Spaul luse static int 10089f51cf32Spaul luse dump_result(void) 10099f51cf32Spaul luse { 10109f51cf32Spaul luse uint64_t total_completed = 0; 10119f51cf32Spaul luse uint64_t total_failed = 0; 1012b9218b7aSpaul luse uint64_t total_miscompared = 0; 1013e7cce062SGang Cao uint64_t total_xfer_per_sec, total_bw_in_MiBps = 0; 10149f51cf32Spaul luse struct worker_thread *worker = g_workers; 10159424e9ebSKonrad Sztyber char tmp[64]; 10169f51cf32Spaul luse 10179424e9ebSKonrad Sztyber printf("\n%-12s %20s %16s %16s %16s\n", 10189424e9ebSKonrad Sztyber "Core,Thread", "Transfers", "Bandwidth", "Failed", "Miscompares"); 10199424e9ebSKonrad Sztyber printf("------------------------------------------------------------------------------------\n"); 10209f51cf32Spaul luse while (worker != NULL) { 10219f51cf32Spaul luse 1022e3babb2bSKonrad Sztyber uint64_t xfer_per_sec = worker->stats.executed / g_time_in_sec; 1023e3babb2bSKonrad Sztyber uint64_t bw_in_MiBps = worker->stats.num_bytes / 10249f51cf32Spaul luse (g_time_in_sec * 1024 * 1024); 10259f51cf32Spaul luse 1026e3babb2bSKonrad Sztyber total_completed += worker->stats.executed; 10279f51cf32Spaul luse total_failed += worker->xfer_failed; 1028b9218b7aSpaul luse total_miscompared += worker->injected_miscompares; 1029e7cce062SGang Cao total_bw_in_MiBps += bw_in_MiBps; 10309f51cf32Spaul luse 10319424e9ebSKonrad Sztyber snprintf(tmp, sizeof(tmp), "%u,%u", worker->display.core, worker->display.thread); 10329f51cf32Spaul luse if (xfer_per_sec) { 10339424e9ebSKonrad Sztyber printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n", 10349424e9ebSKonrad Sztyber tmp, xfer_per_sec, bw_in_MiBps, worker->xfer_failed, 10359424e9ebSKonrad Sztyber worker->injected_miscompares); 10369f51cf32Spaul luse } 10379f51cf32Spaul luse 10389f51cf32Spaul luse worker = worker->next; 10399f51cf32Spaul luse } 10409f51cf32Spaul luse 10419f51cf32Spaul luse total_xfer_per_sec = total_completed / g_time_in_sec; 10429f51cf32Spaul luse 10439424e9ebSKonrad Sztyber printf("====================================================================================\n"); 10449424e9ebSKonrad Sztyber printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n", 10459424e9ebSKonrad Sztyber "Total", total_xfer_per_sec, total_bw_in_MiBps, total_failed, total_miscompared); 10469f51cf32Spaul luse 10479f51cf32Spaul luse return total_failed ? 1 : 0; 10489f51cf32Spaul luse } 10499f51cf32Spaul luse 1050e150f6b8SZiye Yang static inline void 1051e150f6b8SZiye Yang _free_task_buffers_in_pool(struct worker_thread *worker) 1052e150f6b8SZiye Yang { 1053e150f6b8SZiye Yang struct ap_task *task; 1054e150f6b8SZiye Yang 1055e150f6b8SZiye Yang assert(worker); 1056e150f6b8SZiye Yang while ((task = TAILQ_FIRST(&worker->tasks_pool))) { 1057e150f6b8SZiye Yang TAILQ_REMOVE(&worker->tasks_pool, task, link); 1058e150f6b8SZiye Yang _free_task_buffers(task); 1059e150f6b8SZiye Yang } 1060e150f6b8SZiye Yang } 1061e150f6b8SZiye Yang 10629f51cf32Spaul luse static int 10639f51cf32Spaul luse _check_draining(void *arg) 10649f51cf32Spaul luse { 10659f51cf32Spaul luse struct worker_thread *worker = arg; 10669f51cf32Spaul luse 10679f51cf32Spaul luse assert(worker); 10689f51cf32Spaul luse 10699f51cf32Spaul luse if (worker->current_queue_depth == 0) { 1070e150f6b8SZiye Yang _free_task_buffers_in_pool(worker); 10719f51cf32Spaul luse spdk_poller_unregister(&worker->is_draining_poller); 10729f51cf32Spaul luse unregister_worker(worker); 10739f51cf32Spaul luse } 10749f51cf32Spaul luse 1075fa9e703fSpaul Luse return SPDK_POLLER_BUSY; 10769f51cf32Spaul luse } 10779f51cf32Spaul luse 10789f51cf32Spaul luse static int 10799f51cf32Spaul luse _worker_stop(void *arg) 10809f51cf32Spaul luse { 10819f51cf32Spaul luse struct worker_thread *worker = arg; 10829f51cf32Spaul luse 10839f51cf32Spaul luse assert(worker); 10849f51cf32Spaul luse 10859f51cf32Spaul luse spdk_poller_unregister(&worker->stop_poller); 10869f51cf32Spaul luse 10879f51cf32Spaul luse /* now let the worker drain and check it's outstanding IO with a poller */ 10889f51cf32Spaul luse worker->is_draining = true; 1089ab0bc5c2SShuhei Matsumoto worker->is_draining_poller = SPDK_POLLER_REGISTER(_check_draining, worker, 0); 10909f51cf32Spaul luse 1091fa9e703fSpaul Luse return SPDK_POLLER_BUSY; 10929f51cf32Spaul luse } 10939f51cf32Spaul luse 109420b5c460STomasz Zawadzki static void shutdown_cb(void); 109520b5c460STomasz Zawadzki 10969f51cf32Spaul luse static void 1097a34fc12bSpaul luse _init_thread(void *arg1) 1098a34fc12bSpaul luse { 1099a34fc12bSpaul luse struct worker_thread *worker; 1100a34fc12bSpaul luse struct ap_task *task; 1101998b5d66Spaul luse int i, num_tasks = g_allocate_depth; 1102445fe74eSpaul luse struct display_info *display = arg1; 1103a34fc12bSpaul luse 1104a34fc12bSpaul luse worker = calloc(1, sizeof(*worker)); 1105a34fc12bSpaul luse if (worker == NULL) { 1106a34fc12bSpaul luse fprintf(stderr, "Unable to allocate worker\n"); 1107445fe74eSpaul luse free(display); 110820b5c460STomasz Zawadzki spdk_thread_exit(spdk_get_thread()); 110920b5c460STomasz Zawadzki goto no_worker; 1110a34fc12bSpaul luse } 1111a34fc12bSpaul luse 111213067997Spaul luse worker->workload = g_workload_selection; 1113445fe74eSpaul luse worker->display.core = display->core; 1114445fe74eSpaul luse worker->display.thread = display->thread; 1115445fe74eSpaul luse free(display); 11169f51cf32Spaul luse worker->core = spdk_env_get_current_core(); 11179f51cf32Spaul luse worker->thread = spdk_get_thread(); 1118eea826a2Spaul luse pthread_mutex_lock(&g_workers_lock); 1119eea826a2Spaul luse g_num_workers++; 11209f51cf32Spaul luse worker->next = g_workers; 1121eea826a2Spaul luse g_workers = worker; 1122eea826a2Spaul luse pthread_mutex_unlock(&g_workers_lock); 112334c48f1bSBen Walker worker->ch = spdk_accel_get_io_channel(); 11242dd64cf9Spaul luse if (worker->ch == NULL) { 11252dd64cf9Spaul luse fprintf(stderr, "Unable to get an accel channel\n"); 11262dd64cf9Spaul luse goto error; 11272dd64cf9Spaul luse } 1128b9218b7aSpaul luse 1129f17e6705Spaul luse TAILQ_INIT(&worker->tasks_pool); 1130f17e6705Spaul luse 1131ac9a1a83Spaul luse worker->task_base = calloc(num_tasks, sizeof(struct ap_task)); 1132ac9a1a83Spaul luse if (worker->task_base == NULL) { 1133ac9a1a83Spaul luse fprintf(stderr, "Could not allocate task base.\n"); 1134ac9a1a83Spaul luse goto error; 11350cecfcb1Spaul luse } 1136ac9a1a83Spaul luse 1137ac9a1a83Spaul luse task = worker->task_base; 1138ac9a1a83Spaul luse for (i = 0; i < num_tasks; i++) { 1139ac9a1a83Spaul luse TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 11404cd7ca9bSJim Harris task->worker = worker; 1141ac9a1a83Spaul luse if (_get_task_data_bufs(task)) { 1142ac9a1a83Spaul luse fprintf(stderr, "Unable to get data bufs\n"); 1143ac9a1a83Spaul luse goto error; 1144ac9a1a83Spaul luse } 1145ac9a1a83Spaul luse task++; 11469f51cf32Spaul luse } 11479f51cf32Spaul luse 11489f51cf32Spaul luse /* Register a poller that will stop the worker at time elapsed */ 1149ab0bc5c2SShuhei Matsumoto worker->stop_poller = SPDK_POLLER_REGISTER(_worker_stop, worker, 11509f51cf32Spaul luse g_time_in_sec * 1000000ULL); 11519f51cf32Spaul luse 1152998b5d66Spaul luse /* Load up queue depth worth of operations. */ 1153998b5d66Spaul luse for (i = 0; i < g_queue_depth; i++) { 1154ac9a1a83Spaul luse task = _get_task(worker); 1155ac9a1a83Spaul luse if (task == NULL) { 1156a34fc12bSpaul luse goto error; 1157b9218b7aSpaul luse } 1158b9218b7aSpaul luse 11599f51cf32Spaul luse _submit_single(worker, task); 11609f51cf32Spaul luse } 1161a34fc12bSpaul luse return; 1162a34fc12bSpaul luse error: 1163e150f6b8SZiye Yang 1164e150f6b8SZiye Yang _free_task_buffers_in_pool(worker); 1165ac9a1a83Spaul luse free(worker->task_base); 1166*975c1df9SAlexey Marchuk worker->task_base = NULL; 116720b5c460STomasz Zawadzki no_worker: 116820b5c460STomasz Zawadzki shutdown_cb(); 116920b5c460STomasz Zawadzki g_rc = -1; 11709f51cf32Spaul luse } 11719f51cf32Spaul luse 11729f51cf32Spaul luse static void 11739f51cf32Spaul luse accel_perf_start(void *arg1) 11749f51cf32Spaul luse { 1175eea826a2Spaul luse struct spdk_cpuset tmp_cpumask = {}; 1176eea826a2Spaul luse char thread_name[32]; 1177eea826a2Spaul luse uint32_t i; 1178445fe74eSpaul luse int j; 1179eea826a2Spaul luse struct spdk_thread *thread; 1180445fe74eSpaul luse struct display_info *display; 1181514be889Spaul luse 11829f51cf32Spaul luse g_tsc_rate = spdk_get_ticks_hz(); 11839f51cf32Spaul luse g_tsc_end = spdk_get_ticks() + g_time_in_sec * g_tsc_rate; 11849f51cf32Spaul luse 11859260fa0cSpaul luse dump_user_config(); 11869260fa0cSpaul luse 11879f51cf32Spaul luse printf("Running for %d seconds...\n", g_time_in_sec); 11889f51cf32Spaul luse fflush(stdout); 11899f51cf32Spaul luse 1190eea826a2Spaul luse /* Create worker threads for each core that was specified. */ 1191eea826a2Spaul luse SPDK_ENV_FOREACH_CORE(i) { 1192445fe74eSpaul luse for (j = 0; j < g_threads_per_core; j++) { 1193445fe74eSpaul luse snprintf(thread_name, sizeof(thread_name), "ap_worker_%u_%u", i, j); 1194eea826a2Spaul luse spdk_cpuset_zero(&tmp_cpumask); 1195eea826a2Spaul luse spdk_cpuset_set_cpu(&tmp_cpumask, i, true); 1196eea826a2Spaul luse thread = spdk_thread_create(thread_name, &tmp_cpumask); 1197445fe74eSpaul luse display = calloc(1, sizeof(*display)); 1198445fe74eSpaul luse if (display == NULL) { 1199445fe74eSpaul luse fprintf(stderr, "Unable to allocate memory\n"); 1200445fe74eSpaul luse spdk_app_stop(-1); 1201445fe74eSpaul luse return; 1202445fe74eSpaul luse } 1203445fe74eSpaul luse display->core = i; 1204445fe74eSpaul luse display->thread = j; 1205445fe74eSpaul luse spdk_thread_send_msg(thread, _init_thread, display); 1206445fe74eSpaul luse } 1207eea826a2Spaul luse } 12089f51cf32Spaul luse } 12099f51cf32Spaul luse 121027e85f52SBen Walker static void 121127e85f52SBen Walker accel_perf_free_compress_segs(void) 121227e85f52SBen Walker { 121327e85f52SBen Walker struct ap_compress_seg *seg, *tmp; 121427e85f52SBen Walker 121527e85f52SBen Walker STAILQ_FOREACH_SAFE(seg, &g_compress_segs, link, tmp) { 121627e85f52SBen Walker free(seg->uncompressed_iovs); 121727e85f52SBen Walker free(seg->compressed_iovs); 121827e85f52SBen Walker spdk_dma_free(seg->compressed_data); 121927e85f52SBen Walker spdk_dma_free(seg->uncompressed_data); 122027e85f52SBen Walker STAILQ_REMOVE_HEAD(&g_compress_segs, link); 122127e85f52SBen Walker free(seg); 122227e85f52SBen Walker } 122327e85f52SBen Walker } 122427e85f52SBen Walker 122527e85f52SBen Walker struct accel_perf_prep_ctx { 122627e85f52SBen Walker FILE *file; 122727e85f52SBen Walker long remaining; 122827e85f52SBen Walker struct spdk_io_channel *ch; 122927e85f52SBen Walker struct ap_compress_seg *cur_seg; 123027e85f52SBen Walker }; 123127e85f52SBen Walker 123227e85f52SBen Walker static void accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx); 123327e85f52SBen Walker 123427e85f52SBen Walker static void 123527e85f52SBen Walker accel_perf_prep_process_seg_cpl(void *ref, int status) 123627e85f52SBen Walker { 123727e85f52SBen Walker struct accel_perf_prep_ctx *ctx = ref; 123827e85f52SBen Walker struct ap_compress_seg *seg; 123927e85f52SBen Walker 124027e85f52SBen Walker if (status != 0) { 124127e85f52SBen Walker fprintf(stderr, "error (%d) on initial compress completion\n", status); 124227e85f52SBen Walker spdk_dma_free(ctx->cur_seg->compressed_data); 124327e85f52SBen Walker spdk_dma_free(ctx->cur_seg->uncompressed_data); 124427e85f52SBen Walker free(ctx->cur_seg); 124527e85f52SBen Walker spdk_put_io_channel(ctx->ch); 124627e85f52SBen Walker fclose(ctx->file); 124727e85f52SBen Walker free(ctx); 124827e85f52SBen Walker spdk_app_stop(-status); 124927e85f52SBen Walker return; 125027e85f52SBen Walker } 125127e85f52SBen Walker 125227e85f52SBen Walker seg = ctx->cur_seg; 125327e85f52SBen Walker 12545105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 125527e85f52SBen Walker seg->compressed_iovs = calloc(g_chained_count, sizeof(struct iovec)); 125627e85f52SBen Walker if (seg->compressed_iovs == NULL) { 125727e85f52SBen Walker fprintf(stderr, "unable to allocate iovec\n"); 125827e85f52SBen Walker spdk_dma_free(seg->compressed_data); 125927e85f52SBen Walker spdk_dma_free(seg->uncompressed_data); 126027e85f52SBen Walker free(seg); 126127e85f52SBen Walker spdk_put_io_channel(ctx->ch); 126227e85f52SBen Walker fclose(ctx->file); 126327e85f52SBen Walker free(ctx); 126427e85f52SBen Walker spdk_app_stop(-ENOMEM); 126527e85f52SBen Walker return; 126627e85f52SBen Walker } 126727e85f52SBen Walker seg->compressed_iovcnt = g_chained_count; 126827e85f52SBen Walker 126927e85f52SBen Walker accel_perf_construct_iovs(seg->compressed_data, seg->compressed_len, seg->compressed_iovs, 127027e85f52SBen Walker seg->compressed_iovcnt); 127127e85f52SBen Walker } 127227e85f52SBen Walker 127327e85f52SBen Walker STAILQ_INSERT_TAIL(&g_compress_segs, seg, link); 127427e85f52SBen Walker ctx->remaining -= seg->uncompressed_len; 127527e85f52SBen Walker 127627e85f52SBen Walker accel_perf_prep_process_seg(ctx); 127727e85f52SBen Walker } 127827e85f52SBen Walker 127927e85f52SBen Walker static void 128027e85f52SBen Walker accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx) 128127e85f52SBen Walker { 128227e85f52SBen Walker struct ap_compress_seg *seg; 12836afbf3dbSpaul luse int sz, sz_read, sz_padded; 128427e85f52SBen Walker void *ubuf, *cbuf; 128527e85f52SBen Walker struct iovec iov[1]; 128627e85f52SBen Walker int rc; 128727e85f52SBen Walker 128827e85f52SBen Walker if (ctx->remaining == 0) { 128927e85f52SBen Walker spdk_put_io_channel(ctx->ch); 129027e85f52SBen Walker fclose(ctx->file); 129127e85f52SBen Walker free(ctx); 129227e85f52SBen Walker accel_perf_start(NULL); 129327e85f52SBen Walker return; 129427e85f52SBen Walker } 129527e85f52SBen Walker 129627e85f52SBen Walker sz = spdk_min(ctx->remaining, g_xfer_size_bytes); 12976afbf3dbSpaul luse /* Add 10% pad to the compress buffer for incompressible data. Note that a real app 12986afbf3dbSpaul luse * would likely either deal with the failure of not having a large enough buffer 12996afbf3dbSpaul luse * by submitting another operation with a larger one. Or, like the vbdev module 13006afbf3dbSpaul luse * does, just accept the error and use the data uncompressed marking it as such in 13016afbf3dbSpaul luse * its own metadata so that in the future it doesn't try to decompress uncompressed 13026afbf3dbSpaul luse * data, etc. 13036afbf3dbSpaul luse */ 13046afbf3dbSpaul luse sz_padded = sz * COMP_BUF_PAD_PERCENTAGE; 130527e85f52SBen Walker 130627e85f52SBen Walker ubuf = spdk_dma_zmalloc(sz, ALIGN_4K, NULL); 130727e85f52SBen Walker if (!ubuf) { 130827e85f52SBen Walker fprintf(stderr, "unable to allocate uncompress buffer\n"); 130927e85f52SBen Walker rc = -ENOMEM; 131027e85f52SBen Walker goto error; 131127e85f52SBen Walker } 131227e85f52SBen Walker 13136afbf3dbSpaul luse cbuf = spdk_dma_malloc(sz_padded, ALIGN_4K, NULL); 131427e85f52SBen Walker if (!cbuf) { 131527e85f52SBen Walker fprintf(stderr, "unable to allocate compress buffer\n"); 131627e85f52SBen Walker rc = -ENOMEM; 131727e85f52SBen Walker spdk_dma_free(ubuf); 131827e85f52SBen Walker goto error; 131927e85f52SBen Walker } 132027e85f52SBen Walker 132127e85f52SBen Walker seg = calloc(1, sizeof(*seg)); 132227e85f52SBen Walker if (!seg) { 132327e85f52SBen Walker fprintf(stderr, "unable to allocate comp/decomp segment\n"); 132427e85f52SBen Walker spdk_dma_free(ubuf); 132527e85f52SBen Walker spdk_dma_free(cbuf); 132627e85f52SBen Walker rc = -ENOMEM; 132727e85f52SBen Walker goto error; 132827e85f52SBen Walker } 132927e85f52SBen Walker 133027e85f52SBen Walker sz_read = fread(ubuf, sizeof(uint8_t), sz, ctx->file); 133127e85f52SBen Walker if (sz_read != sz) { 133227e85f52SBen Walker fprintf(stderr, "unable to read input file\n"); 133327e85f52SBen Walker free(seg); 133427e85f52SBen Walker spdk_dma_free(ubuf); 133527e85f52SBen Walker spdk_dma_free(cbuf); 133627e85f52SBen Walker rc = -errno; 133727e85f52SBen Walker goto error; 133827e85f52SBen Walker } 133927e85f52SBen Walker 13405105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 134127e85f52SBen Walker seg->uncompressed_iovs = calloc(g_chained_count, sizeof(struct iovec)); 134227e85f52SBen Walker if (seg->uncompressed_iovs == NULL) { 134327e85f52SBen Walker fprintf(stderr, "unable to allocate iovec\n"); 134427e85f52SBen Walker free(seg); 134527e85f52SBen Walker spdk_dma_free(ubuf); 134627e85f52SBen Walker spdk_dma_free(cbuf); 134727e85f52SBen Walker rc = -ENOMEM; 134827e85f52SBen Walker goto error; 134927e85f52SBen Walker } 135027e85f52SBen Walker seg->uncompressed_iovcnt = g_chained_count; 135127e85f52SBen Walker accel_perf_construct_iovs(ubuf, sz, seg->uncompressed_iovs, seg->uncompressed_iovcnt); 135227e85f52SBen Walker } 135327e85f52SBen Walker 135427e85f52SBen Walker seg->uncompressed_data = ubuf; 135527e85f52SBen Walker seg->uncompressed_len = sz; 135627e85f52SBen Walker seg->compressed_data = cbuf; 135727e85f52SBen Walker seg->compressed_len = sz; 13586afbf3dbSpaul luse seg->compressed_len_padded = sz_padded; 135927e85f52SBen Walker 136027e85f52SBen Walker ctx->cur_seg = seg; 136127e85f52SBen Walker iov[0].iov_base = seg->uncompressed_data; 136227e85f52SBen Walker iov[0].iov_len = seg->uncompressed_len; 136327e85f52SBen Walker /* Note that anytime a call is made to spdk_accel_submit_compress() there's a chance 136427e85f52SBen Walker * it will fail with -ENOMEM in the event that the destination buffer is not large enough 13656afbf3dbSpaul luse * to hold the compressed data. This example app simply adds 10% buffer for compressed data 13666afbf3dbSpaul luse * but real applications may want to consider a more sophisticated method. 136727e85f52SBen Walker */ 13686afbf3dbSpaul luse rc = spdk_accel_submit_compress(ctx->ch, seg->compressed_data, seg->compressed_len_padded, iov, 1, 136979e2a56fSKonrad Sztyber &seg->compressed_len, accel_perf_prep_process_seg_cpl, ctx); 137027e85f52SBen Walker if (rc < 0) { 137127e85f52SBen Walker fprintf(stderr, "error (%d) on initial compress submission\n", rc); 137227e85f52SBen Walker goto error; 137327e85f52SBen Walker } 137427e85f52SBen Walker 137527e85f52SBen Walker return; 137627e85f52SBen Walker 137727e85f52SBen Walker error: 137827e85f52SBen Walker spdk_put_io_channel(ctx->ch); 137927e85f52SBen Walker fclose(ctx->file); 138027e85f52SBen Walker free(ctx); 138127e85f52SBen Walker spdk_app_stop(rc); 138227e85f52SBen Walker } 138327e85f52SBen Walker 138427e85f52SBen Walker static void 138527e85f52SBen Walker accel_perf_prep(void *arg1) 138627e85f52SBen Walker { 138727e85f52SBen Walker struct accel_perf_prep_ctx *ctx; 13880a6b7098STomasz Zawadzki const char *module_name = NULL; 138927e85f52SBen Walker int rc = 0; 139027e85f52SBen Walker 13910a6b7098STomasz Zawadzki if (g_module_name) { 13920a6b7098STomasz Zawadzki rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name); 13930a6b7098STomasz Zawadzki if (rc != 0 || strcmp(g_module_name, module_name) != 0) { 13940a6b7098STomasz Zawadzki fprintf(stderr, "Module '%s' was assigned via JSON config or RPC, instead of '%s'\n", 13950a6b7098STomasz Zawadzki module_name, g_module_name); 13960a6b7098STomasz Zawadzki fprintf(stderr, "-M option is not compatible with accel_assign_opc RPC\n"); 13970a6b7098STomasz Zawadzki rc = -EINVAL; 13980a6b7098STomasz Zawadzki goto error_end; 13990a6b7098STomasz Zawadzki } 14000a6b7098STomasz Zawadzki } 14010a6b7098STomasz Zawadzki 14025105dc5dSKonrad Sztyber if (g_workload_selection != SPDK_ACCEL_OPC_COMPRESS && 14035105dc5dSKonrad Sztyber g_workload_selection != SPDK_ACCEL_OPC_DECOMPRESS) { 140427e85f52SBen Walker accel_perf_start(arg1); 140527e85f52SBen Walker return; 140627e85f52SBen Walker } 140727e85f52SBen Walker 140827e85f52SBen Walker if (g_cd_file_in_name == NULL) { 140927e85f52SBen Walker fprintf(stdout, "A filename is required.\n"); 141027e85f52SBen Walker rc = -EINVAL; 141127e85f52SBen Walker goto error_end; 141227e85f52SBen Walker } 141327e85f52SBen Walker 14145105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS && g_verify) { 141527e85f52SBen Walker fprintf(stdout, "\nCompression does not support the verify option, aborting.\n"); 141627e85f52SBen Walker rc = -ENOTSUP; 141727e85f52SBen Walker goto error_end; 141827e85f52SBen Walker } 141927e85f52SBen Walker 142027e85f52SBen Walker printf("Preparing input file...\n"); 142127e85f52SBen Walker 142227e85f52SBen Walker ctx = calloc(1, sizeof(*ctx)); 142327e85f52SBen Walker if (ctx == NULL) { 142427e85f52SBen Walker rc = -ENOMEM; 142527e85f52SBen Walker goto error_end; 142627e85f52SBen Walker } 142727e85f52SBen Walker 142827e85f52SBen Walker ctx->file = fopen(g_cd_file_in_name, "r"); 142927e85f52SBen Walker if (ctx->file == NULL) { 143027e85f52SBen Walker fprintf(stderr, "Could not open file %s.\n", g_cd_file_in_name); 143127e85f52SBen Walker rc = -errno; 143227e85f52SBen Walker goto error_ctx; 143327e85f52SBen Walker } 143427e85f52SBen Walker 143527e85f52SBen Walker fseek(ctx->file, 0L, SEEK_END); 143627e85f52SBen Walker ctx->remaining = ftell(ctx->file); 143727e85f52SBen Walker fseek(ctx->file, 0L, SEEK_SET); 143827e85f52SBen Walker 143927e85f52SBen Walker ctx->ch = spdk_accel_get_io_channel(); 144027e85f52SBen Walker if (ctx->ch == NULL) { 144127e85f52SBen Walker rc = -EAGAIN; 144227e85f52SBen Walker goto error_file; 144327e85f52SBen Walker } 144427e85f52SBen Walker 144527e85f52SBen Walker if (g_xfer_size_bytes == 0) { 144627e85f52SBen Walker /* size of 0 means "file at a time" */ 144727e85f52SBen Walker g_xfer_size_bytes = ctx->remaining; 144827e85f52SBen Walker } 144927e85f52SBen Walker 145027e85f52SBen Walker accel_perf_prep_process_seg(ctx); 145127e85f52SBen Walker return; 145227e85f52SBen Walker 145327e85f52SBen Walker error_file: 145427e85f52SBen Walker fclose(ctx->file); 145527e85f52SBen Walker error_ctx: 145627e85f52SBen Walker free(ctx); 145727e85f52SBen Walker error_end: 145827e85f52SBen Walker spdk_app_stop(rc); 145927e85f52SBen Walker } 146027e85f52SBen Walker 14614c7b5046SKonrad Sztyber static void 14624c7b5046SKonrad Sztyber worker_shutdown(void *ctx) 14634c7b5046SKonrad Sztyber { 14644c7b5046SKonrad Sztyber _worker_stop(ctx); 14654c7b5046SKonrad Sztyber } 14664c7b5046SKonrad Sztyber 14674c7b5046SKonrad Sztyber static void 14684c7b5046SKonrad Sztyber shutdown_cb(void) 14694c7b5046SKonrad Sztyber { 14704c7b5046SKonrad Sztyber struct worker_thread *worker; 14714c7b5046SKonrad Sztyber 14724c7b5046SKonrad Sztyber pthread_mutex_lock(&g_workers_lock); 1473da5ec81fSKonrad Sztyber if (!g_workers) { 1474da5ec81fSKonrad Sztyber spdk_app_stop(1); 1475da5ec81fSKonrad Sztyber goto unlock; 1476da5ec81fSKonrad Sztyber } 1477da5ec81fSKonrad Sztyber 14784c7b5046SKonrad Sztyber worker = g_workers; 14794c7b5046SKonrad Sztyber while (worker) { 14804c7b5046SKonrad Sztyber spdk_thread_send_msg(worker->thread, worker_shutdown, worker); 14814c7b5046SKonrad Sztyber worker = worker->next; 14824c7b5046SKonrad Sztyber } 1483da5ec81fSKonrad Sztyber unlock: 14844c7b5046SKonrad Sztyber pthread_mutex_unlock(&g_workers_lock); 14854c7b5046SKonrad Sztyber } 14864c7b5046SKonrad Sztyber 14879f51cf32Spaul luse int 14889f51cf32Spaul luse main(int argc, char **argv) 14899f51cf32Spaul luse { 14909f51cf32Spaul luse struct worker_thread *worker, *tmp; 1491f5b5a9c4SKonrad Sztyber int rc; 14929f51cf32Spaul luse 14939f51cf32Spaul luse pthread_mutex_init(&g_workers_lock, NULL); 14949260fa0cSpaul luse spdk_app_opts_init(&g_opts, sizeof(g_opts)); 14959260fa0cSpaul luse g_opts.name = "accel_perf"; 14969260fa0cSpaul luse g_opts.reactor_mask = "0x1"; 14974c7b5046SKonrad Sztyber g_opts.shutdown_cb = shutdown_cb; 14985db859daSKrzysztof Karas g_opts.rpc_addr = NULL; 1499f5b5a9c4SKonrad Sztyber 15000a6b7098STomasz Zawadzki rc = spdk_app_parse_args(argc, argv, &g_opts, "a:C:o:q:t:yw:M:P:f:T:l:S:x:", NULL, 1501f5b5a9c4SKonrad Sztyber parse_args, usage); 1502f5b5a9c4SKonrad Sztyber if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) { 1503f5b5a9c4SKonrad Sztyber return rc == SPDK_APP_PARSE_ARGS_HELP ? 0 : 1; 15049f51cf32Spaul luse } 15059f51cf32Spaul luse 150684dbdf08STomasz Zawadzki if (g_workload_selection == SPDK_ACCEL_OPC_LAST) { 150784dbdf08STomasz Zawadzki fprintf(stderr, "Must provide a workload type\n"); 15082a0c66d0Spaul luse usage(); 1509724f3006STomasz Zawadzki return -1; 15102a0c66d0Spaul luse } 15112a0c66d0Spaul luse 1512e1bf63afSJim Harris if (g_allocate_depth > 0 && g_queue_depth > g_allocate_depth) { 1513e1bf63afSJim Harris fprintf(stdout, "allocate depth must be at least as big as queue depth\n"); 1514e1bf63afSJim Harris usage(); 1515724f3006STomasz Zawadzki return -1; 1516e1bf63afSJim Harris } 1517e1bf63afSJim Harris 1518e1bf63afSJim Harris if (g_allocate_depth == 0) { 1519e1bf63afSJim Harris g_allocate_depth = g_queue_depth; 1520e1bf63afSJim Harris } 1521e1bf63afSJim Harris 15225105dc5dSKonrad Sztyber if ((g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 152344bf79a8SKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C || 1524ee2adf2eSKrzysztof Sprzaczkowski g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY || 152580dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE || 152680dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_VERIFY || 152780dfab0aSKrzysztof Karas g_workload_selection == SPDK_ACCEL_OPC_DIX_GENERATE) && 1528850cd900Spaul luse g_chained_count == 0) { 152988754353SZiye Yang usage(); 1530724f3006STomasz Zawadzki return -1; 153188754353SZiye Yang } 153288754353SZiye Yang 15335105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_xor_src_count < 2) { 1534a5d5ab27SArtur Paszkiewicz usage(); 1535724f3006STomasz Zawadzki return -1; 1536a5d5ab27SArtur Paszkiewicz } 1537a5d5ab27SArtur Paszkiewicz 15380a6b7098STomasz Zawadzki if (g_module_name && spdk_accel_assign_opc(g_workload_selection, g_module_name)) { 15390a6b7098STomasz Zawadzki fprintf(stderr, "Was not able to assign '%s' module to the workload\n", g_module_name); 15400a6b7098STomasz Zawadzki usage(); 15410a6b7098STomasz Zawadzki return -1; 15420a6b7098STomasz Zawadzki } 15430a6b7098STomasz Zawadzki 154427e85f52SBen Walker g_rc = spdk_app_start(&g_opts, accel_perf_prep, NULL); 15459b189667Spaul luse if (g_rc) { 15469f51cf32Spaul luse SPDK_ERRLOG("ERROR starting application\n"); 15479f51cf32Spaul luse } 15489f51cf32Spaul luse 15499f51cf32Spaul luse pthread_mutex_destroy(&g_workers_lock); 15509f51cf32Spaul luse 15519f51cf32Spaul luse worker = g_workers; 15529f51cf32Spaul luse while (worker) { 15539f51cf32Spaul luse tmp = worker->next; 15549f51cf32Spaul luse free(worker); 15559f51cf32Spaul luse worker = tmp; 15569f51cf32Spaul luse } 155727e85f52SBen Walker accel_perf_free_compress_segs(); 15589f51cf32Spaul luse spdk_app_fini(); 15599b189667Spaul luse return g_rc; 15609f51cf32Spaul luse } 1561