1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2021 Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk_cunit.h" 8 #include "spdk_internal/mock.h" 9 #include "spdk_internal/accel_module.h" 10 #include "thread/thread_internal.h" 11 #include "common/lib/ut_multithread.c" 12 #include "accel/accel.c" 13 #include "accel/accel_sw.c" 14 #include "unit/lib/json_mock.c" 15 16 #ifdef SPDK_CONFIG_PMDK 17 DEFINE_STUB(pmem_msync, int, (const void *addr, size_t len), 0); 18 DEFINE_STUB(pmem_memcpy_persist, void *, (void *pmemdest, const void *src, size_t len), NULL); 19 DEFINE_STUB(pmem_is_pmem, int, (const void *addr, size_t len), 0); 20 DEFINE_STUB(pmem_memset_persist, void *, (void *pmemdest, int c, size_t len), NULL); 21 #endif 22 DEFINE_STUB(spdk_memory_domain_create, int, 23 (struct spdk_memory_domain **domain, enum spdk_dma_device_type type, 24 struct spdk_memory_domain_ctx *ctx, const char *id), 0); 25 DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *domain)); 26 27 #ifdef SPDK_CONFIG_ISAL 28 DEFINE_STUB_V(XTS_AES_128_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, 29 const uint8_t *src, uint8_t *dst)); 30 DEFINE_STUB_V(XTS_AES_128_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, 31 const uint8_t *src, uint8_t *dst)); 32 DEFINE_STUB_V(XTS_AES_256_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, 33 const uint8_t *src, uint8_t *dst)); 34 DEFINE_STUB_V(XTS_AES_256_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, 35 const uint8_t *src, uint8_t *dst)); 36 #endif 37 38 /* global vars and setup/cleanup functions used for all test functions */ 39 struct spdk_accel_module_if g_module = {}; 40 struct spdk_io_channel *g_ch = NULL; 41 struct accel_io_channel *g_accel_ch = NULL; 42 struct sw_accel_io_channel *g_sw_ch = NULL; 43 struct spdk_io_channel *g_module_ch = NULL; 44 45 static uint64_t g_opc_mask = 0; 46 47 static uint64_t 48 _accel_op_to_bit(enum accel_opcode opc) 49 { 50 return (1 << opc); 51 } 52 53 static bool 54 _supports_opcode(enum accel_opcode opc) 55 { 56 if (_accel_op_to_bit(opc) & g_opc_mask) { 57 return true; 58 } 59 return false; 60 } 61 62 static int 63 test_setup(void) 64 { 65 int i; 66 67 g_ch = calloc(1, sizeof(struct spdk_io_channel) + sizeof(struct accel_io_channel)); 68 if (g_ch == NULL) { 69 /* for some reason the assert fatal macro doesn't work in the setup function. */ 70 CU_ASSERT(false); 71 return -1; 72 } 73 g_accel_ch = (struct accel_io_channel *)((char *)g_ch + sizeof(struct spdk_io_channel)); 74 g_module_ch = calloc(1, sizeof(struct spdk_io_channel) + sizeof(struct sw_accel_io_channel)); 75 if (g_module_ch == NULL) { 76 CU_ASSERT(false); 77 return -1; 78 } 79 80 g_module.submit_tasks = sw_accel_submit_tasks; 81 g_module.name = "software"; 82 for (i = 0; i < ACCEL_OPC_LAST; i++) { 83 g_accel_ch->module_ch[i] = g_module_ch; 84 g_modules_opc[i] = &g_module; 85 } 86 g_sw_ch = (struct sw_accel_io_channel *)((char *)g_module_ch + sizeof( 87 struct spdk_io_channel)); 88 TAILQ_INIT(&g_sw_ch->tasks_to_complete); 89 g_module.supports_opcode = _supports_opcode; 90 return 0; 91 } 92 93 static int 94 test_cleanup(void) 95 { 96 free(g_ch); 97 free(g_module_ch); 98 99 return 0; 100 } 101 102 #define DUMMY_ARG 0xDEADBEEF 103 static bool g_dummy_cb_called = false; 104 static void 105 dummy_cb_fn(void *cb_arg, int status) 106 { 107 CU_ASSERT(*(uint32_t *)cb_arg == DUMMY_ARG); 108 CU_ASSERT(status == 0); 109 g_dummy_cb_called = true; 110 } 111 112 static void 113 test_spdk_accel_task_complete(void) 114 { 115 struct spdk_accel_task accel_task = {}; 116 struct spdk_accel_task *expected_accel_task = NULL; 117 uint32_t cb_arg = DUMMY_ARG; 118 int status = 0; 119 120 accel_task.accel_ch = g_accel_ch; 121 accel_task.cb_fn = dummy_cb_fn; 122 accel_task.cb_arg = &cb_arg; 123 TAILQ_INIT(&g_accel_ch->task_pool); 124 125 /* Confirm cb is called and task added to list. */ 126 spdk_accel_task_complete(&accel_task, status); 127 CU_ASSERT(g_dummy_cb_called == true); 128 expected_accel_task = TAILQ_FIRST(&g_accel_ch->task_pool); 129 TAILQ_REMOVE(&g_accel_ch->task_pool, expected_accel_task, link); 130 CU_ASSERT(expected_accel_task == &accel_task); 131 } 132 133 static void 134 test_get_task(void) 135 { 136 struct spdk_accel_task *task; 137 struct spdk_accel_task _task; 138 void *cb_arg = NULL; 139 140 TAILQ_INIT(&g_accel_ch->task_pool); 141 142 /* no tasks left, return NULL. */ 143 task = _get_task(g_accel_ch, dummy_cb_fn, cb_arg); 144 CU_ASSERT(task == NULL); 145 146 _task.cb_fn = dummy_cb_fn; 147 _task.cb_arg = cb_arg; 148 _task.accel_ch = g_accel_ch; 149 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &_task, link); 150 151 /* Get a valid task. */ 152 task = _get_task(g_accel_ch, dummy_cb_fn, cb_arg); 153 CU_ASSERT(task == &_task); 154 CU_ASSERT(_task.cb_fn == dummy_cb_fn); 155 CU_ASSERT(_task.cb_arg == cb_arg); 156 CU_ASSERT(_task.accel_ch == g_accel_ch); 157 } 158 159 #define TEST_SUBMIT_SIZE 64 160 static void 161 test_spdk_accel_submit_copy(void) 162 { 163 const uint64_t nbytes = TEST_SUBMIT_SIZE; 164 uint8_t dst[TEST_SUBMIT_SIZE] = {0}; 165 uint8_t src[TEST_SUBMIT_SIZE] = {0}; 166 void *cb_arg = NULL; 167 int rc; 168 struct spdk_accel_task task; 169 struct spdk_accel_task *expected_accel_task = NULL; 170 int flags = 0; 171 172 TAILQ_INIT(&g_accel_ch->task_pool); 173 174 /* Fail with no tasks on _get_task() */ 175 rc = spdk_accel_submit_copy(g_ch, src, dst, nbytes, flags, NULL, cb_arg); 176 CU_ASSERT(rc == -ENOMEM); 177 178 task.accel_ch = g_accel_ch; 179 task.flags = 1; 180 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 181 182 /* submission OK. */ 183 rc = spdk_accel_submit_copy(g_ch, dst, src, nbytes, flags, NULL, cb_arg); 184 CU_ASSERT(rc == 0); 185 CU_ASSERT(task.dst == dst); 186 CU_ASSERT(task.src == src); 187 CU_ASSERT(task.op_code == ACCEL_OPC_COPY); 188 CU_ASSERT(task.nbytes == nbytes); 189 CU_ASSERT(task.flags == 0); 190 CU_ASSERT(memcmp(dst, src, TEST_SUBMIT_SIZE) == 0); 191 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 192 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 193 CU_ASSERT(expected_accel_task == &task); 194 } 195 196 static void 197 test_spdk_accel_submit_dualcast(void) 198 { 199 void *dst1; 200 void *dst2; 201 void *src; 202 uint32_t align = ALIGN_4K; 203 uint64_t nbytes = TEST_SUBMIT_SIZE; 204 void *cb_arg = NULL; 205 int rc; 206 struct spdk_accel_task task; 207 struct spdk_accel_task *expected_accel_task = NULL; 208 int flags = 0; 209 210 TAILQ_INIT(&g_accel_ch->task_pool); 211 212 /* Dualcast requires 4K alignment on dst addresses, 213 * hence using the hard coded address to test the buffer alignment 214 */ 215 dst1 = (void *)0x5000; 216 dst2 = (void *)0x60f0; 217 src = calloc(1, TEST_SUBMIT_SIZE); 218 SPDK_CU_ASSERT_FATAL(src != NULL); 219 memset(src, 0x5A, TEST_SUBMIT_SIZE); 220 221 /* This should fail since dst2 is not 4k aligned */ 222 rc = spdk_accel_submit_dualcast(g_ch, dst1, dst2, src, nbytes, flags, NULL, cb_arg); 223 CU_ASSERT(rc == -EINVAL); 224 225 dst1 = (void *)0x7010; 226 dst2 = (void *)0x6000; 227 /* This should fail since dst1 is not 4k aligned */ 228 rc = spdk_accel_submit_dualcast(g_ch, dst1, dst2, src, nbytes, flags, NULL, cb_arg); 229 CU_ASSERT(rc == -EINVAL); 230 231 /* Dualcast requires 4K alignment on dst addresses */ 232 dst1 = (void *)0x7000; 233 dst2 = (void *)0x6000; 234 /* Fail with no tasks on _get_task() */ 235 rc = spdk_accel_submit_dualcast(g_ch, dst1, dst2, src, nbytes, flags, NULL, cb_arg); 236 CU_ASSERT(rc == -ENOMEM); 237 238 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 239 240 /* accel submission OK., since we test the SW path , need to use valid memory addresses 241 * cannot hardcode them anymore */ 242 dst1 = spdk_dma_zmalloc(nbytes, align, NULL); 243 SPDK_CU_ASSERT_FATAL(dst1 != NULL); 244 dst2 = spdk_dma_zmalloc(nbytes, align, NULL); 245 SPDK_CU_ASSERT_FATAL(dst2 != NULL); 246 /* SW module does the dualcast. */ 247 rc = spdk_accel_submit_dualcast(g_ch, dst1, dst2, src, nbytes, flags, NULL, cb_arg); 248 CU_ASSERT(rc == 0); 249 CU_ASSERT(task.dst == dst1); 250 CU_ASSERT(task.dst2 == dst2); 251 CU_ASSERT(task.src == src); 252 CU_ASSERT(task.op_code == ACCEL_OPC_DUALCAST); 253 CU_ASSERT(task.nbytes == nbytes); 254 CU_ASSERT(task.flags == 0); 255 CU_ASSERT(memcmp(dst1, src, TEST_SUBMIT_SIZE) == 0); 256 CU_ASSERT(memcmp(dst2, src, TEST_SUBMIT_SIZE) == 0); 257 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 258 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 259 CU_ASSERT(expected_accel_task == &task); 260 261 free(src); 262 spdk_free(dst1); 263 spdk_free(dst2); 264 } 265 266 static void 267 test_spdk_accel_submit_compare(void) 268 { 269 void *src1; 270 void *src2; 271 uint64_t nbytes = TEST_SUBMIT_SIZE; 272 void *cb_arg = NULL; 273 int rc; 274 struct spdk_accel_task task; 275 struct spdk_accel_task *expected_accel_task = NULL; 276 277 TAILQ_INIT(&g_accel_ch->task_pool); 278 279 src1 = calloc(1, TEST_SUBMIT_SIZE); 280 SPDK_CU_ASSERT_FATAL(src1 != NULL); 281 src2 = calloc(1, TEST_SUBMIT_SIZE); 282 SPDK_CU_ASSERT_FATAL(src2 != NULL); 283 284 /* Fail with no tasks on _get_task() */ 285 rc = spdk_accel_submit_compare(g_ch, src1, src2, nbytes, NULL, cb_arg); 286 CU_ASSERT(rc == -ENOMEM); 287 288 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 289 290 /* accel submission OK. */ 291 rc = spdk_accel_submit_compare(g_ch, src1, src2, nbytes, NULL, cb_arg); 292 CU_ASSERT(rc == 0); 293 CU_ASSERT(task.src == src1); 294 CU_ASSERT(task.src2 == src2); 295 CU_ASSERT(task.op_code == ACCEL_OPC_COMPARE); 296 CU_ASSERT(task.nbytes == nbytes); 297 CU_ASSERT(memcmp(src1, src2, TEST_SUBMIT_SIZE) == 0); 298 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 299 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 300 CU_ASSERT(expected_accel_task == &task); 301 302 free(src1); 303 free(src2); 304 } 305 306 static void 307 test_spdk_accel_submit_fill(void) 308 { 309 void *dst; 310 void *src; 311 uint8_t fill = 0xf; 312 uint64_t fill64; 313 uint64_t nbytes = TEST_SUBMIT_SIZE; 314 void *cb_arg = NULL; 315 int rc; 316 struct spdk_accel_task task; 317 struct spdk_accel_task *expected_accel_task = NULL; 318 int flags = 0; 319 320 TAILQ_INIT(&g_accel_ch->task_pool); 321 322 dst = calloc(1, TEST_SUBMIT_SIZE); 323 SPDK_CU_ASSERT_FATAL(dst != NULL); 324 src = calloc(1, TEST_SUBMIT_SIZE); 325 SPDK_CU_ASSERT_FATAL(src != NULL); 326 memset(src, fill, TEST_SUBMIT_SIZE); 327 memset(&fill64, fill, sizeof(uint64_t)); 328 329 /* Fail with no tasks on _get_task() */ 330 rc = spdk_accel_submit_fill(g_ch, dst, fill, nbytes, flags, NULL, cb_arg); 331 CU_ASSERT(rc == -ENOMEM); 332 333 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 334 335 /* accel submission OK. */ 336 rc = spdk_accel_submit_fill(g_ch, dst, fill, nbytes, flags, NULL, cb_arg); 337 CU_ASSERT(rc == 0); 338 CU_ASSERT(task.dst == dst); 339 CU_ASSERT(task.fill_pattern == fill64); 340 CU_ASSERT(task.op_code == ACCEL_OPC_FILL); 341 CU_ASSERT(task.nbytes == nbytes); 342 CU_ASSERT(task.flags == 0); 343 344 CU_ASSERT(memcmp(dst, src, TEST_SUBMIT_SIZE) == 0); 345 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 346 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 347 CU_ASSERT(expected_accel_task == &task); 348 349 free(dst); 350 free(src); 351 } 352 353 static void 354 test_spdk_accel_submit_crc32c(void) 355 { 356 const uint64_t nbytes = TEST_SUBMIT_SIZE; 357 uint32_t crc_dst; 358 uint8_t src[TEST_SUBMIT_SIZE]; 359 uint32_t seed = 1; 360 void *cb_arg = NULL; 361 int rc; 362 struct spdk_accel_task task; 363 struct spdk_accel_task *expected_accel_task = NULL; 364 365 TAILQ_INIT(&g_accel_ch->task_pool); 366 367 /* Fail with no tasks on _get_task() */ 368 rc = spdk_accel_submit_crc32c(g_ch, &crc_dst, src, seed, nbytes, NULL, cb_arg); 369 CU_ASSERT(rc == -ENOMEM); 370 371 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 372 373 /* accel submission OK. */ 374 rc = spdk_accel_submit_crc32c(g_ch, &crc_dst, src, seed, nbytes, NULL, cb_arg); 375 CU_ASSERT(rc == 0); 376 CU_ASSERT(task.crc_dst == &crc_dst); 377 CU_ASSERT(task.src == src); 378 CU_ASSERT(task.s.iovcnt == 0); 379 CU_ASSERT(task.seed == seed); 380 CU_ASSERT(task.op_code == ACCEL_OPC_CRC32C); 381 CU_ASSERT(task.nbytes == nbytes); 382 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 383 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 384 CU_ASSERT(expected_accel_task == &task); 385 } 386 387 static void 388 test_spdk_accel_submit_crc32cv(void) 389 { 390 uint32_t crc_dst; 391 uint32_t seed = 0; 392 uint32_t iov_cnt = 32; 393 void *cb_arg = NULL; 394 int rc; 395 uint32_t i = 0; 396 struct spdk_accel_task task; 397 struct iovec iov[32]; 398 struct spdk_accel_task *expected_accel_task = NULL; 399 400 TAILQ_INIT(&g_accel_ch->task_pool); 401 402 for (i = 0; i < iov_cnt; i++) { 403 iov[i].iov_base = calloc(1, TEST_SUBMIT_SIZE); 404 SPDK_CU_ASSERT_FATAL(iov[i].iov_base != NULL); 405 iov[i].iov_len = TEST_SUBMIT_SIZE; 406 } 407 408 task.nbytes = TEST_SUBMIT_SIZE; 409 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 410 411 /* accel submission OK. */ 412 rc = spdk_accel_submit_crc32cv(g_ch, &crc_dst, iov, iov_cnt, seed, NULL, cb_arg); 413 CU_ASSERT(rc == 0); 414 CU_ASSERT(task.s.iovs == iov); 415 CU_ASSERT(task.s.iovcnt == iov_cnt); 416 CU_ASSERT(task.crc_dst == &crc_dst); 417 CU_ASSERT(task.seed == seed); 418 CU_ASSERT(task.op_code == ACCEL_OPC_CRC32C); 419 CU_ASSERT(task.cb_arg == cb_arg); 420 CU_ASSERT(task.nbytes == iov[0].iov_len); 421 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 422 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 423 CU_ASSERT(expected_accel_task == &task); 424 425 for (i = 0; i < iov_cnt; i++) { 426 free(iov[i].iov_base); 427 } 428 } 429 430 static void 431 test_spdk_accel_submit_copy_crc32c(void) 432 { 433 const uint64_t nbytes = TEST_SUBMIT_SIZE; 434 uint32_t crc_dst; 435 uint8_t dst[TEST_SUBMIT_SIZE]; 436 uint8_t src[TEST_SUBMIT_SIZE]; 437 uint32_t seed = 0; 438 void *cb_arg = NULL; 439 int rc; 440 struct spdk_accel_task task; 441 struct spdk_accel_task *expected_accel_task = NULL; 442 int flags = 0; 443 444 TAILQ_INIT(&g_accel_ch->task_pool); 445 446 /* Fail with no tasks on _get_task() */ 447 rc = spdk_accel_submit_copy_crc32c(g_ch, dst, src, &crc_dst, seed, nbytes, flags, 448 NULL, cb_arg); 449 CU_ASSERT(rc == -ENOMEM); 450 451 TAILQ_INSERT_TAIL(&g_accel_ch->task_pool, &task, link); 452 453 /* accel submission OK. */ 454 rc = spdk_accel_submit_copy_crc32c(g_ch, dst, src, &crc_dst, seed, nbytes, flags, 455 NULL, cb_arg); 456 CU_ASSERT(rc == 0); 457 CU_ASSERT(task.dst == dst); 458 CU_ASSERT(task.src == src); 459 CU_ASSERT(task.crc_dst == &crc_dst); 460 CU_ASSERT(task.s.iovcnt == 0); 461 CU_ASSERT(task.seed == seed); 462 CU_ASSERT(task.nbytes == nbytes); 463 CU_ASSERT(task.flags == 0); 464 CU_ASSERT(task.op_code == ACCEL_OPC_COPY_CRC32C); 465 expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete); 466 TAILQ_REMOVE(&g_sw_ch->tasks_to_complete, expected_accel_task, link); 467 CU_ASSERT(expected_accel_task == &task); 468 } 469 470 static void 471 test_spdk_accel_module_find_by_name(void) 472 { 473 struct spdk_accel_module_if mod1 = {}; 474 struct spdk_accel_module_if mod2 = {}; 475 struct spdk_accel_module_if mod3 = {}; 476 struct spdk_accel_module_if *accel_module = NULL; 477 478 mod1.name = "ioat"; 479 mod2.name = "idxd"; 480 mod3.name = "software"; 481 482 TAILQ_INIT(&spdk_accel_module_list); 483 TAILQ_INSERT_TAIL(&spdk_accel_module_list, &mod1, tailq); 484 TAILQ_INSERT_TAIL(&spdk_accel_module_list, &mod2, tailq); 485 TAILQ_INSERT_TAIL(&spdk_accel_module_list, &mod3, tailq); 486 487 /* Now let's find a valid engine */ 488 accel_module = _module_find_by_name("ioat"); 489 CU_ASSERT(accel_module != NULL); 490 491 /* Try to find one that doesn't exist */ 492 accel_module = _module_find_by_name("XXX"); 493 CU_ASSERT(accel_module == NULL); 494 } 495 496 static void 497 test_spdk_accel_module_register(void) 498 { 499 struct spdk_accel_module_if mod1 = {}; 500 struct spdk_accel_module_if mod2 = {}; 501 struct spdk_accel_module_if mod3 = {}; 502 struct spdk_accel_module_if mod4 = {}; 503 struct spdk_accel_module_if *accel_module = NULL; 504 int i = 0; 505 506 mod1.name = "ioat"; 507 mod2.name = "idxd"; 508 mod3.name = "software"; 509 mod4.name = "nothing"; 510 511 TAILQ_INIT(&spdk_accel_module_list); 512 513 spdk_accel_module_list_add(&mod1); 514 spdk_accel_module_list_add(&mod2); 515 spdk_accel_module_list_add(&mod3); 516 spdk_accel_module_list_add(&mod4); 517 518 /* Now confirm they're in the right order. */ 519 TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) { 520 switch (i++) { 521 case 0: 522 CU_ASSERT(strcmp(accel_module->name, "software") == 0); 523 break; 524 case 1: 525 CU_ASSERT(strcmp(accel_module->name, "ioat") == 0); 526 break; 527 case 2: 528 CU_ASSERT(strcmp(accel_module->name, "idxd") == 0); 529 break; 530 case 3: 531 CU_ASSERT(strcmp(accel_module->name, "nothing") == 0); 532 break; 533 default: 534 CU_ASSERT(false); 535 break; 536 } 537 } 538 CU_ASSERT(i == 4); 539 } 540 541 struct ut_sequence { 542 bool complete; 543 int status; 544 }; 545 546 static void 547 ut_sequence_step_cb(void *cb_arg) 548 { 549 int *completed = cb_arg; 550 551 (*completed)++; 552 } 553 554 static void 555 ut_sequence_complete_cb(void *cb_arg, int status) 556 { 557 struct ut_sequence *seq = cb_arg; 558 559 seq->complete = true; 560 seq->status = status; 561 } 562 563 static void 564 test_sequence_fill_copy(void) 565 { 566 struct spdk_accel_sequence *seq = NULL; 567 struct spdk_io_channel *ioch; 568 struct ut_sequence ut_seq; 569 char buf[4096], tmp[2][4096], expected[4096]; 570 struct iovec src_iovs[2], dst_iovs[2]; 571 int rc, completed; 572 573 ioch = spdk_accel_get_io_channel(); 574 SPDK_CU_ASSERT_FATAL(ioch != NULL); 575 576 /* First check the simplest case - single task in a sequence */ 577 memset(buf, 0, sizeof(buf)); 578 memset(expected, 0xa5, sizeof(expected)); 579 completed = 0; 580 rc = spdk_accel_append_fill(&seq, ioch, buf, sizeof(buf), NULL, NULL, 0xa5, 0, 581 ut_sequence_step_cb, &completed); 582 CU_ASSERT_EQUAL(rc, 0); 583 CU_ASSERT_EQUAL(completed, 0); 584 585 ut_seq.complete = false; 586 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 587 CU_ASSERT_EQUAL(rc, 0); 588 589 poll_threads(); 590 CU_ASSERT_EQUAL(completed, 1); 591 CU_ASSERT(ut_seq.complete); 592 CU_ASSERT_EQUAL(ut_seq.status, 0); 593 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 594 595 /* Check a single copy operation */ 596 memset(buf, 0, sizeof(buf)); 597 memset(tmp[0], 0xa5, sizeof(tmp[0])); 598 memset(expected, 0xa5, sizeof(expected)); 599 completed = 0; 600 seq = NULL; 601 602 dst_iovs[0].iov_base = buf; 603 dst_iovs[0].iov_len = sizeof(buf); 604 src_iovs[0].iov_base = tmp[0]; 605 src_iovs[0].iov_len = sizeof(tmp[0]); 606 607 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 608 &src_iovs[0], 1, NULL, NULL, 0, 609 ut_sequence_step_cb, &completed); 610 CU_ASSERT_EQUAL(rc, 0); 611 612 ut_seq.complete = false; 613 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 614 CU_ASSERT_EQUAL(rc, 0); 615 616 poll_threads(); 617 CU_ASSERT_EQUAL(completed, 1); 618 CU_ASSERT(ut_seq.complete); 619 CU_ASSERT_EQUAL(ut_seq.status, 0); 620 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 621 622 /* Check multiple fill operations */ 623 memset(buf, 0, sizeof(buf)); 624 memset(expected, 0xfe, 4096); 625 memset(expected, 0xde, 2048); 626 memset(expected, 0xa5, 1024); 627 seq = NULL; 628 completed = 0; 629 rc = spdk_accel_append_fill(&seq, ioch, buf, 4096, NULL, NULL, 0xfe, 0, 630 ut_sequence_step_cb, &completed); 631 CU_ASSERT_EQUAL(rc, 0); 632 rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xde, 0, 633 ut_sequence_step_cb, &completed); 634 CU_ASSERT_EQUAL(rc, 0); 635 rc = spdk_accel_append_fill(&seq, ioch, buf, 1024, NULL, NULL, 0xa5, 0, 636 ut_sequence_step_cb, &completed); 637 CU_ASSERT_EQUAL(rc, 0); 638 639 ut_seq.complete = false; 640 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 641 CU_ASSERT_EQUAL(rc, 0); 642 643 poll_threads(); 644 CU_ASSERT_EQUAL(completed, 3); 645 CU_ASSERT(ut_seq.complete); 646 CU_ASSERT_EQUAL(ut_seq.status, 0); 647 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 648 649 /* Check multiple copy operations */ 650 memset(buf, 0, sizeof(buf)); 651 memset(tmp[0], 0, sizeof(tmp[0])); 652 memset(tmp[1], 0, sizeof(tmp[1])); 653 memset(expected, 0xa5, sizeof(expected)); 654 seq = NULL; 655 completed = 0; 656 657 rc = spdk_accel_append_fill(&seq, ioch, tmp[0], sizeof(tmp[0]), NULL, NULL, 0xa5, 0, 658 ut_sequence_step_cb, &completed); 659 CU_ASSERT_EQUAL(rc, 0); 660 661 dst_iovs[0].iov_base = tmp[1]; 662 dst_iovs[0].iov_len = sizeof(tmp[1]); 663 src_iovs[0].iov_base = tmp[0]; 664 src_iovs[0].iov_len = sizeof(tmp[0]); 665 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 666 &src_iovs[0], 1, NULL, NULL, 0, 667 ut_sequence_step_cb, &completed); 668 CU_ASSERT_EQUAL(rc, 0); 669 670 dst_iovs[1].iov_base = buf; 671 dst_iovs[1].iov_len = sizeof(buf); 672 src_iovs[1].iov_base = tmp[1]; 673 src_iovs[1].iov_len = sizeof(tmp[1]); 674 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 675 &src_iovs[1], 1, NULL, NULL, 0, 676 ut_sequence_step_cb, &completed); 677 CU_ASSERT_EQUAL(rc, 0); 678 679 ut_seq.complete = false; 680 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 681 CU_ASSERT_EQUAL(rc, 0); 682 683 poll_threads(); 684 CU_ASSERT_EQUAL(completed, 3); 685 CU_ASSERT(ut_seq.complete); 686 CU_ASSERT_EQUAL(ut_seq.status, 0); 687 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 688 689 /* Check that adding a copy operation at the end will change destination buffer */ 690 memset(buf, 0, sizeof(buf)); 691 memset(tmp[0], 0, sizeof(tmp[0])); 692 memset(expected, 0xa5, sizeof(buf)); 693 seq = NULL; 694 completed = 0; 695 rc = spdk_accel_append_fill(&seq, ioch, tmp[0], sizeof(tmp[0]), NULL, NULL, 0xa5, 0, 696 ut_sequence_step_cb, &completed); 697 CU_ASSERT_EQUAL(rc, 0); 698 699 dst_iovs[0].iov_base = buf; 700 dst_iovs[0].iov_len = sizeof(buf); 701 src_iovs[0].iov_base = tmp[0]; 702 src_iovs[0].iov_len = sizeof(tmp[0]); 703 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 704 &src_iovs[0], 1, NULL, NULL, 0, 705 ut_sequence_step_cb, &completed); 706 CU_ASSERT_EQUAL(rc, 0); 707 708 ut_seq.complete = false; 709 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 710 CU_ASSERT_EQUAL(rc, 0); 711 712 poll_threads(); 713 CU_ASSERT_EQUAL(completed, 2); 714 CU_ASSERT(ut_seq.complete); 715 CU_ASSERT_EQUAL(ut_seq.status, 0); 716 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 717 718 /* Check that it's also possible to add copy operation at the beginning */ 719 memset(buf, 0, sizeof(buf)); 720 memset(tmp[0], 0xde, sizeof(tmp[0])); 721 memset(tmp[1], 0, sizeof(tmp[1])); 722 memset(expected, 0xa5, sizeof(expected)); 723 seq = NULL; 724 completed = 0; 725 726 dst_iovs[0].iov_base = tmp[1]; 727 dst_iovs[0].iov_len = sizeof(tmp[1]); 728 src_iovs[0].iov_base = tmp[0]; 729 src_iovs[0].iov_len = sizeof(tmp[0]); 730 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 731 &src_iovs[0], 1, NULL, NULL, 0, 732 ut_sequence_step_cb, &completed); 733 CU_ASSERT_EQUAL(rc, 0); 734 735 rc = spdk_accel_append_fill(&seq, ioch, tmp[1], sizeof(tmp[1]), NULL, NULL, 0xa5, 0, 736 ut_sequence_step_cb, &completed); 737 CU_ASSERT_EQUAL(rc, 0); 738 739 dst_iovs[1].iov_base = buf; 740 dst_iovs[1].iov_len = sizeof(buf); 741 src_iovs[1].iov_base = tmp[1]; 742 src_iovs[1].iov_len = sizeof(tmp[1]); 743 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 744 &src_iovs[1], 1, NULL, NULL, 0, 745 ut_sequence_step_cb, &completed); 746 CU_ASSERT_EQUAL(rc, 0); 747 748 ut_seq.complete = false; 749 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 750 CU_ASSERT_EQUAL(rc, 0); 751 752 poll_threads(); 753 CU_ASSERT_EQUAL(completed, 3); 754 CU_ASSERT(ut_seq.complete); 755 CU_ASSERT_EQUAL(ut_seq.status, 0); 756 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 757 758 spdk_put_io_channel(ioch); 759 poll_threads(); 760 } 761 762 static void 763 test_sequence_abort(void) 764 { 765 struct spdk_accel_sequence *seq = NULL; 766 struct spdk_io_channel *ioch; 767 char buf[4096], tmp[2][4096], expected[4096]; 768 struct iovec src_iovs[2], dst_iovs[2]; 769 int rc, completed; 770 771 ioch = spdk_accel_get_io_channel(); 772 SPDK_CU_ASSERT_FATAL(ioch != NULL); 773 774 /* Check that aborting a sequence calls operation's callback, the operation is not executed 775 * and the sequence is freed 776 */ 777 memset(buf, 0, sizeof(buf)); 778 memset(expected, 0, sizeof(buf)); 779 completed = 0; 780 seq = NULL; 781 rc = spdk_accel_append_fill(&seq, ioch, buf, sizeof(buf), NULL, NULL, 0xa5, 0, 782 ut_sequence_step_cb, &completed); 783 CU_ASSERT_EQUAL(rc, 0); 784 785 spdk_accel_sequence_abort(seq); 786 CU_ASSERT_EQUAL(completed, 1); 787 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 788 789 /* Check sequence with multiple operations */ 790 memset(buf, 0, sizeof(buf)); 791 memset(expected, 0, sizeof(buf)); 792 completed = 0; 793 seq = NULL; 794 795 dst_iovs[0].iov_base = tmp[1]; 796 dst_iovs[0].iov_len = sizeof(tmp[1]); 797 src_iovs[0].iov_base = tmp[0]; 798 src_iovs[0].iov_len = sizeof(tmp[0]); 799 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 800 &src_iovs[0], 1, NULL, NULL, 0, 801 ut_sequence_step_cb, &completed); 802 CU_ASSERT_EQUAL(rc, 0); 803 804 rc = spdk_accel_append_fill(&seq, ioch, tmp[1], 4096, NULL, NULL, 0xa5, 0, 805 ut_sequence_step_cb, &completed); 806 CU_ASSERT_EQUAL(rc, 0); 807 808 rc = spdk_accel_append_fill(&seq, ioch, tmp[1], 2048, NULL, NULL, 0xde, 0, 809 ut_sequence_step_cb, &completed); 810 CU_ASSERT_EQUAL(rc, 0); 811 812 dst_iovs[1].iov_base = buf; 813 dst_iovs[1].iov_len = sizeof(buf); 814 src_iovs[1].iov_base = tmp[1]; 815 src_iovs[1].iov_len = sizeof(tmp[1]); 816 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 817 &src_iovs[1], 1, NULL, NULL, 0, 818 ut_sequence_step_cb, &completed); 819 CU_ASSERT_EQUAL(rc, 0); 820 821 spdk_accel_sequence_abort(seq); 822 CU_ASSERT_EQUAL(completed, 4); 823 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 824 825 /* This should be a no-op */ 826 spdk_accel_sequence_abort(NULL); 827 828 spdk_put_io_channel(ioch); 829 poll_threads(); 830 } 831 832 static void 833 test_sequence_append_error(void) 834 { 835 struct spdk_accel_sequence *seq = NULL; 836 struct spdk_io_channel *ioch; 837 struct accel_io_channel *accel_ch; 838 struct iovec src_iovs, dst_iovs; 839 char buf[4096]; 840 TAILQ_HEAD(, spdk_accel_task) tasks = TAILQ_HEAD_INITIALIZER(tasks); 841 TAILQ_HEAD(, spdk_accel_sequence) seqs = TAILQ_HEAD_INITIALIZER(seqs); 842 int rc; 843 844 ioch = spdk_accel_get_io_channel(); 845 SPDK_CU_ASSERT_FATAL(ioch != NULL); 846 accel_ch = spdk_io_channel_get_ctx(ioch); 847 848 /* Check that append fails and no sequence object is allocated when there are no more free 849 * tasks */ 850 TAILQ_SWAP(&tasks, &accel_ch->task_pool, spdk_accel_task, link); 851 852 rc = spdk_accel_append_fill(&seq, ioch, buf, sizeof(buf), NULL, NULL, 0xa5, 0, 853 ut_sequence_step_cb, NULL); 854 CU_ASSERT_EQUAL(rc, -ENOMEM); 855 CU_ASSERT_PTR_NULL(seq); 856 857 dst_iovs.iov_base = buf; 858 dst_iovs.iov_len = 2048; 859 src_iovs.iov_base = &buf[2048]; 860 src_iovs.iov_len = 2048; 861 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 862 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, NULL); 863 CU_ASSERT_EQUAL(rc, -ENOMEM); 864 CU_ASSERT_PTR_NULL(seq); 865 866 dst_iovs.iov_base = buf; 867 dst_iovs.iov_len = 2048; 868 src_iovs.iov_base = &buf[2048]; 869 src_iovs.iov_len = 2048; 870 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs, 1, NULL, NULL, 871 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, NULL); 872 CU_ASSERT_EQUAL(rc, -ENOMEM); 873 CU_ASSERT_PTR_NULL(seq); 874 875 /* Check that the same happens when the sequence queue is empty */ 876 TAILQ_SWAP(&tasks, &accel_ch->task_pool, spdk_accel_task, link); 877 TAILQ_SWAP(&seqs, &accel_ch->seq_pool, spdk_accel_sequence, link); 878 879 rc = spdk_accel_append_fill(&seq, ioch, buf, sizeof(buf), NULL, NULL, 0xa5, 0, 880 ut_sequence_step_cb, NULL); 881 CU_ASSERT_EQUAL(rc, -ENOMEM); 882 CU_ASSERT_PTR_NULL(seq); 883 884 dst_iovs.iov_base = buf; 885 dst_iovs.iov_len = 2048; 886 src_iovs.iov_base = &buf[2048]; 887 src_iovs.iov_len = 2048; 888 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 889 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, NULL); 890 CU_ASSERT_EQUAL(rc, -ENOMEM); 891 CU_ASSERT_PTR_NULL(seq); 892 893 dst_iovs.iov_base = buf; 894 dst_iovs.iov_len = 2048; 895 src_iovs.iov_base = &buf[2048]; 896 src_iovs.iov_len = 2048; 897 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs, 1, NULL, NULL, 898 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, NULL); 899 CU_ASSERT_EQUAL(rc, -ENOMEM); 900 CU_ASSERT_PTR_NULL(seq); 901 902 TAILQ_SWAP(&tasks, &accel_ch->task_pool, spdk_accel_task, link); 903 904 spdk_put_io_channel(ioch); 905 poll_threads(); 906 } 907 908 struct ut_sequence_operation { 909 int complete_status; 910 int submit_status; 911 int count; 912 struct iovec *src_iovs; 913 uint32_t src_iovcnt; 914 struct iovec *dst_iovs; 915 uint32_t dst_iovcnt; 916 }; 917 918 static struct ut_sequence_operation g_seq_operations[ACCEL_OPC_LAST]; 919 920 static int 921 ut_sequnce_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *task) 922 { 923 struct ut_sequence_operation *op = &g_seq_operations[task->op_code]; 924 925 if (op->src_iovs != NULL) { 926 CU_ASSERT_EQUAL(task->s.iovcnt, op->src_iovcnt); 927 CU_ASSERT_EQUAL(memcmp(task->s.iovs, op->src_iovs, 928 sizeof(struct iovec) * op->src_iovcnt), 0); 929 } 930 if (op->dst_iovs != NULL) { 931 CU_ASSERT_EQUAL(task->d.iovcnt, op->dst_iovcnt); 932 CU_ASSERT_EQUAL(memcmp(task->d.iovs, op->dst_iovs, 933 sizeof(struct iovec) * op->dst_iovcnt), 0); 934 } 935 936 op->count++; 937 if (op->submit_status != 0) { 938 return op->submit_status; 939 } 940 941 spdk_accel_task_complete(task, op->complete_status); 942 943 return 0; 944 } 945 946 static void 947 test_sequence_completion_error(void) 948 { 949 struct spdk_accel_sequence *seq = NULL; 950 struct spdk_io_channel *ioch; 951 struct ut_sequence ut_seq; 952 struct iovec src_iovs, dst_iovs; 953 char buf[4096], tmp[4096]; 954 struct spdk_accel_module_if *modules[ACCEL_OPC_LAST]; 955 int i, rc, completed; 956 957 ioch = spdk_accel_get_io_channel(); 958 SPDK_CU_ASSERT_FATAL(ioch != NULL); 959 960 /* Override the submit_tasks function */ 961 g_module.submit_tasks = ut_sequnce_submit_tasks; 962 for (i = 0; i < ACCEL_OPC_LAST; ++i) { 963 modules[i] = g_modules_opc[i]; 964 g_modules_opc[i] = &g_module; 965 } 966 967 memset(buf, 0, sizeof(buf)); 968 memset(tmp, 0, sizeof(tmp)); 969 970 /* Check that if the first operation completes with an error, the whole sequence is 971 * completed with that error and that all operations' completion callbacks are executed 972 */ 973 g_seq_operations[ACCEL_OPC_FILL].complete_status = -E2BIG; 974 completed = 0; 975 seq = NULL; 976 rc = spdk_accel_append_fill(&seq, ioch, tmp, sizeof(tmp), NULL, NULL, 0xa5, 0, 977 ut_sequence_step_cb, &completed); 978 CU_ASSERT_EQUAL(rc, 0); 979 980 dst_iovs.iov_base = buf; 981 dst_iovs.iov_len = sizeof(buf); 982 src_iovs.iov_base = tmp; 983 src_iovs.iov_len = sizeof(tmp); 984 985 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 986 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, &completed); 987 CU_ASSERT_EQUAL(rc, 0); 988 989 ut_seq.complete = false; 990 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 991 CU_ASSERT_EQUAL(rc, 0); 992 993 poll_threads(); 994 CU_ASSERT_EQUAL(completed, 2); 995 CU_ASSERT_EQUAL(ut_seq.status, -E2BIG); 996 997 /* Check the same with a second operation in the sequence */ 998 g_seq_operations[ACCEL_OPC_COPY].complete_status = -EACCES; 999 g_seq_operations[ACCEL_OPC_FILL].complete_status = 0; 1000 completed = 0; 1001 seq = NULL; 1002 rc = spdk_accel_append_fill(&seq, ioch, tmp, sizeof(tmp), NULL, NULL, 0xa5, 0, 1003 ut_sequence_step_cb, &completed); 1004 CU_ASSERT_EQUAL(rc, 0); 1005 1006 dst_iovs.iov_base = buf; 1007 dst_iovs.iov_len = sizeof(buf); 1008 src_iovs.iov_base = tmp; 1009 src_iovs.iov_len = sizeof(tmp); 1010 1011 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 1012 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, &completed); 1013 CU_ASSERT_EQUAL(rc, 0); 1014 1015 ut_seq.complete = false; 1016 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1017 CU_ASSERT_EQUAL(rc, 0); 1018 1019 poll_threads(); 1020 CU_ASSERT_EQUAL(completed, 2); 1021 CU_ASSERT_EQUAL(ut_seq.status, -EACCES); 1022 1023 g_seq_operations[ACCEL_OPC_COPY].complete_status = 0; 1024 g_seq_operations[ACCEL_OPC_FILL].complete_status = 0; 1025 1026 /* Check submission failure of the first operation */ 1027 g_seq_operations[ACCEL_OPC_FILL].submit_status = -EADDRINUSE; 1028 completed = 0; 1029 seq = NULL; 1030 rc = spdk_accel_append_fill(&seq, ioch, tmp, sizeof(tmp), NULL, NULL, 0xa5, 0, 1031 ut_sequence_step_cb, &completed); 1032 CU_ASSERT_EQUAL(rc, 0); 1033 1034 dst_iovs.iov_base = buf; 1035 dst_iovs.iov_len = sizeof(buf); 1036 src_iovs.iov_base = tmp; 1037 src_iovs.iov_len = sizeof(tmp); 1038 1039 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 1040 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, &completed); 1041 CU_ASSERT_EQUAL(rc, 0); 1042 1043 ut_seq.complete = false; 1044 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1045 CU_ASSERT_EQUAL(rc, 0); 1046 1047 poll_threads(); 1048 CU_ASSERT_EQUAL(completed, 2); 1049 CU_ASSERT_EQUAL(ut_seq.status, -EADDRINUSE); 1050 1051 /* Check the same with a second operation */ 1052 g_seq_operations[ACCEL_OPC_COPY].submit_status = -EADDRNOTAVAIL; 1053 g_seq_operations[ACCEL_OPC_FILL].submit_status = 0; 1054 completed = 0; 1055 seq = NULL; 1056 rc = spdk_accel_append_fill(&seq, ioch, tmp, sizeof(tmp), NULL, NULL, 0xa5, 0, 1057 ut_sequence_step_cb, &completed); 1058 CU_ASSERT_EQUAL(rc, 0); 1059 1060 dst_iovs.iov_base = buf; 1061 dst_iovs.iov_len = sizeof(buf); 1062 src_iovs.iov_base = tmp; 1063 src_iovs.iov_len = sizeof(tmp); 1064 1065 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs, 1, NULL, NULL, 1066 &src_iovs, 1, NULL, NULL, 0, ut_sequence_step_cb, &completed); 1067 CU_ASSERT_EQUAL(rc, 0); 1068 1069 ut_seq.complete = false; 1070 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1071 CU_ASSERT_EQUAL(rc, 0); 1072 1073 poll_threads(); 1074 CU_ASSERT_EQUAL(completed, 2); 1075 CU_ASSERT_EQUAL(ut_seq.status, -EADDRNOTAVAIL); 1076 1077 /* Cleanup module pointers to make subsequent tests work correctly */ 1078 for (i = 0; i < ACCEL_OPC_LAST; ++i) { 1079 g_modules_opc[i] = modules[i]; 1080 } 1081 1082 spdk_put_io_channel(ioch); 1083 poll_threads(); 1084 } 1085 1086 #ifdef SPDK_CONFIG_ISAL 1087 static void 1088 ut_compress_cb(void *cb_arg, int status) 1089 { 1090 int *completed = cb_arg; 1091 1092 CU_ASSERT_EQUAL(status, 0); 1093 1094 *completed = 1; 1095 } 1096 1097 static void 1098 test_sequence_decompress(void) 1099 { 1100 struct spdk_accel_sequence *seq = NULL; 1101 struct spdk_io_channel *ioch; 1102 struct ut_sequence ut_seq; 1103 char buf[4096], tmp[2][4096], expected[4096]; 1104 struct iovec src_iovs[2], dst_iovs[2]; 1105 uint32_t compressed_size; 1106 int rc, completed = 0; 1107 1108 ioch = spdk_accel_get_io_channel(); 1109 SPDK_CU_ASSERT_FATAL(ioch != NULL); 1110 1111 memset(expected, 0xa5, sizeof(expected)); 1112 src_iovs[0].iov_base = expected; 1113 src_iovs[0].iov_len = sizeof(expected); 1114 rc = spdk_accel_submit_compress(ioch, tmp[0], sizeof(tmp[0]), &src_iovs[0], 1, 1115 &compressed_size, 0, ut_compress_cb, &completed); 1116 CU_ASSERT_EQUAL(rc, 0); 1117 1118 while (!completed) { 1119 poll_threads(); 1120 } 1121 1122 /* Check a single decompress operation in a sequence */ 1123 seq = NULL; 1124 completed = 0; 1125 1126 dst_iovs[0].iov_base = buf; 1127 dst_iovs[0].iov_len = sizeof(buf); 1128 src_iovs[0].iov_base = tmp[0]; 1129 src_iovs[0].iov_len = compressed_size; 1130 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1131 &src_iovs[0], 1, NULL, NULL, 0, 1132 ut_sequence_step_cb, &completed); 1133 CU_ASSERT_EQUAL(rc, 0); 1134 1135 ut_seq.complete = false; 1136 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1137 CU_ASSERT_EQUAL(rc, 0); 1138 1139 poll_threads(); 1140 1141 CU_ASSERT_EQUAL(completed, 1); 1142 CU_ASSERT(ut_seq.complete); 1143 CU_ASSERT_EQUAL(ut_seq.status, 0); 1144 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1145 1146 /* Put the decompress operation in the middle of a sequence with a copy operation at the 1147 * beginning and a fill at the end modifying the first 2048B of the buffer. 1148 */ 1149 memset(expected, 0xfe, 2048); 1150 memset(buf, 0, sizeof(buf)); 1151 seq = NULL; 1152 completed = 0; 1153 1154 dst_iovs[0].iov_base = tmp[1]; 1155 dst_iovs[0].iov_len = compressed_size; 1156 src_iovs[0].iov_base = tmp[0]; 1157 src_iovs[0].iov_len = compressed_size; 1158 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1159 &src_iovs[0], 1, NULL, NULL, 0, 1160 ut_sequence_step_cb, &completed); 1161 CU_ASSERT_EQUAL(rc, 0); 1162 1163 dst_iovs[1].iov_base = buf; 1164 dst_iovs[1].iov_len = sizeof(buf); 1165 src_iovs[1].iov_base = tmp[1]; 1166 src_iovs[1].iov_len = compressed_size; 1167 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1168 &src_iovs[1], 1, NULL, NULL, 0, 1169 ut_sequence_step_cb, &completed); 1170 CU_ASSERT_EQUAL(rc, 0); 1171 1172 rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xfe, 0, 1173 ut_sequence_step_cb, &completed); 1174 CU_ASSERT_EQUAL(rc, 0); 1175 1176 ut_seq.complete = false; 1177 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1178 CU_ASSERT_EQUAL(rc, 0); 1179 1180 poll_threads(); 1181 1182 CU_ASSERT_EQUAL(completed, 3); 1183 CU_ASSERT(ut_seq.complete); 1184 CU_ASSERT_EQUAL(ut_seq.status, 0); 1185 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1186 1187 /* Check sequence with decompress at the beginning: decompress -> copy */ 1188 memset(expected, 0xa5, sizeof(expected)); 1189 memset(buf, 0, sizeof(buf)); 1190 seq = NULL; 1191 completed = 0; 1192 1193 dst_iovs[0].iov_base = tmp[1]; 1194 dst_iovs[0].iov_len = sizeof(tmp[1]); 1195 src_iovs[0].iov_base = tmp[0]; 1196 src_iovs[0].iov_len = compressed_size; 1197 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1198 &src_iovs[0], 1, NULL, NULL, 0, 1199 ut_sequence_step_cb, &completed); 1200 CU_ASSERT_EQUAL(rc, 0); 1201 1202 dst_iovs[1].iov_base = buf; 1203 dst_iovs[1].iov_len = sizeof(buf); 1204 src_iovs[1].iov_base = tmp[1]; 1205 src_iovs[1].iov_len = sizeof(tmp[1]); 1206 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1207 &src_iovs[1], 1, NULL, NULL, 0, 1208 ut_sequence_step_cb, &completed); 1209 CU_ASSERT_EQUAL(rc, 0); 1210 1211 ut_seq.complete = false; 1212 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1213 CU_ASSERT_EQUAL(rc, 0); 1214 1215 poll_threads(); 1216 1217 CU_ASSERT_EQUAL(completed, 2); 1218 CU_ASSERT(ut_seq.complete); 1219 CU_ASSERT_EQUAL(ut_seq.status, 0); 1220 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1221 1222 spdk_put_io_channel(ioch); 1223 poll_threads(); 1224 } 1225 1226 static void 1227 test_sequence_reverse(void) 1228 { 1229 struct spdk_accel_sequence *seq = NULL; 1230 struct spdk_io_channel *ioch; 1231 struct ut_sequence ut_seq; 1232 char buf[4096], tmp[2][4096], expected[4096]; 1233 struct iovec src_iovs[2], dst_iovs[2]; 1234 uint32_t compressed_size; 1235 int rc, completed = 0; 1236 1237 ioch = spdk_accel_get_io_channel(); 1238 SPDK_CU_ASSERT_FATAL(ioch != NULL); 1239 1240 memset(expected, 0xa5, sizeof(expected)); 1241 src_iovs[0].iov_base = expected; 1242 src_iovs[0].iov_len = sizeof(expected); 1243 rc = spdk_accel_submit_compress(ioch, tmp[0], sizeof(tmp[0]), &src_iovs[0], 1, 1244 &compressed_size, 0, ut_compress_cb, &completed); 1245 CU_ASSERT_EQUAL(rc, 0); 1246 1247 while (!completed) { 1248 poll_threads(); 1249 } 1250 1251 /* First check that reversing a sequnce with a single operation is a no-op */ 1252 memset(buf, 0, sizeof(buf)); 1253 seq = NULL; 1254 completed = 0; 1255 1256 dst_iovs[0].iov_base = buf; 1257 dst_iovs[0].iov_len = sizeof(buf); 1258 src_iovs[0].iov_base = tmp[0]; 1259 src_iovs[0].iov_len = compressed_size; 1260 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1261 &src_iovs[0], 1, NULL, NULL, 0, 1262 ut_sequence_step_cb, &completed); 1263 CU_ASSERT_EQUAL(rc, 0); 1264 1265 spdk_accel_sequence_reverse(seq); 1266 1267 ut_seq.complete = false; 1268 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1269 CU_ASSERT_EQUAL(rc, 0); 1270 1271 poll_threads(); 1272 1273 CU_ASSERT_EQUAL(completed, 1); 1274 CU_ASSERT(ut_seq.complete); 1275 CU_ASSERT_EQUAL(ut_seq.status, 0); 1276 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1277 1278 /* Add a copy operation at the end with src set to the compressed data. After reverse(), 1279 * that copy operation should be first, so decompress() should receive compressed data in 1280 * its src buffer. 1281 */ 1282 memset(buf, 0, sizeof(buf)); 1283 memset(tmp[1], 0, sizeof(tmp[1])); 1284 seq = NULL; 1285 completed = 0; 1286 1287 dst_iovs[0].iov_base = buf; 1288 dst_iovs[0].iov_len = sizeof(buf); 1289 src_iovs[0].iov_base = tmp[1]; 1290 src_iovs[0].iov_len = compressed_size; 1291 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1292 &src_iovs[0], 1, NULL, NULL, 0, 1293 ut_sequence_step_cb, &completed); 1294 CU_ASSERT_EQUAL(rc, 0); 1295 1296 dst_iovs[1].iov_base = tmp[1]; 1297 dst_iovs[1].iov_len = compressed_size; 1298 src_iovs[1].iov_base = tmp[0]; 1299 src_iovs[1].iov_len = compressed_size; 1300 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1301 &src_iovs[1], 1, NULL, NULL, 0, 1302 ut_sequence_step_cb, &completed); 1303 CU_ASSERT_EQUAL(rc, 0); 1304 1305 spdk_accel_sequence_reverse(seq); 1306 1307 ut_seq.complete = false; 1308 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1309 CU_ASSERT_EQUAL(rc, 0); 1310 1311 poll_threads(); 1312 1313 CU_ASSERT_EQUAL(completed, 2); 1314 CU_ASSERT(ut_seq.complete); 1315 CU_ASSERT_EQUAL(ut_seq.status, 0); 1316 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1317 1318 /* Check the same, but add an extra fill operation at the beginning that should execute last 1319 * after reverse(). 1320 */ 1321 memset(buf, 0, sizeof(buf)); 1322 memset(tmp[1], 0, sizeof(tmp[1])); 1323 memset(expected, 0xfe, 2048); 1324 seq = NULL; 1325 completed = 0; 1326 1327 rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xfe, 0, 1328 ut_sequence_step_cb, &completed); 1329 CU_ASSERT_EQUAL(rc, 0); 1330 1331 dst_iovs[0].iov_base = buf; 1332 dst_iovs[0].iov_len = sizeof(buf); 1333 src_iovs[0].iov_base = tmp[1]; 1334 src_iovs[0].iov_len = compressed_size; 1335 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1336 &src_iovs[0], 1, NULL, NULL, 0, 1337 ut_sequence_step_cb, &completed); 1338 CU_ASSERT_EQUAL(rc, 0); 1339 1340 dst_iovs[1].iov_base = tmp[1]; 1341 dst_iovs[1].iov_len = compressed_size; 1342 src_iovs[1].iov_base = tmp[0]; 1343 src_iovs[1].iov_len = compressed_size; 1344 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1345 &src_iovs[1], 1, NULL, NULL, 0, 1346 ut_sequence_step_cb, &completed); 1347 CU_ASSERT_EQUAL(rc, 0); 1348 1349 spdk_accel_sequence_reverse(seq); 1350 1351 ut_seq.complete = false; 1352 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1353 CU_ASSERT_EQUAL(rc, 0); 1354 1355 poll_threads(); 1356 1357 CU_ASSERT_EQUAL(completed, 3); 1358 CU_ASSERT(ut_seq.complete); 1359 CU_ASSERT_EQUAL(ut_seq.status, 0); 1360 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1361 1362 /* Build the sequence in order and then reverse it twice */ 1363 memset(buf, 0, sizeof(buf)); 1364 memset(tmp[1], 0, sizeof(tmp[1])); 1365 seq = NULL; 1366 completed = 0; 1367 1368 dst_iovs[0].iov_base = tmp[1]; 1369 dst_iovs[0].iov_len = compressed_size; 1370 src_iovs[0].iov_base = tmp[0]; 1371 src_iovs[0].iov_len = compressed_size; 1372 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1373 &src_iovs[0], 1, NULL, NULL, 0, 1374 ut_sequence_step_cb, &completed); 1375 CU_ASSERT_EQUAL(rc, 0); 1376 1377 dst_iovs[1].iov_base = buf; 1378 dst_iovs[1].iov_len = sizeof(buf); 1379 src_iovs[1].iov_base = tmp[1]; 1380 src_iovs[1].iov_len = compressed_size; 1381 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1382 &src_iovs[1], 1, NULL, NULL, 0, 1383 ut_sequence_step_cb, &completed); 1384 CU_ASSERT_EQUAL(rc, 0); 1385 1386 rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xfe, 0, 1387 ut_sequence_step_cb, &completed); 1388 CU_ASSERT_EQUAL(rc, 0); 1389 1390 spdk_accel_sequence_reverse(seq); 1391 spdk_accel_sequence_reverse(seq); 1392 1393 ut_seq.complete = false; 1394 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1395 CU_ASSERT_EQUAL(rc, 0); 1396 1397 poll_threads(); 1398 1399 CU_ASSERT_EQUAL(completed, 3); 1400 CU_ASSERT(ut_seq.complete); 1401 CU_ASSERT_EQUAL(ut_seq.status, 0); 1402 CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0); 1403 1404 spdk_put_io_channel(ioch); 1405 poll_threads(); 1406 } 1407 #endif 1408 1409 static void 1410 test_sequence_copy_elision(void) 1411 { 1412 struct spdk_accel_sequence *seq = NULL; 1413 struct spdk_io_channel *ioch; 1414 struct ut_sequence ut_seq; 1415 struct iovec src_iovs[4], dst_iovs[4], exp_iovs[2]; 1416 char buf[4096], tmp[4][4096]; 1417 struct spdk_accel_module_if *modules[ACCEL_OPC_LAST]; 1418 int i, rc, completed; 1419 1420 ioch = spdk_accel_get_io_channel(); 1421 SPDK_CU_ASSERT_FATAL(ioch != NULL); 1422 1423 /* Override the submit_tasks function */ 1424 g_module.submit_tasks = ut_sequnce_submit_tasks; 1425 for (i = 0; i < ACCEL_OPC_LAST; ++i) { 1426 g_seq_operations[i].complete_status = 0; 1427 g_seq_operations[i].submit_status = 0; 1428 g_seq_operations[i].count = 0; 1429 1430 modules[i] = g_modules_opc[i]; 1431 g_modules_opc[i] = &g_module; 1432 } 1433 1434 /* Check that a copy operation at the beginning is removed */ 1435 seq = NULL; 1436 completed = 0; 1437 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovcnt = 1; 1438 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovcnt = 1; 1439 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = &exp_iovs[0]; 1440 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = &exp_iovs[1]; 1441 exp_iovs[0].iov_base = tmp[0]; 1442 exp_iovs[0].iov_len = sizeof(tmp[0]); 1443 exp_iovs[1].iov_base = buf; 1444 exp_iovs[1].iov_len = 2048; 1445 1446 dst_iovs[0].iov_base = tmp[1]; 1447 dst_iovs[0].iov_len = sizeof(tmp[1]); 1448 src_iovs[0].iov_base = tmp[0]; 1449 src_iovs[0].iov_len = sizeof(tmp[0]); 1450 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1451 &src_iovs[0], 1, NULL, NULL, 0, 1452 ut_sequence_step_cb, &completed); 1453 CU_ASSERT_EQUAL(rc, 0); 1454 1455 dst_iovs[1].iov_base = buf; 1456 dst_iovs[1].iov_len = 2048; 1457 src_iovs[1].iov_base = tmp[1]; 1458 src_iovs[1].iov_len = sizeof(tmp[1]); 1459 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1460 &src_iovs[1], 1, NULL, NULL, 0, 1461 ut_sequence_step_cb, &completed); 1462 CU_ASSERT_EQUAL(rc, 0); 1463 1464 ut_seq.complete = false; 1465 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1466 CU_ASSERT_EQUAL(rc, 0); 1467 1468 poll_threads(); 1469 1470 CU_ASSERT_EQUAL(completed, 2); 1471 CU_ASSERT(ut_seq.complete); 1472 CU_ASSERT_EQUAL(ut_seq.status, 0); 1473 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); 1474 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_DECOMPRESS].count, 1); 1475 1476 /* Check that a copy operation at the end is removed too */ 1477 seq = NULL; 1478 completed = 0; 1479 g_seq_operations[ACCEL_OPC_COPY].count = 0; 1480 g_seq_operations[ACCEL_OPC_DECOMPRESS].count = 0; 1481 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = &exp_iovs[0]; 1482 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = &exp_iovs[1]; 1483 exp_iovs[0].iov_base = tmp[0]; 1484 exp_iovs[0].iov_len = sizeof(tmp[0]); 1485 exp_iovs[1].iov_base = buf; 1486 exp_iovs[1].iov_len = 2048; 1487 1488 dst_iovs[0].iov_base = tmp[1]; 1489 dst_iovs[0].iov_len = 2048; 1490 src_iovs[0].iov_base = tmp[0]; 1491 src_iovs[0].iov_len = sizeof(tmp[0]); 1492 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1493 &src_iovs[0], 1, NULL, NULL, 0, 1494 ut_sequence_step_cb, &completed); 1495 CU_ASSERT_EQUAL(rc, 0); 1496 1497 dst_iovs[1].iov_base = buf; 1498 dst_iovs[1].iov_len = 2048; 1499 src_iovs[1].iov_base = tmp[1]; 1500 src_iovs[1].iov_len = 2048; 1501 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1502 &src_iovs[1], 1, NULL, NULL, 0, 1503 ut_sequence_step_cb, &completed); 1504 CU_ASSERT_EQUAL(rc, 0); 1505 1506 ut_seq.complete = false; 1507 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1508 CU_ASSERT_EQUAL(rc, 0); 1509 1510 poll_threads(); 1511 1512 CU_ASSERT_EQUAL(completed, 2); 1513 CU_ASSERT(ut_seq.complete); 1514 CU_ASSERT_EQUAL(ut_seq.status, 0); 1515 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); 1516 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_DECOMPRESS].count, 1); 1517 1518 /* Check a copy operation both at the beginning and the end */ 1519 seq = NULL; 1520 completed = 0; 1521 g_seq_operations[ACCEL_OPC_COPY].count = 0; 1522 g_seq_operations[ACCEL_OPC_DECOMPRESS].count = 0; 1523 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = &exp_iovs[0]; 1524 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = &exp_iovs[1]; 1525 exp_iovs[0].iov_base = tmp[0]; 1526 exp_iovs[0].iov_len = sizeof(tmp[0]); 1527 exp_iovs[1].iov_base = buf; 1528 exp_iovs[1].iov_len = 2048; 1529 1530 dst_iovs[0].iov_base = tmp[1]; 1531 dst_iovs[0].iov_len = sizeof(tmp[1]); 1532 src_iovs[0].iov_base = tmp[0]; 1533 src_iovs[0].iov_len = sizeof(tmp[0]); 1534 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1535 &src_iovs[0], 1, NULL, NULL, 0, 1536 ut_sequence_step_cb, &completed); 1537 CU_ASSERT_EQUAL(rc, 0); 1538 1539 dst_iovs[1].iov_base = tmp[2]; 1540 dst_iovs[1].iov_len = 2048; 1541 src_iovs[1].iov_base = tmp[1]; 1542 src_iovs[1].iov_len = sizeof(tmp[1]); 1543 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1544 &src_iovs[1], 1, NULL, NULL, 0, 1545 ut_sequence_step_cb, &completed); 1546 CU_ASSERT_EQUAL(rc, 0); 1547 1548 dst_iovs[2].iov_base = buf; 1549 dst_iovs[2].iov_len = 2048; 1550 src_iovs[2].iov_base = tmp[2]; 1551 src_iovs[2].iov_len = 2048; 1552 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, 1553 &src_iovs[2], 1, NULL, NULL, 0, 1554 ut_sequence_step_cb, &completed); 1555 CU_ASSERT_EQUAL(rc, 0); 1556 1557 ut_seq.complete = false; 1558 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1559 CU_ASSERT_EQUAL(rc, 0); 1560 1561 poll_threads(); 1562 1563 CU_ASSERT_EQUAL(completed, 3); 1564 CU_ASSERT(ut_seq.complete); 1565 CU_ASSERT_EQUAL(ut_seq.status, 0); 1566 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); 1567 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_DECOMPRESS].count, 1); 1568 1569 /* Check decompress + copy + decompress + copy */ 1570 seq = NULL; 1571 completed = 0; 1572 g_seq_operations[ACCEL_OPC_COPY].count = 0; 1573 g_seq_operations[ACCEL_OPC_DECOMPRESS].count = 0; 1574 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = NULL; 1575 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = NULL; 1576 1577 dst_iovs[0].iov_base = tmp[1]; 1578 dst_iovs[0].iov_len = sizeof(tmp[1]); 1579 src_iovs[0].iov_base = tmp[0]; 1580 src_iovs[0].iov_len = sizeof(tmp[0]); 1581 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1582 &src_iovs[0], 1, NULL, NULL, 0, 1583 ut_sequence_step_cb, &completed); 1584 CU_ASSERT_EQUAL(rc, 0); 1585 1586 dst_iovs[1].iov_base = tmp[2]; 1587 dst_iovs[1].iov_len = 2048; 1588 src_iovs[1].iov_base = tmp[1]; 1589 src_iovs[1].iov_len = sizeof(tmp[1]); 1590 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1591 &src_iovs[1], 1, NULL, NULL, 0, 1592 ut_sequence_step_cb, &completed); 1593 CU_ASSERT_EQUAL(rc, 0); 1594 1595 dst_iovs[2].iov_base = tmp[3]; 1596 dst_iovs[2].iov_len = 1024; 1597 src_iovs[2].iov_base = tmp[2]; 1598 src_iovs[2].iov_len = 2048; 1599 rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, 1600 &src_iovs[2], 1, NULL, NULL, 0, 1601 ut_sequence_step_cb, &completed); 1602 CU_ASSERT_EQUAL(rc, 0); 1603 1604 dst_iovs[3].iov_base = buf; 1605 dst_iovs[3].iov_len = 1024; 1606 src_iovs[3].iov_base = tmp[3]; 1607 src_iovs[3].iov_len = 1024; 1608 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[3], 1, NULL, NULL, 1609 &src_iovs[3], 1, NULL, NULL, 0, 1610 ut_sequence_step_cb, &completed); 1611 CU_ASSERT_EQUAL(rc, 0); 1612 1613 ut_seq.complete = false; 1614 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1615 CU_ASSERT_EQUAL(rc, 0); 1616 1617 poll_threads(); 1618 1619 CU_ASSERT_EQUAL(completed, 4); 1620 CU_ASSERT(ut_seq.complete); 1621 CU_ASSERT_EQUAL(ut_seq.status, 0); 1622 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); 1623 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_DECOMPRESS].count, 2); 1624 1625 /* Check two copy operations - one of them should be removed, while the other should be 1626 * executed normally */ 1627 seq = NULL; 1628 completed = 0; 1629 g_seq_operations[ACCEL_OPC_COPY].count = 0; 1630 1631 dst_iovs[0].iov_base = tmp[1]; 1632 dst_iovs[0].iov_len = sizeof(tmp[1]); 1633 src_iovs[0].iov_base = tmp[0]; 1634 src_iovs[0].iov_len = sizeof(tmp[0]); 1635 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, 1636 &src_iovs[0], 1, NULL, NULL, 0, 1637 ut_sequence_step_cb, &completed); 1638 CU_ASSERT_EQUAL(rc, 0); 1639 1640 dst_iovs[1].iov_base = buf; 1641 dst_iovs[1].iov_len = sizeof(buf); 1642 src_iovs[1].iov_base = tmp[1]; 1643 src_iovs[1].iov_len = sizeof(tmp[1]); 1644 rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL, 1645 &src_iovs[1], 1, NULL, NULL, 0, 1646 ut_sequence_step_cb, &completed); 1647 CU_ASSERT_EQUAL(rc, 0); 1648 1649 ut_seq.complete = false; 1650 rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); 1651 CU_ASSERT_EQUAL(rc, 0); 1652 1653 poll_threads(); 1654 1655 CU_ASSERT_EQUAL(completed, 2); 1656 CU_ASSERT(ut_seq.complete); 1657 CU_ASSERT_EQUAL(ut_seq.status, 0); 1658 CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 1); 1659 1660 /* Cleanup module pointers to make subsequent tests work correctly */ 1661 for (i = 0; i < ACCEL_OPC_LAST; ++i) { 1662 g_modules_opc[i] = modules[i]; 1663 } 1664 1665 g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = NULL; 1666 g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = NULL; 1667 1668 spdk_put_io_channel(ioch); 1669 poll_threads(); 1670 } 1671 1672 static int 1673 test_sequence_setup(void) 1674 { 1675 int rc; 1676 1677 allocate_cores(1); 1678 allocate_threads(1); 1679 set_thread(0); 1680 1681 rc = spdk_iobuf_initialize(); 1682 if (rc != 0) { 1683 CU_ASSERT(false); 1684 return -1; 1685 } 1686 1687 rc = spdk_accel_initialize(); 1688 if (rc != 0) { 1689 CU_ASSERT(false); 1690 return -1; 1691 } 1692 1693 return 0; 1694 } 1695 1696 static void 1697 finish_cb(void *cb_arg) 1698 { 1699 bool *done = cb_arg; 1700 1701 *done = true; 1702 } 1703 1704 static int 1705 test_sequence_cleanup(void) 1706 { 1707 bool done = false; 1708 1709 spdk_accel_finish(finish_cb, &done); 1710 1711 while (!done) { 1712 poll_threads(); 1713 } 1714 1715 done = false; 1716 spdk_iobuf_finish(finish_cb, &done); 1717 while (!done) { 1718 poll_threads(); 1719 } 1720 1721 free_threads(); 1722 free_cores(); 1723 1724 return 0; 1725 } 1726 1727 int 1728 main(int argc, char **argv) 1729 { 1730 CU_pSuite suite = NULL, seq_suite; 1731 unsigned int num_failures; 1732 1733 CU_set_error_action(CUEA_ABORT); 1734 CU_initialize_registry(); 1735 1736 /* Sequence tests require accel to be initialized normally, so run them before the other 1737 * tests which register accel modules which aren't fully implemented, causing accel 1738 * initialization to fail. 1739 */ 1740 seq_suite = CU_add_suite("accel_sequence", test_sequence_setup, test_sequence_cleanup); 1741 CU_ADD_TEST(seq_suite, test_sequence_fill_copy); 1742 CU_ADD_TEST(seq_suite, test_sequence_abort); 1743 CU_ADD_TEST(seq_suite, test_sequence_append_error); 1744 CU_ADD_TEST(seq_suite, test_sequence_completion_error); 1745 #ifdef SPDK_CONFIG_ISAL /* accel_sw requires isa-l for compression */ 1746 CU_ADD_TEST(seq_suite, test_sequence_decompress); 1747 CU_ADD_TEST(seq_suite, test_sequence_reverse); 1748 #endif 1749 CU_ADD_TEST(seq_suite, test_sequence_copy_elision); 1750 1751 suite = CU_add_suite("accel", test_setup, test_cleanup); 1752 CU_ADD_TEST(suite, test_spdk_accel_task_complete); 1753 CU_ADD_TEST(suite, test_get_task); 1754 CU_ADD_TEST(suite, test_spdk_accel_submit_copy); 1755 CU_ADD_TEST(suite, test_spdk_accel_submit_dualcast); 1756 CU_ADD_TEST(suite, test_spdk_accel_submit_compare); 1757 CU_ADD_TEST(suite, test_spdk_accel_submit_fill); 1758 CU_ADD_TEST(suite, test_spdk_accel_submit_crc32c); 1759 CU_ADD_TEST(suite, test_spdk_accel_submit_crc32cv); 1760 CU_ADD_TEST(suite, test_spdk_accel_submit_copy_crc32c); 1761 CU_ADD_TEST(suite, test_spdk_accel_module_find_by_name); 1762 CU_ADD_TEST(suite, test_spdk_accel_module_register); 1763 1764 CU_basic_set_mode(CU_BRM_VERBOSE); 1765 CU_basic_run_tests(); 1766 num_failures = CU_get_number_of_failures(); 1767 CU_cleanup_registry(); 1768 1769 return num_failures; 1770 } 1771