1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2023 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/event.h" 7 #include "spdk/accel.h" 8 9 #define TEST_XFER_SIZE 4096 10 #define INITIAL_PATTERN_0 0 11 #define INITIAL_PATTERN_1 1 12 #define INITIAL_PATTERN_2 2 13 #define FILL_PATTERN_1 255 14 #define FILL_PATTERN_2 111 15 #define IOVCNT 1 16 17 struct test_ctx { 18 char *driver_name; 19 struct spdk_io_channel *ch; 20 char buf1[TEST_XFER_SIZE]; 21 char buf1_bck[TEST_XFER_SIZE]; 22 char buf2[TEST_XFER_SIZE]; 23 char buf2_bck[TEST_XFER_SIZE]; 24 struct iovec iov1, iov2, iov1_bck, iov2_bck; 25 }; 26 27 static void 28 test_seq_complete_cb(void *_ctx, int status) 29 { 30 struct test_ctx *ctx = _ctx; 31 char expected_buf1[TEST_XFER_SIZE], expected_buf2[TEST_XFER_SIZE]; 32 char expected_buf1_bck[TEST_XFER_SIZE], expected_buf2_bck[TEST_XFER_SIZE]; 33 34 printf("Running sequence callback\n"); 35 36 if (status != 0) { 37 SPDK_ERRLOG("Unexpected status code: %d", status); 38 goto out; 39 } 40 41 memset(expected_buf1, FILL_PATTERN_1, sizeof(expected_buf1)); 42 memset(expected_buf2, FILL_PATTERN_2, sizeof(expected_buf2)); 43 memset(expected_buf1_bck, 1, sizeof(expected_buf2)); 44 memset(expected_buf2_bck, 2, sizeof(expected_buf2)); 45 46 if (memcmp(ctx->buf1, expected_buf1, TEST_XFER_SIZE) != 0 || 47 memcmp(ctx->buf2, expected_buf2, TEST_XFER_SIZE) != 0 || 48 memcmp(ctx->buf1_bck, expected_buf1_bck, TEST_XFER_SIZE != 0) || 49 memcmp(ctx->buf2_bck, expected_buf2_bck, TEST_XFER_SIZE != 0)) { 50 SPDK_ERRLOG("Sequence failed: buffers mismatch\n"); 51 status = 1; 52 } 53 out: 54 spdk_put_io_channel(ctx->ch); 55 spdk_app_stop(status); 56 } 57 58 static void 59 start_driver(void *_ctx) 60 { 61 int rc = 0, completed = 0; 62 struct test_ctx *ctx = _ctx; 63 struct spdk_accel_sequence *seq = NULL; 64 65 ctx->ch = spdk_accel_get_io_channel(); 66 if (ctx->ch == NULL) { 67 SPDK_ERRLOG("Failed to get IO channel\n"); 68 spdk_app_stop(1); 69 return; 70 } 71 72 /* Prepare buffers */ 73 memset(ctx->buf1, INITIAL_PATTERN_1, TEST_XFER_SIZE); 74 memset(ctx->buf2, INITIAL_PATTERN_2, TEST_XFER_SIZE); 75 memset(ctx->buf1_bck, INITIAL_PATTERN_0, TEST_XFER_SIZE); 76 memset(ctx->buf2_bck, INITIAL_PATTERN_0, TEST_XFER_SIZE); 77 78 ctx->iov1.iov_base = ctx->buf1; 79 ctx->iov1.iov_len = TEST_XFER_SIZE; 80 81 ctx->iov2.iov_base = ctx->buf2; 82 ctx->iov2.iov_len = TEST_XFER_SIZE; 83 84 ctx->iov1_bck.iov_base = ctx->buf1_bck; 85 ctx->iov1_bck.iov_len = TEST_XFER_SIZE; 86 87 ctx->iov2_bck.iov_base = ctx->buf2_bck; 88 ctx->iov2_bck.iov_len = TEST_XFER_SIZE; 89 90 /* Test driver implementation. Test scenario is: 91 * copy buf1 -> buf1_bck 92 * fill buf1 <- FILL_PATTERN_1 93 * copy buf2 -> buf2_bck 94 * fill buf2 <- FILL_PATTERN_2 95 */ 96 rc = spdk_accel_append_copy(&seq, ctx->ch, &ctx->iov1_bck, IOVCNT, NULL, NULL, 97 &ctx->iov1, IOVCNT, NULL, NULL, 98 NULL, NULL); 99 if (rc) { 100 SPDK_ERRLOG("ERROR running append copy 1! exiting.\n"); 101 goto error; 102 } 103 rc = spdk_accel_append_fill(&seq, ctx->ch, &ctx->buf1, TEST_XFER_SIZE, 104 NULL, NULL, FILL_PATTERN_1, 105 NULL, NULL); 106 if (rc) { 107 SPDK_ERRLOG("ERROR running append fill 1! exiting.\n"); 108 goto error; 109 } 110 rc = spdk_accel_append_copy(&seq, ctx->ch, &ctx->iov2_bck, IOVCNT, NULL, NULL, 111 &ctx->iov2, IOVCNT, NULL, NULL, 112 NULL, NULL); 113 if (rc) { 114 SPDK_ERRLOG("ERROR running append copy 2! exiting.\n"); 115 goto error; 116 } 117 rc = spdk_accel_append_fill(&seq, ctx->ch, &ctx->buf2, TEST_XFER_SIZE, 118 NULL, NULL, FILL_PATTERN_2, 119 NULL, NULL); 120 if (rc) { 121 SPDK_ERRLOG("ERROR running append fill 2! exiting.\n"); 122 goto error; 123 } 124 spdk_accel_sequence_finish(seq, test_seq_complete_cb, ctx); 125 return; 126 error: 127 spdk_accel_sequence_abort(seq); 128 spdk_put_io_channel(ctx->ch); 129 spdk_app_stop(rc); 130 } 131 132 int 133 main(int argc, char **argv) 134 { 135 int rc; 136 struct spdk_app_opts opts = {}; 137 struct test_ctx ctx = {}; 138 139 spdk_app_opts_init(&opts, sizeof(opts)); 140 opts.name = "accel_external_driver"; 141 opts.rpc_addr = NULL; 142 143 /* 144 * Parse built-in SPDK command line parameters as well 145 * as our custom one(s). 146 */ 147 if ((rc = spdk_app_parse_args(argc, argv, &opts, NULL, NULL, NULL, 148 NULL)) != SPDK_APP_PARSE_ARGS_SUCCESS) { 149 exit(rc); 150 } 151 152 rc = spdk_app_start(&opts, start_driver, &ctx); 153 154 /* Gracefully close out all of the SPDK subsystems. */ 155 spdk_app_fini(); 156 return rc; 157 } 158