/** * cc_get_sgl_nents() - Get scatterlist number of entries. * * @dev: Device object * @sg_list: SG list * @nbytes: [IN] Total SGL data bytes. * @lbytes: [OUT] Returns the amount of bytes at the last entry * * Return: * Number of entries in the scatterlist
*/ staticunsignedint cc_get_sgl_nents(struct device *dev, struct scatterlist *sg_list, unsignedint nbytes, u32 *lbytes)
{ unsignedint nents = 0;
*lbytes = 0;
while (nbytes && sg_list) {
nents++; /* get the number of bytes in the last entry */
*lbytes = nbytes;
nbytes -= (sg_list->length > nbytes) ?
nbytes : sg_list->length;
sg_list = sg_next(sg_list);
}
/** * cc_copy_sg_portion() - Copy scatter list data, * from to_skip to end, to dest and vice versa * * @dev: Device object * @dest: Buffer to copy to/from * @sg: SG list * @to_skip: Number of bytes to skip before copying * @end: Offset of last byte to copy * @direct: Transfer direction (true == from SG list to buffer, false == from * buffer to SG list)
*/ void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg,
u32 to_skip, u32 end, enum cc_sg_cpy_direct direct)
{
u32 nents;
/* Verify there is no memory overflow*/
new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1); if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES) {
dev_err(dev, "Too many mlli entries. current %d max %d\n",
new_nents, MAX_NUM_OF_TOTAL_MLLI_ENTRIES); return -ENOMEM;
}
dev_dbg(dev, "NUM of SG's = %d\n", sg_data->num_of_buffers);
/* Allocate memory from the pointed pool */
mlli_params->mlli_virt_addr =
dma_pool_alloc(mlli_params->curr_pool, flags,
&mlli_params->mlli_dma_addr); if (!mlli_params->mlli_virt_addr) {
dev_err(dev, "dma_pool_alloc() failed\n");
rc = -ENOMEM; goto build_mlli_exit;
} /* Point to start of MLLI */
mlli_p = mlli_params->mlli_virt_addr; /* go over all SG's and link it to one MLLI table */ for (i = 0; i < sg_data->num_of_buffers; i++) { union buffer_array_entry *entry = &sg_data->entry[i];
u32 tot_len = sg_data->total_data_len[i];
u32 offset = sg_data->offset[i];
/* set last bit in the current table */ if (sg_data->mlli_nents[i]) { /*Calculate the current MLLI table length for the *length field in the descriptor
*/
*sg_data->mlli_nents[i] +=
(total_nents - prev_total_nents);
prev_total_nents = total_nents;
}
}
/* Set MLLI size for the bypass operation */
mlli_params->mlli_len = (total_nents * LLI_ENTRY_BYTE_SIZE);
/* Map IV buffer */ if (ivsize) {
dump_byte_array("iv", info, ivsize);
req_ctx->gen_ctx.iv_dma_addr =
dma_map_single(dev, info, ivsize, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, req_ctx->gen_ctx.iv_dma_addr)) {
dev_err(dev, "Mapping iv %u B at va=%p for DMA failed\n",
ivsize, info); return -ENOMEM;
}
dev_dbg(dev, "Mapped iv %u B at va=%p to dma=%pad\n",
ivsize, info, &req_ctx->gen_ctx.iv_dma_addr);
} else {
req_ctx->gen_ctx.iv_dma_addr = 0;
}
/* Map the src SGL */
rc = cc_map_sg(dev, src, nbytes, src_direction, &req_ctx->in_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); if (rc) goto cipher_exit; if (mapped_nents > 1)
req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
mapped_nents = sg_nents_for_len(req->src, areq_ctx->assoclen); if (mapped_nents < 0) return mapped_nents;
if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
dev_err(dev, "Too many fragments. current %d max %d\n",
mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); return -ENOMEM;
}
areq_ctx->assoc.nents = mapped_nents;
/* in CCM case we have additional entry for * ccm header configurations
*/ if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { if ((mapped_nents + 1) > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
dev_err(dev, "CCM case.Too many fragments. Current %d max %d\n",
(areq_ctx->assoc.nents + 1),
LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
rc = -ENOMEM; goto chain_assoc_exit;
}
}
if (areq_ctx->is_icv_fragmented) { /* Backup happens only when ICV is fragmented, ICV * verification is made by CPU compare in order to * simplify MAC verification upon request completion
*/ if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /* In coherent platforms (e.g. ACP) * already copying ICV for any * INPLACE-DECRYPT operation, hence * we must neglect this code.
*/ if (!drvdata->coherent)
cc_copy_mac(dev, req, CC_SG_TO_BUF);
areq_ctx->is_icv_fragmented =
cc_is_icv_frag(areq_ctx->src.nents, authsize,
*src_last_bytes); /* Backup happens only when ICV is fragmented, ICV
* verification is made by CPU compare in order to simplify * MAC verification upon request completion
*/ if (areq_ctx->is_icv_fragmented) {
cc_copy_mac(dev, req, CC_SG_TO_BUF);
areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
} else { /* Contig. ICV */
sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1]; /*Should hanlde if the sg is not contig.*/
areq_ctx->icv_dma_addr = sg_dma_address(sg) +
(*src_last_bytes - authsize);
areq_ctx->icv_virt_addr = sg_virt(sg) +
(*src_last_bytes - authsize);
}
/* copy mac to a temporary location to deal with possible * data memory overriding that caused by cache coherence problem.
*/ if (drvdata->coherent &&
areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
req->src == req->dst)
cc_copy_mac(dev, req, CC_SG_TO_BUF);
/* cacluate the size for cipher remove ICV in decrypt*/
areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
DRV_CRYPTO_DIRECTION_ENCRYPT) ?
req->cryptlen :
(req->cryptlen - authsize);
dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE,
DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "Mapping mac_buf %u B at va=%p for DMA failed\n",
MAX_MAC_SIZE, areq_ctx->mac_buf);
rc = -ENOMEM; goto aead_map_failure;
}
areq_ctx->mac_buf_dma_addr = dma_addr;
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%p for DMA failed\n",
AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2));
areq_ctx->gcm_iv_inc2_dma_addr = 0;
rc = -ENOMEM; goto aead_map_failure;
}
areq_ctx->gcm_iv_inc2_dma_addr = dma_addr;
}
size_to_map = req->cryptlen + req->assoclen; /* If we do in-place encryption, we also need the auth tag */ if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT) &&
(req->src == req->dst)) {
size_to_map += authsize;
}
if (areq_ctx->is_single_pass) { /* * Create MLLI table for: * (1) Assoc. data * (2) Src/Dst SGLs * Note: IV is contg. buffer (not an SGL)
*/
rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false); if (rc) goto aead_map_failure;
rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false); if (rc) goto aead_map_failure;
rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false); if (rc) goto aead_map_failure;
} else { /* DOUBLE-PASS flow */ /* * Prepare MLLI table(s) in this order: * * If ENCRYPT/DECRYPT (inplace): * (1) MLLI table for assoc * (2) IV entry (chained right after end of assoc) * (3) MLLI for src/dst (inplace operation) * * If ENCRYPT (non-inplace) * (1) MLLI table for assoc * (2) IV entry (chained right after end of assoc) * (3) MLLI for dst * (4) MLLI for src * * If DECRYPT (non-inplace) * (1) MLLI table for assoc * (2) IV entry (chained right after end of assoc) * (3) MLLI for src * (4) MLLI for dst
*/
rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true); if (rc) goto aead_map_failure;
rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true); if (rc) goto aead_map_failure;
rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true); if (rc) goto aead_map_failure;
}
/* Mlli support -start building the MLLI according to the above * results
*/ if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
mlli_params->curr_pool = drvdata->mlli_buffs_pool;
rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags); if (rc) goto aead_map_failure;
/* Copy the new residue to next buffer */ if (*next_buff_cnt) {
dev_dbg(dev, " handle residue: next buff %p skip data %u residue %u\n",
next_buff, (update_data_len - *curr_buff_cnt),
*next_buff_cnt);
cc_copy_sg_portion(dev, next_buff, src,
(update_data_len - *curr_buff_cnt),
nbytes, CC_SG_TO_BUF); /* change the buffer index for next operation */
swap_index = 1;
}
if (*curr_buff_cnt) {
rc = cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
&sg_data); if (rc) return rc; /* change the buffer index for next operation */
swap_index = 1;
}
if (update_data_len > *curr_buff_cnt) {
rc = cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt),
DMA_TO_DEVICE, &areq_ctx->in_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
&mapped_nents); if (rc) goto unmap_curr_buff; if (mapped_nents == 1 &&
areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) { /* only one entry in the SG and no previous data */
memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist));
areq_ctx->buff_sg->length = update_data_len;
areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
areq_ctx->curr_sg = areq_ctx->buff_sg;
} else {
areq_ctx->data_dma_buf_type = CC_DMA_BUF_MLLI;
}
}
if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_MLLI) {
mlli_params->curr_pool = drvdata->mlli_buffs_pool; /* add the src data to the sg_data */
cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src,
(update_data_len - *curr_buff_cnt), 0, true,
&areq_ctx->mlli_nents);
rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags); if (rc) goto fail_unmap_din;
}
areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
/*In case a pool was set, a table was *allocated and should be released
*/ if (areq_ctx->mlli_params.curr_pool) {
dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%p\n",
&areq_ctx->mlli_params.mlli_dma_addr,
areq_ctx->mlli_params.mlli_virt_addr);
dma_pool_free(areq_ctx->mlli_params.curr_pool,
areq_ctx->mlli_params.mlli_virt_addr,
areq_ctx->mlli_params.mlli_dma_addr);
}
int cc_buffer_mgr_fini(struct cc_drvdata *drvdata)
{
dma_pool_destroy(drvdata->mlli_buffs_pool); return 0;
}
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.16Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.