// SPDX-License-Identifier: GPL-2.0-only /* * Provide TDMA helper functions used by cipher and hash algorithm * implementations. * * Author: Boris Brezillon <boris.brezillon@free-electrons.com> * Author: Arnaud Ebalard <arno@natisbad.org> * * This work is based on an initial version written by * Sebastian Andrzej Siewior < sebastian at breakpoint dot cc >
*/
/* * Break the DMA chain if the request being queued needs the IV * regs to be set before lauching the request.
*/ if (!last || dreq->chain.first->flags & CESA_TDMA_SET_STATE)
engine->chain_sw.first = dreq->chain.first; else {
last->next = dreq->chain.first;
last->next_dma = cpu_to_le32(dreq->chain.first->cur_dma);
}
last = dreq->chain.last;
engine->chain_sw.last = last; /* * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on * the last element of the current chain.
*/ if (last->flags & CESA_TDMA_BREAK_CHAIN) {
engine->chain_sw.first = NULL;
engine->chain_sw.last = NULL;
}
}
int mv_cesa_tdma_process(struct mv_cesa_engine *engine, u32 status)
{ struct crypto_async_request *req = NULL; struct mv_cesa_tdma_desc *tdma = NULL, *next = NULL;
dma_addr_t tdma_cur; int res = 0;
tdma_cur = readl(engine->regs + CESA_TDMA_CUR);
for (tdma = engine->chain_hw.first; tdma; tdma = next) {
spin_lock_bh(&engine->lock);
next = tdma->next;
spin_unlock_bh(&engine->lock);
spin_lock_bh(&engine->lock); /* * if req is NULL, this means we're processing the * request in engine->req.
*/ if (!req)
req = engine->req; else
req = mv_cesa_dequeue_req_locked(engine,
&backlog);
/* Re-chaining to the next request */
engine->chain_hw.first = tdma->next;
tdma->next = NULL;
/* If this is the last request, clear the chain */ if (engine->chain_hw.first == NULL)
engine->chain_hw.last = NULL;
spin_unlock_bh(&engine->lock);
ctx = crypto_tfm_ctx(req->tfm);
current_status = (tdma->cur_dma == tdma_cur) ?
status : CESA_SA_INT_ACC0_IDMA_DONE;
res = ctx->ops->process(req, current_status);
ctx->ops->complete(req);
if (res == 0)
mv_cesa_engine_enqueue_complete_request(engine,
req);
if (backlog)
crypto_request_complete(backlog, -EINPROGRESS);
}
if (res || tdma->cur_dma == tdma_cur) break;
}
/* * Save the last request in error to engine->req, so that the core * knows which request was faulty
*/ if (res) {
spin_lock_bh(&engine->lock);
engine->req = req;
spin_unlock_bh(&engine->lock);
}
tdma = mv_cesa_dma_add_desc(chain, gfp_flags); if (IS_ERR(tdma)) return PTR_ERR(tdma);
/* We re-use an existing op_desc object to retrieve the context * and result instead of allocating a new one. * There is at least one object of this type in a CESA crypto * req, just pick the first one in the chain.
*/ for (op_desc = chain->first; op_desc; op_desc = op_desc->next) {
u32 type = op_desc->flags & CESA_TDMA_TYPE_MSK;
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.