1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2020 Intel Corporation. 39f51cf32Spaul luse * All rights reserved. 49f51cf32Spaul luse */ 59f51cf32Spaul luse 69f51cf32Spaul luse #include "spdk/stdinc.h" 79f51cf32Spaul luse #include "spdk/thread.h" 89f51cf32Spaul luse #include "spdk/env.h" 99f51cf32Spaul luse #include "spdk/event.h" 109f51cf32Spaul luse #include "spdk/log.h" 119f51cf32Spaul luse #include "spdk/string.h" 12081f080aSBen Walker #include "spdk/accel.h" 13e69375bfSpaul luse #include "spdk/crc32.h" 140cecfcb1Spaul luse #include "spdk/util.h" 15a5d5ab27SArtur Paszkiewicz #include "spdk/xor.h" 169f51cf32Spaul luse 17b9218b7aSpaul luse #define DATA_PATTERN 0x5a 180ef079c6Spaul luse #define ALIGN_4K 0x1000 196afbf3dbSpaul luse #define COMP_BUF_PAD_PERCENTAGE 1.1L 20b9218b7aSpaul luse 219f51cf32Spaul luse static uint64_t g_tsc_rate; 229f51cf32Spaul luse static uint64_t g_tsc_end; 239b189667Spaul luse static int g_rc; 249f51cf32Spaul luse static int g_xfer_size_bytes = 4096; 259f51cf32Spaul luse static int g_queue_depth = 32; 26e1bf63afSJim Harris /* g_allocate_depth indicates how many tasks we allocate per worker. It will 27e1bf63afSJim Harris * be at least as much as the queue depth. 28e1bf63afSJim Harris */ 29e1bf63afSJim Harris static int g_allocate_depth = 0; 30445fe74eSpaul luse static int g_threads_per_core = 1; 319f51cf32Spaul luse static int g_time_in_sec = 5; 32e69375bfSpaul luse static uint32_t g_crc32c_seed = 0; 33850cd900Spaul luse static uint32_t g_chained_count = 1; 34b9218b7aSpaul luse static int g_fail_percent_goal = 0; 3589495464Spaul luse static uint8_t g_fill_pattern = 255; 36a5d5ab27SArtur Paszkiewicz static uint32_t g_xor_src_count = 2; 379f51cf32Spaul luse static bool g_verify = false; 382a0c66d0Spaul luse static const char *g_workload_type = NULL; 3984dbdf08STomasz Zawadzki static enum spdk_accel_opcode g_workload_selection = SPDK_ACCEL_OPC_LAST; 40*0a6b7098STomasz Zawadzki static const char *g_module_name = NULL; 419f51cf32Spaul luse static struct worker_thread *g_workers = NULL; 429f51cf32Spaul luse static int g_num_workers = 0; 4327e85f52SBen Walker static char *g_cd_file_in_name = NULL; 449f51cf32Spaul luse static pthread_mutex_t g_workers_lock = PTHREAD_MUTEX_INITIALIZER; 459260fa0cSpaul luse static struct spdk_app_opts g_opts = {}; 46cdefd3d3Spaul luse 4727e85f52SBen Walker struct ap_compress_seg { 4827e85f52SBen Walker void *uncompressed_data; 4927e85f52SBen Walker uint32_t uncompressed_len; 5027e85f52SBen Walker struct iovec *uncompressed_iovs; 5127e85f52SBen Walker uint32_t uncompressed_iovcnt; 5227e85f52SBen Walker 5327e85f52SBen Walker void *compressed_data; 5427e85f52SBen Walker uint32_t compressed_len; 556afbf3dbSpaul luse uint32_t compressed_len_padded; 5627e85f52SBen Walker struct iovec *compressed_iovs; 5727e85f52SBen Walker uint32_t compressed_iovcnt; 5827e85f52SBen Walker 5927e85f52SBen Walker STAILQ_ENTRY(ap_compress_seg) link; 6027e85f52SBen Walker }; 6127e85f52SBen Walker 6227e85f52SBen Walker static STAILQ_HEAD(, ap_compress_seg) g_compress_segs = STAILQ_HEAD_INITIALIZER(g_compress_segs); 6327e85f52SBen Walker 64cdefd3d3Spaul luse struct worker_thread; 65cdefd3d3Spaul luse static void accel_done(void *ref, int status); 66cdefd3d3Spaul luse 67445fe74eSpaul luse struct display_info { 68445fe74eSpaul luse int core; 69445fe74eSpaul luse int thread; 70445fe74eSpaul luse }; 71445fe74eSpaul luse 72cdefd3d3Spaul luse struct ap_task { 73cdefd3d3Spaul luse void *src; 7428886ac3Spaul luse struct iovec *src_iovs; 7528886ac3Spaul luse uint32_t src_iovcnt; 76a5d5ab27SArtur Paszkiewicz void **sources; 77850cd900Spaul luse struct iovec *dst_iovs; 78850cd900Spaul luse uint32_t dst_iovcnt; 79cdefd3d3Spaul luse void *dst; 80cdefd3d3Spaul luse void *dst2; 81221eb3f4Spaul luse uint32_t crc_dst; 8227e85f52SBen Walker uint32_t compressed_sz; 8327e85f52SBen Walker struct ap_compress_seg *cur_seg; 84cdefd3d3Spaul luse struct worker_thread *worker; 85cdefd3d3Spaul luse int expected_status; /* used for the compare operation */ 86cdefd3d3Spaul luse TAILQ_ENTRY(ap_task) link; 87cdefd3d3Spaul luse }; 889f51cf32Spaul luse 899f51cf32Spaul luse struct worker_thread { 909f51cf32Spaul luse struct spdk_io_channel *ch; 91e3babb2bSKonrad Sztyber struct spdk_accel_opcode_stats stats; 929f51cf32Spaul luse uint64_t xfer_failed; 93b9218b7aSpaul luse uint64_t injected_miscompares; 949f51cf32Spaul luse uint64_t current_queue_depth; 95ac9a1a83Spaul luse TAILQ_HEAD(, ap_task) tasks_pool; 969f51cf32Spaul luse struct worker_thread *next; 979f51cf32Spaul luse unsigned core; 989f51cf32Spaul luse struct spdk_thread *thread; 999f51cf32Spaul luse bool is_draining; 1009f51cf32Spaul luse struct spdk_poller *is_draining_poller; 1019f51cf32Spaul luse struct spdk_poller *stop_poller; 102ac9a1a83Spaul luse void *task_base; 103445fe74eSpaul luse struct display_info display; 1045105dc5dSKonrad Sztyber enum spdk_accel_opcode workload; 1059f51cf32Spaul luse }; 1069f51cf32Spaul luse 1079f51cf32Spaul luse static void 1089260fa0cSpaul luse dump_user_config(void) 1099f51cf32Spaul luse { 110712e8cb7SBen Walker const char *module_name = NULL; 1119260fa0cSpaul luse int rc; 1129260fa0cSpaul luse 113712e8cb7SBen Walker rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name); 1149260fa0cSpaul luse if (rc) { 115712e8cb7SBen Walker printf("error getting module name (%d)\n", rc); 1169260fa0cSpaul luse } 1179260fa0cSpaul luse 1189260fa0cSpaul luse printf("\nSPDK Configuration:\n"); 1199260fa0cSpaul luse printf("Core mask: %s\n\n", g_opts.reactor_mask); 1209f51cf32Spaul luse printf("Accel Perf Configuration:\n"); 1212a0c66d0Spaul luse printf("Workload Type: %s\n", g_workload_type); 1225105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 1235105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 124b9218b7aSpaul luse printf("CRC-32C seed: %u\n", g_crc32c_seed); 1255105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_FILL) { 12689495464Spaul luse printf("Fill pattern: 0x%x\n", g_fill_pattern); 1275105dc5dSKonrad Sztyber } else if ((g_workload_selection == SPDK_ACCEL_OPC_COMPARE) && g_fail_percent_goal > 0) { 12889495464Spaul luse printf("Failure inject: %u percent\n", g_fail_percent_goal); 1295105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 130a5d5ab27SArtur Paszkiewicz printf("Source buffers: %u\n", g_xor_src_count); 131e69375bfSpaul luse } 1325105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 133221eb3f4Spaul luse printf("Vector size: %u bytes\n", g_xfer_size_bytes); 134850cd900Spaul luse printf("Transfer size: %u bytes\n", g_xfer_size_bytes * g_chained_count); 135221eb3f4Spaul luse } else { 1369f51cf32Spaul luse printf("Transfer size: %u bytes\n", g_xfer_size_bytes); 137221eb3f4Spaul luse } 138850cd900Spaul luse printf("vector count %u\n", g_chained_count); 139712e8cb7SBen Walker printf("Module: %s\n", module_name); 1405105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS || 1415105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 14227e85f52SBen Walker printf("File Name: %s\n", g_cd_file_in_name); 14327e85f52SBen Walker } 1449f51cf32Spaul luse printf("Queue depth: %u\n", g_queue_depth); 145e1bf63afSJim Harris printf("Allocate depth: %u\n", g_allocate_depth); 146445fe74eSpaul luse printf("# threads/core: %u\n", g_threads_per_core); 1479f51cf32Spaul luse printf("Run time: %u seconds\n", g_time_in_sec); 1489f51cf32Spaul luse printf("Verify: %s\n\n", g_verify ? "Yes" : "No"); 1499f51cf32Spaul luse } 1509f51cf32Spaul luse 1519f51cf32Spaul luse static void 1529f51cf32Spaul luse usage(void) 1539f51cf32Spaul luse { 1549f51cf32Spaul luse printf("accel_perf options:\n"); 1559f51cf32Spaul luse printf("\t[-h help message]\n"); 156f17e6705Spaul luse printf("\t[-q queue depth per core]\n"); 157850cd900Spaul luse printf("\t[-C for supported workloads, use this value to configure the io vector size to test (default 1)\n"); 158445fe74eSpaul luse printf("\t[-T number of threads per core\n"); 15927e85f52SBen Walker printf("\t[-o transfer size in bytes (default: 4KiB. For compress/decompress, 0 means the input file size)]\n"); 1609f51cf32Spaul luse printf("\t[-t time in seconds]\n"); 161a5d5ab27SArtur Paszkiewicz printf("\t[-w workload type must be one of these: copy, fill, crc32c, copy_crc32c, compare, compress, decompress, dualcast, xor\n"); 162*0a6b7098STomasz Zawadzki printf("\t[-M assign module to the operation, not compatible with accel_assign_opc RPC\n"); 16327e85f52SBen Walker printf("\t[-l for compress/decompress workloads, name of uncompressed input file\n"); 164436877a4SKonrad Sztyber printf("\t[-S for crc32c workload, use this seed value (default 0)\n"); 165b9218b7aSpaul luse printf("\t[-P for compare workload, percentage of operations that should miscompare (percent, default 0)\n"); 16689495464Spaul luse printf("\t[-f for fill workload, use this BYTE value (default 255)\n"); 167a5d5ab27SArtur Paszkiewicz printf("\t[-x for xor workload, use this number of source buffers (default, minimum: 2)]\n"); 1682a0c66d0Spaul luse printf("\t[-y verify result if this switch is on]\n"); 169e1bf63afSJim Harris printf("\t[-a tasks to allocate per core (default: same value as -q)]\n"); 170e1bf63afSJim Harris printf("\t\tCan be used to spread operations across a wider range of memory.\n"); 1719f51cf32Spaul luse } 1729f51cf32Spaul luse 1739f51cf32Spaul luse static int 174436877a4SKonrad Sztyber parse_args(int ch, char *arg) 1759f51cf32Spaul luse { 176358b84b4SZiye Yang int argval = 0; 177c82d5789SJim Harris 178436877a4SKonrad Sztyber switch (ch) { 179e1bf63afSJim Harris case 'a': 180c82d5789SJim Harris case 'C': 181c82d5789SJim Harris case 'f': 182c82d5789SJim Harris case 'T': 183c82d5789SJim Harris case 'o': 184c82d5789SJim Harris case 'P': 185c82d5789SJim Harris case 'q': 186436877a4SKonrad Sztyber case 'S': 187c82d5789SJim Harris case 't': 188a5d5ab27SArtur Paszkiewicz case 'x': 189c82d5789SJim Harris argval = spdk_strtol(optarg, 10); 190c82d5789SJim Harris if (argval < 0) { 191436877a4SKonrad Sztyber fprintf(stderr, "-%c option must be non-negative.\n", ch); 192c82d5789SJim Harris usage(); 193c82d5789SJim Harris return 1; 194c82d5789SJim Harris } 195c82d5789SJim Harris break; 196c82d5789SJim Harris default: 197c82d5789SJim Harris break; 198c82d5789SJim Harris }; 199c82d5789SJim Harris 200436877a4SKonrad Sztyber switch (ch) { 201e1bf63afSJim Harris case 'a': 202e1bf63afSJim Harris g_allocate_depth = argval; 203e1bf63afSJim Harris break; 20488754353SZiye Yang case 'C': 205850cd900Spaul luse g_chained_count = argval; 20688754353SZiye Yang break; 20727e85f52SBen Walker case 'l': 20827e85f52SBen Walker g_cd_file_in_name = optarg; 20927e85f52SBen Walker break; 21089495464Spaul luse case 'f': 211c82d5789SJim Harris g_fill_pattern = (uint8_t)argval; 21289495464Spaul luse break; 213445fe74eSpaul luse case 'T': 214c82d5789SJim Harris g_threads_per_core = argval; 215445fe74eSpaul luse break; 2169f51cf32Spaul luse case 'o': 217c82d5789SJim Harris g_xfer_size_bytes = argval; 2189f51cf32Spaul luse break; 219b9218b7aSpaul luse case 'P': 220c82d5789SJim Harris g_fail_percent_goal = argval; 221b9218b7aSpaul luse break; 2229f51cf32Spaul luse case 'q': 223c82d5789SJim Harris g_queue_depth = argval; 2249f51cf32Spaul luse break; 225436877a4SKonrad Sztyber case 'S': 226c82d5789SJim Harris g_crc32c_seed = argval; 227e69375bfSpaul luse break; 2289f51cf32Spaul luse case 't': 229c82d5789SJim Harris g_time_in_sec = argval; 2309f51cf32Spaul luse break; 231a5d5ab27SArtur Paszkiewicz case 'x': 232a5d5ab27SArtur Paszkiewicz g_xor_src_count = argval; 233a5d5ab27SArtur Paszkiewicz break; 2349f51cf32Spaul luse case 'y': 2359f51cf32Spaul luse g_verify = true; 2369f51cf32Spaul luse break; 2372a0c66d0Spaul luse case 'w': 2382a0c66d0Spaul luse g_workload_type = optarg; 239514be889Spaul luse if (!strcmp(g_workload_type, "copy")) { 2405105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COPY; 241514be889Spaul luse } else if (!strcmp(g_workload_type, "fill")) { 2425105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_FILL; 243e69375bfSpaul luse } else if (!strcmp(g_workload_type, "crc32c")) { 2445105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_CRC32C; 245221eb3f4Spaul luse } else if (!strcmp(g_workload_type, "copy_crc32c")) { 2465105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COPY_CRC32C; 247b9218b7aSpaul luse } else if (!strcmp(g_workload_type, "compare")) { 2485105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COMPARE; 2490ef079c6Spaul luse } else if (!strcmp(g_workload_type, "dualcast")) { 2505105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_DUALCAST; 25127e85f52SBen Walker } else if (!strcmp(g_workload_type, "compress")) { 2525105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_COMPRESS; 25327e85f52SBen Walker } else if (!strcmp(g_workload_type, "decompress")) { 2545105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_DECOMPRESS; 255a5d5ab27SArtur Paszkiewicz } else if (!strcmp(g_workload_type, "xor")) { 2565105dc5dSKonrad Sztyber g_workload_selection = SPDK_ACCEL_OPC_XOR; 257b21221e1Spaul luse } else { 25884dbdf08STomasz Zawadzki fprintf(stderr, "Unsupported workload type: %s\n", optarg); 259b21221e1Spaul luse usage(); 260b21221e1Spaul luse return 1; 261514be889Spaul luse } 2622a0c66d0Spaul luse break; 263*0a6b7098STomasz Zawadzki case 'M': 264*0a6b7098STomasz Zawadzki g_module_name = optarg; 265*0a6b7098STomasz Zawadzki break; 266*0a6b7098STomasz Zawadzki 2679f51cf32Spaul luse default: 2689f51cf32Spaul luse usage(); 2699f51cf32Spaul luse return 1; 2709f51cf32Spaul luse } 27188754353SZiye Yang 2729f51cf32Spaul luse return 0; 2739f51cf32Spaul luse } 2749f51cf32Spaul luse 275eea826a2Spaul luse static int dump_result(void); 2769f51cf32Spaul luse static void 2779f51cf32Spaul luse unregister_worker(void *arg1) 2789f51cf32Spaul luse { 2799f51cf32Spaul luse struct worker_thread *worker = arg1; 2809f51cf32Spaul luse 28120b5c460STomasz Zawadzki if (worker->ch) { 282e3babb2bSKonrad Sztyber spdk_accel_get_opcode_stats(worker->ch, worker->workload, 283e3babb2bSKonrad Sztyber &worker->stats, sizeof(worker->stats)); 2849f51cf32Spaul luse spdk_put_io_channel(worker->ch); 28520b5c460STomasz Zawadzki worker->ch = NULL; 28620b5c460STomasz Zawadzki } 28720b5c460STomasz Zawadzki free(worker->task_base); 2880e7821e9SJim Harris spdk_thread_exit(spdk_get_thread()); 2899f51cf32Spaul luse pthread_mutex_lock(&g_workers_lock); 2909f51cf32Spaul luse assert(g_num_workers >= 1); 2919f51cf32Spaul luse if (--g_num_workers == 0) { 2929f51cf32Spaul luse pthread_mutex_unlock(&g_workers_lock); 29320b5c460STomasz Zawadzki /* Only dump results on successful runs */ 29420b5c460STomasz Zawadzki if (g_rc == 0) { 2959b189667Spaul luse g_rc = dump_result(); 29620b5c460STomasz Zawadzki } 29720b5c460STomasz Zawadzki spdk_app_stop(g_rc); 298f042d6baSGangCao } else { 2999f51cf32Spaul luse pthread_mutex_unlock(&g_workers_lock); 3009f51cf32Spaul luse } 301f042d6baSGangCao } 3029f51cf32Spaul luse 30327e85f52SBen Walker static void 30427e85f52SBen Walker accel_perf_construct_iovs(void *buf, uint64_t sz, struct iovec *iovs, uint32_t iovcnt) 30527e85f52SBen Walker { 30627e85f52SBen Walker uint64_t ele_size; 30727e85f52SBen Walker uint8_t *data; 30827e85f52SBen Walker uint32_t i; 30927e85f52SBen Walker 31027e85f52SBen Walker ele_size = spdk_divide_round_up(sz, iovcnt); 31127e85f52SBen Walker 31227e85f52SBen Walker data = buf; 31327e85f52SBen Walker for (i = 0; i < iovcnt; i++) { 31427e85f52SBen Walker ele_size = spdk_min(ele_size, sz); 31527e85f52SBen Walker assert(ele_size > 0); 31627e85f52SBen Walker 31727e85f52SBen Walker iovs[i].iov_base = data; 31827e85f52SBen Walker iovs[i].iov_len = ele_size; 31927e85f52SBen Walker 32027e85f52SBen Walker data += ele_size; 32127e85f52SBen Walker sz -= ele_size; 32227e85f52SBen Walker } 32327e85f52SBen Walker assert(sz == 0); 32427e85f52SBen Walker } 32527e85f52SBen Walker 3268da995c4Spaul luse static int 3278da995c4Spaul luse _get_task_data_bufs(struct ap_task *task) 3288da995c4Spaul luse { 3298da995c4Spaul luse uint32_t align = 0; 33088754353SZiye Yang uint32_t i = 0; 331221eb3f4Spaul luse int dst_buff_len = g_xfer_size_bytes; 3328da995c4Spaul luse 3338da995c4Spaul luse /* For dualcast, the DSA HW requires 4K alignment on destination addresses but 334712e8cb7SBen Walker * we do this for all modules to keep it simple. 3358da995c4Spaul luse */ 3365105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST) { 3378da995c4Spaul luse align = ALIGN_4K; 3388da995c4Spaul luse } 3398da995c4Spaul luse 3405105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS || 3415105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 34227e85f52SBen Walker task->cur_seg = STAILQ_FIRST(&g_compress_segs); 3436afbf3dbSpaul luse 3445105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 3456afbf3dbSpaul luse dst_buff_len = task->cur_seg->compressed_len_padded; 3466afbf3dbSpaul luse } 3476afbf3dbSpaul luse 3486afbf3dbSpaul luse task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL); 3496afbf3dbSpaul luse if (task->dst == NULL) { 3506afbf3dbSpaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 3516afbf3dbSpaul luse return -ENOMEM; 3526afbf3dbSpaul luse } 3536afbf3dbSpaul luse 3546afbf3dbSpaul luse task->dst_iovs = calloc(g_chained_count, sizeof(struct iovec)); 3556afbf3dbSpaul luse if (!task->dst_iovs) { 3566afbf3dbSpaul luse fprintf(stderr, "cannot allocate task->dst_iovs for task=%p\n", task); 3576afbf3dbSpaul luse return -ENOMEM; 3586afbf3dbSpaul luse } 3596afbf3dbSpaul luse task->dst_iovcnt = g_chained_count; 3606afbf3dbSpaul luse accel_perf_construct_iovs(task->dst, dst_buff_len, task->dst_iovs, task->dst_iovcnt); 3616afbf3dbSpaul luse 3626afbf3dbSpaul luse return 0; 3636afbf3dbSpaul luse } 3646afbf3dbSpaul luse 3655105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 3665105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 367850cd900Spaul luse assert(g_chained_count > 0); 368850cd900Spaul luse task->src_iovcnt = g_chained_count; 36928886ac3Spaul luse task->src_iovs = calloc(task->src_iovcnt, sizeof(struct iovec)); 37028886ac3Spaul luse if (!task->src_iovs) { 37128886ac3Spaul luse fprintf(stderr, "cannot allocated task->src_iovs fot task=%p\n", task); 37288754353SZiye Yang return -ENOMEM; 37388754353SZiye Yang } 37488754353SZiye Yang 3755105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 376850cd900Spaul luse dst_buff_len = g_xfer_size_bytes * g_chained_count; 377221eb3f4Spaul luse } 378221eb3f4Spaul luse 37928886ac3Spaul luse for (i = 0; i < task->src_iovcnt; i++) { 38028886ac3Spaul luse task->src_iovs[i].iov_base = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL); 38128886ac3Spaul luse if (task->src_iovs[i].iov_base == NULL) { 38288754353SZiye Yang return -ENOMEM; 38388754353SZiye Yang } 38428886ac3Spaul luse memset(task->src_iovs[i].iov_base, DATA_PATTERN, g_xfer_size_bytes); 38528886ac3Spaul luse task->src_iovs[i].iov_len = g_xfer_size_bytes; 38688754353SZiye Yang } 3875105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 388a5d5ab27SArtur Paszkiewicz assert(g_xor_src_count > 1); 389a5d5ab27SArtur Paszkiewicz task->sources = calloc(g_xor_src_count, sizeof(*task->sources)); 390a5d5ab27SArtur Paszkiewicz if (!task->sources) { 391a5d5ab27SArtur Paszkiewicz return -ENOMEM; 392a5d5ab27SArtur Paszkiewicz } 39388754353SZiye Yang 394a5d5ab27SArtur Paszkiewicz for (i = 0; i < g_xor_src_count; i++) { 395a5d5ab27SArtur Paszkiewicz task->sources[i] = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL); 396a5d5ab27SArtur Paszkiewicz if (!task->sources[i]) { 397a5d5ab27SArtur Paszkiewicz return -ENOMEM; 398a5d5ab27SArtur Paszkiewicz } 399a5d5ab27SArtur Paszkiewicz memset(task->sources[i], DATA_PATTERN, g_xfer_size_bytes); 400a5d5ab27SArtur Paszkiewicz } 40188754353SZiye Yang } else { 4028da995c4Spaul luse task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL); 4038da995c4Spaul luse if (task->src == NULL) { 4048da995c4Spaul luse fprintf(stderr, "Unable to alloc src buffer\n"); 4058da995c4Spaul luse return -ENOMEM; 4068da995c4Spaul luse } 40788754353SZiye Yang 40888754353SZiye Yang /* For fill, set the entire src buffer so we can check if verify is enabled. */ 4095105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_FILL) { 41088754353SZiye Yang memset(task->src, g_fill_pattern, g_xfer_size_bytes); 41188754353SZiye Yang } else { 4128da995c4Spaul luse memset(task->src, DATA_PATTERN, g_xfer_size_bytes); 41388754353SZiye Yang } 41488754353SZiye Yang } 4158da995c4Spaul luse 4165105dc5dSKonrad Sztyber if (g_workload_selection != SPDK_ACCEL_OPC_CRC32C) { 417221eb3f4Spaul luse task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL); 4188da995c4Spaul luse if (task->dst == NULL) { 4198da995c4Spaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 4208da995c4Spaul luse return -ENOMEM; 4218da995c4Spaul luse } 4228da995c4Spaul luse 4238da995c4Spaul luse /* For compare we want the buffers to match, otherwise not. */ 4245105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPARE) { 425221eb3f4Spaul luse memset(task->dst, DATA_PATTERN, dst_buff_len); 4268da995c4Spaul luse } else { 427221eb3f4Spaul luse memset(task->dst, ~DATA_PATTERN, dst_buff_len); 428221eb3f4Spaul luse } 4298da995c4Spaul luse } 4308da995c4Spaul luse 43184162738Spaul luse /* For dualcast 2 buffers are needed for the operation. */ 4325105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST || 4335105dc5dSKonrad Sztyber (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_verify)) { 4348da995c4Spaul luse task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL); 4358da995c4Spaul luse if (task->dst2 == NULL) { 4368da995c4Spaul luse fprintf(stderr, "Unable to alloc dst buffer\n"); 4378da995c4Spaul luse return -ENOMEM; 4388da995c4Spaul luse } 4398da995c4Spaul luse memset(task->dst2, ~DATA_PATTERN, g_xfer_size_bytes); 4408da995c4Spaul luse } 4418da995c4Spaul luse 4428da995c4Spaul luse return 0; 4438da995c4Spaul luse } 4448da995c4Spaul luse 445ac9a1a83Spaul luse inline static struct ap_task * 446ac9a1a83Spaul luse _get_task(struct worker_thread *worker) 447ac9a1a83Spaul luse { 448ac9a1a83Spaul luse struct ap_task *task; 449ac9a1a83Spaul luse 450ac9a1a83Spaul luse if (!TAILQ_EMPTY(&worker->tasks_pool)) { 451ac9a1a83Spaul luse task = TAILQ_FIRST(&worker->tasks_pool); 452ac9a1a83Spaul luse TAILQ_REMOVE(&worker->tasks_pool, task, link); 453ac9a1a83Spaul luse } else { 454ac9a1a83Spaul luse fprintf(stderr, "Unable to get ap_task\n"); 455ac9a1a83Spaul luse return NULL; 456ac9a1a83Spaul luse } 457ac9a1a83Spaul luse 458ac9a1a83Spaul luse return task; 459ac9a1a83Spaul luse } 460ac9a1a83Spaul luse 461f17e6705Spaul luse /* Submit one operation using the same ap task that just completed. */ 4629f51cf32Spaul luse static void 463ac9a1a83Spaul luse _submit_single(struct worker_thread *worker, struct ap_task *task) 4649f51cf32Spaul luse { 465b9218b7aSpaul luse int random_num; 46640ec8e97Spaul luse int rc = 0; 46712c40f05Spaul luse int flags = 0; 4689f51cf32Spaul luse 4699f51cf32Spaul luse assert(worker); 4709f51cf32Spaul luse 47113067997Spaul luse switch (worker->workload) { 4725105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY: 473e8463f87Spaul luse rc = spdk_accel_submit_copy(worker->ch, task->dst, task->src, 47412c40f05Spaul luse g_xfer_size_bytes, flags, accel_done, task); 475e69375bfSpaul luse break; 4765105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_FILL: 4772a0c66d0Spaul luse /* For fill use the first byte of the task->dst buffer */ 478ee7e31f9Spaul luse rc = spdk_accel_submit_fill(worker->ch, task->dst, *(uint8_t *)task->src, 47912c40f05Spaul luse g_xfer_size_bytes, flags, accel_done, task); 480e69375bfSpaul luse break; 4815105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_CRC32C: 482a738acd5Spaul luse rc = spdk_accel_submit_crc32cv(worker->ch, &task->crc_dst, 48328886ac3Spaul luse task->src_iovs, task->src_iovcnt, g_crc32c_seed, 48490c56d96SZiye Yang accel_done, task); 485e69375bfSpaul luse break; 4865105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY_CRC32C: 48728886ac3Spaul luse rc = spdk_accel_submit_copy_crc32cv(worker->ch, task->dst, task->src_iovs, task->src_iovcnt, 48812c40f05Spaul luse &task->crc_dst, g_crc32c_seed, flags, accel_done, task); 489221eb3f4Spaul luse break; 4905105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPARE: 491b9218b7aSpaul luse random_num = rand() % 100; 492b9218b7aSpaul luse if (random_num < g_fail_percent_goal) { 493b9218b7aSpaul luse task->expected_status = -EILSEQ; 494b9218b7aSpaul luse *(uint8_t *)task->dst = ~DATA_PATTERN; 495b9218b7aSpaul luse } else { 496b9218b7aSpaul luse task->expected_status = 0; 497b9218b7aSpaul luse *(uint8_t *)task->dst = DATA_PATTERN; 498b9218b7aSpaul luse } 499ee7e31f9Spaul luse rc = spdk_accel_submit_compare(worker->ch, task->dst, task->src, 500e8463f87Spaul luse g_xfer_size_bytes, accel_done, task); 501b9218b7aSpaul luse break; 5025105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DUALCAST: 503ee7e31f9Spaul luse rc = spdk_accel_submit_dualcast(worker->ch, task->dst, task->dst2, 50412c40f05Spaul luse task->src, g_xfer_size_bytes, flags, accel_done, task); 5050ef079c6Spaul luse break; 5065105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPRESS: 50727e85f52SBen Walker task->src_iovs = task->cur_seg->uncompressed_iovs; 50827e85f52SBen Walker task->src_iovcnt = task->cur_seg->uncompressed_iovcnt; 5096afbf3dbSpaul luse rc = spdk_accel_submit_compress(worker->ch, task->dst, task->cur_seg->compressed_len_padded, 5106afbf3dbSpaul luse task->src_iovs, 51127e85f52SBen Walker task->src_iovcnt, &task->compressed_sz, flags, accel_done, task); 51227e85f52SBen Walker break; 5135105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DECOMPRESS: 51427e85f52SBen Walker task->src_iovs = task->cur_seg->compressed_iovs; 51527e85f52SBen Walker task->src_iovcnt = task->cur_seg->compressed_iovcnt; 51627e85f52SBen Walker rc = spdk_accel_submit_decompress(worker->ch, task->dst_iovs, task->dst_iovcnt, task->src_iovs, 51791f3063bSpaul luse task->src_iovcnt, NULL, flags, accel_done, task); 51827e85f52SBen Walker break; 5195105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_XOR: 520a5d5ab27SArtur Paszkiewicz rc = spdk_accel_submit_xor(worker->ch, task->dst, task->sources, g_xor_src_count, 521a5d5ab27SArtur Paszkiewicz g_xfer_size_bytes, accel_done, task); 522a5d5ab27SArtur Paszkiewicz break; 523e69375bfSpaul luse default: 5242a0c66d0Spaul luse assert(false); 525e69375bfSpaul luse break; 526e69375bfSpaul luse 5272a0c66d0Spaul luse } 52840ec8e97Spaul luse 5296799d46aSpaul luse worker->current_queue_depth++; 53040ec8e97Spaul luse if (rc) { 531e8463f87Spaul luse accel_done(task, rc); 53240ec8e97Spaul luse } 5339f51cf32Spaul luse } 5349f51cf32Spaul luse 5359f51cf32Spaul luse static void 536e150f6b8SZiye Yang _free_task_buffers(struct ap_task *task) 537ac9a1a83Spaul luse { 53888754353SZiye Yang uint32_t i; 53988754353SZiye Yang 5405105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS || 5415105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 54227e85f52SBen Walker free(task->dst_iovs); 5435105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 5445105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) { 54528886ac3Spaul luse if (task->src_iovs) { 54628886ac3Spaul luse for (i = 0; i < task->src_iovcnt; i++) { 54728886ac3Spaul luse if (task->src_iovs[i].iov_base) { 54828886ac3Spaul luse spdk_dma_free(task->src_iovs[i].iov_base); 54988754353SZiye Yang } 55088754353SZiye Yang } 55128886ac3Spaul luse free(task->src_iovs); 55288754353SZiye Yang } 5535105dc5dSKonrad Sztyber } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) { 554a5d5ab27SArtur Paszkiewicz if (task->sources) { 555a5d5ab27SArtur Paszkiewicz for (i = 0; i < g_xor_src_count; i++) { 556a5d5ab27SArtur Paszkiewicz spdk_dma_free(task->sources[i]); 557a5d5ab27SArtur Paszkiewicz } 558a5d5ab27SArtur Paszkiewicz free(task->sources); 559a5d5ab27SArtur Paszkiewicz } 56088754353SZiye Yang } else { 561ac9a1a83Spaul luse spdk_dma_free(task->src); 56288754353SZiye Yang } 56388754353SZiye Yang 564ac9a1a83Spaul luse spdk_dma_free(task->dst); 5655105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST || g_workload_selection == SPDK_ACCEL_OPC_XOR) { 566ac9a1a83Spaul luse spdk_dma_free(task->dst2); 567ac9a1a83Spaul luse } 568ac9a1a83Spaul luse } 569ac9a1a83Spaul luse 570221eb3f4Spaul luse static int 57128886ac3Spaul luse _vector_memcmp(void *_dst, struct iovec *src_src_iovs, uint32_t iovcnt) 572221eb3f4Spaul luse { 573221eb3f4Spaul luse uint32_t i; 574221eb3f4Spaul luse uint32_t ttl_len = 0; 575221eb3f4Spaul luse uint8_t *dst = (uint8_t *)_dst; 576221eb3f4Spaul luse 577221eb3f4Spaul luse for (i = 0; i < iovcnt; i++) { 57828886ac3Spaul luse if (memcmp(dst, src_src_iovs[i].iov_base, src_src_iovs[i].iov_len)) { 579221eb3f4Spaul luse return -1; 580221eb3f4Spaul luse } 58128886ac3Spaul luse dst += src_src_iovs[i].iov_len; 58228886ac3Spaul luse ttl_len += src_src_iovs[i].iov_len; 583221eb3f4Spaul luse } 584221eb3f4Spaul luse 585221eb3f4Spaul luse if (ttl_len != iovcnt * g_xfer_size_bytes) { 586221eb3f4Spaul luse return -1; 587221eb3f4Spaul luse } 588221eb3f4Spaul luse 589221eb3f4Spaul luse return 0; 590221eb3f4Spaul luse } 591221eb3f4Spaul luse 59213067997Spaul luse static int _worker_stop(void *arg); 59313067997Spaul luse 594fab40895Spaul luse static void 595df42f358Spaul luse accel_done(void *arg1, int status) 5969f51cf32Spaul luse { 5979f51cf32Spaul luse struct ap_task *task = arg1; 5989f51cf32Spaul luse struct worker_thread *worker = task->worker; 599e69375bfSpaul luse uint32_t sw_crc32c; 6009f51cf32Spaul luse 6019f51cf32Spaul luse assert(worker); 6029f51cf32Spaul luse assert(worker->current_queue_depth > 0); 6039f51cf32Spaul luse 604df42f358Spaul luse if (g_verify && status == 0) { 60513067997Spaul luse switch (worker->workload) { 6065105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY_CRC32C: 60728886ac3Spaul luse sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed); 608221eb3f4Spaul luse if (task->crc_dst != sw_crc32c) { 609221eb3f4Spaul luse SPDK_NOTICELOG("CRC-32C miscompare\n"); 610221eb3f4Spaul luse worker->xfer_failed++; 611221eb3f4Spaul luse } 61228886ac3Spaul luse if (_vector_memcmp(task->dst, task->src_iovs, task->src_iovcnt)) { 613221eb3f4Spaul luse SPDK_NOTICELOG("Data miscompare\n"); 614221eb3f4Spaul luse worker->xfer_failed++; 615221eb3f4Spaul luse } 616221eb3f4Spaul luse break; 6175105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_CRC32C: 61828886ac3Spaul luse sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed); 619a738acd5Spaul luse if (task->crc_dst != sw_crc32c) { 620e69375bfSpaul luse SPDK_NOTICELOG("CRC-32C miscompare\n"); 621e69375bfSpaul luse worker->xfer_failed++; 622e69375bfSpaul luse } 623b9218b7aSpaul luse break; 6245105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COPY: 625b9218b7aSpaul luse if (memcmp(task->src, task->dst, g_xfer_size_bytes)) { 6269f51cf32Spaul luse SPDK_NOTICELOG("Data miscompare\n"); 6279f51cf32Spaul luse worker->xfer_failed++; 628b9218b7aSpaul luse } 629b9218b7aSpaul luse break; 6305105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DUALCAST: 6310ef079c6Spaul luse if (memcmp(task->src, task->dst, g_xfer_size_bytes)) { 6320ef079c6Spaul luse SPDK_NOTICELOG("Data miscompare, first destination\n"); 6330ef079c6Spaul luse worker->xfer_failed++; 6340ef079c6Spaul luse } 6350ef079c6Spaul luse if (memcmp(task->src, task->dst2, g_xfer_size_bytes)) { 6360ef079c6Spaul luse SPDK_NOTICELOG("Data miscompare, second destination\n"); 6370ef079c6Spaul luse worker->xfer_failed++; 6380ef079c6Spaul luse } 6390ef079c6Spaul luse break; 6405105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_FILL: 641d207237fSpaul luse if (memcmp(task->dst, task->src, g_xfer_size_bytes)) { 642d207237fSpaul luse SPDK_NOTICELOG("Data miscompare\n"); 643d207237fSpaul luse worker->xfer_failed++; 644d207237fSpaul luse } 645d207237fSpaul luse break; 6465105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPARE: 6478cee297cSpaul luse break; 6485105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_COMPRESS: 64927e85f52SBen Walker break; 6505105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_DECOMPRESS: 65127e85f52SBen Walker if (memcmp(task->dst, task->cur_seg->uncompressed_data, task->cur_seg->uncompressed_len)) { 65227e85f52SBen Walker SPDK_NOTICELOG("Data miscompare on decompression\n"); 65327e85f52SBen Walker worker->xfer_failed++; 65427e85f52SBen Walker } 65527e85f52SBen Walker break; 6565105dc5dSKonrad Sztyber case SPDK_ACCEL_OPC_XOR: 657a5d5ab27SArtur Paszkiewicz if (spdk_xor_gen(task->dst2, task->sources, g_xor_src_count, 658a5d5ab27SArtur Paszkiewicz g_xfer_size_bytes) != 0) { 659a5d5ab27SArtur Paszkiewicz SPDK_ERRLOG("Failed to generate xor for verification\n"); 660a5d5ab27SArtur Paszkiewicz } else if (memcmp(task->dst, task->dst2, g_xfer_size_bytes)) { 661a5d5ab27SArtur Paszkiewicz SPDK_NOTICELOG("Data miscompare\n"); 662a5d5ab27SArtur Paszkiewicz worker->xfer_failed++; 663a5d5ab27SArtur Paszkiewicz } 664a5d5ab27SArtur Paszkiewicz break; 665b9218b7aSpaul luse default: 666b9218b7aSpaul luse assert(false); 667b9218b7aSpaul luse break; 6689f51cf32Spaul luse } 6699f51cf32Spaul luse } 670b9218b7aSpaul luse 6715105dc5dSKonrad Sztyber if (worker->workload == SPDK_ACCEL_OPC_COMPRESS || 6725105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 67327e85f52SBen Walker /* Advance the task to the next segment */ 67427e85f52SBen Walker task->cur_seg = STAILQ_NEXT(task->cur_seg, link); 67527e85f52SBen Walker if (task->cur_seg == NULL) { 67627e85f52SBen Walker task->cur_seg = STAILQ_FIRST(&g_compress_segs); 67727e85f52SBen Walker } 67827e85f52SBen Walker } 67927e85f52SBen Walker 680b9218b7aSpaul luse if (task->expected_status == -EILSEQ) { 681df42f358Spaul luse assert(status != 0); 682b9218b7aSpaul luse worker->injected_miscompares++; 68313067997Spaul luse status = 0; 684df42f358Spaul luse } else if (status) { 685712e8cb7SBen Walker /* Expected to pass but the accel module reported an error (ex: COMPARE operation). */ 686b9218b7aSpaul luse worker->xfer_failed++; 687b9218b7aSpaul luse } 688b9218b7aSpaul luse 6899f51cf32Spaul luse worker->current_queue_depth--; 6909f51cf32Spaul luse 69113067997Spaul luse if (!worker->is_draining && status == 0) { 692451462f6SJim Harris TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 693451462f6SJim Harris task = _get_task(worker); 6949f51cf32Spaul luse _submit_single(worker, task); 695f17e6705Spaul luse } else { 696b34883e0SZiye Yang TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 697f17e6705Spaul luse } 6989f51cf32Spaul luse } 6999f51cf32Spaul luse 7009f51cf32Spaul luse static int 7019f51cf32Spaul luse dump_result(void) 7029f51cf32Spaul luse { 7039f51cf32Spaul luse uint64_t total_completed = 0; 7049f51cf32Spaul luse uint64_t total_failed = 0; 705b9218b7aSpaul luse uint64_t total_miscompared = 0; 7069f51cf32Spaul luse uint64_t total_xfer_per_sec, total_bw_in_MiBps; 7079f51cf32Spaul luse struct worker_thread *worker = g_workers; 7089424e9ebSKonrad Sztyber char tmp[64]; 7099f51cf32Spaul luse 7109424e9ebSKonrad Sztyber printf("\n%-12s %20s %16s %16s %16s\n", 7119424e9ebSKonrad Sztyber "Core,Thread", "Transfers", "Bandwidth", "Failed", "Miscompares"); 7129424e9ebSKonrad Sztyber printf("------------------------------------------------------------------------------------\n"); 7139f51cf32Spaul luse while (worker != NULL) { 7149f51cf32Spaul luse 715e3babb2bSKonrad Sztyber uint64_t xfer_per_sec = worker->stats.executed / g_time_in_sec; 716e3babb2bSKonrad Sztyber uint64_t bw_in_MiBps = worker->stats.num_bytes / 7179f51cf32Spaul luse (g_time_in_sec * 1024 * 1024); 7189f51cf32Spaul luse 719e3babb2bSKonrad Sztyber total_completed += worker->stats.executed; 7209f51cf32Spaul luse total_failed += worker->xfer_failed; 721b9218b7aSpaul luse total_miscompared += worker->injected_miscompares; 7229f51cf32Spaul luse 7239424e9ebSKonrad Sztyber snprintf(tmp, sizeof(tmp), "%u,%u", worker->display.core, worker->display.thread); 7249f51cf32Spaul luse if (xfer_per_sec) { 7259424e9ebSKonrad Sztyber printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n", 7269424e9ebSKonrad Sztyber tmp, xfer_per_sec, bw_in_MiBps, worker->xfer_failed, 7279424e9ebSKonrad Sztyber worker->injected_miscompares); 7289f51cf32Spaul luse } 7299f51cf32Spaul luse 7309f51cf32Spaul luse worker = worker->next; 7319f51cf32Spaul luse } 7329f51cf32Spaul luse 7339f51cf32Spaul luse total_xfer_per_sec = total_completed / g_time_in_sec; 7349f51cf32Spaul luse total_bw_in_MiBps = (total_completed * g_xfer_size_bytes) / 7359f51cf32Spaul luse (g_time_in_sec * 1024 * 1024); 7369f51cf32Spaul luse 7379424e9ebSKonrad Sztyber printf("====================================================================================\n"); 7389424e9ebSKonrad Sztyber printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n", 7399424e9ebSKonrad Sztyber "Total", total_xfer_per_sec, total_bw_in_MiBps, total_failed, total_miscompared); 7409f51cf32Spaul luse 7419f51cf32Spaul luse return total_failed ? 1 : 0; 7429f51cf32Spaul luse } 7439f51cf32Spaul luse 744e150f6b8SZiye Yang static inline void 745e150f6b8SZiye Yang _free_task_buffers_in_pool(struct worker_thread *worker) 746e150f6b8SZiye Yang { 747e150f6b8SZiye Yang struct ap_task *task; 748e150f6b8SZiye Yang 749e150f6b8SZiye Yang assert(worker); 750e150f6b8SZiye Yang while ((task = TAILQ_FIRST(&worker->tasks_pool))) { 751e150f6b8SZiye Yang TAILQ_REMOVE(&worker->tasks_pool, task, link); 752e150f6b8SZiye Yang _free_task_buffers(task); 753e150f6b8SZiye Yang } 754e150f6b8SZiye Yang } 755e150f6b8SZiye Yang 7569f51cf32Spaul luse static int 7579f51cf32Spaul luse _check_draining(void *arg) 7589f51cf32Spaul luse { 7599f51cf32Spaul luse struct worker_thread *worker = arg; 7609f51cf32Spaul luse 7619f51cf32Spaul luse assert(worker); 7629f51cf32Spaul luse 7639f51cf32Spaul luse if (worker->current_queue_depth == 0) { 764e150f6b8SZiye Yang _free_task_buffers_in_pool(worker); 7659f51cf32Spaul luse spdk_poller_unregister(&worker->is_draining_poller); 7669f51cf32Spaul luse unregister_worker(worker); 7679f51cf32Spaul luse } 7689f51cf32Spaul luse 769fa9e703fSpaul Luse return SPDK_POLLER_BUSY; 7709f51cf32Spaul luse } 7719f51cf32Spaul luse 7729f51cf32Spaul luse static int 7739f51cf32Spaul luse _worker_stop(void *arg) 7749f51cf32Spaul luse { 7759f51cf32Spaul luse struct worker_thread *worker = arg; 7769f51cf32Spaul luse 7779f51cf32Spaul luse assert(worker); 7789f51cf32Spaul luse 7799f51cf32Spaul luse spdk_poller_unregister(&worker->stop_poller); 7809f51cf32Spaul luse 7819f51cf32Spaul luse /* now let the worker drain and check it's outstanding IO with a poller */ 7829f51cf32Spaul luse worker->is_draining = true; 783ab0bc5c2SShuhei Matsumoto worker->is_draining_poller = SPDK_POLLER_REGISTER(_check_draining, worker, 0); 7849f51cf32Spaul luse 785fa9e703fSpaul Luse return SPDK_POLLER_BUSY; 7869f51cf32Spaul luse } 7879f51cf32Spaul luse 78820b5c460STomasz Zawadzki static void shutdown_cb(void); 78920b5c460STomasz Zawadzki 7909f51cf32Spaul luse static void 791a34fc12bSpaul luse _init_thread(void *arg1) 792a34fc12bSpaul luse { 793a34fc12bSpaul luse struct worker_thread *worker; 794a34fc12bSpaul luse struct ap_task *task; 795998b5d66Spaul luse int i, num_tasks = g_allocate_depth; 796445fe74eSpaul luse struct display_info *display = arg1; 797a34fc12bSpaul luse 798a34fc12bSpaul luse worker = calloc(1, sizeof(*worker)); 799a34fc12bSpaul luse if (worker == NULL) { 800a34fc12bSpaul luse fprintf(stderr, "Unable to allocate worker\n"); 801445fe74eSpaul luse free(display); 80220b5c460STomasz Zawadzki spdk_thread_exit(spdk_get_thread()); 80320b5c460STomasz Zawadzki goto no_worker; 804a34fc12bSpaul luse } 805a34fc12bSpaul luse 80613067997Spaul luse worker->workload = g_workload_selection; 807445fe74eSpaul luse worker->display.core = display->core; 808445fe74eSpaul luse worker->display.thread = display->thread; 809445fe74eSpaul luse free(display); 8109f51cf32Spaul luse worker->core = spdk_env_get_current_core(); 8119f51cf32Spaul luse worker->thread = spdk_get_thread(); 812eea826a2Spaul luse pthread_mutex_lock(&g_workers_lock); 813eea826a2Spaul luse g_num_workers++; 8149f51cf32Spaul luse worker->next = g_workers; 815eea826a2Spaul luse g_workers = worker; 816eea826a2Spaul luse pthread_mutex_unlock(&g_workers_lock); 81734c48f1bSBen Walker worker->ch = spdk_accel_get_io_channel(); 8182dd64cf9Spaul luse if (worker->ch == NULL) { 8192dd64cf9Spaul luse fprintf(stderr, "Unable to get an accel channel\n"); 8202dd64cf9Spaul luse goto error; 8212dd64cf9Spaul luse } 822b9218b7aSpaul luse 823f17e6705Spaul luse TAILQ_INIT(&worker->tasks_pool); 824f17e6705Spaul luse 825ac9a1a83Spaul luse worker->task_base = calloc(num_tasks, sizeof(struct ap_task)); 826ac9a1a83Spaul luse if (worker->task_base == NULL) { 827ac9a1a83Spaul luse fprintf(stderr, "Could not allocate task base.\n"); 828ac9a1a83Spaul luse goto error; 8290cecfcb1Spaul luse } 830ac9a1a83Spaul luse 831ac9a1a83Spaul luse task = worker->task_base; 832ac9a1a83Spaul luse for (i = 0; i < num_tasks; i++) { 833ac9a1a83Spaul luse TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link); 8344cd7ca9bSJim Harris task->worker = worker; 835ac9a1a83Spaul luse if (_get_task_data_bufs(task)) { 836ac9a1a83Spaul luse fprintf(stderr, "Unable to get data bufs\n"); 837ac9a1a83Spaul luse goto error; 838ac9a1a83Spaul luse } 839ac9a1a83Spaul luse task++; 8409f51cf32Spaul luse } 8419f51cf32Spaul luse 8429f51cf32Spaul luse /* Register a poller that will stop the worker at time elapsed */ 843ab0bc5c2SShuhei Matsumoto worker->stop_poller = SPDK_POLLER_REGISTER(_worker_stop, worker, 8449f51cf32Spaul luse g_time_in_sec * 1000000ULL); 8459f51cf32Spaul luse 846998b5d66Spaul luse /* Load up queue depth worth of operations. */ 847998b5d66Spaul luse for (i = 0; i < g_queue_depth; i++) { 848ac9a1a83Spaul luse task = _get_task(worker); 849ac9a1a83Spaul luse if (task == NULL) { 850a34fc12bSpaul luse goto error; 851b9218b7aSpaul luse } 852b9218b7aSpaul luse 8539f51cf32Spaul luse _submit_single(worker, task); 8549f51cf32Spaul luse } 855a34fc12bSpaul luse return; 856a34fc12bSpaul luse error: 857e150f6b8SZiye Yang 858e150f6b8SZiye Yang _free_task_buffers_in_pool(worker); 859ac9a1a83Spaul luse free(worker->task_base); 86020b5c460STomasz Zawadzki no_worker: 86120b5c460STomasz Zawadzki shutdown_cb(); 86220b5c460STomasz Zawadzki g_rc = -1; 8639f51cf32Spaul luse } 8649f51cf32Spaul luse 8659f51cf32Spaul luse static void 8669f51cf32Spaul luse accel_perf_start(void *arg1) 8679f51cf32Spaul luse { 868eea826a2Spaul luse struct spdk_cpuset tmp_cpumask = {}; 869eea826a2Spaul luse char thread_name[32]; 870eea826a2Spaul luse uint32_t i; 871445fe74eSpaul luse int j; 872eea826a2Spaul luse struct spdk_thread *thread; 873445fe74eSpaul luse struct display_info *display; 874514be889Spaul luse 8759f51cf32Spaul luse g_tsc_rate = spdk_get_ticks_hz(); 8769f51cf32Spaul luse g_tsc_end = spdk_get_ticks() + g_time_in_sec * g_tsc_rate; 8779f51cf32Spaul luse 8789260fa0cSpaul luse dump_user_config(); 8799260fa0cSpaul luse 8809f51cf32Spaul luse printf("Running for %d seconds...\n", g_time_in_sec); 8819f51cf32Spaul luse fflush(stdout); 8829f51cf32Spaul luse 883eea826a2Spaul luse /* Create worker threads for each core that was specified. */ 884eea826a2Spaul luse SPDK_ENV_FOREACH_CORE(i) { 885445fe74eSpaul luse for (j = 0; j < g_threads_per_core; j++) { 886445fe74eSpaul luse snprintf(thread_name, sizeof(thread_name), "ap_worker_%u_%u", i, j); 887eea826a2Spaul luse spdk_cpuset_zero(&tmp_cpumask); 888eea826a2Spaul luse spdk_cpuset_set_cpu(&tmp_cpumask, i, true); 889eea826a2Spaul luse thread = spdk_thread_create(thread_name, &tmp_cpumask); 890445fe74eSpaul luse display = calloc(1, sizeof(*display)); 891445fe74eSpaul luse if (display == NULL) { 892445fe74eSpaul luse fprintf(stderr, "Unable to allocate memory\n"); 893445fe74eSpaul luse spdk_app_stop(-1); 894445fe74eSpaul luse return; 895445fe74eSpaul luse } 896445fe74eSpaul luse display->core = i; 897445fe74eSpaul luse display->thread = j; 898445fe74eSpaul luse spdk_thread_send_msg(thread, _init_thread, display); 899445fe74eSpaul luse } 900eea826a2Spaul luse } 9019f51cf32Spaul luse } 9029f51cf32Spaul luse 90327e85f52SBen Walker static void 90427e85f52SBen Walker accel_perf_free_compress_segs(void) 90527e85f52SBen Walker { 90627e85f52SBen Walker struct ap_compress_seg *seg, *tmp; 90727e85f52SBen Walker 90827e85f52SBen Walker STAILQ_FOREACH_SAFE(seg, &g_compress_segs, link, tmp) { 90927e85f52SBen Walker free(seg->uncompressed_iovs); 91027e85f52SBen Walker free(seg->compressed_iovs); 91127e85f52SBen Walker spdk_dma_free(seg->compressed_data); 91227e85f52SBen Walker spdk_dma_free(seg->uncompressed_data); 91327e85f52SBen Walker STAILQ_REMOVE_HEAD(&g_compress_segs, link); 91427e85f52SBen Walker free(seg); 91527e85f52SBen Walker } 91627e85f52SBen Walker } 91727e85f52SBen Walker 91827e85f52SBen Walker struct accel_perf_prep_ctx { 91927e85f52SBen Walker FILE *file; 92027e85f52SBen Walker long remaining; 92127e85f52SBen Walker struct spdk_io_channel *ch; 92227e85f52SBen Walker struct ap_compress_seg *cur_seg; 92327e85f52SBen Walker }; 92427e85f52SBen Walker 92527e85f52SBen Walker static void accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx); 92627e85f52SBen Walker 92727e85f52SBen Walker static void 92827e85f52SBen Walker accel_perf_prep_process_seg_cpl(void *ref, int status) 92927e85f52SBen Walker { 93027e85f52SBen Walker struct accel_perf_prep_ctx *ctx = ref; 93127e85f52SBen Walker struct ap_compress_seg *seg; 93227e85f52SBen Walker 93327e85f52SBen Walker if (status != 0) { 93427e85f52SBen Walker fprintf(stderr, "error (%d) on initial compress completion\n", status); 93527e85f52SBen Walker spdk_dma_free(ctx->cur_seg->compressed_data); 93627e85f52SBen Walker spdk_dma_free(ctx->cur_seg->uncompressed_data); 93727e85f52SBen Walker free(ctx->cur_seg); 93827e85f52SBen Walker spdk_put_io_channel(ctx->ch); 93927e85f52SBen Walker fclose(ctx->file); 94027e85f52SBen Walker free(ctx); 94127e85f52SBen Walker spdk_app_stop(-status); 94227e85f52SBen Walker return; 94327e85f52SBen Walker } 94427e85f52SBen Walker 94527e85f52SBen Walker seg = ctx->cur_seg; 94627e85f52SBen Walker 9475105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) { 94827e85f52SBen Walker seg->compressed_iovs = calloc(g_chained_count, sizeof(struct iovec)); 94927e85f52SBen Walker if (seg->compressed_iovs == NULL) { 95027e85f52SBen Walker fprintf(stderr, "unable to allocate iovec\n"); 95127e85f52SBen Walker spdk_dma_free(seg->compressed_data); 95227e85f52SBen Walker spdk_dma_free(seg->uncompressed_data); 95327e85f52SBen Walker free(seg); 95427e85f52SBen Walker spdk_put_io_channel(ctx->ch); 95527e85f52SBen Walker fclose(ctx->file); 95627e85f52SBen Walker free(ctx); 95727e85f52SBen Walker spdk_app_stop(-ENOMEM); 95827e85f52SBen Walker return; 95927e85f52SBen Walker } 96027e85f52SBen Walker seg->compressed_iovcnt = g_chained_count; 96127e85f52SBen Walker 96227e85f52SBen Walker accel_perf_construct_iovs(seg->compressed_data, seg->compressed_len, seg->compressed_iovs, 96327e85f52SBen Walker seg->compressed_iovcnt); 96427e85f52SBen Walker } 96527e85f52SBen Walker 96627e85f52SBen Walker STAILQ_INSERT_TAIL(&g_compress_segs, seg, link); 96727e85f52SBen Walker ctx->remaining -= seg->uncompressed_len; 96827e85f52SBen Walker 96927e85f52SBen Walker accel_perf_prep_process_seg(ctx); 97027e85f52SBen Walker } 97127e85f52SBen Walker 97227e85f52SBen Walker static void 97327e85f52SBen Walker accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx) 97427e85f52SBen Walker { 97527e85f52SBen Walker struct ap_compress_seg *seg; 9766afbf3dbSpaul luse int sz, sz_read, sz_padded; 97727e85f52SBen Walker void *ubuf, *cbuf; 97827e85f52SBen Walker struct iovec iov[1]; 97927e85f52SBen Walker int rc; 98027e85f52SBen Walker 98127e85f52SBen Walker if (ctx->remaining == 0) { 98227e85f52SBen Walker spdk_put_io_channel(ctx->ch); 98327e85f52SBen Walker fclose(ctx->file); 98427e85f52SBen Walker free(ctx); 98527e85f52SBen Walker accel_perf_start(NULL); 98627e85f52SBen Walker return; 98727e85f52SBen Walker } 98827e85f52SBen Walker 98927e85f52SBen Walker sz = spdk_min(ctx->remaining, g_xfer_size_bytes); 9906afbf3dbSpaul luse /* Add 10% pad to the compress buffer for incompressible data. Note that a real app 9916afbf3dbSpaul luse * would likely either deal with the failure of not having a large enough buffer 9926afbf3dbSpaul luse * by submitting another operation with a larger one. Or, like the vbdev module 9936afbf3dbSpaul luse * does, just accept the error and use the data uncompressed marking it as such in 9946afbf3dbSpaul luse * its own metadata so that in the future it doesn't try to decompress uncompressed 9956afbf3dbSpaul luse * data, etc. 9966afbf3dbSpaul luse */ 9976afbf3dbSpaul luse sz_padded = sz * COMP_BUF_PAD_PERCENTAGE; 99827e85f52SBen Walker 99927e85f52SBen Walker ubuf = spdk_dma_zmalloc(sz, ALIGN_4K, NULL); 100027e85f52SBen Walker if (!ubuf) { 100127e85f52SBen Walker fprintf(stderr, "unable to allocate uncompress buffer\n"); 100227e85f52SBen Walker rc = -ENOMEM; 100327e85f52SBen Walker goto error; 100427e85f52SBen Walker } 100527e85f52SBen Walker 10066afbf3dbSpaul luse cbuf = spdk_dma_malloc(sz_padded, ALIGN_4K, NULL); 100727e85f52SBen Walker if (!cbuf) { 100827e85f52SBen Walker fprintf(stderr, "unable to allocate compress buffer\n"); 100927e85f52SBen Walker rc = -ENOMEM; 101027e85f52SBen Walker spdk_dma_free(ubuf); 101127e85f52SBen Walker goto error; 101227e85f52SBen Walker } 101327e85f52SBen Walker 101427e85f52SBen Walker seg = calloc(1, sizeof(*seg)); 101527e85f52SBen Walker if (!seg) { 101627e85f52SBen Walker fprintf(stderr, "unable to allocate comp/decomp segment\n"); 101727e85f52SBen Walker spdk_dma_free(ubuf); 101827e85f52SBen Walker spdk_dma_free(cbuf); 101927e85f52SBen Walker rc = -ENOMEM; 102027e85f52SBen Walker goto error; 102127e85f52SBen Walker } 102227e85f52SBen Walker 102327e85f52SBen Walker sz_read = fread(ubuf, sizeof(uint8_t), sz, ctx->file); 102427e85f52SBen Walker if (sz_read != sz) { 102527e85f52SBen Walker fprintf(stderr, "unable to read input file\n"); 102627e85f52SBen Walker free(seg); 102727e85f52SBen Walker spdk_dma_free(ubuf); 102827e85f52SBen Walker spdk_dma_free(cbuf); 102927e85f52SBen Walker rc = -errno; 103027e85f52SBen Walker goto error; 103127e85f52SBen Walker } 103227e85f52SBen Walker 10335105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) { 103427e85f52SBen Walker seg->uncompressed_iovs = calloc(g_chained_count, sizeof(struct iovec)); 103527e85f52SBen Walker if (seg->uncompressed_iovs == NULL) { 103627e85f52SBen Walker fprintf(stderr, "unable to allocate iovec\n"); 103727e85f52SBen Walker free(seg); 103827e85f52SBen Walker spdk_dma_free(ubuf); 103927e85f52SBen Walker spdk_dma_free(cbuf); 104027e85f52SBen Walker rc = -ENOMEM; 104127e85f52SBen Walker goto error; 104227e85f52SBen Walker } 104327e85f52SBen Walker seg->uncompressed_iovcnt = g_chained_count; 104427e85f52SBen Walker accel_perf_construct_iovs(ubuf, sz, seg->uncompressed_iovs, seg->uncompressed_iovcnt); 104527e85f52SBen Walker } 104627e85f52SBen Walker 104727e85f52SBen Walker seg->uncompressed_data = ubuf; 104827e85f52SBen Walker seg->uncompressed_len = sz; 104927e85f52SBen Walker seg->compressed_data = cbuf; 105027e85f52SBen Walker seg->compressed_len = sz; 10516afbf3dbSpaul luse seg->compressed_len_padded = sz_padded; 105227e85f52SBen Walker 105327e85f52SBen Walker ctx->cur_seg = seg; 105427e85f52SBen Walker iov[0].iov_base = seg->uncompressed_data; 105527e85f52SBen Walker iov[0].iov_len = seg->uncompressed_len; 105627e85f52SBen Walker /* Note that anytime a call is made to spdk_accel_submit_compress() there's a chance 105727e85f52SBen Walker * it will fail with -ENOMEM in the event that the destination buffer is not large enough 10586afbf3dbSpaul luse * to hold the compressed data. This example app simply adds 10% buffer for compressed data 10596afbf3dbSpaul luse * but real applications may want to consider a more sophisticated method. 106027e85f52SBen Walker */ 10616afbf3dbSpaul luse rc = spdk_accel_submit_compress(ctx->ch, seg->compressed_data, seg->compressed_len_padded, iov, 1, 106227e85f52SBen Walker &seg->compressed_len, 0, accel_perf_prep_process_seg_cpl, ctx); 106327e85f52SBen Walker if (rc < 0) { 106427e85f52SBen Walker fprintf(stderr, "error (%d) on initial compress submission\n", rc); 106527e85f52SBen Walker goto error; 106627e85f52SBen Walker } 106727e85f52SBen Walker 106827e85f52SBen Walker return; 106927e85f52SBen Walker 107027e85f52SBen Walker error: 107127e85f52SBen Walker spdk_put_io_channel(ctx->ch); 107227e85f52SBen Walker fclose(ctx->file); 107327e85f52SBen Walker free(ctx); 107427e85f52SBen Walker spdk_app_stop(rc); 107527e85f52SBen Walker } 107627e85f52SBen Walker 107727e85f52SBen Walker static void 107827e85f52SBen Walker accel_perf_prep(void *arg1) 107927e85f52SBen Walker { 108027e85f52SBen Walker struct accel_perf_prep_ctx *ctx; 1081*0a6b7098STomasz Zawadzki const char *module_name = NULL; 108227e85f52SBen Walker int rc = 0; 108327e85f52SBen Walker 1084*0a6b7098STomasz Zawadzki if (g_module_name) { 1085*0a6b7098STomasz Zawadzki rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name); 1086*0a6b7098STomasz Zawadzki if (rc != 0 || strcmp(g_module_name, module_name) != 0) { 1087*0a6b7098STomasz Zawadzki fprintf(stderr, "Module '%s' was assigned via JSON config or RPC, instead of '%s'\n", 1088*0a6b7098STomasz Zawadzki module_name, g_module_name); 1089*0a6b7098STomasz Zawadzki fprintf(stderr, "-M option is not compatible with accel_assign_opc RPC\n"); 1090*0a6b7098STomasz Zawadzki rc = -EINVAL; 1091*0a6b7098STomasz Zawadzki goto error_end; 1092*0a6b7098STomasz Zawadzki } 1093*0a6b7098STomasz Zawadzki } 1094*0a6b7098STomasz Zawadzki 10955105dc5dSKonrad Sztyber if (g_workload_selection != SPDK_ACCEL_OPC_COMPRESS && 10965105dc5dSKonrad Sztyber g_workload_selection != SPDK_ACCEL_OPC_DECOMPRESS) { 109727e85f52SBen Walker accel_perf_start(arg1); 109827e85f52SBen Walker return; 109927e85f52SBen Walker } 110027e85f52SBen Walker 110127e85f52SBen Walker if (g_cd_file_in_name == NULL) { 110227e85f52SBen Walker fprintf(stdout, "A filename is required.\n"); 110327e85f52SBen Walker rc = -EINVAL; 110427e85f52SBen Walker goto error_end; 110527e85f52SBen Walker } 110627e85f52SBen Walker 11075105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS && g_verify) { 110827e85f52SBen Walker fprintf(stdout, "\nCompression does not support the verify option, aborting.\n"); 110927e85f52SBen Walker rc = -ENOTSUP; 111027e85f52SBen Walker goto error_end; 111127e85f52SBen Walker } 111227e85f52SBen Walker 111327e85f52SBen Walker printf("Preparing input file...\n"); 111427e85f52SBen Walker 111527e85f52SBen Walker ctx = calloc(1, sizeof(*ctx)); 111627e85f52SBen Walker if (ctx == NULL) { 111727e85f52SBen Walker rc = -ENOMEM; 111827e85f52SBen Walker goto error_end; 111927e85f52SBen Walker } 112027e85f52SBen Walker 112127e85f52SBen Walker ctx->file = fopen(g_cd_file_in_name, "r"); 112227e85f52SBen Walker if (ctx->file == NULL) { 112327e85f52SBen Walker fprintf(stderr, "Could not open file %s.\n", g_cd_file_in_name); 112427e85f52SBen Walker rc = -errno; 112527e85f52SBen Walker goto error_ctx; 112627e85f52SBen Walker } 112727e85f52SBen Walker 112827e85f52SBen Walker fseek(ctx->file, 0L, SEEK_END); 112927e85f52SBen Walker ctx->remaining = ftell(ctx->file); 113027e85f52SBen Walker fseek(ctx->file, 0L, SEEK_SET); 113127e85f52SBen Walker 113227e85f52SBen Walker ctx->ch = spdk_accel_get_io_channel(); 113327e85f52SBen Walker if (ctx->ch == NULL) { 113427e85f52SBen Walker rc = -EAGAIN; 113527e85f52SBen Walker goto error_file; 113627e85f52SBen Walker } 113727e85f52SBen Walker 113827e85f52SBen Walker if (g_xfer_size_bytes == 0) { 113927e85f52SBen Walker /* size of 0 means "file at a time" */ 114027e85f52SBen Walker g_xfer_size_bytes = ctx->remaining; 114127e85f52SBen Walker } 114227e85f52SBen Walker 114327e85f52SBen Walker accel_perf_prep_process_seg(ctx); 114427e85f52SBen Walker return; 114527e85f52SBen Walker 114627e85f52SBen Walker error_file: 114727e85f52SBen Walker fclose(ctx->file); 114827e85f52SBen Walker error_ctx: 114927e85f52SBen Walker free(ctx); 115027e85f52SBen Walker error_end: 115127e85f52SBen Walker spdk_app_stop(rc); 115227e85f52SBen Walker } 115327e85f52SBen Walker 11544c7b5046SKonrad Sztyber static void 11554c7b5046SKonrad Sztyber worker_shutdown(void *ctx) 11564c7b5046SKonrad Sztyber { 11574c7b5046SKonrad Sztyber _worker_stop(ctx); 11584c7b5046SKonrad Sztyber } 11594c7b5046SKonrad Sztyber 11604c7b5046SKonrad Sztyber static void 11614c7b5046SKonrad Sztyber shutdown_cb(void) 11624c7b5046SKonrad Sztyber { 11634c7b5046SKonrad Sztyber struct worker_thread *worker; 11644c7b5046SKonrad Sztyber 11654c7b5046SKonrad Sztyber pthread_mutex_lock(&g_workers_lock); 1166da5ec81fSKonrad Sztyber if (!g_workers) { 1167da5ec81fSKonrad Sztyber spdk_app_stop(1); 1168da5ec81fSKonrad Sztyber goto unlock; 1169da5ec81fSKonrad Sztyber } 1170da5ec81fSKonrad Sztyber 11714c7b5046SKonrad Sztyber worker = g_workers; 11724c7b5046SKonrad Sztyber while (worker) { 11734c7b5046SKonrad Sztyber spdk_thread_send_msg(worker->thread, worker_shutdown, worker); 11744c7b5046SKonrad Sztyber worker = worker->next; 11754c7b5046SKonrad Sztyber } 1176da5ec81fSKonrad Sztyber unlock: 11774c7b5046SKonrad Sztyber pthread_mutex_unlock(&g_workers_lock); 11784c7b5046SKonrad Sztyber } 11794c7b5046SKonrad Sztyber 11809f51cf32Spaul luse int 11819f51cf32Spaul luse main(int argc, char **argv) 11829f51cf32Spaul luse { 11839f51cf32Spaul luse struct worker_thread *worker, *tmp; 1184f5b5a9c4SKonrad Sztyber int rc; 11859f51cf32Spaul luse 11869f51cf32Spaul luse pthread_mutex_init(&g_workers_lock, NULL); 11879260fa0cSpaul luse spdk_app_opts_init(&g_opts, sizeof(g_opts)); 11889260fa0cSpaul luse g_opts.name = "accel_perf"; 11899260fa0cSpaul luse g_opts.reactor_mask = "0x1"; 11904c7b5046SKonrad Sztyber g_opts.shutdown_cb = shutdown_cb; 1191f5b5a9c4SKonrad Sztyber 1192*0a6b7098STomasz Zawadzki rc = spdk_app_parse_args(argc, argv, &g_opts, "a:C:o:q:t:yw:M:P:f:T:l:S:x:", NULL, 1193f5b5a9c4SKonrad Sztyber parse_args, usage); 1194f5b5a9c4SKonrad Sztyber if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) { 1195f5b5a9c4SKonrad Sztyber return rc == SPDK_APP_PARSE_ARGS_HELP ? 0 : 1; 11969f51cf32Spaul luse } 11979f51cf32Spaul luse 119884dbdf08STomasz Zawadzki if (g_workload_selection == SPDK_ACCEL_OPC_LAST) { 119984dbdf08STomasz Zawadzki fprintf(stderr, "Must provide a workload type\n"); 12002a0c66d0Spaul luse usage(); 1201724f3006STomasz Zawadzki return -1; 12022a0c66d0Spaul luse } 12032a0c66d0Spaul luse 1204e1bf63afSJim Harris if (g_allocate_depth > 0 && g_queue_depth > g_allocate_depth) { 1205e1bf63afSJim Harris fprintf(stdout, "allocate depth must be at least as big as queue depth\n"); 1206e1bf63afSJim Harris usage(); 1207724f3006STomasz Zawadzki return -1; 1208e1bf63afSJim Harris } 1209e1bf63afSJim Harris 1210e1bf63afSJim Harris if (g_allocate_depth == 0) { 1211e1bf63afSJim Harris g_allocate_depth = g_queue_depth; 1212e1bf63afSJim Harris } 1213e1bf63afSJim Harris 12145105dc5dSKonrad Sztyber if ((g_workload_selection == SPDK_ACCEL_OPC_CRC32C || 12155105dc5dSKonrad Sztyber g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) && 1216850cd900Spaul luse g_chained_count == 0) { 121788754353SZiye Yang usage(); 1218724f3006STomasz Zawadzki return -1; 121988754353SZiye Yang } 122088754353SZiye Yang 12215105dc5dSKonrad Sztyber if (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_xor_src_count < 2) { 1222a5d5ab27SArtur Paszkiewicz usage(); 1223724f3006STomasz Zawadzki return -1; 1224a5d5ab27SArtur Paszkiewicz } 1225a5d5ab27SArtur Paszkiewicz 1226*0a6b7098STomasz Zawadzki if (g_module_name && spdk_accel_assign_opc(g_workload_selection, g_module_name)) { 1227*0a6b7098STomasz Zawadzki fprintf(stderr, "Was not able to assign '%s' module to the workload\n", g_module_name); 1228*0a6b7098STomasz Zawadzki usage(); 1229*0a6b7098STomasz Zawadzki return -1; 1230*0a6b7098STomasz Zawadzki } 1231*0a6b7098STomasz Zawadzki 123227e85f52SBen Walker g_rc = spdk_app_start(&g_opts, accel_perf_prep, NULL); 12339b189667Spaul luse if (g_rc) { 12349f51cf32Spaul luse SPDK_ERRLOG("ERROR starting application\n"); 12359f51cf32Spaul luse } 12369f51cf32Spaul luse 12379f51cf32Spaul luse pthread_mutex_destroy(&g_workers_lock); 12389f51cf32Spaul luse 12399f51cf32Spaul luse worker = g_workers; 12409f51cf32Spaul luse while (worker) { 12419f51cf32Spaul luse tmp = worker->next; 12429f51cf32Spaul luse free(worker); 12439f51cf32Spaul luse worker = tmp; 12449f51cf32Spaul luse } 124527e85f52SBen Walker accel_perf_free_compress_segs(); 12469f51cf32Spaul luse spdk_app_fini(); 12479b189667Spaul luse return g_rc; 12489f51cf32Spaul luse } 1249