lib/accel: add RPC to enable override of opcode to engine

Docs explaining how to use the RPC are in the next patch in the
series.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: I7dab8fdbeb90cdfde8b3e916ed6d19930ad36e66
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12848
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
paul luse 2022-05-31 17:13:04 -07:00 committed by Tomasz Zawadzki
parent ab356d4079
commit efa33b8590
8 changed files with 190 additions and 1 deletions

View File

@ -39,6 +39,9 @@ writes (read-modify-write) are not.
Added a new runtime RPC `accel_get_opc_assignments` to get a list of current opcode to engine Added a new runtime RPC `accel_get_opc_assignments` to get a list of current opcode to engine
assignements. assignements.
Added a new startup RPC `accel_assign_opc` to assign/override a specific opcode to
an engine.
## v22.05 ## v22.05
### sock ### sock

View File

@ -1587,6 +1587,43 @@ Example response:
} }
~~~ ~~~
### accel_assign_opc {#rpc_accel_assign_opc}
Manually assign an operation to an engine.
#### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------------
opname | Required | string | name of operation
engine | Required | string | name of engine
#### Example
Example request:
~~~json
{
"jsonrpc": "2.0",
"method": "accel_assign_opc",
"id": 1,
"params": {
"opanme": "copy",
"engine": "software"
}
}
~~~
Example response:
~~~json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
~~~
### dsa_scan_accel_engine {#rpc_dsa_scan_accel_engine} ### dsa_scan_accel_engine {#rpc_dsa_scan_accel_engine}
Set config and enable dsa accel engine offload. Set config and enable dsa accel engine offload.

View File

@ -275,6 +275,19 @@ int spdk_accel_submit_decompress(struct spdk_io_channel *ch, void *dst, void *sr
*/ */
int spdk_accel_get_opc_engine_name(enum accel_opcode opcode, const char **engine_name); int spdk_accel_get_opc_engine_name(enum accel_opcode opcode, const char **engine_name);
/**
* Override the assignment of an opcode to an engine.
*
* \param opcode Accel Framework Opcode enum value. Valid codes can be retrieved using
* `accel_get_opc_assignments` or `spdk_accel_get_opc_name`.
* \param name Name of the engine to assign. Valid engine names may be retrieved
* with `spdk_accel_get_opc_engine_name`
*
* \return 0 if a valid opcode name was provided. -EINVAL for invalid opcode
* or if the framework has started (cannot change engines after startup)
*/
int spdk_accel_assign_opc(enum accel_opcode opcode, const char *name);
struct spdk_json_write_ctx; struct spdk_json_write_ctx;
/** /**

View File

@ -35,6 +35,7 @@ static size_t g_max_accel_module_size = 0;
static struct spdk_accel_module_if *g_accel_engine_module = NULL; static struct spdk_accel_module_if *g_accel_engine_module = NULL;
static spdk_accel_fini_cb g_fini_cb_fn = NULL; static spdk_accel_fini_cb g_fini_cb_fn = NULL;
static void *g_fini_cb_arg = NULL; static void *g_fini_cb_arg = NULL;
static bool g_engine_started = false;
/* Global list of registered accelerator modules */ /* Global list of registered accelerator modules */
static TAILQ_HEAD(, spdk_accel_module_if) spdk_accel_module_list = static TAILQ_HEAD(, spdk_accel_module_if) spdk_accel_module_list =
@ -46,6 +47,7 @@ static TAILQ_HEAD(, spdk_accel_engine) g_engine_list =
/* Global array mapping capabilities to engines */ /* Global array mapping capabilities to engines */
static struct spdk_accel_engine *g_engines_opc[ACCEL_OPC_LAST] = {}; static struct spdk_accel_engine *g_engines_opc[ACCEL_OPC_LAST] = {};
static char *g_engines_opc_override[ACCEL_OPC_LAST] = {};
static int sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *first_task); static int sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *first_task);
@ -87,6 +89,25 @@ _accel_for_each_engine(struct engine_info *info, _accel_for_each_engine_fn fn)
} }
} }
int
spdk_accel_assign_opc(enum accel_opcode opcode, const char *name)
{
if (g_engine_started == true) {
/* we don't allow re-assignment once things have started */
return -EINVAL;
}
if (opcode >= ACCEL_OPC_LAST) {
/* invalid opcode */
return -EINVAL;
}
/* engine selection will be validated after the framework starts. */
g_engines_opc_override[opcode] = strdup(name);
return 0;
}
static struct spdk_accel_engine * static struct spdk_accel_engine *
_engine_find_by_name(const char *name) _engine_find_by_name(const char *name)
{ {
@ -585,6 +606,7 @@ spdk_accel_engine_initialize(void)
enum accel_opcode op; enum accel_opcode op;
struct spdk_accel_engine *accel_engine = NULL; struct spdk_accel_engine *accel_engine = NULL;
g_engine_started = true;
accel_engine_module_initialize(); accel_engine_module_initialize();
/* Create our priority global map of opcodes to engines, we populate starting /* Create our priority global map of opcodes to engines, we populate starting
@ -601,6 +623,23 @@ spdk_accel_engine_initialize(void)
} }
} }
} }
/* Now lets check for overrides and apply all that exist */
for (op = 0; op < ACCEL_OPC_LAST; op++) {
if (g_engines_opc_override[op] != NULL) {
accel_engine = _engine_find_by_name(g_engines_opc_override[op]);
if (accel_engine == NULL) {
SPDK_ERRLOG("Invalid engine name of %s\n", g_engines_opc_override[op]);
return -EINVAL;
}
if (accel_engine->supports_opcode(op) == false) {
SPDK_ERRLOG("Engine %s does not support op code %d\n", accel_engine->name, op);
return -EINVAL;
}
g_engines_opc[op] = accel_engine;
}
}
#ifdef DEBUG #ifdef DEBUG
for (op = 0; op < ACCEL_OPC_LAST; op++) { for (op = 0; op < ACCEL_OPC_LAST; op++) {
assert(g_engines_opc[op] != NULL); assert(g_engines_opc[op] != NULL);
@ -668,11 +707,19 @@ spdk_accel_engine_module_finish(void)
void void
spdk_accel_engine_finish(spdk_accel_fini_cb cb_fn, void *cb_arg) spdk_accel_engine_finish(spdk_accel_fini_cb cb_fn, void *cb_arg)
{ {
enum accel_opcode op;
assert(cb_fn != NULL); assert(cb_fn != NULL);
g_fini_cb_fn = cb_fn; g_fini_cb_fn = cb_fn;
g_fini_cb_arg = cb_arg; g_fini_cb_arg = cb_arg;
for (op = 0; op < ACCEL_OPC_LAST; op++) {
if (g_engines_opc_override[op] != NULL) {
free(g_engines_opc_override[op]);
}
}
spdk_io_device_unregister(&spdk_accel_module_list, NULL); spdk_io_device_unregister(&spdk_accel_module_list, NULL);
spdk_accel_engine_module_finish(); spdk_accel_engine_module_finish();
} }

View File

@ -122,3 +122,68 @@ rpc_accel_get_engine_info(struct spdk_jsonrpc_request *request,
} }
SPDK_RPC_REGISTER("accel_get_engine_info", rpc_accel_get_engine_info, SPDK_RPC_REGISTER("accel_get_engine_info", rpc_accel_get_engine_info,
SPDK_RPC_RUNTIME) SPDK_RPC_RUNTIME)
struct rpc_accel_assign_opc {
char *opname;
char *engine;
};
static const struct spdk_json_object_decoder rpc_accel_assign_opc_decoders[] = {
{"opname", offsetof(struct rpc_accel_assign_opc, opname), spdk_json_decode_string},
{"engine", offsetof(struct rpc_accel_assign_opc, engine), spdk_json_decode_string},
};
static void
free_accel_assign_opc(struct rpc_accel_assign_opc *r)
{
free(r->opname);
free(r->engine);
}
static void
rpc_accel_assign_opc(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_accel_assign_opc req = {};
enum accel_opcode opcode;
bool found = false;
int rc;
if (spdk_json_decode_object(params, rpc_accel_assign_opc_decoders,
SPDK_COUNTOF(rpc_accel_assign_opc_decoders),
&req)) {
SPDK_DEBUGLOG(accel, "spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
for (opcode = 0; opcode < ACCEL_OPC_LAST; opcode++) {
if (strcmp(g_opcode_strings[opcode], req.opname) == 0) {
found = true;
break;
}
}
if (found == false) {
SPDK_DEBUGLOG(accel, "Invalid operation name\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"spdk_json_decode_object failed");
goto cleanup;
}
rc = spdk_accel_assign_opc(opcode, req.engine);
if (rc) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"error assigning opcode");
goto cleanup;
}
SPDK_NOTICELOG("Operation %s will be assigned to engine %s\n", req.opname, req.engine);
spdk_jsonrpc_send_bool_response(request, true);
cleanup:
free_accel_assign_opc(&req);
}
SPDK_RPC_REGISTER("accel_assign_opc", rpc_accel_assign_opc, SPDK_RPC_STARTUP)

View File

@ -17,6 +17,7 @@
spdk_accel_submit_compress; spdk_accel_submit_compress;
spdk_accel_submit_decompress; spdk_accel_submit_decompress;
spdk_accel_get_opc_engine_name; spdk_accel_get_opc_engine_name;
spdk_accel_assign_opc;
spdk_accel_write_config_json; spdk_accel_write_config_json;
# functions needed by modules # functions needed by modules

View File

@ -7,4 +7,19 @@ def accel_get_opc_assignments(client):
def accel_get_engine_info(client): def accel_get_engine_info(client):
"""Get list of valid engine names and their operations. """Get list of valid engine names and their operations.
""" """
return client.call('accel_get_engine_info') return client.call('accel_get_engine_names')
def accel_assign_opc(client, opname, engine):
"""Manually assign an operation to an engine.
Args:
opname: name of operation
engine: name of engine
"""
params = {
'opname': opname,
'engine': engine,
}
return client.call('accel_assign_opc', params)

View File

@ -2575,6 +2575,14 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p = subparsers.add_parser('accel_get_engine_info', help='Get list of valid engine names and their operations.') p = subparsers.add_parser('accel_get_engine_info', help='Get list of valid engine names and their operations.')
p.set_defaults(func=accel_get_engine_info) p.set_defaults(func=accel_get_engine_info)
def accel_assign_opc(args):
rpc.accel.accel_assign_opc(args.client, opname=args.opname, engine=args.engine)
p = subparsers.add_parser('accel_assign_opc', help='Manually assign an operation to an engine.')
p.add_argument('-o', '--opname', help='opname')
p.add_argument('-e', '--engine', help='name of engine')
p.set_defaults(func=accel_assign_opc)
# ioat # ioat
def ioat_scan_accel_engine(args): def ioat_scan_accel_engine(args):
rpc.ioat.ioat_scan_accel_engine(args.client) rpc.ioat.ioat_scan_accel_engine(args.client)