mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
crypto: acomp - Add async nondma fallback
Add support for passing non-DMA virtual addresses to async drivers by passing them along to the fallback software algorithm. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -152,20 +152,6 @@ struct crypto_acomp *crypto_alloc_acomp_node(const char *alg_name, u32 type,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alloc_acomp_node);
|
||||
|
||||
static bool acomp_request_has_nondma(struct acomp_req *req)
|
||||
{
|
||||
struct acomp_req *r2;
|
||||
|
||||
if (acomp_request_isnondma(req))
|
||||
return true;
|
||||
|
||||
list_for_each_entry(r2, &req->base.list, base.list)
|
||||
if (acomp_request_isnondma(r2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt)
|
||||
{
|
||||
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
|
||||
@@ -234,6 +220,45 @@ static void acomp_virt_to_sg(struct acomp_req *req)
|
||||
}
|
||||
}
|
||||
|
||||
static int acomp_do_nondma(struct acomp_req_chain *state,
|
||||
struct acomp_req *req)
|
||||
{
|
||||
u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT |
|
||||
CRYPTO_ACOMP_REQ_SRC_NONDMA |
|
||||
CRYPTO_ACOMP_REQ_DST_VIRT |
|
||||
CRYPTO_ACOMP_REQ_DST_NONDMA;
|
||||
ACOMP_REQUEST_ON_STACK(fbreq, crypto_acomp_reqtfm(req));
|
||||
int err;
|
||||
|
||||
acomp_request_set_callback(fbreq, req->base.flags, NULL, NULL);
|
||||
fbreq->base.flags &= ~keep;
|
||||
fbreq->base.flags |= req->base.flags & keep;
|
||||
fbreq->src = req->src;
|
||||
fbreq->dst = req->dst;
|
||||
fbreq->slen = req->slen;
|
||||
fbreq->dlen = req->dlen;
|
||||
|
||||
if (state->op == crypto_acomp_reqtfm(req)->compress)
|
||||
err = crypto_acomp_compress(fbreq);
|
||||
else
|
||||
err = crypto_acomp_decompress(fbreq);
|
||||
|
||||
req->dlen = fbreq->dlen;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int acomp_do_one_req(struct acomp_req_chain *state,
|
||||
struct acomp_req *req)
|
||||
{
|
||||
state->cur = req;
|
||||
|
||||
if (acomp_request_isnondma(req))
|
||||
return acomp_do_nondma(state, req);
|
||||
|
||||
acomp_virt_to_sg(req);
|
||||
return state->op(req);
|
||||
}
|
||||
|
||||
static int acomp_reqchain_finish(struct acomp_req_chain *state,
|
||||
int err, u32 mask)
|
||||
{
|
||||
@@ -252,10 +277,8 @@ static int acomp_reqchain_finish(struct acomp_req_chain *state,
|
||||
req->base.flags &= mask;
|
||||
req->base.complete = acomp_reqchain_done;
|
||||
req->base.data = state;
|
||||
state->cur = req;
|
||||
|
||||
acomp_virt_to_sg(req);
|
||||
err = state->op(req);
|
||||
err = acomp_do_one_req(state, req);
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
if (!list_empty(&state->head))
|
||||
@@ -308,27 +331,17 @@ static int acomp_do_req_chain(struct acomp_req *req,
|
||||
(!acomp_request_chained(req) && !acomp_request_isvirt(req)))
|
||||
return op(req);
|
||||
|
||||
/*
|
||||
* There are no in-kernel users that do this. If and ever
|
||||
* such users come into being then we could add a fall-back
|
||||
* path.
|
||||
*/
|
||||
if (acomp_request_has_nondma(req))
|
||||
return -EINVAL;
|
||||
|
||||
if (acomp_is_async(tfm)) {
|
||||
acomp_save_req(req, acomp_reqchain_done);
|
||||
state = req->base.data;
|
||||
}
|
||||
|
||||
state->op = op;
|
||||
state->cur = req;
|
||||
state->src = NULL;
|
||||
INIT_LIST_HEAD(&state->head);
|
||||
list_splice_init(&req->base.list, &state->head);
|
||||
|
||||
acomp_virt_to_sg(req);
|
||||
err = op(req);
|
||||
err = acomp_do_one_req(state, req);
|
||||
if (err == -EBUSY || err == -EINPROGRESS)
|
||||
return -EBUSY;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user