accel: introduce platform drivers
The goal of a platform driver is to execute chained accel operations in the most efficient way possible. A driver is aware of the hardware available on a platform and can execute several operations as a single one. For instance, if we want to do DMA and then encrypt the data, the driver can do both at the same time, if the hardware is capable of doing that. Platform drivers aren't required to support all operations. If a given operation cannot be executed, the driver should notify accel to continue processing a sequence, via spdk_accel_sequence_continue(), and that operation will processed by a module assigned to its opcode. It is required however, that all platform drivers support memory domains, including the "virtual" accel domain. A method for allocating those buffers will be added in the following patches. This patch only adds methods to register and select platorm drivers, but doesn't change the way a sequnce is executed (i.e. it doesn't use the driver to execute it). Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: I97a0b07e264601ab3cf980735319fe8cea54d38e Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16375 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
11e67d93ff
commit
b2454dfbcc
@ -1904,6 +1904,42 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
### accel_set_driver {#rpc_accel_set_driver}
|
||||
|
||||
Select platform driver to execute operation chains. Until a driver is selected, all operations are
|
||||
executed through accel modules.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- |----------| ----------- | -----------------
|
||||
name | Required | string | Name of the platform driver
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "accel_set_driver",
|
||||
"id": 1
|
||||
"params": {
|
||||
"name": "xeon"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
### compressdev_scan_accel_module {#rpc_compressdev_scan_accel_module}
|
||||
|
||||
Set config and enable compressdev accel module offload.
|
||||
|
@ -611,6 +611,15 @@ struct spdk_json_write_ctx;
|
||||
*/
|
||||
void spdk_accel_write_config_json(struct spdk_json_write_ctx *w);
|
||||
|
||||
/**
|
||||
* Select platform driver to execute operation chains.
|
||||
*
|
||||
* \param name Name of the driver.
|
||||
*
|
||||
* \return 0 on success, negetive errno otherwise.
|
||||
*/
|
||||
int spdk_accel_set_driver(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -169,4 +169,45 @@ static void __attribute__((constructor)) _spdk_accel_module_register_##name(void
|
||||
*/
|
||||
void spdk_accel_module_finish(void);
|
||||
|
||||
/**
|
||||
* Platform driver responsible for executing tasks in a sequence. If no driver is selected, tasks
|
||||
* are submitted to accel modules. All drivers are required to be aware of memory domains.
|
||||
*/
|
||||
struct spdk_accel_driver {
|
||||
/** Name of the driver */
|
||||
const char *name;
|
||||
/**
|
||||
* Executes a sequence of accel operations. The driver should notify accel about each
|
||||
* completed task using `spdk_accel_task_complete()`. Once all tasks are completed or the
|
||||
* driver cannot proceed with a given task (e.g. because it doesn't handle specific opcode),
|
||||
* accel should be notified via `spdk_accel_sequence_continue()`. If there are tasks left
|
||||
* in a sequence, the first will be submitted to a module, while the rest will be sent back
|
||||
* to the driver. `spdk_accel_sequence_continue()` should only be called if this function
|
||||
* succeeds (i.e. returns 0).
|
||||
*
|
||||
* \param Sequence of tasks to execute.
|
||||
*
|
||||
* \return 0 on success, negative errno on failure.
|
||||
*/
|
||||
int (*execute_sequence)(struct spdk_accel_sequence *seq);
|
||||
|
||||
TAILQ_ENTRY(spdk_accel_driver) tailq;
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies accel that a driver has finished executing a sequence (or its part) and accel should
|
||||
* continue processing it.
|
||||
*
|
||||
* \param seq Sequence object.
|
||||
*/
|
||||
void spdk_accel_sequence_continue(struct spdk_accel_sequence *seq);
|
||||
|
||||
void spdk_accel_driver_register(struct spdk_accel_driver *driver);
|
||||
|
||||
#define SPDK_ACCEL_DRIVER_REGISTER(name, driver) \
|
||||
static void __attribute__((constructor)) _spdk_accel_driver_register_##name(void) \
|
||||
{ \
|
||||
spdk_accel_driver_register(driver); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -60,6 +60,8 @@ static struct spdk_spinlock g_keyring_spin;
|
||||
/* Global array mapping capabilities to modules */
|
||||
static struct accel_module g_modules_opc[ACCEL_OPC_LAST] = {};
|
||||
static char *g_modules_opc_override[ACCEL_OPC_LAST] = {};
|
||||
TAILQ_HEAD(, spdk_accel_driver) g_accel_drivers = TAILQ_HEAD_INITIALIZER(g_accel_drivers);
|
||||
static struct spdk_accel_driver *g_accel_driver;
|
||||
|
||||
static const char *g_opcode_strings[ACCEL_OPC_LAST] = {
|
||||
"copy", "fill", "dualcast", "compare", "crc32c", "copy_crc32c",
|
||||
@ -1548,6 +1550,12 @@ accel_sequence_task_cb(void *cb_arg, int status)
|
||||
accel_process_sequence(seq);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_accel_sequence_continue(struct spdk_accel_sequence *seq)
|
||||
{
|
||||
assert(0 && "unsupported");
|
||||
}
|
||||
|
||||
static bool
|
||||
accel_compare_iovs(struct iovec *iova, uint32_t iovacnt, struct iovec *iovb, uint32_t iovbcnt)
|
||||
{
|
||||
@ -2279,4 +2287,46 @@ spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg)
|
||||
spdk_accel_module_finish();
|
||||
}
|
||||
|
||||
static struct spdk_accel_driver *
|
||||
accel_find_driver(const char *name)
|
||||
{
|
||||
struct spdk_accel_driver *driver;
|
||||
|
||||
TAILQ_FOREACH(driver, &g_accel_drivers, tailq) {
|
||||
if (strcmp(driver->name, name) == 0) {
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_accel_set_driver(const char *name)
|
||||
{
|
||||
struct spdk_accel_driver *driver;
|
||||
|
||||
driver = accel_find_driver(name);
|
||||
if (driver == NULL) {
|
||||
SPDK_ERRLOG("Couldn't find driver named '%s'\n", name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
g_accel_driver = driver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_accel_driver_register(struct spdk_accel_driver *driver)
|
||||
{
|
||||
if (accel_find_driver(driver->name)) {
|
||||
SPDK_ERRLOG("Driver named '%s' has already been registered\n", driver->name);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_accel_drivers, driver, tailq);
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(accel)
|
||||
|
@ -26,5 +26,4 @@ int _accel_get_opc_name(enum accel_opcode opcode, const char **opcode_name);
|
||||
void _accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key);
|
||||
void _accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/event.h"
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
@ -313,3 +314,43 @@ rpc_accel_crypto_key_destroy(struct spdk_jsonrpc_request *request,
|
||||
free(req.key_name);
|
||||
}
|
||||
SPDK_RPC_REGISTER("accel_crypto_key_destroy", rpc_accel_crypto_key_destroy, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_accel_set_driver {
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_accel_set_driver_decoders[] = {
|
||||
{"name", offsetof(struct rpc_accel_set_driver, name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_accel_set_driver(struct rpc_accel_set_driver *r)
|
||||
{
|
||||
free(r->name);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_accel_set_driver(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_accel_set_driver req = {};
|
||||
int rc;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_accel_set_driver_decoders,
|
||||
SPDK_COUNTOF(rpc_accel_set_driver_decoders), &req)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = spdk_accel_set_driver(req.name);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
SPDK_NOTICELOG("Using accel driver: %s\n", req.name);
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
cleanup:
|
||||
free_rpc_accel_set_driver(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("accel_set_driver", rpc_accel_set_driver, SPDK_RPC_STARTUP)
|
||||
|
@ -33,11 +33,14 @@
|
||||
spdk_accel_crypto_key_create;
|
||||
spdk_accel_crypto_key_destroy;
|
||||
spdk_accel_crypto_key_get;
|
||||
spdk_accel_set_driver;
|
||||
|
||||
# functions needed by modules
|
||||
spdk_accel_module_list_add;
|
||||
spdk_accel_module_finish;
|
||||
spdk_accel_task_complete;
|
||||
spdk_accel_sequence_continue;
|
||||
spdk_accel_driver_register;
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
@ -79,3 +79,12 @@ def accel_crypto_keys_get(client, key_name):
|
||||
params['key_name'] = key_name
|
||||
|
||||
return client.call('accel_crypto_keys_get', params)
|
||||
|
||||
|
||||
def accel_set_driver(client, name):
|
||||
"""Select accel platform driver to execute operation chains.
|
||||
|
||||
Args:
|
||||
name: name of the driver
|
||||
"""
|
||||
return client.call('accel_set_driver', {'name': name})
|
||||
|
@ -2894,6 +2894,14 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('-k', '--key-name', help='Get information about a specific key', type=str)
|
||||
p.set_defaults(func=accel_crypto_keys_get)
|
||||
|
||||
def accel_set_driver(args):
|
||||
rpc.accel.accel_set_driver(args.client, name=args.name)
|
||||
|
||||
p = subparsers.add_parser('accel_set_driver', help='Select accel platform driver to execute ' +
|
||||
'operation chains')
|
||||
p.add_argument('name', help='name of the platform driver')
|
||||
p.set_defaults(func=accel_set_driver)
|
||||
|
||||
# ioat
|
||||
def ioat_scan_accel_module(args):
|
||||
rpc.ioat.ioat_scan_accel_module(args.client)
|
||||
|
Loading…
Reference in New Issue
Block a user