Skip to content

Commit 8a6771c

Browse files
committed
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 <[email protected]>
1 parent dfd3bc6 commit 8a6771c

File tree

4 files changed

+184
-35
lines changed

4 files changed

+184
-35
lines changed

crypto/acompress.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/errno.h>
1313
#include <linux/kernel.h>
1414
#include <linux/module.h>
15+
#include <linux/page-flags.h>
1516
#include <linux/seq_file.h>
1617
#include <linux/slab.h>
1718
#include <linux/string.h>
@@ -189,25 +190,43 @@ static void acomp_reqchain_virt(struct acomp_req_chain *state, int err)
189190
req->base.err = err;
190191
state = &req->chain;
191192

192-
if (state->src)
193+
if (state->flags & CRYPTO_ACOMP_REQ_SRC_VIRT)
193194
acomp_request_set_src_dma(req, state->src, slen);
194-
if (state->dst)
195+
else if (state->flags & CRYPTO_ACOMP_REQ_SRC_FOLIO)
196+
acomp_request_set_src_folio(req, state->sfolio, state->soff, slen);
197+
if (state->flags & CRYPTO_ACOMP_REQ_DST_VIRT)
195198
acomp_request_set_dst_dma(req, state->dst, dlen);
196-
state->src = NULL;
197-
state->dst = NULL;
199+
else if (state->flags & CRYPTO_ACOMP_REQ_DST_FOLIO)
200+
acomp_request_set_dst_folio(req, state->dfolio, state->doff, dlen);
198201
}
199202

200203
static void acomp_virt_to_sg(struct acomp_req *req)
201204
{
202205
struct acomp_req_chain *state = &req->chain;
203206

207+
state->flags = req->base.flags & (CRYPTO_ACOMP_REQ_SRC_VIRT |
208+
CRYPTO_ACOMP_REQ_DST_VIRT |
209+
CRYPTO_ACOMP_REQ_SRC_FOLIO |
210+
CRYPTO_ACOMP_REQ_DST_FOLIO);
211+
204212
if (acomp_request_src_isvirt(req)) {
205213
unsigned int slen = req->slen;
206214
const u8 *svirt = req->svirt;
207215

208216
state->src = svirt;
209217
sg_init_one(&state->ssg, svirt, slen);
210218
acomp_request_set_src_sg(req, &state->ssg, slen);
219+
} else if (acomp_request_src_isfolio(req)) {
220+
struct folio *folio = req->sfolio;
221+
unsigned int slen = req->slen;
222+
size_t off = req->soff;
223+
224+
state->sfolio = folio;
225+
state->soff = off;
226+
sg_init_table(&state->ssg, 1);
227+
sg_set_page(&state->ssg, folio_page(folio, off / PAGE_SIZE),
228+
slen, off % PAGE_SIZE);
229+
acomp_request_set_src_sg(req, &state->ssg, slen);
211230
}
212231

213232
if (acomp_request_dst_isvirt(req)) {
@@ -217,6 +236,17 @@ static void acomp_virt_to_sg(struct acomp_req *req)
217236
state->dst = dvirt;
218237
sg_init_one(&state->dsg, dvirt, dlen);
219238
acomp_request_set_dst_sg(req, &state->dsg, dlen);
239+
} else if (acomp_request_dst_isfolio(req)) {
240+
struct folio *folio = req->dfolio;
241+
unsigned int dlen = req->dlen;
242+
size_t off = req->doff;
243+
244+
state->dfolio = folio;
245+
state->doff = off;
246+
sg_init_table(&state->dsg, 1);
247+
sg_set_page(&state->dsg, folio_page(folio, off / PAGE_SIZE),
248+
dlen, off % PAGE_SIZE);
249+
acomp_request_set_src_sg(req, &state->dsg, dlen);
220250
}
221251
}
222252

@@ -328,7 +358,7 @@ static int acomp_do_req_chain(struct acomp_req *req,
328358
int err;
329359

330360
if (crypto_acomp_req_chain(tfm) ||
331-
(!acomp_request_chained(req) && !acomp_request_isvirt(req)))
361+
(!acomp_request_chained(req) && acomp_request_issg(req)))
332362
return op(req);
333363

334364
if (acomp_is_async(tfm)) {

crypto/scompress.c

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,10 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
177177
unsigned int slen = req->slen;
178178
unsigned int dlen = req->dlen;
179179
struct page *spage, *dpage;
180-
unsigned int soff, doff;
181180
unsigned int n;
182181
const u8 *src;
182+
size_t soff;
183+
size_t doff;
183184
u8 *dst;
184185
int ret;
185186

@@ -192,38 +193,57 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
192193
if (acomp_request_src_isvirt(req))
193194
src = req->svirt;
194195
else {
195-
soff = req->src->offset;
196-
spage = nth_page(sg_page(req->src), soff / PAGE_SIZE);
197-
soff = offset_in_page(soff);
198-
199-
n = slen / PAGE_SIZE;
200-
n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE;
201-
if (slen <= req->src->length &&
202-
(!PageHighMem(nth_page(spage, n)) ||
203-
size_add(soff, slen) <= PAGE_SIZE))
196+
src = scratch->src;
197+
do {
198+
if (acomp_request_src_isfolio(req)) {
199+
spage = folio_page(req->sfolio, 0);
200+
soff = req->soff;
201+
} else if (slen <= req->src->length) {
202+
spage = sg_page(req->src);
203+
soff = req->src->offset;
204+
} else
205+
break;
206+
207+
spage = nth_page(spage, soff / PAGE_SIZE);
208+
soff = offset_in_page(soff);
209+
210+
n = slen / PAGE_SIZE;
211+
n += (offset_in_page(slen) + soff - 1) / PAGE_SIZE;
212+
if (PageHighMem(nth_page(spage, n)) &&
213+
size_add(soff, slen) > PAGE_SIZE)
214+
break;
204215
src = kmap_local_page(spage) + soff;
205-
else
206-
src = scratch->src;
216+
} while (0);
207217
}
208218

209219
if (acomp_request_dst_isvirt(req))
210220
dst = req->dvirt;
211221
else {
212-
doff = req->dst->offset;
213-
dpage = nth_page(sg_page(req->dst), doff / PAGE_SIZE);
214-
doff = offset_in_page(doff);
215-
216-
n = dlen / PAGE_SIZE;
217-
n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE;
218-
if (dlen <= req->dst->length &&
219-
(!PageHighMem(nth_page(dpage, n)) ||
220-
size_add(doff, dlen) <= PAGE_SIZE))
222+
unsigned int max = SCOMP_SCRATCH_SIZE;
223+
224+
dst = scratch->dst;
225+
do {
226+
if (acomp_request_dst_isfolio(req)) {
227+
dpage = folio_page(req->dfolio, 0);
228+
doff = req->doff;
229+
} else if (dlen <= req->dst->length) {
230+
dpage = sg_page(req->dst);
231+
doff = req->dst->offset;
232+
} else
233+
break;
234+
235+
dpage = nth_page(dpage, doff / PAGE_SIZE);
236+
doff = offset_in_page(doff);
237+
238+
n = dlen / PAGE_SIZE;
239+
n += (offset_in_page(dlen) + doff - 1) / PAGE_SIZE;
240+
if (PageHighMem(dpage + n) &&
241+
size_add(doff, dlen) > PAGE_SIZE)
242+
break;
221243
dst = kmap_local_page(dpage) + doff;
222-
else {
223-
if (dlen > SCOMP_SCRATCH_SIZE)
224-
dlen = SCOMP_SCRATCH_SIZE;
225-
dst = scratch->dst;
226-
}
244+
max = dlen;
245+
} while (0);
246+
dlen = min(dlen, max);
227247
}
228248

229249
spin_lock_bh(&scratch->lock);

include/crypto/acompress.h

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
/* Set this bit for if virtual address destination cannot be used for DMA. */
3333
#define CRYPTO_ACOMP_REQ_DST_NONDMA 0x00000010
3434

35+
/* Set this bit if source is a folio. */
36+
#define CRYPTO_ACOMP_REQ_SRC_FOLIO 0x00000020
37+
38+
/* Set this bit if destination is a folio. */
39+
#define CRYPTO_ACOMP_REQ_DST_FOLIO 0x00000040
40+
3541
#define CRYPTO_ACOMP_DST_MAX 131072
3642

3743
#define MAX_SYNC_COMP_REQSIZE 0
@@ -43,6 +49,7 @@
4349
__##name##_req, (tfm), (gfp), false)
4450

4551
struct acomp_req;
52+
struct folio;
4653

4754
struct acomp_req_chain {
4855
struct list_head head;
@@ -53,16 +60,31 @@ struct acomp_req_chain {
5360
void *data;
5461
struct scatterlist ssg;
5562
struct scatterlist dsg;
56-
const u8 *src;
57-
u8 *dst;
63+
union {
64+
const u8 *src;
65+
struct folio *sfolio;
66+
};
67+
union {
68+
u8 *dst;
69+
struct folio *dfolio;
70+
};
71+
size_t soff;
72+
size_t doff;
73+
u32 flags;
5874
};
5975

6076
/**
6177
* struct acomp_req - asynchronous (de)compression request
6278
*
6379
* @base: Common attributes for asynchronous crypto requests
64-
* @src: Source Data
65-
* @dst: Destination data
80+
* @src: Source scatterlist
81+
* @dst: Destination scatterlist
82+
* @svirt: Source virtual address
83+
* @dvirt: Destination virtual address
84+
* @sfolio: Source folio
85+
* @soff: Source folio offset
86+
* @dfolio: Destination folio
87+
* @doff: Destination folio offset
6688
* @slen: Size of the input buffer
6789
* @dlen: Size of the output buffer and number of bytes produced
6890
* @chain: Private API code data, do not use
@@ -73,11 +95,15 @@ struct acomp_req {
7395
union {
7496
struct scatterlist *src;
7597
const u8 *svirt;
98+
struct folio *sfolio;
7699
};
77100
union {
78101
struct scatterlist *dst;
79102
u8 *dvirt;
103+
struct folio *dfolio;
80104
};
105+
size_t soff;
106+
size_t doff;
81107
unsigned int slen;
82108
unsigned int dlen;
83109

@@ -316,6 +342,7 @@ static inline void acomp_request_set_callback(struct acomp_req *req,
316342
{
317343
u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT | CRYPTO_ACOMP_REQ_SRC_NONDMA |
318344
CRYPTO_ACOMP_REQ_DST_VIRT | CRYPTO_ACOMP_REQ_DST_NONDMA |
345+
CRYPTO_ACOMP_REQ_SRC_FOLIO | CRYPTO_ACOMP_REQ_DST_FOLIO |
319346
CRYPTO_TFM_REQ_ON_STACK;
320347

321348
req->base.complete = cmpl;
@@ -352,6 +379,8 @@ static inline void acomp_request_set_params(struct acomp_req *req,
352379

353380
req->base.flags &= ~(CRYPTO_ACOMP_REQ_SRC_VIRT |
354381
CRYPTO_ACOMP_REQ_SRC_NONDMA |
382+
CRYPTO_ACOMP_REQ_SRC_FOLIO |
383+
CRYPTO_ACOMP_REQ_DST_FOLIO |
355384
CRYPTO_ACOMP_REQ_DST_VIRT |
356385
CRYPTO_ACOMP_REQ_DST_NONDMA);
357386
}
@@ -374,6 +403,7 @@ static inline void acomp_request_set_src_sg(struct acomp_req *req,
374403

375404
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_NONDMA;
376405
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_VIRT;
406+
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_FOLIO;
377407
}
378408

379409
/**
@@ -393,6 +423,7 @@ static inline void acomp_request_set_src_dma(struct acomp_req *req,
393423
req->slen = slen;
394424

395425
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_NONDMA;
426+
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_FOLIO;
396427
req->base.flags |= CRYPTO_ACOMP_REQ_SRC_VIRT;
397428
}
398429

@@ -413,10 +444,34 @@ static inline void acomp_request_set_src_nondma(struct acomp_req *req,
413444
req->svirt = src;
414445
req->slen = slen;
415446

447+
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_FOLIO;
416448
req->base.flags |= CRYPTO_ACOMP_REQ_SRC_NONDMA;
417449
req->base.flags |= CRYPTO_ACOMP_REQ_SRC_VIRT;
418450
}
419451

452+
/**
453+
* acomp_request_set_src_folio() -- Sets source folio
454+
*
455+
* Sets source folio required by an acomp operation.
456+
*
457+
* @req: asynchronous compress request
458+
* @folio: pointer to input folio
459+
* @off: input folio offset
460+
* @len: size of the input buffer
461+
*/
462+
static inline void acomp_request_set_src_folio(struct acomp_req *req,
463+
struct folio *folio, size_t off,
464+
unsigned int len)
465+
{
466+
req->sfolio = folio;
467+
req->soff = off;
468+
req->slen = len;
469+
470+
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_NONDMA;
471+
req->base.flags &= ~CRYPTO_ACOMP_REQ_SRC_VIRT;
472+
req->base.flags |= CRYPTO_ACOMP_REQ_SRC_FOLIO;
473+
}
474+
420475
/**
421476
* acomp_request_set_dst_sg() -- Sets destination scatterlist
422477
*
@@ -435,6 +490,7 @@ static inline void acomp_request_set_dst_sg(struct acomp_req *req,
435490

436491
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_NONDMA;
437492
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_VIRT;
493+
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_FOLIO;
438494
}
439495

440496
/**
@@ -454,6 +510,7 @@ static inline void acomp_request_set_dst_dma(struct acomp_req *req,
454510
req->dlen = dlen;
455511

456512
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_NONDMA;
513+
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_FOLIO;
457514
req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT;
458515
}
459516

@@ -473,10 +530,34 @@ static inline void acomp_request_set_dst_nondma(struct acomp_req *req,
473530
req->dvirt = dst;
474531
req->dlen = dlen;
475532

533+
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_FOLIO;
476534
req->base.flags |= CRYPTO_ACOMP_REQ_DST_NONDMA;
477535
req->base.flags |= CRYPTO_ACOMP_REQ_DST_VIRT;
478536
}
479537

538+
/**
539+
* acomp_request_set_dst_folio() -- Sets destination folio
540+
*
541+
* Sets destination folio required by an acomp operation.
542+
*
543+
* @req: asynchronous compress request
544+
* @folio: pointer to input folio
545+
* @off: input folio offset
546+
* @len: size of the input buffer
547+
*/
548+
static inline void acomp_request_set_dst_folio(struct acomp_req *req,
549+
struct folio *folio, size_t off,
550+
unsigned int len)
551+
{
552+
req->dfolio = folio;
553+
req->doff = off;
554+
req->dlen = len;
555+
556+
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_NONDMA;
557+
req->base.flags &= ~CRYPTO_ACOMP_REQ_DST_VIRT;
558+
req->base.flags |= CRYPTO_ACOMP_REQ_DST_FOLIO;
559+
}
560+
480561
static inline void acomp_request_chain(struct acomp_req *req,
481562
struct acomp_req *head)
482563
{

0 commit comments

Comments
 (0)