Loading crypto/acompress.c +116 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <crypto/internal/acompress.h> #include <crypto/scatterwalk.h> #include <linux/cryptouser.h> #include <linux/cpumask.h> #include <linux/errno.h> Loading @@ -15,6 +16,8 @@ #include <linux/module.h> #include <linux/page-flags.h> #include <linux/percpu.h> #include <linux/scatterlist.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/smp.h> Loading @@ -27,6 +30,14 @@ struct crypto_scomp; enum { ACOMP_WALK_SLEEP = 1 << 0, ACOMP_WALK_SRC_LINEAR = 1 << 1, ACOMP_WALK_SRC_FOLIO = 1 << 2, ACOMP_WALK_DST_LINEAR = 1 << 3, ACOMP_WALK_DST_FOLIO = 1 << 4, }; static const struct crypto_type crypto_acomp_type; static void acomp_reqchain_done(void *data, int err); Loading Loading @@ -546,5 +557,110 @@ struct crypto_acomp_stream *crypto_acomp_lock_stream_bh( } EXPORT_SYMBOL_GPL(crypto_acomp_lock_stream_bh); void acomp_walk_done_src(struct acomp_walk *walk, int used) { walk->slen -= used; if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) scatterwalk_advance(&walk->in, used); else scatterwalk_done_src(&walk->in, used); if ((walk->flags & ACOMP_WALK_SLEEP)) cond_resched(); } EXPORT_SYMBOL_GPL(acomp_walk_done_src); void acomp_walk_done_dst(struct acomp_walk *walk, int used) { walk->dlen -= used; if ((walk->flags & ACOMP_WALK_DST_LINEAR)) scatterwalk_advance(&walk->out, used); else scatterwalk_done_dst(&walk->out, used); if ((walk->flags & ACOMP_WALK_SLEEP)) cond_resched(); } EXPORT_SYMBOL_GPL(acomp_walk_done_dst); int acomp_walk_next_src(struct acomp_walk *walk) { unsigned int slen = walk->slen; unsigned int max = UINT_MAX; if (!preempt_model_preemptible() && (walk->flags & ACOMP_WALK_SLEEP)) max = PAGE_SIZE; if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) { walk->in.__addr = (void *)(((u8 *)walk->in.sg) + walk->in.offset); return min(slen, max); } return slen ? scatterwalk_next(&walk->in, slen) : 0; } EXPORT_SYMBOL_GPL(acomp_walk_next_src); int acomp_walk_next_dst(struct acomp_walk *walk) { unsigned int dlen = walk->dlen; unsigned int max = UINT_MAX; if (!preempt_model_preemptible() && (walk->flags & ACOMP_WALK_SLEEP)) max = PAGE_SIZE; if ((walk->flags & ACOMP_WALK_DST_LINEAR)) { walk->out.__addr = (void *)(((u8 *)walk->out.sg) + walk->out.offset); return min(dlen, max); } return dlen ? scatterwalk_next(&walk->out, dlen) : 0; } EXPORT_SYMBOL_GPL(acomp_walk_next_dst); int acomp_walk_virt(struct acomp_walk *__restrict walk, struct acomp_req *__restrict req) { struct scatterlist *src = req->src; struct scatterlist *dst = req->dst; walk->slen = req->slen; walk->dlen = req->dlen; if (!walk->slen || !walk->dlen) return -EINVAL; walk->flags = 0; if ((req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP)) walk->flags |= ACOMP_WALK_SLEEP; if ((req->base.flags & CRYPTO_ACOMP_REQ_SRC_VIRT)) walk->flags |= ACOMP_WALK_SRC_LINEAR; else if ((req->base.flags & CRYPTO_ACOMP_REQ_SRC_FOLIO)) { src = &req->chain.ssg; sg_init_table(src, 1); sg_set_folio(src, req->sfolio, walk->slen, req->soff); } if ((req->base.flags & CRYPTO_ACOMP_REQ_DST_VIRT)) walk->flags |= ACOMP_WALK_DST_LINEAR; else if ((req->base.flags & CRYPTO_ACOMP_REQ_DST_FOLIO)) { dst = &req->chain.dsg; sg_init_table(dst, 1); sg_set_folio(dst, req->dfolio, walk->dlen, req->doff); } if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) { walk->in.sg = (void *)req->svirt; walk->in.offset = 0; } else scatterwalk_start(&walk->in, src); if ((walk->flags & ACOMP_WALK_DST_LINEAR)) { walk->out.sg = (void *)req->dvirt; walk->out.offset = 0; } else scatterwalk_start(&walk->out, dst); return 0; } EXPORT_SYMBOL_GPL(acomp_walk_virt); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Asynchronous compression type"); include/crypto/internal/acompress.h +44 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <crypto/acompress.h> #include <crypto/algapi.h> #include <crypto/scatterwalk.h> #include <linux/compiler_types.h> #include <linux/cpumask_types.h> #include <linux/spinlock.h> Loading Loading @@ -75,6 +76,37 @@ struct crypto_acomp_streams { cpumask_t stream_want; }; struct acomp_walk { union { /* Virtual address of the source. */ struct { struct { const void *const addr; } virt; } src; /* Private field for the API, do not use. */ struct scatter_walk in; }; union { /* Virtual address of the destination. */ struct { struct { void *const addr; } virt; } dst; /* Private field for the API, do not use. */ struct scatter_walk out; }; unsigned int slen; unsigned int dlen; int flags; }; /* * Transform internal helpers. */ Loading Loading @@ -190,4 +222,16 @@ static inline void crypto_acomp_unlock_stream_bh( { spin_unlock_bh(&stream->lock); } void acomp_walk_done_src(struct acomp_walk *walk, int used); void acomp_walk_done_dst(struct acomp_walk *walk, int used); int acomp_walk_next_src(struct acomp_walk *walk); int acomp_walk_next_dst(struct acomp_walk *walk); int acomp_walk_virt(struct acomp_walk *__restrict walk, struct acomp_req *__restrict req); static inline bool acomp_walk_more_src(const struct acomp_walk *walk, int cur) { return walk->slen != cur; } #endif Loading
crypto/acompress.c +116 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <crypto/internal/acompress.h> #include <crypto/scatterwalk.h> #include <linux/cryptouser.h> #include <linux/cpumask.h> #include <linux/errno.h> Loading @@ -15,6 +16,8 @@ #include <linux/module.h> #include <linux/page-flags.h> #include <linux/percpu.h> #include <linux/scatterlist.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/smp.h> Loading @@ -27,6 +30,14 @@ struct crypto_scomp; enum { ACOMP_WALK_SLEEP = 1 << 0, ACOMP_WALK_SRC_LINEAR = 1 << 1, ACOMP_WALK_SRC_FOLIO = 1 << 2, ACOMP_WALK_DST_LINEAR = 1 << 3, ACOMP_WALK_DST_FOLIO = 1 << 4, }; static const struct crypto_type crypto_acomp_type; static void acomp_reqchain_done(void *data, int err); Loading Loading @@ -546,5 +557,110 @@ struct crypto_acomp_stream *crypto_acomp_lock_stream_bh( } EXPORT_SYMBOL_GPL(crypto_acomp_lock_stream_bh); void acomp_walk_done_src(struct acomp_walk *walk, int used) { walk->slen -= used; if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) scatterwalk_advance(&walk->in, used); else scatterwalk_done_src(&walk->in, used); if ((walk->flags & ACOMP_WALK_SLEEP)) cond_resched(); } EXPORT_SYMBOL_GPL(acomp_walk_done_src); void acomp_walk_done_dst(struct acomp_walk *walk, int used) { walk->dlen -= used; if ((walk->flags & ACOMP_WALK_DST_LINEAR)) scatterwalk_advance(&walk->out, used); else scatterwalk_done_dst(&walk->out, used); if ((walk->flags & ACOMP_WALK_SLEEP)) cond_resched(); } EXPORT_SYMBOL_GPL(acomp_walk_done_dst); int acomp_walk_next_src(struct acomp_walk *walk) { unsigned int slen = walk->slen; unsigned int max = UINT_MAX; if (!preempt_model_preemptible() && (walk->flags & ACOMP_WALK_SLEEP)) max = PAGE_SIZE; if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) { walk->in.__addr = (void *)(((u8 *)walk->in.sg) + walk->in.offset); return min(slen, max); } return slen ? scatterwalk_next(&walk->in, slen) : 0; } EXPORT_SYMBOL_GPL(acomp_walk_next_src); int acomp_walk_next_dst(struct acomp_walk *walk) { unsigned int dlen = walk->dlen; unsigned int max = UINT_MAX; if (!preempt_model_preemptible() && (walk->flags & ACOMP_WALK_SLEEP)) max = PAGE_SIZE; if ((walk->flags & ACOMP_WALK_DST_LINEAR)) { walk->out.__addr = (void *)(((u8 *)walk->out.sg) + walk->out.offset); return min(dlen, max); } return dlen ? scatterwalk_next(&walk->out, dlen) : 0; } EXPORT_SYMBOL_GPL(acomp_walk_next_dst); int acomp_walk_virt(struct acomp_walk *__restrict walk, struct acomp_req *__restrict req) { struct scatterlist *src = req->src; struct scatterlist *dst = req->dst; walk->slen = req->slen; walk->dlen = req->dlen; if (!walk->slen || !walk->dlen) return -EINVAL; walk->flags = 0; if ((req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP)) walk->flags |= ACOMP_WALK_SLEEP; if ((req->base.flags & CRYPTO_ACOMP_REQ_SRC_VIRT)) walk->flags |= ACOMP_WALK_SRC_LINEAR; else if ((req->base.flags & CRYPTO_ACOMP_REQ_SRC_FOLIO)) { src = &req->chain.ssg; sg_init_table(src, 1); sg_set_folio(src, req->sfolio, walk->slen, req->soff); } if ((req->base.flags & CRYPTO_ACOMP_REQ_DST_VIRT)) walk->flags |= ACOMP_WALK_DST_LINEAR; else if ((req->base.flags & CRYPTO_ACOMP_REQ_DST_FOLIO)) { dst = &req->chain.dsg; sg_init_table(dst, 1); sg_set_folio(dst, req->dfolio, walk->dlen, req->doff); } if ((walk->flags & ACOMP_WALK_SRC_LINEAR)) { walk->in.sg = (void *)req->svirt; walk->in.offset = 0; } else scatterwalk_start(&walk->in, src); if ((walk->flags & ACOMP_WALK_DST_LINEAR)) { walk->out.sg = (void *)req->dvirt; walk->out.offset = 0; } else scatterwalk_start(&walk->out, dst); return 0; } EXPORT_SYMBOL_GPL(acomp_walk_virt); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Asynchronous compression type");
include/crypto/internal/acompress.h +44 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <crypto/acompress.h> #include <crypto/algapi.h> #include <crypto/scatterwalk.h> #include <linux/compiler_types.h> #include <linux/cpumask_types.h> #include <linux/spinlock.h> Loading Loading @@ -75,6 +76,37 @@ struct crypto_acomp_streams { cpumask_t stream_want; }; struct acomp_walk { union { /* Virtual address of the source. */ struct { struct { const void *const addr; } virt; } src; /* Private field for the API, do not use. */ struct scatter_walk in; }; union { /* Virtual address of the destination. */ struct { struct { void *const addr; } virt; } dst; /* Private field for the API, do not use. */ struct scatter_walk out; }; unsigned int slen; unsigned int dlen; int flags; }; /* * Transform internal helpers. */ Loading Loading @@ -190,4 +222,16 @@ static inline void crypto_acomp_unlock_stream_bh( { spin_unlock_bh(&stream->lock); } void acomp_walk_done_src(struct acomp_walk *walk, int used); void acomp_walk_done_dst(struct acomp_walk *walk, int used); int acomp_walk_next_src(struct acomp_walk *walk); int acomp_walk_next_dst(struct acomp_walk *walk); int acomp_walk_virt(struct acomp_walk *__restrict walk, struct acomp_req *__restrict req); static inline bool acomp_walk_more_src(const struct acomp_walk *walk, int cur) { return walk->slen != cur; } #endif