numam-dpdk/drivers/crypto/dpaa_sec/dpaa_sec_raw_dp.c
Akhil Goyal 3f3fc3308b security: remove private mempool usage
As per current design, rte_security_session_create()
unnecessarily use 2 mempool objects for a single session.

To address this, the API will now take only 1 mempool
object instead of 2. With this change, the library layer
will get the object from mempool and session priv data is
stored contiguously in the same mempool object.

User need to ensure that the mempool created in application
is big enough for session private data as well. This can be
ensured if the pool is created after getting size of session
priv data using API rte_security_session_get_size().

Since set and get pkt metadata for security sessions are now
made inline for Inline crypto/proto mode, a new member fast_mdata
is added to the rte_security_session.
To access opaque data and fast_mdata will be accessed via inline
APIs which can do pointer manipulations inside library from
session_private_data pointer coming from application.

Signed-off-by: Akhil Goyal <gakhil@marvell.com>
Tested-by: Gagandeep Singh <g.singh@nxp.com>
Tested-by: David Coyle <david.coyle@intel.com>
Tested-by: Kevin O'Sullivan <kevin.osullivan@intel.com>
2022-10-04 22:37:00 +02:00

1056 lines
25 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright 2021-2022 NXP
*/
#include <rte_byteorder.h>
#include <rte_common.h>
#include <cryptodev_pmd.h>
#include <rte_crypto.h>
#include <rte_cryptodev.h>
#ifdef RTE_LIB_SECURITY
#include <rte_security_driver.h>
#endif
/* RTA header files */
#include <desc/algo.h>
#include <desc/ipsec.h>
#include <bus_dpaa_driver.h>
#include <dpaa_sec.h>
#include <dpaa_sec_log.h>
struct dpaa_sec_raw_dp_ctx {
dpaa_sec_session *session;
uint32_t tail;
uint32_t head;
uint16_t cached_enqueue;
uint16_t cached_dequeue;
};
static inline int
is_encode(dpaa_sec_session *ses)
{
return ses->dir == DIR_ENC;
}
static inline int is_decode(dpaa_sec_session *ses)
{
return ses->dir == DIR_DEC;
}
static __rte_always_inline int
dpaa_sec_raw_enqueue_done(void *qp_data, uint8_t *drv_ctx, uint32_t n)
{
RTE_SET_USED(qp_data);
RTE_SET_USED(drv_ctx);
RTE_SET_USED(n);
return 0;
}
static __rte_always_inline int
dpaa_sec_raw_dequeue_done(void *qp_data, uint8_t *drv_ctx, uint32_t n)
{
RTE_SET_USED(qp_data);
RTE_SET_USED(drv_ctx);
RTE_SET_USED(n);
return 0;
}
static inline struct dpaa_sec_op_ctx *
dpaa_sec_alloc_raw_ctx(dpaa_sec_session *ses, int sg_count)
{
struct dpaa_sec_op_ctx *ctx;
int i, retval;
retval = rte_mempool_get(
ses->qp[rte_lcore_id() % MAX_DPAA_CORES]->ctx_pool,
(void **)(&ctx));
if (!ctx || retval) {
DPAA_SEC_DP_WARN("Alloc sec descriptor failed!");
return NULL;
}
/*
* Clear SG memory. There are 16 SG entries of 16 Bytes each.
* one call to dcbz_64() clear 64 bytes, hence calling it 4 times
* to clear all the SG entries. dpaa_sec_alloc_ctx() is called for
* each packet, memset is costlier than dcbz_64().
*/
for (i = 0; i < sg_count && i < MAX_JOB_SG_ENTRIES; i += 4)
dcbz_64(&ctx->job.sg[i]);
ctx->ctx_pool = ses->qp[rte_lcore_id() % MAX_DPAA_CORES]->ctx_pool;
ctx->vtop_offset = (size_t) ctx - rte_mempool_virt2iova(ctx);
return ctx;
}
static struct dpaa_sec_job *
build_dpaa_raw_dp_auth_fd(uint8_t *drv_ctx,
struct rte_crypto_sgl *sgl,
struct rte_crypto_sgl *dest_sgl,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *auth_iv,
union rte_crypto_sym_ofs ofs,
void *userdata,
struct qm_fd *fd)
{
RTE_SET_USED(dest_sgl);
RTE_SET_USED(iv);
RTE_SET_USED(auth_iv);
RTE_SET_USED(fd);
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
struct dpaa_sec_job *cf;
struct dpaa_sec_op_ctx *ctx;
struct qm_sg_entry *sg, *out_sg, *in_sg;
phys_addr_t start_addr;
uint8_t *old_digest, extra_segs;
int data_len, data_offset, total_len = 0;
unsigned int i;
for (i = 0; i < sgl->num; i++)
total_len += sgl->vec[i].len;
data_len = total_len - ofs.ofs.auth.head - ofs.ofs.auth.tail;
data_offset = ofs.ofs.auth.head;
/* Support only length in bits for SNOW3G and ZUC */
if (is_decode(ses))
extra_segs = 3;
else
extra_segs = 2;
if (sgl->num > MAX_SG_ENTRIES) {
DPAA_SEC_DP_ERR("Auth: Max sec segs supported is %d",
MAX_SG_ENTRIES);
return NULL;
}
ctx = dpaa_sec_alloc_raw_ctx(ses, sgl->num * 2 + extra_segs);
if (!ctx)
return NULL;
cf = &ctx->job;
ctx->userdata = (void *)userdata;
old_digest = ctx->digest;
/* output */
out_sg = &cf->sg[0];
qm_sg_entry_set64(out_sg, digest->iova);
out_sg->length = ses->digest_length;
cpu_to_hw_sg(out_sg);
/* input */
in_sg = &cf->sg[1];
/* need to extend the input to a compound frame */
in_sg->extension = 1;
in_sg->final = 1;
in_sg->length = data_len;
qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
/* 1st seg */
sg = in_sg + 1;
if (ses->iv.length) {
uint8_t *iv_ptr;
iv_ptr = rte_crypto_op_ctod_offset(userdata, uint8_t *,
ses->iv.offset);
if (ses->auth_alg == RTE_CRYPTO_AUTH_SNOW3G_UIA2) {
iv_ptr = conv_to_snow_f9_iv(iv_ptr);
sg->length = 12;
} else if (ses->auth_alg == RTE_CRYPTO_AUTH_ZUC_EIA3) {
iv_ptr = conv_to_zuc_eia_iv(iv_ptr);
sg->length = 8;
} else {
sg->length = ses->iv.length;
}
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(iv_ptr));
in_sg->length += sg->length;
cpu_to_hw_sg(sg);
sg++;
}
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->offset = data_offset;
if (data_len <= (int)(sgl->vec[0].len - data_offset)) {
sg->length = data_len;
} else {
sg->length = sgl->vec[0].len - data_offset;
/* remaining i/p segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
if (data_len > (int)sgl->vec[i].len)
sg->length = sgl->vec[0].len;
else
sg->length = data_len;
data_len = data_len - sg->length;
if (data_len < 1)
break;
}
}
if (is_decode(ses)) {
/* Digest verification case */
cpu_to_hw_sg(sg);
sg++;
rte_memcpy(old_digest, digest->va,
ses->digest_length);
start_addr = rte_dpaa_mem_vtop(old_digest);
qm_sg_entry_set64(sg, start_addr);
sg->length = ses->digest_length;
in_sg->length += ses->digest_length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
cpu_to_hw_sg(in_sg);
return cf;
}
static inline struct dpaa_sec_job *
build_raw_cipher_auth_gcm_sg(uint8_t *drv_ctx,
struct rte_crypto_sgl *sgl,
struct rte_crypto_sgl *dest_sgl,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *auth_iv,
union rte_crypto_sym_ofs ofs,
void *userdata,
struct qm_fd *fd)
{
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
struct dpaa_sec_job *cf;
struct dpaa_sec_op_ctx *ctx;
struct qm_sg_entry *sg, *out_sg, *in_sg;
uint8_t extra_req_segs;
uint8_t *IV_ptr = iv->va;
int data_len = 0, aead_len = 0;
unsigned int i;
for (i = 0; i < sgl->num; i++)
data_len += sgl->vec[i].len;
extra_req_segs = 4;
aead_len = data_len - ofs.ofs.cipher.head - ofs.ofs.cipher.tail;
if (ses->auth_only_len)
extra_req_segs++;
if (sgl->num > MAX_SG_ENTRIES) {
DPAA_SEC_DP_ERR("AEAD: Max sec segs supported is %d",
MAX_SG_ENTRIES);
return NULL;
}
ctx = dpaa_sec_alloc_raw_ctx(ses, sgl->num * 2 + extra_req_segs);
if (!ctx)
return NULL;
cf = &ctx->job;
ctx->userdata = (void *)userdata;
rte_prefetch0(cf->sg);
/* output */
out_sg = &cf->sg[0];
out_sg->extension = 1;
if (is_encode(ses))
out_sg->length = aead_len + ses->digest_length;
else
out_sg->length = aead_len;
/* output sg entries */
sg = &cf->sg[2];
qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(sg));
cpu_to_hw_sg(out_sg);
if (dest_sgl) {
/* 1st seg */
qm_sg_entry_set64(sg, dest_sgl->vec[0].iova);
sg->length = dest_sgl->vec[0].len - ofs.ofs.cipher.head;
sg->offset = ofs.ofs.cipher.head;
/* Successive segs */
for (i = 1; i < dest_sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, dest_sgl->vec[i].iova);
sg->length = dest_sgl->vec[i].len;
}
} else {
/* 1st seg */
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - ofs.ofs.cipher.head;
sg->offset = ofs.ofs.cipher.head;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
}
if (is_encode(ses)) {
cpu_to_hw_sg(sg);
/* set auth output */
sg++;
qm_sg_entry_set64(sg, digest->iova);
sg->length = ses->digest_length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
/* input */
in_sg = &cf->sg[1];
in_sg->extension = 1;
in_sg->final = 1;
if (is_encode(ses))
in_sg->length = ses->iv.length + aead_len
+ ses->auth_only_len;
else
in_sg->length = ses->iv.length + aead_len
+ ses->auth_only_len + ses->digest_length;
/* input sg entries */
sg++;
qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
cpu_to_hw_sg(in_sg);
/* 1st seg IV */
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
sg->length = ses->iv.length;
cpu_to_hw_sg(sg);
/* 2 seg auth only */
if (ses->auth_only_len) {
sg++;
qm_sg_entry_set64(sg, auth_iv->iova);
sg->length = ses->auth_only_len;
cpu_to_hw_sg(sg);
}
/* 3rd seg */
sg++;
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - ofs.ofs.cipher.head;
sg->offset = ofs.ofs.cipher.head;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
if (is_decode(ses)) {
cpu_to_hw_sg(sg);
sg++;
memcpy(ctx->digest, digest->va,
ses->digest_length);
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
sg->length = ses->digest_length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
if (ses->auth_only_len)
fd->cmd = 0x80000000 | ses->auth_only_len;
return cf;
}
static inline struct dpaa_sec_job *
build_dpaa_raw_dp_chain_fd(uint8_t *drv_ctx,
struct rte_crypto_sgl *sgl,
struct rte_crypto_sgl *dest_sgl,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *auth_iv,
union rte_crypto_sym_ofs ofs,
void *userdata,
struct qm_fd *fd)
{
RTE_SET_USED(auth_iv);
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
struct dpaa_sec_job *cf;
struct dpaa_sec_op_ctx *ctx;
struct qm_sg_entry *sg, *out_sg, *in_sg;
uint8_t *IV_ptr = iv->va;
unsigned int i;
uint16_t auth_hdr_len = ofs.ofs.cipher.head -
ofs.ofs.auth.head;
uint16_t auth_tail_len;
uint32_t auth_only_len;
int data_len = 0, auth_len = 0, cipher_len = 0;
for (i = 0; i < sgl->num; i++)
data_len += sgl->vec[i].len;
cipher_len = data_len - ofs.ofs.cipher.head - ofs.ofs.cipher.tail;
auth_len = data_len - ofs.ofs.auth.head - ofs.ofs.auth.tail;
auth_tail_len = auth_len - cipher_len - auth_hdr_len;
auth_only_len = (auth_tail_len << 16) | auth_hdr_len;
if (sgl->num > MAX_SG_ENTRIES) {
DPAA_SEC_DP_ERR("Cipher-Auth: Max sec segs supported is %d",
MAX_SG_ENTRIES);
return NULL;
}
ctx = dpaa_sec_alloc_raw_ctx(ses, sgl->num * 2 + 4);
if (!ctx)
return NULL;
cf = &ctx->job;
ctx->userdata = (void *)userdata;
rte_prefetch0(cf->sg);
/* output */
out_sg = &cf->sg[0];
out_sg->extension = 1;
if (is_encode(ses))
out_sg->length = cipher_len + ses->digest_length;
else
out_sg->length = cipher_len;
/* output sg entries */
sg = &cf->sg[2];
qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(sg));
cpu_to_hw_sg(out_sg);
/* 1st seg */
if (dest_sgl) {
qm_sg_entry_set64(sg, dest_sgl->vec[0].iova);
sg->length = dest_sgl->vec[0].len - ofs.ofs.cipher.head;
sg->offset = ofs.ofs.cipher.head;
/* Successive segs */
for (i = 1; i < dest_sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, dest_sgl->vec[i].iova);
sg->length = dest_sgl->vec[i].len;
}
sg->length -= ofs.ofs.cipher.tail;
} else {
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - ofs.ofs.cipher.head;
sg->offset = ofs.ofs.cipher.head;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
sg->length -= ofs.ofs.cipher.tail;
}
if (is_encode(ses)) {
cpu_to_hw_sg(sg);
/* set auth output */
sg++;
qm_sg_entry_set64(sg, digest->iova);
sg->length = ses->digest_length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
/* input */
in_sg = &cf->sg[1];
in_sg->extension = 1;
in_sg->final = 1;
if (is_encode(ses))
in_sg->length = ses->iv.length + auth_len;
else
in_sg->length = ses->iv.length + auth_len
+ ses->digest_length;
/* input sg entries */
sg++;
qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
cpu_to_hw_sg(in_sg);
/* 1st seg IV */
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
sg->length = ses->iv.length;
cpu_to_hw_sg(sg);
/* 2 seg */
sg++;
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - ofs.ofs.auth.head;
sg->offset = ofs.ofs.auth.head;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
if (is_decode(ses)) {
cpu_to_hw_sg(sg);
sg++;
memcpy(ctx->digest, digest->va,
ses->digest_length);
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
sg->length = ses->digest_length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
if (auth_only_len)
fd->cmd = 0x80000000 | auth_only_len;
return cf;
}
static struct dpaa_sec_job *
build_dpaa_raw_dp_cipher_fd(uint8_t *drv_ctx,
struct rte_crypto_sgl *sgl,
struct rte_crypto_sgl *dest_sgl,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *auth_iv,
union rte_crypto_sym_ofs ofs,
void *userdata,
struct qm_fd *fd)
{
RTE_SET_USED(digest);
RTE_SET_USED(auth_iv);
RTE_SET_USED(fd);
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
struct dpaa_sec_job *cf;
struct dpaa_sec_op_ctx *ctx;
struct qm_sg_entry *sg, *out_sg, *in_sg;
unsigned int i;
uint8_t *IV_ptr = iv->va;
int data_len, total_len = 0, data_offset;
for (i = 0; i < sgl->num; i++)
total_len += sgl->vec[i].len;
data_len = total_len - ofs.ofs.cipher.head - ofs.ofs.cipher.tail;
data_offset = ofs.ofs.cipher.head;
/* Support lengths in bits only for SNOW3G and ZUC */
if (sgl->num > MAX_SG_ENTRIES) {
DPAA_SEC_DP_ERR("Cipher: Max sec segs supported is %d",
MAX_SG_ENTRIES);
return NULL;
}
ctx = dpaa_sec_alloc_raw_ctx(ses, sgl->num * 2 + 3);
if (!ctx)
return NULL;
cf = &ctx->job;
ctx->userdata = (void *)userdata;
/* output */
out_sg = &cf->sg[0];
out_sg->extension = 1;
out_sg->length = data_len;
qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
cpu_to_hw_sg(out_sg);
if (dest_sgl) {
/* 1st seg */
sg = &cf->sg[2];
qm_sg_entry_set64(sg, dest_sgl->vec[0].iova);
sg->length = dest_sgl->vec[0].len - data_offset;
sg->offset = data_offset;
/* Successive segs */
for (i = 1; i < dest_sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, dest_sgl->vec[i].iova);
sg->length = dest_sgl->vec[i].len;
}
} else {
/* 1st seg */
sg = &cf->sg[2];
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - data_offset;
sg->offset = data_offset;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
}
sg->final = 1;
cpu_to_hw_sg(sg);
/* input */
in_sg = &cf->sg[1];
in_sg->extension = 1;
in_sg->final = 1;
in_sg->length = data_len + ses->iv.length;
sg++;
qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
cpu_to_hw_sg(in_sg);
/* IV */
qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
sg->length = ses->iv.length;
cpu_to_hw_sg(sg);
/* 1st seg */
sg++;
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len - data_offset;
sg->offset = data_offset;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
}
sg->final = 1;
cpu_to_hw_sg(sg);
return cf;
}
#ifdef RTE_LIB_SECURITY
static inline struct dpaa_sec_job *
build_dpaa_raw_proto_sg(uint8_t *drv_ctx,
struct rte_crypto_sgl *sgl,
struct rte_crypto_sgl *dest_sgl,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *auth_iv,
union rte_crypto_sym_ofs ofs,
void *userdata,
struct qm_fd *fd)
{
RTE_SET_USED(iv);
RTE_SET_USED(digest);
RTE_SET_USED(auth_iv);
RTE_SET_USED(ofs);
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
struct dpaa_sec_job *cf;
struct dpaa_sec_op_ctx *ctx;
struct qm_sg_entry *sg, *out_sg, *in_sg;
uint32_t in_len = 0, out_len = 0;
unsigned int i;
if (sgl->num > MAX_SG_ENTRIES) {
DPAA_SEC_DP_ERR("Proto: Max sec segs supported is %d",
MAX_SG_ENTRIES);
return NULL;
}
ctx = dpaa_sec_alloc_raw_ctx(ses, sgl->num * 2 + 4);
if (!ctx)
return NULL;
cf = &ctx->job;
ctx->userdata = (void *)userdata;
/* output */
out_sg = &cf->sg[0];
out_sg->extension = 1;
qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
if (dest_sgl) {
/* 1st seg */
sg = &cf->sg[2];
qm_sg_entry_set64(sg, dest_sgl->vec[0].iova);
sg->offset = 0;
sg->length = dest_sgl->vec[0].len;
out_len += sg->length;
for (i = 1; i < dest_sgl->num; i++) {
/* Successive segs */
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, dest_sgl->vec[i].iova);
sg->offset = 0;
sg->length = dest_sgl->vec[i].len;
out_len += sg->length;
}
sg->length = dest_sgl->vec[i - 1].tot_len;
} else {
/* 1st seg */
sg = &cf->sg[2];
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->offset = 0;
sg->length = sgl->vec[0].len;
out_len += sg->length;
for (i = 1; i < sgl->num; i++) {
/* Successive segs */
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->offset = 0;
sg->length = sgl->vec[i].len;
out_len += sg->length;
}
sg->length = sgl->vec[i - 1].tot_len;
}
out_len += sg->length;
sg->final = 1;
cpu_to_hw_sg(sg);
out_sg->length = out_len;
cpu_to_hw_sg(out_sg);
/* input */
in_sg = &cf->sg[1];
in_sg->extension = 1;
in_sg->final = 1;
in_len = sgl->vec[0].len;
sg++;
qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
/* 1st seg */
qm_sg_entry_set64(sg, sgl->vec[0].iova);
sg->length = sgl->vec[0].len;
sg->offset = 0;
/* Successive segs */
for (i = 1; i < sgl->num; i++) {
cpu_to_hw_sg(sg);
sg++;
qm_sg_entry_set64(sg, sgl->vec[i].iova);
sg->length = sgl->vec[i].len;
sg->offset = 0;
in_len += sg->length;
}
sg->final = 1;
cpu_to_hw_sg(sg);
in_sg->length = in_len;
cpu_to_hw_sg(in_sg);
if ((ses->ctxt == DPAA_SEC_PDCP) && ses->pdcp.hfn_ovd) {
fd->cmd = 0x80000000 |
*((uint32_t *)((uint8_t *)userdata +
ses->pdcp.hfn_ovd_offset));
DPAA_SEC_DP_DEBUG("Per packet HFN: %x, ovd:%u\n",
*((uint32_t *)((uint8_t *)userdata +
ses->pdcp.hfn_ovd_offset)),
ses->pdcp.hfn_ovd);
}
return cf;
}
#endif
static uint32_t
dpaa_sec_raw_enqueue_burst(void *qp_data, uint8_t *drv_ctx,
struct rte_crypto_sym_vec *vec, union rte_crypto_sym_ofs ofs,
void *user_data[], int *status)
{
/* Function to transmit the frames to given device and queuepair */
uint32_t loop;
struct dpaa_sec_qp *dpaa_qp = (struct dpaa_sec_qp *)qp_data;
uint16_t num_tx = 0;
struct qm_fd fds[DPAA_SEC_BURST], *fd;
uint32_t frames_to_send;
struct dpaa_sec_job *cf;
dpaa_sec_session *ses =
((struct dpaa_sec_raw_dp_ctx *)drv_ctx)->session;
uint32_t flags[DPAA_SEC_BURST] = {0};
struct qman_fq *inq[DPAA_SEC_BURST];
if (unlikely(!DPAA_PER_LCORE_PORTAL)) {
if (rte_dpaa_portal_init((void *)0)) {
DPAA_SEC_ERR("Failure in affining portal");
return 0;
}
}
while (vec->num) {
frames_to_send = (vec->num > DPAA_SEC_BURST) ?
DPAA_SEC_BURST : vec->num;
for (loop = 0; loop < frames_to_send; loop++) {
if (unlikely(!ses->qp[rte_lcore_id() % MAX_DPAA_CORES])) {
if (dpaa_sec_attach_sess_q(dpaa_qp, ses)) {
frames_to_send = loop;
goto send_pkts;
}
} else if (unlikely(ses->qp[rte_lcore_id() %
MAX_DPAA_CORES] != dpaa_qp)) {
DPAA_SEC_DP_ERR("Old:sess->qp = %p"
" New qp = %p\n",
ses->qp[rte_lcore_id() %
MAX_DPAA_CORES], dpaa_qp);
frames_to_send = loop;
goto send_pkts;
}
/*Clear the unused FD fields before sending*/
fd = &fds[loop];
memset(fd, 0, sizeof(struct qm_fd));
cf = ses->build_raw_dp_fd(drv_ctx,
&vec->src_sgl[loop],
&vec->dest_sgl[loop],
&vec->iv[loop],
&vec->digest[loop],
&vec->auth_iv[loop],
ofs,
user_data[loop],
fd);
if (!cf) {
DPAA_SEC_ERR("error: Improper packet contents"
" for crypto operation");
goto skip_tx;
}
inq[loop] = ses->inq[rte_lcore_id() % MAX_DPAA_CORES];
qm_fd_addr_set64(fd, rte_dpaa_mem_vtop(cf->sg));
fd->_format1 = qm_fd_compound;
fd->length29 = 2 * sizeof(struct qm_sg_entry);
status[loop] = 1;
}
send_pkts:
loop = 0;
while (loop < frames_to_send) {
loop += qman_enqueue_multi_fq(&inq[loop], &fds[loop],
&flags[loop], frames_to_send - loop);
}
vec->num -= frames_to_send;
num_tx += frames_to_send;
}
skip_tx:
dpaa_qp->tx_pkts += num_tx;
dpaa_qp->tx_errs += vec->num - num_tx;
return num_tx;
}
static int
dpaa_sec_deq_raw(struct dpaa_sec_qp *qp, void **out_user_data,
uint8_t is_user_data_array,
rte_cryptodev_raw_post_dequeue_t post_dequeue,
int nb_ops)
{
struct qman_fq *fq;
unsigned int pkts = 0;
int num_rx_bufs, ret;
struct qm_dqrr_entry *dq;
uint32_t vdqcr_flags = 0;
uint8_t is_success = 0;
fq = &qp->outq;
/*
* Until request for four buffers, we provide exact number of buffers.
* Otherwise we do not set the QM_VDQCR_EXACT flag.
* Not setting QM_VDQCR_EXACT flag can provide two more buffers than
* requested, so we request two less in this case.
*/
if (nb_ops < 4) {
vdqcr_flags = QM_VDQCR_EXACT;
num_rx_bufs = nb_ops;
} else {
num_rx_bufs = nb_ops > DPAA_MAX_DEQUEUE_NUM_FRAMES ?
(DPAA_MAX_DEQUEUE_NUM_FRAMES - 2) : (nb_ops - 2);
}
ret = qman_set_vdq(fq, num_rx_bufs, vdqcr_flags);
if (ret)
return 0;
do {
const struct qm_fd *fd;
struct dpaa_sec_job *job;
struct dpaa_sec_op_ctx *ctx;
dq = qman_dequeue(fq);
if (!dq)
continue;
fd = &dq->fd;
/* sg is embedded in an op ctx,
* sg[0] is for output
* sg[1] for input
*/
job = rte_dpaa_mem_ptov(qm_fd_addr_get64(fd));
ctx = container_of(job, struct dpaa_sec_op_ctx, job);
ctx->fd_status = fd->status;
if (is_user_data_array)
out_user_data[pkts] = ctx->userdata;
else
out_user_data[0] = ctx->userdata;
if (!ctx->fd_status) {
is_success = true;
} else {
is_success = false;
DPAA_SEC_DP_WARN("SEC return err:0x%x", ctx->fd_status);
}
post_dequeue(ctx->op, pkts, is_success);
pkts++;
/* report op status to sym->op and then free the ctx memory */
rte_mempool_put(ctx->ctx_pool, (void *)ctx);
qman_dqrr_consume(fq, dq);
} while (fq->flags & QMAN_FQ_STATE_VDQCR);
return pkts;
}
static __rte_always_inline uint32_t
dpaa_sec_raw_dequeue_burst(void *qp_data, uint8_t *drv_ctx,
rte_cryptodev_raw_get_dequeue_count_t get_dequeue_count,
uint32_t max_nb_to_dequeue,
rte_cryptodev_raw_post_dequeue_t post_dequeue,
void **out_user_data, uint8_t is_user_data_array,
uint32_t *n_success, int *dequeue_status)
{
RTE_SET_USED(drv_ctx);
RTE_SET_USED(get_dequeue_count);
uint16_t num_rx;
struct dpaa_sec_qp *dpaa_qp = (struct dpaa_sec_qp *)qp_data;
uint32_t nb_ops = max_nb_to_dequeue;
if (unlikely(!DPAA_PER_LCORE_PORTAL)) {
if (rte_dpaa_portal_init((void *)0)) {
DPAA_SEC_ERR("Failure in affining portal");
return 0;
}
}
num_rx = dpaa_sec_deq_raw(dpaa_qp, out_user_data,
is_user_data_array, post_dequeue, nb_ops);
dpaa_qp->rx_pkts += num_rx;
*dequeue_status = 1;
*n_success = num_rx;
DPAA_SEC_DP_DEBUG("SEC Received %d Packets\n", num_rx);
return num_rx;
}
static __rte_always_inline int
dpaa_sec_raw_enqueue(void *qp_data, uint8_t *drv_ctx,
struct rte_crypto_vec *data_vec,
uint16_t n_data_vecs, union rte_crypto_sym_ofs ofs,
struct rte_crypto_va_iova_ptr *iv,
struct rte_crypto_va_iova_ptr *digest,
struct rte_crypto_va_iova_ptr *aad_or_auth_iv,
void *user_data)
{
RTE_SET_USED(qp_data);
RTE_SET_USED(drv_ctx);
RTE_SET_USED(data_vec);
RTE_SET_USED(n_data_vecs);
RTE_SET_USED(ofs);
RTE_SET_USED(iv);
RTE_SET_USED(digest);
RTE_SET_USED(aad_or_auth_iv);
RTE_SET_USED(user_data);
return 0;
}
static __rte_always_inline void *
dpaa_sec_raw_dequeue(void *qp_data, uint8_t *drv_ctx, int *dequeue_status,
enum rte_crypto_op_status *op_status)
{
RTE_SET_USED(qp_data);
RTE_SET_USED(drv_ctx);
RTE_SET_USED(dequeue_status);
RTE_SET_USED(op_status);
return NULL;
}
int
dpaa_sec_configure_raw_dp_ctx(struct rte_cryptodev *dev, uint16_t qp_id,
struct rte_crypto_raw_dp_ctx *raw_dp_ctx,
enum rte_crypto_op_sess_type sess_type,
union rte_cryptodev_session_ctx session_ctx, uint8_t is_update)
{
dpaa_sec_session *sess;
struct dpaa_sec_raw_dp_ctx *dp_ctx;
RTE_SET_USED(qp_id);
if (!is_update) {
memset(raw_dp_ctx, 0, sizeof(*raw_dp_ctx));
raw_dp_ctx->qp_data = dev->data->queue_pairs[qp_id];
}
if (sess_type == RTE_CRYPTO_OP_SECURITY_SESSION)
sess = SECURITY_GET_SESS_PRIV(session_ctx.sec_sess);
else if (sess_type == RTE_CRYPTO_OP_WITH_SESSION)
sess = (dpaa_sec_session *)
CRYPTODEV_GET_SYM_SESS_PRIV(session_ctx.crypto_sess);
else
return -ENOTSUP;
raw_dp_ctx->dequeue_burst = dpaa_sec_raw_dequeue_burst;
raw_dp_ctx->dequeue = dpaa_sec_raw_dequeue;
raw_dp_ctx->dequeue_done = dpaa_sec_raw_dequeue_done;
raw_dp_ctx->enqueue_burst = dpaa_sec_raw_enqueue_burst;
raw_dp_ctx->enqueue = dpaa_sec_raw_enqueue;
raw_dp_ctx->enqueue_done = dpaa_sec_raw_enqueue_done;
if (sess->ctxt == DPAA_SEC_CIPHER)
sess->build_raw_dp_fd = build_dpaa_raw_dp_cipher_fd;
else if (sess->ctxt == DPAA_SEC_AUTH)
sess->build_raw_dp_fd = build_dpaa_raw_dp_auth_fd;
else if (sess->ctxt == DPAA_SEC_CIPHER_HASH)
sess->build_raw_dp_fd = build_dpaa_raw_dp_chain_fd;
else if (sess->ctxt == DPAA_SEC_AEAD)
sess->build_raw_dp_fd = build_raw_cipher_auth_gcm_sg;
#ifdef RTE_LIB_SECURITY
else if (sess->ctxt == DPAA_SEC_IPSEC ||
sess->ctxt == DPAA_SEC_PDCP)
sess->build_raw_dp_fd = build_dpaa_raw_proto_sg;
#endif
else
return -ENOTSUP;
dp_ctx = (struct dpaa_sec_raw_dp_ctx *)raw_dp_ctx->drv_ctx_data;
dp_ctx->session = sess;
return 0;
}
int
dpaa_sec_get_dp_ctx_size(__rte_unused struct rte_cryptodev *dev)
{
return sizeof(struct dpaa_sec_raw_dp_ctx);
}