dma: Add infrstructure for push operation
Push operation complements existing pull operation and allows to implement read data flow using memory domains. Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com> Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com> Change-Id: I0a3ddcb88c433dff7a9c761a99838658c72c43fd Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9701 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
b794726807
commit
0ecbe09bc1
@ -63,12 +63,12 @@ enum spdk_dma_device_type {
|
||||
struct spdk_memory_domain;
|
||||
|
||||
/**
|
||||
* Definition of completion callback to be called by pull function.
|
||||
* Definition of completion callback to be called by pull or push functions.
|
||||
*
|
||||
* \param ctx User context passed to pull function
|
||||
* \param rc Result of asynchronous pull function
|
||||
* \param ctx User context passed to pull of push functions
|
||||
* \param rc Result of asynchronous data pull or push function
|
||||
*/
|
||||
typedef void (*spdk_memory_domain_pull_data_cpl_cb)(void *ctx, int rc);
|
||||
typedef void (*spdk_memory_domain_data_cpl_cb)(void *ctx, int rc);
|
||||
|
||||
/**
|
||||
* Definition of function which asynchronously pulles data from src_domain to local memory domain.
|
||||
@ -88,7 +88,26 @@ typedef void (*spdk_memory_domain_pull_data_cpl_cb)(void *ctx, int rc);
|
||||
typedef int (*spdk_memory_domain_pull_data_cb)(struct spdk_memory_domain *src_domain,
|
||||
void *src_domain_ctx,
|
||||
struct iovec *src_iov, uint32_t src_iovcnt, struct iovec *dst_iov, uint32_t dst_iovcnt,
|
||||
spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
|
||||
/**
|
||||
* Definition of function which asynchronously pushes data from local memory to destination memory domain.
|
||||
* Implementation of this function must call \b cpl_cb only when it returns 0. All other return codes mean failure.
|
||||
*
|
||||
* \param dst_domain Memory domain to which the data should be pushed
|
||||
* \param dst_domain_ctx Optional context passed by upper layer with IO request
|
||||
* \param dst_iov Iov vector in dst_domain space
|
||||
* \param dst_iovcnt dst_iov array size
|
||||
* \param src_iov Iov vector in local memory
|
||||
* \param src_iovcnt src_iov array size
|
||||
* \param cpl_cb A callback to be called when push operation completes
|
||||
* \param cpl_cb_arg Optional argument to be passed to \b cpl_cb
|
||||
* \return 0 on success, negated errno on failure
|
||||
*/
|
||||
typedef int (*spdk_memory_domain_push_data_cb)(struct spdk_memory_domain *dst_domain,
|
||||
void *dst_domain_ctx,
|
||||
struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
|
||||
struct spdk_memory_domain_translation_result {
|
||||
/** size of this structure in bytes */
|
||||
@ -181,6 +200,15 @@ void spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
|
||||
void spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
|
||||
spdk_memory_domain_pull_data_cb pull_cb);
|
||||
|
||||
/**
|
||||
* Set push function for memory domain. Overwrites existing push function.
|
||||
*
|
||||
* \param domain Memory domain
|
||||
* \param push_cb push function
|
||||
*/
|
||||
void spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
|
||||
spdk_memory_domain_push_data_cb push_cb);
|
||||
|
||||
/**
|
||||
* Get the context passed by the user in \ref spdk_memory_domain_create
|
||||
*
|
||||
@ -228,7 +256,25 @@ void spdk_memory_domain_destroy(struct spdk_memory_domain *domain);
|
||||
*/
|
||||
int spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
|
||||
struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
|
||||
spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
|
||||
/**
|
||||
* Asynchronously push data located in local memory to \b dst_domain
|
||||
*
|
||||
* \param dst_domain Memory domain to which the data should be pushed
|
||||
* \param dst_domain_ctx Optional context passed by upper layer with IO request
|
||||
* \param dst_iov Iov vector in dst_domain space
|
||||
* \param dst_iovcnt dst_iov array size
|
||||
* \param src_iov Iov vector in local memory
|
||||
* \param src_iovcnt src_iov array size
|
||||
* \param cpl_cb Completion callback
|
||||
* \param cpl_cb_arg Completion callback argument
|
||||
* \return 0 on success, negated errno on failure. push_cb implementation must only call the callback when 0
|
||||
* is returned
|
||||
*/
|
||||
int spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
|
||||
struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg);
|
||||
|
||||
/**
|
||||
* Translate data located in \b src_domain space at address \b addr with size \b len into an equivalent
|
||||
|
@ -42,6 +42,7 @@ TAILQ_HEAD(, spdk_memory_domain) g_dma_memory_domains = TAILQ_HEAD_INITIALIZER(
|
||||
struct spdk_memory_domain {
|
||||
enum spdk_dma_device_type type;
|
||||
spdk_memory_domain_pull_data_cb pull_cb;
|
||||
spdk_memory_domain_push_data_cb push_cb;
|
||||
spdk_memory_domain_translate_memory_cb translate_cb;
|
||||
TAILQ_ENTRY(spdk_memory_domain) link;
|
||||
struct spdk_memory_domain_ctx *ctx;
|
||||
@ -126,6 +127,17 @@ spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
|
||||
domain->pull_cb = pull_cb;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
|
||||
spdk_memory_domain_push_data_cb push_cb)
|
||||
{
|
||||
if (!domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
domain->push_cb = push_cb;
|
||||
}
|
||||
|
||||
struct spdk_memory_domain_ctx *
|
||||
spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
|
||||
{
|
||||
@ -168,7 +180,7 @@ spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
|
||||
int
|
||||
spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
|
||||
struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
|
||||
spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
{
|
||||
assert(src_domain);
|
||||
assert(src_iov);
|
||||
@ -182,6 +194,23 @@ spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_do
|
||||
cpl_cb, cpl_cb_arg);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
|
||||
struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
{
|
||||
assert(dst_domain);
|
||||
assert(dst_iov);
|
||||
assert(src_iov);
|
||||
|
||||
if (spdk_unlikely(!dst_domain->push_cb)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt,
|
||||
cpl_cb, cpl_cb_arg);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
|
||||
struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx,
|
||||
|
@ -5,11 +5,13 @@
|
||||
spdk_memory_domain_create;
|
||||
spdk_memory_domain_set_translation;
|
||||
spdk_memory_domain_set_pull;
|
||||
spdk_memory_domain_set_push;
|
||||
spdk_memory_domain_get_context;
|
||||
spdk_memory_domain_get_dma_device_type;
|
||||
spdk_memory_domain_get_dma_device_id;
|
||||
spdk_memory_domain_destroy;
|
||||
spdk_memory_domain_pull_data;
|
||||
spdk_memory_domain_push_data;
|
||||
spdk_memory_domain_translate_data;
|
||||
spdk_memory_domain_get_first;
|
||||
spdk_memory_domain_get_next;
|
||||
|
@ -37,23 +37,34 @@
|
||||
#include "dma/dma.c"
|
||||
|
||||
static bool g_memory_domain_pull_called;
|
||||
static bool g_memory_domain_push_called;
|
||||
static bool g_memory_domain_translate_called;
|
||||
static int g_memory_domain_cb_rc = 123;
|
||||
|
||||
static void
|
||||
test_memory_domain_pull_data_cpl_cb(void *ctx, int rc)
|
||||
test_memory_domain_data_cpl_cb(void *ctx, int rc)
|
||||
{
|
||||
}
|
||||
|
||||
static int test_memory_domain_pull_data_cb(struct spdk_memory_domain *src_device,
|
||||
void *src_device_ctx, struct iovec *src_iov, uint32_t src_iovcnt, struct iovec *dst_iov,
|
||||
uint32_t dst_iovcnt, spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
uint32_t dst_iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
{
|
||||
g_memory_domain_pull_called = true;
|
||||
|
||||
return g_memory_domain_cb_rc;
|
||||
}
|
||||
|
||||
static int test_memory_domain_push_data_cb(struct spdk_memory_domain *dst_domain,
|
||||
void *dst_domain_ctx,
|
||||
struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
|
||||
spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
|
||||
{
|
||||
g_memory_domain_push_called = true;
|
||||
|
||||
return g_memory_domain_cb_rc;
|
||||
}
|
||||
|
||||
static int
|
||||
test_memory_domain_translate_memory_cb(struct spdk_memory_domain *src_device, void *src_device_ctx,
|
||||
struct spdk_memory_domain *dst_device, struct spdk_memory_domain_translation_ctx *dst_device_ctx,
|
||||
@ -108,7 +119,7 @@ test_dma(void)
|
||||
/* pull data, callback is NULL. Expect fail */
|
||||
g_memory_domain_pull_called = false;
|
||||
rc = spdk_memory_domain_pull_data(domain, NULL, &src_iov, 1, &dst_iov, 1,
|
||||
test_memory_domain_pull_data_cpl_cb, NULL);
|
||||
test_memory_domain_data_cpl_cb, NULL);
|
||||
CU_ASSERT(rc == -ENOTSUP);
|
||||
CU_ASSERT(g_memory_domain_pull_called == false);
|
||||
|
||||
@ -117,10 +128,26 @@ test_dma(void)
|
||||
|
||||
/* pull data. Expect pass */
|
||||
rc = spdk_memory_domain_pull_data(domain, NULL, &src_iov, 1, &dst_iov, 1,
|
||||
test_memory_domain_pull_data_cpl_cb, NULL);
|
||||
test_memory_domain_data_cpl_cb, NULL);
|
||||
CU_ASSERT(rc == g_memory_domain_cb_rc);
|
||||
CU_ASSERT(g_memory_domain_pull_called == true);
|
||||
|
||||
/* push data, callback is NULL. Expect fail */
|
||||
g_memory_domain_push_called = false;
|
||||
rc = spdk_memory_domain_push_data(domain, NULL, &dst_iov, 1, &src_iov, 1,
|
||||
test_memory_domain_data_cpl_cb, NULL);
|
||||
CU_ASSERT(rc == -ENOTSUP);
|
||||
CU_ASSERT(g_memory_domain_push_called == false);
|
||||
|
||||
/* Set push callback */
|
||||
spdk_memory_domain_set_push(domain, test_memory_domain_push_data_cb);
|
||||
|
||||
/* push data. Expect pass */
|
||||
rc = spdk_memory_domain_push_data(domain, NULL, &dst_iov, 1, &src_iov, 1,
|
||||
test_memory_domain_data_cpl_cb, NULL);
|
||||
CU_ASSERT(rc == g_memory_domain_cb_rc);
|
||||
CU_ASSERT(g_memory_domain_push_called == true);
|
||||
|
||||
/* Translate data, callback is NULL. Expect fail */
|
||||
g_memory_domain_translate_called = false;
|
||||
rc = spdk_memory_domain_translate_data(domain, NULL, domain, NULL, (void *)0xfeeddbeef, 0x1000,
|
||||
|
@ -69,7 +69,7 @@ DEFINE_STUB(spdk_memory_domain_get_dma_device_type, enum spdk_dma_device_type,
|
||||
DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *device));
|
||||
DEFINE_STUB(spdk_memory_domain_pull_data, int, (struct spdk_memory_domain *src_domain,
|
||||
void *src_domain_ctx, struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov,
|
||||
uint32_t dst_iov_cnt, spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg), 0);
|
||||
uint32_t dst_iov_cnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg), 0);
|
||||
|
||||
DEFINE_RETURN_MOCK(spdk_memory_domain_create, int);
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user