1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "accel_internal.h" 7 8 #include "spdk/rpc.h" 9 #include "spdk/util.h" 10 #include "spdk/event.h" 11 #include "spdk/stdinc.h" 12 #include "spdk/env.h" 13 14 const char *g_opcode_strings[ACCEL_OPC_LAST] = { 15 "copy", "fill", "dualcast", "compare", "crc32c", "copy_crc32c", 16 "compress", "decompress" 17 }; 18 19 static int 20 _get_opc_name(enum accel_opcode opcode, const char **opcode_name) 21 { 22 int rc = 0; 23 24 if (opcode < ACCEL_OPC_LAST) { 25 *opcode_name = g_opcode_strings[opcode]; 26 } else { 27 /* invalid opcode */ 28 rc = -EINVAL; 29 } 30 31 return rc; 32 } 33 34 static void 35 rpc_accel_get_opc_assignments(struct spdk_jsonrpc_request *request, 36 const struct spdk_json_val *params) 37 { 38 struct spdk_json_write_ctx *w; 39 enum accel_opcode opcode; 40 const char *name, *engine_name; 41 int rc; 42 43 if (params != NULL) { 44 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 45 "accel_get_opc_assignments requires no parameters"); 46 return; 47 } 48 49 w = spdk_jsonrpc_begin_result(request); 50 51 spdk_json_write_object_begin(w); 52 for (opcode = 0; opcode < ACCEL_OPC_LAST; opcode++) { 53 rc = _get_opc_name(opcode, &name); 54 if (rc == 0) { 55 rc = spdk_accel_get_opc_engine_name(opcode, &engine_name); 56 if (rc != 0) { 57 /* This isn't fatal but throw an informational message if we 58 * cant get an engine name right now */ 59 SPDK_NOTICELOG("FYI error (%d) getting engine name.\n", rc); 60 } 61 spdk_json_write_named_string(w, name, engine_name); 62 } else { 63 /* this should never happen */ 64 SPDK_ERRLOG("Invalid opcode (%d)).\n", opcode); 65 assert(0); 66 } 67 } 68 spdk_json_write_object_end(w); 69 70 spdk_jsonrpc_end_result(request, w); 71 } 72 SPDK_RPC_REGISTER("accel_get_opc_assignments", rpc_accel_get_opc_assignments, 73 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 74 75 static void 76 rpc_dump_engine_info(struct engine_info *info) 77 { 78 struct spdk_json_write_ctx *w = info->w; 79 const char *name; 80 uint32_t i; 81 int rc; 82 83 spdk_json_write_object_begin(w); 84 85 spdk_json_write_named_string(w, "engine", info->name); 86 spdk_json_write_named_array_begin(w, "suppoerted ops"); 87 88 for (i = 0; i < info->num_ops; i++) { 89 rc = _get_opc_name(i, &name); 90 if (rc == 0) { 91 spdk_json_write_string(w, name); 92 } else { 93 /* this should never happen */ 94 SPDK_ERRLOG("Invalid opcode (%d)).\n", i); 95 assert(0); 96 } 97 } 98 99 spdk_json_write_array_end(w); 100 spdk_json_write_object_end(w); 101 } 102 103 static void 104 rpc_accel_get_engine_info(struct spdk_jsonrpc_request *request, 105 const struct spdk_json_val *params) 106 { 107 struct engine_info info; 108 109 if (params != NULL) { 110 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 111 "accel_get_engine_info requires no parameters"); 112 return; 113 } 114 115 info.w = spdk_jsonrpc_begin_result(request); 116 spdk_json_write_array_begin(info.w); 117 118 _accel_for_each_engine(&info, rpc_dump_engine_info); 119 120 spdk_json_write_array_end(info.w); 121 spdk_jsonrpc_end_result(request, info.w); 122 } 123 SPDK_RPC_REGISTER("accel_get_engine_info", rpc_accel_get_engine_info, 124 SPDK_RPC_RUNTIME) 125 126 struct rpc_accel_assign_opc { 127 char *opname; 128 char *engine; 129 }; 130 131 static const struct spdk_json_object_decoder rpc_accel_assign_opc_decoders[] = { 132 {"opname", offsetof(struct rpc_accel_assign_opc, opname), spdk_json_decode_string}, 133 {"engine", offsetof(struct rpc_accel_assign_opc, engine), spdk_json_decode_string}, 134 }; 135 136 static void 137 free_accel_assign_opc(struct rpc_accel_assign_opc *r) 138 { 139 free(r->opname); 140 free(r->engine); 141 } 142 143 static void 144 rpc_accel_assign_opc(struct spdk_jsonrpc_request *request, 145 const struct spdk_json_val *params) 146 { 147 struct rpc_accel_assign_opc req = {}; 148 enum accel_opcode opcode; 149 bool found = false; 150 int rc; 151 152 if (spdk_json_decode_object(params, rpc_accel_assign_opc_decoders, 153 SPDK_COUNTOF(rpc_accel_assign_opc_decoders), 154 &req)) { 155 SPDK_DEBUGLOG(accel, "spdk_json_decode_object failed\n"); 156 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 157 "spdk_json_decode_object failed"); 158 goto cleanup; 159 } 160 161 for (opcode = 0; opcode < ACCEL_OPC_LAST; opcode++) { 162 if (strcmp(g_opcode_strings[opcode], req.opname) == 0) { 163 found = true; 164 break; 165 } 166 } 167 168 if (found == false) { 169 SPDK_DEBUGLOG(accel, "Invalid operation name\n"); 170 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 171 "spdk_json_decode_object failed"); 172 goto cleanup; 173 } 174 175 rc = spdk_accel_assign_opc(opcode, req.engine); 176 if (rc) { 177 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 178 "error assigning opcode"); 179 goto cleanup; 180 } 181 182 SPDK_NOTICELOG("Operation %s will be assigned to engine %s\n", req.opname, req.engine); 183 spdk_jsonrpc_send_bool_response(request, true); 184 185 cleanup: 186 free_accel_assign_opc(&req); 187 188 } 189 SPDK_RPC_REGISTER("accel_assign_opc", rpc_accel_assign_opc, SPDK_RPC_STARTUP) 190