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>pull/1188/head
parent
dfd28c89fa
commit
dfd3bc6977
|
|
@ -152,20 +152,6 @@ struct crypto_acomp *crypto_alloc_acomp_node(const char *alg_name, u32 type,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_alloc_acomp_node);
|
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)
|
static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt)
|
||||||
{
|
{
|
||||||
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
|
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,
|
static int acomp_reqchain_finish(struct acomp_req_chain *state,
|
||||||
int err, u32 mask)
|
int err, u32 mask)
|
||||||
{
|
{
|
||||||
|
|
@ -252,10 +277,8 @@ static int acomp_reqchain_finish(struct acomp_req_chain *state,
|
||||||
req->base.flags &= mask;
|
req->base.flags &= mask;
|
||||||
req->base.complete = acomp_reqchain_done;
|
req->base.complete = acomp_reqchain_done;
|
||||||
req->base.data = state;
|
req->base.data = state;
|
||||||
state->cur = req;
|
|
||||||
|
|
||||||
acomp_virt_to_sg(req);
|
err = acomp_do_one_req(state, req);
|
||||||
err = state->op(req);
|
|
||||||
|
|
||||||
if (err == -EINPROGRESS) {
|
if (err == -EINPROGRESS) {
|
||||||
if (!list_empty(&state->head))
|
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)))
|
(!acomp_request_chained(req) && !acomp_request_isvirt(req)))
|
||||||
return op(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)) {
|
if (acomp_is_async(tfm)) {
|
||||||
acomp_save_req(req, acomp_reqchain_done);
|
acomp_save_req(req, acomp_reqchain_done);
|
||||||
state = req->base.data;
|
state = req->base.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->op = op;
|
state->op = op;
|
||||||
state->cur = req;
|
|
||||||
state->src = NULL;
|
state->src = NULL;
|
||||||
INIT_LIST_HEAD(&state->head);
|
INIT_LIST_HEAD(&state->head);
|
||||||
list_splice_init(&req->base.list, &state->head);
|
list_splice_init(&req->base.list, &state->head);
|
||||||
|
|
||||||
acomp_virt_to_sg(req);
|
err = acomp_do_one_req(state, req);
|
||||||
err = op(req);
|
|
||||||
if (err == -EBUSY || err == -EINPROGRESS)
|
if (err == -EBUSY || err == -EINPROGRESS)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue