summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2025-03-15 18:30:40 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2025-03-21 17:35:26 +0800
commit8a6771cda3f48a4d954647d69ff0094346db6191 (patch)
treeda7a3debcf41d3f1cef1e8e25368935b299d197f /crypto
parentdfd3bc6977e8b99458169c19cd703d34ffa86acc (diff)
crypto: acomp - Add support for folios
For many users, it's easier to supply a folio rather than an SG list since they already have them. Add support for folios to the acomp interface. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/acompress.c40
-rw-r--r--crypto/scompress.c72
2 files changed, 81 insertions, 31 deletions
diff --git a/crypto/acompress.c b/crypto/acompress.c
index d54abc27330f..6ef335f5bf27 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/page-flags.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -189,18 +190,25 @@ static void acomp_reqchain_virt(struct acomp_req_chain *state, int err)
req->base.err = err;
state = &req->chain;
- if (state->src)
+ if (state->flags & CRYPTO_ACOMP_REQ_SRC_VIRT)
acomp_request_set_src_dma(req, state->src, slen);
- if (state->dst)
+ else if (state->flags & CRYPTO_ACOMP_REQ_SRC_FOLIO)
+ acomp_request_set_src_folio(req, state->sfolio, state->soff, slen);
+ if (state->flags & CRYPTO_ACOMP_REQ_DST_VIRT)
acomp_request_set_dst_dma(req, state->dst, dlen);
- state->src = NULL;
- state->dst = NULL;
+ else if (state->flags & CRYPTO_ACOMP_REQ_DST_FOLIO)
+ acomp_request_set_dst_folio(req, state->dfolio, state->doff, dlen);
}
static void acomp_virt_to_sg(struct acomp_req *req)
{
struct acomp_req_chain *state = &req->chain;
+ state->flags = req->base.flags & (CRYPTO_ACOMP_REQ_SRC_VIRT |
+ CRYPTO_ACOMP_REQ_DST_VIRT |
+ CRYPTO_ACOMP_REQ_SRC_FOLIO |
+ CRYPTO_ACOMP_REQ_DST_FOLIO);
+
if (acomp_request_src_isvirt(req)) {
unsigned int slen = req->slen;
const u8 *svirt = req->svirt;
@@ -208,6 +216,17 @@ static void acomp_virt_to_sg(struct acomp_req *req)
state->src = svirt;
sg_init_one(&state->ssg, svirt, slen);
acomp_request_set_src_sg(req, &state->ssg, slen);
+ } else if (acomp_request_src_isfolio(req)) {
+ struct folio *folio = req->sfolio;
+ unsigned int slen = req->slen;
+ size_t off = req->soff;
+
+ state->sfolio = folio;
+ state->soff = off;
+ sg_init_table(&state->ssg, 1);
+ sg_set_page(&state->ssg, folio_page(folio, off / PAGE_SIZE),
+ slen, off % PAGE_SIZE);
+ acomp_request_set_src_sg(req, &state->ssg, slen);
}
if (acomp_request_dst_isvirt(req)) {
@@ -217,6 +236,17 @@ static void acomp_virt_to_sg(struct acomp_req *req)
state->dst = dvirt;
sg_init_one(&state->dsg, dvirt, dlen);
acomp_request_set_dst_sg(req, &state->dsg, dlen);
+ } else if (acomp_request_dst_isfolio(req)) {
+ struct folio *folio = req->dfolio;
+ unsigned int dlen = req->dlen;
+ size_t off = req->doff;
+
+ state->dfolio = folio;
+ state->doff = off;
+ sg_init_table(&state->dsg, 1);
+ sg_set_page(&state->dsg, folio_page(folio, off / PAGE_SIZE),
+ dlen, off % PAGE_SIZE);
+ acomp_request_set_src_sg(req, &state->dsg, dlen);
}
}
@@ -328,7 +358,7 @@ static int acomp_do_req_chain(struct acomp_req *req,
int err;
if (crypto_acomp_req_chain(tfm) ||
- (!acomp_request_chained(req) && !acomp_request_isvirt(req)))
+ (!acomp_request_chained(req) && acomp_request_issg(req)))
return op(req);
if (acomp_is_async(tfm)) {
diff --git a/crypto/scompress.c b/crypto/scompress.c
index ba9b22ba53fe..f85cc0d83164 100644
--- a/crypto/scompress.c
+++ b/crypto/scompress.c
@@ -177,9 +177,10 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
unsigned int slen = req->slen;
unsigned int dlen = req->dlen;
struct page *spage, *dpage;
- unsigned int soff, doff;
unsigned int n;
const u8 *src;
+ size_t soff;
+ size_t doff;
u8 *dst;
int ret;
@@ -192,38 +193,57 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
if (acomp_request_src_isvirt(req))
src = req->svirt;
else {
- soff = req->src->offset;
- spage = nth_page(sg_page(req->src), soff / PAGE_SIZE);
- soff = offset_in_page(soff);
-
- n = slen / PAGE_SIZE;
- n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE;
- if (slen <= req->src->length &&
- (!PageHighMem(nth_page(spage, n)) ||
- size_add(soff, slen) <= PAGE_SIZE))
+ src = scratch->src;
+ do {
+ if (acomp_request_src_isfolio(req)) {
+ spage = folio_page(req->sfolio, 0);
+ soff = req->soff;
+ } else if (slen <= req->src->length) {
+ spage = sg_page(req->src);
+ soff = req->src->offset;
+ } else
+ break;
+
+ spage = nth_page(spage, soff / PAGE_SIZE);
+ soff = offset_in_page(soff);
+
+ n = slen / PAGE_SIZE;
+ n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE;
+ if (PageHighMem(nth_page(spage, n)) &&
+ size_add(soff, slen) > PAGE_SIZE)
+ break;
src = kmap_local_page(spage) + soff;
- else
- src = scratch->src;
+ } while (0);
}
if (acomp_request_dst_isvirt(req))
dst = req->dvirt;
else {
- doff = req->dst->offset;
- dpage = nth_page(sg_page(req->dst), doff / PAGE_SIZE);
- doff = offset_in_page(doff);
-
- n = dlen / PAGE_SIZE;
- n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE;
- if (dlen <= req->dst->length &&
- (!PageHighMem(nth_page(dpage, n)) ||
- size_add(doff, dlen) <= PAGE_SIZE))
+ unsigned int max = SCOMP_SCRATCH_SIZE;
+
+ dst = scratch->dst;
+ do {
+ if (acomp_request_dst_isfolio(req)) {
+ dpage = folio_page(req->dfolio, 0);
+ doff = req->doff;
+ } else if (dlen <= req->dst->length) {
+ dpage = sg_page(req->dst);
+ doff = req->dst->offset;
+ } else
+ break;
+
+ dpage = nth_page(dpage, doff / PAGE_SIZE);
+ doff = offset_in_page(doff);
+
+ n = dlen / PAGE_SIZE;
+ n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE;
+ if (PageHighMem(dpage + n) &&
+ size_add(doff, dlen) > PAGE_SIZE)
+ break;
dst = kmap_local_page(dpage) + doff;
- else {
- if (dlen > SCOMP_SCRATCH_SIZE)
- dlen = SCOMP_SCRATCH_SIZE;
- dst = scratch->dst;
- }
+ max = dlen;
+ } while (0);
+ dlen = min(dlen, max);
}
spin_lock_bh(&scratch->lock);