Compare commits

...

9 Commits

Author SHA1 Message Date
Herbert Xu
324216a6b8 crypto: scomp - Drop the dst scratch buffer
As deflate has been converted over to acomp, and cavium zip has been
removed, there are no longer any scomp algorithms that can be used
by IPsec.

Since IPsec was the only user of the dst scratch buffer, remove it.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:55 +08:00
Herbert Xu
5e69de5eb7 crypto: cavium/zip - Remove driver
Remove cavium/zip as it is obsolete and stands in the way of
acomp API work.  If this is ever resurrected, please turn it
into an acomp driver.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:55 +08:00
Herbert Xu
4da75ae038 crypto: cavium - Move cpt and nitrox rules into cavium Makefile
Move the cpt and nitrox rules into the cavium Makefile.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:55 +08:00
Herbert Xu
b9ee7aacd4 crypto: deflate - Convert to acomp
This is based on work by Ard Biesheuvel <ardb@kernel.org>.

Convert deflate from scomp to acomp.  This removes the need for
the caller to linearise the source and destination.

Link: https://lore.kernel.org/all/20230718125847.3869700-21-ardb@kernel.org/
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:55 +08:00
Herbert Xu
2be1b77bcd crypto: acomp - Add acomp_walk
Add acomp_walk which is similar to skcipher_walk but tailored for
acomp.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:55 +08:00
Herbert Xu
662361605b crypto: acomp - Move scomp stream allocation code into acomp
Move the dynamic stream allocation code into acomp and make it
available as a helper for acomp algorithms.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:54 +08:00
Herbert Xu
a545074ee7 crypto: scomp - Allocate per-cpu buffer on first use of each CPU
Per-cpu buffers can be wasteful when the number of CPUs is large,
especially if the buffer itself is likely to never be used.  Reduce
such wastage by only allocating them on first use of a particular
CPU.

On start-up allocate a single buffer on the first possible CPU.
For every other CPU a work struct will be scheduled on first use
to allocate the buffer for that CPU.  Until the allocation succeeds
simply use the first CPU's buffer which is protected under a spin
lock.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:54 +08:00
Herbert Xu
51768a21f4 crypto: api - Ensure cra_type->destroy is done in process context
Move the cra_type->destroy call out of crypto_alg_put and into
crypto_unregister_alg and crypto_free_instance.  This ensures
that it's always done in process context so calls such as flush_work
can be done.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:54 +08:00
Herbert Xu
d24f97c031 crypto: api - Move alg destroy work from instance to template
Commit 9ae4577bc0 ("crypto: api - Use work queue in
crypto_destroy_instance") introduced a work struct to free an
instance after the last user goes away.

Move the delayed work from the instance into its template so that
when the template is unregistered it can ensure that all its
instances have been freed before returning.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2025-03-22 07:28:54 +08:00
28 changed files with 684 additions and 4049 deletions

View File

@@ -8,20 +8,36 @@
*/
#include <crypto/internal/acompress.h>
#include <crypto/scatterwalk.h>
#include <linux/cryptouser.h>
#include <linux/cpumask.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#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>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <net/netlink.h>
#include "compress.h"
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);
@@ -434,5 +450,217 @@ void crypto_unregister_acomps(struct acomp_alg *algs, int count)
}
EXPORT_SYMBOL_GPL(crypto_unregister_acomps);
static void acomp_stream_workfn(struct work_struct *work)
{
struct crypto_acomp_streams *s =
container_of(work, struct crypto_acomp_streams, stream_work);
struct crypto_acomp_stream __percpu *streams = s->streams;
int cpu;
for_each_cpu(cpu, &s->stream_want) {
struct crypto_acomp_stream *ps;
void *ctx;
ps = per_cpu_ptr(streams, cpu);
if (ps->ctx)
continue;
ctx = s->alloc_ctx();
if (IS_ERR(ctx))
break;
spin_lock_bh(&ps->lock);
ps->ctx = ctx;
spin_unlock_bh(&ps->lock);
cpumask_clear_cpu(cpu, &s->stream_want);
}
}
void crypto_acomp_free_streams(struct crypto_acomp_streams *s)
{
struct crypto_acomp_stream __percpu *streams = s->streams;
void (*free_ctx)(void *);
int i;
cancel_work_sync(&s->stream_work);
free_ctx = s->free_ctx;
for_each_possible_cpu(i) {
struct crypto_acomp_stream *ps = per_cpu_ptr(streams, i);
if (!ps->ctx)
continue;
free_ctx(ps->ctx);
}
free_percpu(streams);
}
EXPORT_SYMBOL_GPL(crypto_acomp_free_streams);
int crypto_acomp_alloc_streams(struct crypto_acomp_streams *s)
{
struct crypto_acomp_stream __percpu *streams;
struct crypto_acomp_stream *ps;
unsigned int i;
void *ctx;
if (s->streams)
return 0;
streams = alloc_percpu(struct crypto_acomp_stream);
if (!streams)
return -ENOMEM;
ctx = s->alloc_ctx();
if (IS_ERR(ctx)) {
free_percpu(streams);
return PTR_ERR(ctx);
}
i = cpumask_first(cpu_possible_mask);
ps = per_cpu_ptr(streams, i);
ps->ctx = ctx;
for_each_possible_cpu(i) {
ps = per_cpu_ptr(streams, i);
spin_lock_init(&ps->lock);
}
s->streams = streams;
INIT_WORK(&s->stream_work, acomp_stream_workfn);
return 0;
}
EXPORT_SYMBOL_GPL(crypto_acomp_alloc_streams);
struct crypto_acomp_stream *crypto_acomp_lock_stream_bh(
struct crypto_acomp_streams *s) __acquires(stream)
{
struct crypto_acomp_stream __percpu *streams = s->streams;
int cpu = raw_smp_processor_id();
struct crypto_acomp_stream *ps;
ps = per_cpu_ptr(streams, cpu);
spin_lock_bh(&ps->lock);
if (likely(ps->ctx))
return ps;
spin_unlock(&ps->lock);
cpumask_set_cpu(cpu, &s->stream_want);
schedule_work(&s->stream_work);
ps = per_cpu_ptr(streams, cpumask_first(cpu_possible_mask));
spin_lock(&ps->lock);
return ps;
}
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 = INT_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 = INT_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");

View File

@@ -66,17 +66,34 @@ static int crypto_check_alg(struct crypto_alg *alg)
static void crypto_free_instance(struct crypto_instance *inst)
{
inst->alg.cra_type->free(inst);
struct crypto_alg *alg = &inst->alg;
const struct crypto_type *type;
type = alg->cra_type;
if (type->destroy)
type->destroy(alg);
type->free(inst);
}
static void crypto_destroy_instance_workfn(struct work_struct *w)
{
struct crypto_instance *inst = container_of(w, struct crypto_instance,
struct crypto_template *tmpl = container_of(w, struct crypto_template,
free_work);
struct crypto_template *tmpl = inst->tmpl;
struct crypto_instance *inst;
struct hlist_node *n;
HLIST_HEAD(list);
crypto_free_instance(inst);
crypto_tmpl_put(tmpl);
down_write(&crypto_alg_sem);
hlist_for_each_entry_safe(inst, n, &tmpl->dead, list) {
if (refcount_read(&inst->alg.cra_refcnt) != -1)
continue;
hlist_del(&inst->list);
hlist_add_head(&inst->list, &list);
}
up_write(&crypto_alg_sem);
hlist_for_each_entry_safe(inst, n, &list, list)
crypto_free_instance(inst);
}
static void crypto_destroy_instance(struct crypto_alg *alg)
@@ -84,9 +101,10 @@ static void crypto_destroy_instance(struct crypto_alg *alg)
struct crypto_instance *inst = container_of(alg,
struct crypto_instance,
alg);
struct crypto_template *tmpl = inst->tmpl;
INIT_WORK(&inst->free_work, crypto_destroy_instance_workfn);
schedule_work(&inst->free_work);
refcount_set(&alg->cra_refcnt, -1);
schedule_work(&tmpl->free_work);
}
/*
@@ -132,14 +150,16 @@ static void crypto_remove_instance(struct crypto_instance *inst,
inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
if (!tmpl || !crypto_tmpl_get(tmpl))
if (!tmpl)
return;
list_move(&inst->alg.cra_list, list);
list_del_init(&inst->alg.cra_list);
hlist_del(&inst->list);
inst->alg.cra_destroy = crypto_destroy_instance;
hlist_add_head(&inst->list, &tmpl->dead);
BUG_ON(!list_empty(&inst->alg.cra_users));
crypto_alg_put(&inst->alg);
}
/*
@@ -464,7 +484,8 @@ void crypto_unregister_alg(struct crypto_alg *alg)
if (WARN_ON(refcount_read(&alg->cra_refcnt) != 1))
return;
crypto_alg_put(alg);
if (alg->cra_type && alg->cra_type->destroy)
alg->cra_type->destroy(alg);
crypto_remove_final(&list);
}
@@ -504,6 +525,8 @@ int crypto_register_template(struct crypto_template *tmpl)
struct crypto_template *q;
int err = -EEXIST;
INIT_WORK(&tmpl->free_work, crypto_destroy_instance_workfn);
down_write(&crypto_alg_sem);
crypto_check_module_sig(tmpl->module);
@@ -565,6 +588,8 @@ void crypto_unregister_template(struct crypto_template *tmpl)
crypto_free_instance(inst);
}
crypto_remove_final(&users);
flush_work(&tmpl->free_work);
}
EXPORT_SYMBOL_GPL(crypto_unregister_template);
@@ -618,6 +643,7 @@ int crypto_register_instance(struct crypto_template *tmpl,
inst->alg.cra_module = tmpl->module;
inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
inst->alg.cra_destroy = crypto_destroy_instance;
down_write(&crypto_alg_sem);

View File

@@ -703,15 +703,5 @@ void crypto_req_done(void *data, int err)
}
EXPORT_SYMBOL_GPL(crypto_req_done);
void crypto_destroy_alg(struct crypto_alg *alg)
{
if (alg->cra_type && alg->cra_type->destroy)
alg->cra_type->destroy(alg);
if (alg->cra_destroy)
alg->cra_destroy(alg);
}
EXPORT_SYMBOL_GPL(crypto_destroy_alg);
MODULE_DESCRIPTION("Cryptographic core API");
MODULE_LICENSE("GPL");

View File

@@ -6,246 +6,254 @@
* by IPCOMP (RFC 3173 & RFC 2394).
*
* Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
*
* FIXME: deflate transforms will require up to a total of about 436k of kernel
* memory on i386 (390k for compression, the rest for decompression), as the
* current zlib kernel code uses a worst case pre-allocation system by default.
* This needs to be fixed so that the amount of memory required is properly
* related to the winbits and memlevel parameters.
*
* The default winbits of 11 should suit most packets, and it may be something
* to configure on a per-tfm basis in the future.
*
* Currently, compression history is not maintained between tfm calls, as
* it is not needed for IPCOMP and keeps the code simpler. It can be
* implemented if someone wants it.
* Copyright (c) 2023 Google, LLC. <ardb@kernel.org>
* Copyright (c) 2025 Herbert Xu <herbert@gondor.apana.org.au>
*/
#include <crypto/internal/acompress.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/mutex.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/zlib.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/net.h>
#include <crypto/internal/scompress.h>
#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
#define DEFLATE_DEF_WINBITS 11
#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
struct deflate_ctx {
struct z_stream_s comp_stream;
struct z_stream_s decomp_stream;
struct deflate_stream {
struct z_stream_s stream;
u8 workspace[];
};
static int deflate_comp_init(struct deflate_ctx *ctx)
static DEFINE_MUTEX(deflate_stream_lock);
static void *deflate_alloc_stream(void)
{
int ret = 0;
struct z_stream_s *stream = &ctx->comp_stream;
size_t size = max(zlib_inflate_workspacesize(),
zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS,
DEFLATE_DEF_MEMLEVEL));
struct deflate_stream *ctx;
stream->workspace = vzalloc(zlib_deflate_workspacesize(
-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL));
if (!stream->workspace) {
ret = -ENOMEM;
goto out;
}
ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
Z_DEFAULT_STRATEGY);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
}
out:
return ret;
out_free:
vfree(stream->workspace);
goto out;
}
static int deflate_decomp_init(struct deflate_ctx *ctx)
{
int ret = 0;
struct z_stream_s *stream = &ctx->decomp_stream;
stream->workspace = vzalloc(zlib_inflate_workspacesize());
if (!stream->workspace) {
ret = -ENOMEM;
goto out;
}
ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
}
out:
return ret;
out_free:
vfree(stream->workspace);
goto out;
}
static void deflate_comp_exit(struct deflate_ctx *ctx)
{
zlib_deflateEnd(&ctx->comp_stream);
vfree(ctx->comp_stream.workspace);
}
static void deflate_decomp_exit(struct deflate_ctx *ctx)
{
zlib_inflateEnd(&ctx->decomp_stream);
vfree(ctx->decomp_stream.workspace);
}
static int __deflate_init(void *ctx)
{
int ret;
ret = deflate_comp_init(ctx);
if (ret)
goto out;
ret = deflate_decomp_init(ctx);
if (ret)
deflate_comp_exit(ctx);
out:
return ret;
}
static void *deflate_alloc_ctx(void)
{
struct deflate_ctx *ctx;
int ret;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
ctx = kvmalloc(sizeof(*ctx) + size, GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ret = __deflate_init(ctx);
if (ret) {
kfree(ctx);
return ERR_PTR(ret);
}
ctx->stream.workspace = ctx->workspace;
return ctx;
}
static void __deflate_exit(void *ctx)
static struct crypto_acomp_streams deflate_streams = {
.alloc_ctx = deflate_alloc_stream,
.cfree_ctx = kvfree,
};
static int deflate_compress_one(struct acomp_req *req,
struct deflate_stream *ds)
{
deflate_comp_exit(ctx);
deflate_decomp_exit(ctx);
struct z_stream_s *stream = &ds->stream;
struct acomp_walk walk;
int ret;
ret = acomp_walk_virt(&walk, req);
if (ret)
return ret;
do {
int scur, dcur;
dcur = acomp_walk_next_dst(&walk);
if (dcur <= 0)
return dcur ?: -ENOSPC;
stream->avail_out = dcur;
stream->next_out = walk.dst.virt.addr;
do {
int flush = Z_FINISH;
stream->avail_in = 0;
stream->next_in = NULL;
scur = acomp_walk_next_src(&walk);
if (scur < 0)
break;
if (scur) {
if (acomp_walk_more_src(&walk, scur))
flush = Z_NO_FLUSH;
stream->avail_in = scur;
stream->next_in = walk.src.virt.addr;
}
ret = zlib_deflate(stream, flush);
if (scur) {
scur -= stream->avail_in;
acomp_walk_done_src(&walk, scur);
}
} while (ret == Z_OK && stream->avail_out);
acomp_walk_done_dst(&walk, dcur);
if (scur < 0)
return scur;
} while (ret == Z_OK);
if (ret != Z_STREAM_END)
return -EINVAL;
req->dlen = stream->total_out;
return 0;
}
static void deflate_free_ctx(void *ctx)
static int deflate_compress(struct acomp_req *req)
{
__deflate_exit(ctx);
kfree_sensitive(ctx);
}
struct crypto_acomp_stream *s;
struct deflate_stream *ds;
struct acomp_req *r2;
int err;
static int __deflate_compress(const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx)
{
int ret = 0;
struct deflate_ctx *dctx = ctx;
struct z_stream_s *stream = &dctx->comp_stream;
s = crypto_acomp_lock_stream_bh(&deflate_streams);
ds = s->ctx;
ret = zlib_deflateReset(stream);
if (ret != Z_OK) {
ret = -EINVAL;
err = zlib_deflateInit2(&ds->stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
Z_DEFAULT_STRATEGY);
if (err != Z_OK) {
err = -EINVAL;
goto out;
}
stream->next_in = (u8 *)src;
stream->avail_in = slen;
stream->next_out = (u8 *)dst;
stream->avail_out = *dlen;
err = deflate_compress_one(req, ds);
req->base.err = err;
ret = zlib_deflate(stream, Z_FINISH);
if (ret != Z_STREAM_END) {
ret = -EINVAL;
goto out;
list_for_each_entry(r2, &req->base.list, base.list) {
zlib_deflateReset(&ds->stream);
r2->base.err = deflate_compress_one(r2, ds);
}
ret = 0;
*dlen = stream->total_out;
out:
crypto_acomp_unlock_stream_bh(s);
return err;
}
static int deflate_decompress_one(struct acomp_req *req,
struct deflate_stream *ds)
{
struct z_stream_s *stream = &ds->stream;
struct acomp_walk walk;
int ret;
ret = acomp_walk_virt(&walk, req);
if (ret)
return ret;
do {
int scur, dcur;
stream->avail_in = 0;
stream->next_in = NULL;
scur = acomp_walk_next_src(&walk);
if (scur < 0)
return scur;
if (scur) {
stream->avail_in = scur;
stream->next_in = walk.src.virt.addr;
}
do {
dcur = acomp_walk_next_dst(&walk);
if (dcur <= 0)
break;
stream->avail_out = dcur;
stream->next_out = walk.dst.virt.addr;
ret = zlib_inflate(stream, Z_NO_FLUSH);
dcur -= stream->avail_out;
acomp_walk_done_dst(&walk, dcur);
} while (ret == Z_OK && stream->avail_in);
if (scur)
acomp_walk_done_src(&walk, scur);
if (dcur <= 0)
return dcur ?: -ENOMEM;
} while (ret == Z_OK);
if (ret != Z_STREAM_END)
return -EINVAL;
req->dlen = stream->total_out;
return 0;
}
static int deflate_decompress(struct acomp_req *req)
{
struct crypto_acomp_stream *s;
struct deflate_stream *ds;
struct acomp_req *r2;
int err;
s = crypto_acomp_lock_stream_bh(&deflate_streams);
ds = s->ctx;
err = zlib_inflateInit2(&ds->stream, -DEFLATE_DEF_WINBITS);
if (err != Z_OK) {
err = -EINVAL;
goto out;
}
err = deflate_decompress_one(req, ds);
req->base.err = err;
list_for_each_entry(r2, &req->base.list, base.list) {
zlib_inflateReset(&ds->stream);
r2->base.err = deflate_decompress_one(r2, ds);
}
out:
crypto_acomp_unlock_stream_bh(s);
return err;
}
static int deflate_init(struct crypto_acomp *tfm)
{
int ret;
mutex_lock(&deflate_stream_lock);
ret = crypto_acomp_alloc_streams(&deflate_streams);
mutex_unlock(&deflate_stream_lock);
return ret;
}
static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int *dlen,
void *ctx)
{
return __deflate_compress(src, slen, dst, dlen, ctx);
}
static int __deflate_decompress(const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx)
{
int ret = 0;
struct deflate_ctx *dctx = ctx;
struct z_stream_s *stream = &dctx->decomp_stream;
ret = zlib_inflateReset(stream);
if (ret != Z_OK) {
ret = -EINVAL;
goto out;
}
stream->next_in = (u8 *)src;
stream->avail_in = slen;
stream->next_out = (u8 *)dst;
stream->avail_out = *dlen;
ret = zlib_inflate(stream, Z_SYNC_FLUSH);
/*
* Work around a bug in zlib, which sometimes wants to taste an extra
* byte when being used in the (undocumented) raw deflate mode.
* (From USAGI).
*/
if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
u8 zerostuff = 0;
stream->next_in = &zerostuff;
stream->avail_in = 1;
ret = zlib_inflate(stream, Z_FINISH);
}
if (ret != Z_STREAM_END) {
ret = -EINVAL;
goto out;
}
ret = 0;
*dlen = stream->total_out;
out:
return ret;
}
static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int *dlen,
void *ctx)
{
return __deflate_decompress(src, slen, dst, dlen, ctx);
}
static struct scomp_alg scomp = {
.alloc_ctx = deflate_alloc_ctx,
.free_ctx = deflate_free_ctx,
.compress = deflate_scompress,
.decompress = deflate_sdecompress,
.base = {
.cra_name = "deflate",
.cra_driver_name = "deflate-scomp",
.cra_module = THIS_MODULE,
}
static struct acomp_alg acomp = {
.compress = deflate_compress,
.decompress = deflate_decompress,
.init = deflate_init,
.base.cra_name = "deflate",
.base.cra_driver_name = "deflate-generic",
.base.cra_flags = CRYPTO_ALG_REQ_CHAIN,
.base.cra_module = THIS_MODULE,
};
static int __init deflate_mod_init(void)
{
return crypto_register_scomp(&scomp);
return crypto_register_acomp(&acomp);
}
static void __exit deflate_mod_fini(void)
{
crypto_unregister_scomp(&scomp);
crypto_unregister_acomp(&acomp);
crypto_acomp_free_streams(&deflate_streams);
}
subsys_initcall(deflate_mod_init);
@@ -254,5 +262,7 @@ module_exit(deflate_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
MODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>");
MODULE_AUTHOR("Herbert Xu <herbert@gondor.apana.org.au>");
MODULE_ALIAS_CRYPTO("deflate");
MODULE_ALIAS_CRYPTO("deflate-generic");

View File

@@ -128,7 +128,6 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
const struct crypto_type *frontend, int node);
void *crypto_clone_tfm(const struct crypto_type *frontend,
struct crypto_tfm *otfm);
void crypto_destroy_alg(struct crypto_alg *alg);
static inline void *crypto_create_tfm(struct crypto_alg *alg,
const struct crypto_type *frontend)
@@ -166,7 +165,7 @@ static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
static inline void crypto_alg_put(struct crypto_alg *alg)
{
if (refcount_dec_and_test(&alg->cra_refcnt))
crypto_destroy_alg(alg);
alg->cra_destroy(alg);
}
static inline int crypto_tmpl_get(struct crypto_template *tmpl)

View File

@@ -7,9 +7,9 @@
* Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
*/
#include <crypto/internal/acompress.h>
#include <crypto/internal/scompress.h>
#include <crypto/scatterwalk.h>
#include <linux/cpumask.h>
#include <linux/cryptouser.h>
#include <linux/err.h>
#include <linux/highmem.h>
@@ -20,20 +20,17 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <net/netlink.h>
#include "compress.h"
#define SCOMP_SCRATCH_SIZE 65400
struct scomp_scratch {
spinlock_t lock;
union {
void *src;
unsigned long saddr;
};
void *dst;
};
static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
@@ -44,6 +41,10 @@ static const struct crypto_type crypto_scomp_type;
static int scomp_scratch_users;
static DEFINE_MUTEX(scomp_lock);
static cpumask_t scomp_scratch_want;
static void scomp_scratch_workfn(struct work_struct *work);
static DECLARE_WORK(scomp_scratch_work, scomp_scratch_workfn);
static int __maybe_unused crypto_scomp_report(
struct sk_buff *skb, struct crypto_alg *alg)
{
@@ -74,78 +75,48 @@ static void crypto_scomp_free_scratches(void)
scratch = per_cpu_ptr(&scomp_scratch, i);
free_page(scratch->saddr);
vfree(scratch->dst);
scratch->src = NULL;
scratch->dst = NULL;
}
}
static int scomp_alloc_scratch(struct scomp_scratch *scratch, int cpu)
{
int node = cpu_to_node(cpu);
struct page *page;
page = alloc_pages_node(node, GFP_KERNEL, 0);
if (!page)
return -ENOMEM;
spin_lock_bh(&scratch->lock);
scratch->src = page_address(page);
spin_unlock_bh(&scratch->lock);
return 0;
}
static void scomp_scratch_workfn(struct work_struct *work)
{
int cpu;
for_each_cpu(cpu, &scomp_scratch_want) {
struct scomp_scratch *scratch;
scratch = per_cpu_ptr(&scomp_scratch, cpu);
if (scratch->src)
continue;
if (scomp_alloc_scratch(scratch, cpu))
break;
cpumask_clear_cpu(cpu, &scomp_scratch_want);
}
}
static int crypto_scomp_alloc_scratches(void)
{
unsigned int i = cpumask_first(cpu_possible_mask);
struct scomp_scratch *scratch;
int i;
for_each_possible_cpu(i) {
struct page *page;
void *mem;
scratch = per_cpu_ptr(&scomp_scratch, i);
page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, 0);
if (!page)
goto error;
scratch->src = page_address(page);
mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
if (!mem)
goto error;
scratch->dst = mem;
}
return 0;
error:
crypto_scomp_free_scratches();
return -ENOMEM;
}
static void scomp_free_streams(struct scomp_alg *alg)
{
struct crypto_acomp_stream __percpu *stream = alg->stream;
int i;
for_each_possible_cpu(i) {
struct crypto_acomp_stream *ps = per_cpu_ptr(stream, i);
if (!ps->ctx)
break;
alg->free_ctx(ps->ctx);
}
free_percpu(stream);
}
static int scomp_alloc_streams(struct scomp_alg *alg)
{
struct crypto_acomp_stream __percpu *stream;
int i;
stream = alloc_percpu(struct crypto_acomp_stream);
if (!stream)
return -ENOMEM;
for_each_possible_cpu(i) {
struct crypto_acomp_stream *ps = per_cpu_ptr(stream, i);
ps->ctx = alg->alloc_ctx();
if (IS_ERR(ps->ctx)) {
scomp_free_streams(alg);
return PTR_ERR(ps->ctx);
}
spin_lock_init(&ps->lock);
}
alg->stream = stream;
return 0;
scratch = per_cpu_ptr(&scomp_scratch, i);
return scomp_alloc_scratch(scratch, i);
}
static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
@@ -154,11 +125,9 @@ static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
int ret = 0;
mutex_lock(&scomp_lock);
if (!alg->stream) {
ret = scomp_alloc_streams(alg);
if (ret)
goto unlock;
}
ret = crypto_acomp_alloc_streams(&alg->streams);
if (ret)
goto unlock;
if (!scomp_scratch_users) {
ret = crypto_scomp_alloc_scratches();
if (ret)
@@ -171,13 +140,40 @@ unlock:
return ret;
}
static struct scomp_scratch *scomp_lock_scratch(void) __acquires(scratch)
{
int cpu = raw_smp_processor_id();
struct scomp_scratch *scratch;
scratch = per_cpu_ptr(&scomp_scratch, cpu);
spin_lock(&scratch->lock);
if (likely(scratch->src))
return scratch;
spin_unlock(&scratch->lock);
cpumask_set_cpu(cpu, &scomp_scratch_want);
schedule_work(&scomp_scratch_work);
scratch = per_cpu_ptr(&scomp_scratch, cpumask_first(cpu_possible_mask));
spin_lock(&scratch->lock);
return scratch;
}
static inline void scomp_unlock_scratch(struct scomp_scratch *scratch)
__releases(scratch)
{
spin_unlock(&scratch->lock);
}
static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
{
struct scomp_scratch *scratch = raw_cpu_ptr(&scomp_scratch);
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
struct crypto_scomp **tfm_ctx = acomp_tfm_ctx(tfm);
bool src_isvirt = acomp_request_src_isvirt(req);
bool dst_isvirt = acomp_request_dst_isvirt(req);
struct crypto_scomp *scomp = *tfm_ctx;
struct crypto_acomp_stream *stream;
struct scomp_scratch *scratch;
unsigned int slen = req->slen;
unsigned int dlen = req->dlen;
struct page *spage, *dpage;
@@ -194,10 +190,33 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
if (!req->dst || !dlen)
return -EINVAL;
if (acomp_request_src_isvirt(req))
if (dst_isvirt)
dst = req->dvirt;
else {
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
return -ENOSYS;
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)
return -ENOSYS;
dst = kmap_local_page(dpage) + doff;
}
if (src_isvirt)
src = req->svirt;
else {
src = scratch->src;
src = NULL;
do {
if (acomp_request_src_isfolio(req)) {
spage = folio_page(req->sfolio, 0);
@@ -220,59 +239,37 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
} while (0);
}
if (acomp_request_dst_isvirt(req))
dst = req->dvirt;
else {
unsigned int max = SCOMP_SCRATCH_SIZE;
stream = crypto_acomp_lock_stream_bh(&crypto_scomp_alg(scomp)->streams);
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;
if (!src_isvirt && !src) {
const u8 *src;
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;
max = dlen;
} while (0);
dlen = min(dlen, max);
}
spin_lock_bh(&scratch->lock);
if (src == scratch->src)
scratch = scomp_lock_scratch();
src = scratch->src;
memcpy_from_sglist(scratch->src, req->src, 0, slen);
stream = raw_cpu_ptr(crypto_scomp_alg(scomp)->stream);
spin_lock(&stream->lock);
if (dir)
if (dir)
ret = crypto_scomp_compress(scomp, src, slen,
dst, &dlen, stream->ctx);
else
ret = crypto_scomp_decompress(scomp, src, slen,
dst, &dlen, stream->ctx);
scomp_unlock_scratch(scratch);
} else if (dir)
ret = crypto_scomp_compress(scomp, src, slen,
dst, &dlen, stream->ctx);
else
ret = crypto_scomp_decompress(scomp, src, slen,
dst, &dlen, stream->ctx);
if (dst == scratch->dst)
memcpy_to_sglist(req->dst, 0, dst, dlen);
spin_unlock(&stream->lock);
spin_unlock_bh(&scratch->lock);
crypto_acomp_unlock_stream_bh(stream);
req->dlen = dlen;
if (!acomp_request_dst_isvirt(req) && dst != scratch->dst) {
if (!src_isvirt && src)
kunmap_local(src);
if (!dst_isvirt) {
kunmap_local(dst);
dlen += doff;
for (;;) {
@@ -283,8 +280,6 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
dpage = nth_page(dpage, 1);
}
}
if (!acomp_request_src_isvirt(req) && src != scratch->src)
kunmap_local(src);
return ret;
}
@@ -319,6 +314,7 @@ static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
crypto_free_scomp(*ctx);
flush_work(&scomp_scratch_work);
mutex_lock(&scomp_lock);
if (!--scomp_scratch_users)
crypto_scomp_free_scratches();
@@ -352,7 +348,9 @@ int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
static void crypto_scomp_destroy(struct crypto_alg *alg)
{
scomp_free_streams(__crypto_scomp_alg(alg));
struct scomp_alg *scomp = __crypto_scomp_alg(alg);
crypto_acomp_free_streams(&scomp->streams);
}
static const struct crypto_type crypto_scomp_type = {

View File

@@ -530,13 +530,6 @@ source "drivers/crypto/cavium/nitrox/Kconfig"
source "drivers/crypto/marvell/Kconfig"
source "drivers/crypto/intel/Kconfig"
config CRYPTO_DEV_CAVIUM_ZIP
tristate "Cavium ZIP driver"
depends on PCI && 64BIT && (ARM64 || COMPILE_TEST)
help
Select this option if you want to enable compression/decompression
acceleration on Cavium's ARM based SoCs
config CRYPTO_DEV_QCE
tristate "Qualcomm crypto engine accelerator"
depends on ARCH_QCOM || COMPILE_TEST

View File

@@ -8,12 +8,9 @@ obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
obj-$(CONFIG_CRYPTO_DEV_ATMEL_I2C) += atmel-i2c.o
obj-$(CONFIG_CRYPTO_DEV_ATMEL_ECC) += atmel-ecc.o
obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA204A) += atmel-sha204a.o
obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += cavium/
obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/
obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
obj-$(CONFIG_CRYPTO_DEV_CPT) += cavium/cpt/
obj-$(CONFIG_CRYPTO_DEV_NITROX) += cavium/nitrox/
obj-$(CONFIG_CRYPTO_DEV_EXYNOS_RNG) += exynos-rng.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON) += caam/
obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
@@ -50,3 +47,4 @@ obj-y += hisilicon/
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
obj-y += intel/
obj-y += starfive/
obj-y += cavium/

View File

@@ -2,4 +2,5 @@
#
# Makefile for Cavium crypto device drivers
#
obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += zip/
obj-$(CONFIG_CRYPTO_DEV_CPT) += cpt/
obj-$(CONFIG_CRYPTO_DEV_NITROX) += nitrox/

View File

@@ -1,12 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for Cavium's ZIP Driver.
#
obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += thunderx_zip.o
thunderx_zip-y := zip_main.o \
zip_device.o \
zip_crypto.o \
zip_mem.o \
zip_deflate.o \
zip_inflate.o

View File

@@ -1,222 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __COMMON_H__
#define __COMMON_H__
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/types.h>
/* Device specific zlib function definitions */
#include "zip_device.h"
/* ZIP device definitions */
#include "zip_main.h"
/* ZIP memory allocation/deallocation related definitions */
#include "zip_mem.h"
/* Device specific structure definitions */
#include "zip_regs.h"
#define ZIP_ERROR -1
#define ZIP_FLUSH_FINISH 4
#define RAW_FORMAT 0 /* for rawpipe */
#define ZLIB_FORMAT 1 /* for zpipe */
#define GZIP_FORMAT 2 /* for gzpipe */
#define LZS_FORMAT 3 /* for lzspipe */
/* Max number of ZIP devices supported */
#define MAX_ZIP_DEVICES 2
/* Configures the number of zip queues to be used */
#define ZIP_NUM_QUEUES 2
#define DYNAMIC_STOP_EXCESS 1024
/* Maximum buffer sizes in direct mode */
#define MAX_INPUT_BUFFER_SIZE (64 * 1024)
#define MAX_OUTPUT_BUFFER_SIZE (64 * 1024)
/**
* struct zip_operation - common data structure for comp and decomp operations
* @input: Next input byte is read from here
* @output: Next output byte written here
* @ctx_addr: Inflate context buffer address
* @history: Pointer to the history buffer
* @input_len: Number of bytes available at next_in
* @input_total_len: Total number of input bytes read
* @output_len: Remaining free space at next_out
* @output_total_len: Total number of bytes output so far
* @csum: Checksum value of the uncompressed data
* @flush: Flush flag
* @format: Format (depends on stream's wrap)
* @speed: Speed depends on stream's level
* @ccode: Compression code ( stream's strategy)
* @lzs_flag: Flag for LZS support
* @begin_file: Beginning of file indication for inflate
* @history_len: Size of the history data
* @end_file: Ending of the file indication for inflate
* @compcode: Completion status of the ZIP invocation
* @bytes_read: Input bytes read in current instruction
* @bits_processed: Total bits processed for entire file
* @sizeofptr: To distinguish between ILP32 and LP64
* @sizeofzops: Optional just for padding
*
* This structure is used to maintain the required meta data for the
* comp and decomp operations.
*/
struct zip_operation {
u8 *input;
u8 *output;
u64 ctx_addr;
u64 history;
u32 input_len;
u32 input_total_len;
u32 output_len;
u32 output_total_len;
u32 csum;
u32 flush;
u32 format;
u32 speed;
u32 ccode;
u32 lzs_flag;
u32 begin_file;
u32 history_len;
u32 end_file;
u32 compcode;
u32 bytes_read;
u32 bits_processed;
u32 sizeofptr;
u32 sizeofzops;
};
static inline int zip_poll_result(union zip_zres_s *result)
{
int retries = 1000;
while (!result->s.compcode) {
if (!--retries) {
pr_err("ZIP ERR: request timed out");
return -ETIMEDOUT;
}
udelay(10);
/*
* Force re-reading of compcode which is updated
* by the ZIP coprocessor.
*/
rmb();
}
return 0;
}
/* error messages */
#define zip_err(fmt, args...) pr_err("ZIP ERR:%s():%d: " \
fmt "\n", __func__, __LINE__, ## args)
#ifdef MSG_ENABLE
/* Enable all messages */
#define zip_msg(fmt, args...) pr_info("ZIP_MSG:" fmt "\n", ## args)
#else
#define zip_msg(fmt, args...)
#endif
#if defined(ZIP_DEBUG_ENABLE) && defined(MSG_ENABLE)
#ifdef DEBUG_LEVEL
#define FILE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : \
strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#if DEBUG_LEVEL >= 4
#define zip_dbg(fmt, args...) pr_info("ZIP DBG: %s: %s() : %d: " \
fmt "\n", FILE_NAME, __func__, __LINE__, ## args)
#elif DEBUG_LEVEL >= 3
#define zip_dbg(fmt, args...) pr_info("ZIP DBG: %s: %s() : %d: " \
fmt "\n", FILE_NAME, __func__, __LINE__, ## args)
#elif DEBUG_LEVEL >= 2
#define zip_dbg(fmt, args...) pr_info("ZIP DBG: %s() : %d: " \
fmt "\n", __func__, __LINE__, ## args)
#else
#define zip_dbg(fmt, args...) pr_info("ZIP DBG:" fmt "\n", ## args)
#endif /* DEBUG LEVEL >=4 */
#else
#define zip_dbg(fmt, args...) pr_info("ZIP DBG:" fmt "\n", ## args)
#endif /* DEBUG_LEVEL */
#else
#define zip_dbg(fmt, args...)
#endif /* ZIP_DEBUG_ENABLE && MSG_ENABLE*/
#endif

View File

@@ -1,261 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include "zip_crypto.h"
static void zip_static_init_zip_ops(struct zip_operation *zip_ops,
int lzs_flag)
{
zip_ops->flush = ZIP_FLUSH_FINISH;
/* equivalent to level 6 of opensource zlib */
zip_ops->speed = 1;
if (!lzs_flag) {
zip_ops->ccode = 0; /* Auto Huffman */
zip_ops->lzs_flag = 0;
zip_ops->format = ZLIB_FORMAT;
} else {
zip_ops->ccode = 3; /* LZS Encoding */
zip_ops->lzs_flag = 1;
zip_ops->format = LZS_FORMAT;
}
zip_ops->begin_file = 1;
zip_ops->history_len = 0;
zip_ops->end_file = 1;
zip_ops->compcode = 0;
zip_ops->csum = 1; /* Adler checksum desired */
}
static int zip_ctx_init(struct zip_kernel_ctx *zip_ctx, int lzs_flag)
{
struct zip_operation *comp_ctx = &zip_ctx->zip_comp;
struct zip_operation *decomp_ctx = &zip_ctx->zip_decomp;
zip_static_init_zip_ops(comp_ctx, lzs_flag);
zip_static_init_zip_ops(decomp_ctx, lzs_flag);
comp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE);
if (!comp_ctx->input)
return -ENOMEM;
comp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE);
if (!comp_ctx->output)
goto err_comp_input;
decomp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE);
if (!decomp_ctx->input)
goto err_comp_output;
decomp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE);
if (!decomp_ctx->output)
goto err_decomp_input;
return 0;
err_decomp_input:
zip_data_buf_free(decomp_ctx->input, MAX_INPUT_BUFFER_SIZE);
err_comp_output:
zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE);
err_comp_input:
zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE);
return -ENOMEM;
}
static void zip_ctx_exit(struct zip_kernel_ctx *zip_ctx)
{
struct zip_operation *comp_ctx = &zip_ctx->zip_comp;
struct zip_operation *dec_ctx = &zip_ctx->zip_decomp;
zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE);
zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE);
zip_data_buf_free(dec_ctx->input, MAX_INPUT_BUFFER_SIZE);
zip_data_buf_free(dec_ctx->output, MAX_OUTPUT_BUFFER_SIZE);
}
static int zip_compress(const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen,
struct zip_kernel_ctx *zip_ctx)
{
struct zip_operation *zip_ops = NULL;
struct zip_state *zip_state;
struct zip_device *zip = NULL;
int ret;
if (!zip_ctx || !src || !dst || !dlen)
return -ENOMEM;
zip = zip_get_device(zip_get_node_id());
if (!zip)
return -ENODEV;
zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
if (!zip_state)
return -ENOMEM;
zip_ops = &zip_ctx->zip_comp;
zip_ops->input_len = slen;
zip_ops->output_len = *dlen;
memcpy(zip_ops->input, src, slen);
ret = zip_deflate(zip_ops, zip_state, zip);
if (!ret) {
*dlen = zip_ops->output_len;
memcpy(dst, zip_ops->output, *dlen);
}
kfree(zip_state);
return ret;
}
static int zip_decompress(const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen,
struct zip_kernel_ctx *zip_ctx)
{
struct zip_operation *zip_ops = NULL;
struct zip_state *zip_state;
struct zip_device *zip = NULL;
int ret;
if (!zip_ctx || !src || !dst || !dlen)
return -ENOMEM;
zip = zip_get_device(zip_get_node_id());
if (!zip)
return -ENODEV;
zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
if (!zip_state)
return -ENOMEM;
zip_ops = &zip_ctx->zip_decomp;
memcpy(zip_ops->input, src, slen);
/* Work around for a bug in zlib which needs an extra bytes sometimes */
if (zip_ops->ccode != 3) /* Not LZS Encoding */
zip_ops->input[slen++] = 0;
zip_ops->input_len = slen;
zip_ops->output_len = *dlen;
ret = zip_inflate(zip_ops, zip_state, zip);
if (!ret) {
*dlen = zip_ops->output_len;
memcpy(dst, zip_ops->output, *dlen);
}
kfree(zip_state);
return ret;
}
/* SCOMP framework start */
void *zip_alloc_scomp_ctx_deflate(void)
{
int ret;
struct zip_kernel_ctx *zip_ctx;
zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL);
if (!zip_ctx)
return ERR_PTR(-ENOMEM);
ret = zip_ctx_init(zip_ctx, 0);
if (ret) {
kfree_sensitive(zip_ctx);
return ERR_PTR(ret);
}
return zip_ctx;
}
void *zip_alloc_scomp_ctx_lzs(void)
{
int ret;
struct zip_kernel_ctx *zip_ctx;
zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL);
if (!zip_ctx)
return ERR_PTR(-ENOMEM);
ret = zip_ctx_init(zip_ctx, 1);
if (ret) {
kfree_sensitive(zip_ctx);
return ERR_PTR(ret);
}
return zip_ctx;
}
void zip_free_scomp_ctx(void *ctx)
{
struct zip_kernel_ctx *zip_ctx = ctx;
zip_ctx_exit(zip_ctx);
kfree_sensitive(zip_ctx);
}
int zip_scomp_compress(struct crypto_scomp *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx)
{
struct zip_kernel_ctx *zip_ctx = ctx;
return zip_compress(src, slen, dst, dlen, zip_ctx);
}
int zip_scomp_decompress(struct crypto_scomp *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx)
{
struct zip_kernel_ctx *zip_ctx = ctx;
return zip_decompress(src, slen, dst, dlen, zip_ctx);
} /* SCOMP framework end */

View File

@@ -1,68 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_CRYPTO_H__
#define __ZIP_CRYPTO_H__
#include <crypto/internal/scompress.h>
#include "common.h"
#include "zip_deflate.h"
#include "zip_inflate.h"
struct zip_kernel_ctx {
struct zip_operation zip_comp;
struct zip_operation zip_decomp;
};
void *zip_alloc_scomp_ctx_deflate(void);
void *zip_alloc_scomp_ctx_lzs(void);
void zip_free_scomp_ctx(void *zip_ctx);
int zip_scomp_compress(struct crypto_scomp *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx);
int zip_scomp_decompress(struct crypto_scomp *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen, void *ctx);
#endif

View File

@@ -1,200 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include <linux/delay.h>
#include <linux/sched.h>
#include "common.h"
#include "zip_deflate.h"
/* Prepares the deflate zip command */
static int prepare_zip_command(struct zip_operation *zip_ops,
struct zip_state *s, union zip_inst_s *zip_cmd)
{
union zip_zres_s *result_ptr = &s->result;
memset(zip_cmd, 0, sizeof(s->zip_cmd));
memset(result_ptr, 0, sizeof(s->result));
/* IWORD #0 */
/* History gather */
zip_cmd->s.hg = 0;
/* compression enable = 1 for deflate */
zip_cmd->s.ce = 1;
/* sf (sync flush) */
zip_cmd->s.sf = 1;
/* ef (end of file) */
if (zip_ops->flush == ZIP_FLUSH_FINISH) {
zip_cmd->s.ef = 1;
zip_cmd->s.sf = 0;
}
zip_cmd->s.cc = zip_ops->ccode;
/* ss (compression speed/storage) */
zip_cmd->s.ss = zip_ops->speed;
/* IWORD #1 */
/* adler checksum */
zip_cmd->s.adlercrc32 = zip_ops->csum;
zip_cmd->s.historylength = zip_ops->history_len;
zip_cmd->s.dg = 0;
/* IWORD # 6 and 7 - compression input/history pointer */
zip_cmd->s.inp_ptr_addr.s.addr = __pa(zip_ops->input);
zip_cmd->s.inp_ptr_ctl.s.length = (zip_ops->input_len +
zip_ops->history_len);
zip_cmd->s.ds = 0;
/* IWORD # 8 and 9 - Output pointer */
zip_cmd->s.out_ptr_addr.s.addr = __pa(zip_ops->output);
zip_cmd->s.out_ptr_ctl.s.length = zip_ops->output_len;
/* maximum number of output-stream bytes that can be written */
zip_cmd->s.totaloutputlength = zip_ops->output_len;
/* IWORD # 10 and 11 - Result pointer */
zip_cmd->s.res_ptr_addr.s.addr = __pa(result_ptr);
/* Clearing completion code */
result_ptr->s.compcode = 0;
return 0;
}
/**
* zip_deflate - API to offload deflate operation to hardware
* @zip_ops: Pointer to zip operation structure
* @s: Pointer to the structure representing zip state
* @zip_dev: Pointer to zip device structure
*
* This function prepares the zip deflate command and submits it to the zip
* engine for processing.
*
* Return: 0 if successful or error code
*/
int zip_deflate(struct zip_operation *zip_ops, struct zip_state *s,
struct zip_device *zip_dev)
{
union zip_inst_s *zip_cmd = &s->zip_cmd;
union zip_zres_s *result_ptr = &s->result;
u32 queue;
/* Prepares zip command based on the input parameters */
prepare_zip_command(zip_ops, s, zip_cmd);
atomic64_add(zip_ops->input_len, &zip_dev->stats.comp_in_bytes);
/* Loads zip command into command queues and rings door bell */
queue = zip_load_instr(zip_cmd, zip_dev);
/* Stats update for compression requests submitted */
atomic64_inc(&zip_dev->stats.comp_req_submit);
/* Wait for completion or error */
zip_poll_result(result_ptr);
/* Stats update for compression requests completed */
atomic64_inc(&zip_dev->stats.comp_req_complete);
zip_ops->compcode = result_ptr->s.compcode;
switch (zip_ops->compcode) {
case ZIP_CMD_NOTDONE:
zip_dbg("Zip instruction not yet completed");
return ZIP_ERROR;
case ZIP_CMD_SUCCESS:
zip_dbg("Zip instruction completed successfully");
zip_update_cmd_bufs(zip_dev, queue);
break;
case ZIP_CMD_DTRUNC:
zip_dbg("Output Truncate error");
/* Returning ZIP_ERROR to avoid copy to user */
return ZIP_ERROR;
default:
zip_err("Zip instruction failed. Code:%d", zip_ops->compcode);
return ZIP_ERROR;
}
/* Update the CRC depending on the format */
switch (zip_ops->format) {
case RAW_FORMAT:
zip_dbg("RAW Format: %d ", zip_ops->format);
/* Get checksum from engine, need to feed it again */
zip_ops->csum = result_ptr->s.adler32;
break;
case ZLIB_FORMAT:
zip_dbg("ZLIB Format: %d ", zip_ops->format);
zip_ops->csum = result_ptr->s.adler32;
break;
case GZIP_FORMAT:
zip_dbg("GZIP Format: %d ", zip_ops->format);
zip_ops->csum = result_ptr->s.crc32;
break;
case LZS_FORMAT:
zip_dbg("LZS Format: %d ", zip_ops->format);
break;
default:
zip_err("Unknown Format:%d\n", zip_ops->format);
}
atomic64_add(result_ptr->s.totalbyteswritten,
&zip_dev->stats.comp_out_bytes);
/* Update output_len */
if (zip_ops->output_len < result_ptr->s.totalbyteswritten) {
/* Dynamic stop && strm->output_len < zipconstants[onfsize] */
zip_err("output_len (%d) < total bytes written(%d)\n",
zip_ops->output_len, result_ptr->s.totalbyteswritten);
zip_ops->output_len = 0;
} else {
zip_ops->output_len = result_ptr->s.totalbyteswritten;
}
return 0;
}

View File

@@ -1,62 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_DEFLATE_H__
#define __ZIP_DEFLATE_H__
/**
* zip_deflate - API to offload deflate operation to hardware
* @zip_ops: Pointer to zip operation structure
* @s: Pointer to the structure representing zip state
* @zip_dev: Pointer to the structure representing zip device
*
* This function prepares the zip deflate command and submits it to the zip
* engine by ringing the doorbell.
*
* Return: 0 if successful or error code
*/
int zip_deflate(struct zip_operation *zip_ops, struct zip_state *s,
struct zip_device *zip_dev);
#endif

View File

@@ -1,202 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include "common.h"
#include "zip_deflate.h"
/**
* zip_cmd_queue_consumed - Calculates the space consumed in the command queue.
*
* @zip_dev: Pointer to zip device structure
* @queue: Queue number
*
* Return: Bytes consumed in the command queue buffer.
*/
static inline u32 zip_cmd_queue_consumed(struct zip_device *zip_dev, int queue)
{
return ((zip_dev->iq[queue].sw_head - zip_dev->iq[queue].sw_tail) *
sizeof(u64 *));
}
/**
* zip_load_instr - Submits the instruction into the ZIP command queue
* @instr: Pointer to the instruction to be submitted
* @zip_dev: Pointer to ZIP device structure to which the instruction is to
* be submitted
*
* This function copies the ZIP instruction to the command queue and rings the
* doorbell to notify the engine of the instruction submission. The command
* queue is maintained in a circular fashion. When there is space for exactly
* one instruction in the queue, next chunk pointer of the queue is made to
* point to the head of the queue, thus maintaining a circular queue.
*
* Return: Queue number to which the instruction was submitted
*/
u32 zip_load_instr(union zip_inst_s *instr,
struct zip_device *zip_dev)
{
union zip_quex_doorbell dbell;
u32 queue = 0;
u32 consumed = 0;
u64 *ncb_ptr = NULL;
union zip_nptr_s ncp;
/*
* Distribute the instructions between the enabled queues based on
* the CPU id.
*/
if (raw_smp_processor_id() % 2 == 0)
queue = 0;
else
queue = 1;
zip_dbg("CPU Core: %d Queue number:%d", raw_smp_processor_id(), queue);
/* Take cmd buffer lock */
spin_lock(&zip_dev->iq[queue].lock);
/*
* Command Queue implementation
* 1. If there is place for new instructions, push the cmd at sw_head.
* 2. If there is place for exactly one instruction, push the new cmd
* at the sw_head. Make sw_head point to the sw_tail to make it
* circular. Write sw_head's physical address to the "Next-Chunk
* Buffer Ptr" to make it cmd_hw_tail.
* 3. Ring the door bell.
*/
zip_dbg("sw_head : %lx", zip_dev->iq[queue].sw_head);
zip_dbg("sw_tail : %lx", zip_dev->iq[queue].sw_tail);
consumed = zip_cmd_queue_consumed(zip_dev, queue);
/* Check if there is space to push just one cmd */
if ((consumed + 128) == (ZIP_CMD_QBUF_SIZE - 8)) {
zip_dbg("Cmd queue space available for single command");
/* Space for one cmd, pust it and make it circular queue */
memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr,
sizeof(union zip_inst_s));
zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */
/* Now, point the "Next-Chunk Buffer Ptr" to sw_head */
ncb_ptr = zip_dev->iq[queue].sw_head;
zip_dbg("ncb addr :0x%lx sw_head addr :0x%lx",
ncb_ptr, zip_dev->iq[queue].sw_head - 16);
/* Using Circular command queue */
zip_dev->iq[queue].sw_head = zip_dev->iq[queue].sw_tail;
/* Mark this buffer for free */
zip_dev->iq[queue].free_flag = 1;
/* Write new chunk buffer address at "Next-Chunk Buffer Ptr" */
ncp.u_reg64 = 0ull;
ncp.s.addr = __pa(zip_dev->iq[queue].sw_head);
*ncb_ptr = ncp.u_reg64;
zip_dbg("*ncb_ptr :0x%lx sw_head[phys] :0x%lx",
*ncb_ptr, __pa(zip_dev->iq[queue].sw_head));
zip_dev->iq[queue].pend_cnt++;
} else {
zip_dbg("Enough space is available for commands");
/* Push this cmd to cmd queue buffer */
memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr,
sizeof(union zip_inst_s));
zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */
zip_dev->iq[queue].pend_cnt++;
}
zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx",
zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail,
zip_dev->iq[queue].hw_tail);
zip_dbg(" Pushed the new cmd : pend_cnt : %d",
zip_dev->iq[queue].pend_cnt);
/* Ring the doorbell */
dbell.u_reg64 = 0ull;
dbell.s.dbell_cnt = 1;
zip_reg_write(dbell.u_reg64,
(zip_dev->reg_base + ZIP_QUEX_DOORBELL(queue)));
/* Unlock cmd buffer lock */
spin_unlock(&zip_dev->iq[queue].lock);
return queue;
}
/**
* zip_update_cmd_bufs - Updates the queue statistics after posting the
* instruction
* @zip_dev: Pointer to zip device structure
* @queue: Queue number
*/
void zip_update_cmd_bufs(struct zip_device *zip_dev, u32 queue)
{
/* Take cmd buffer lock */
spin_lock(&zip_dev->iq[queue].lock);
/* Check if the previous buffer can be freed */
if (zip_dev->iq[queue].free_flag == 1) {
zip_dbg("Free flag. Free cmd buffer, adjust sw head and tail");
/* Reset the free flag */
zip_dev->iq[queue].free_flag = 0;
/* Point the hw_tail to start of the new chunk buffer */
zip_dev->iq[queue].hw_tail = zip_dev->iq[queue].sw_head;
} else {
zip_dbg("Free flag not set. increment hw tail");
zip_dev->iq[queue].hw_tail += 16; /* 16 64_bit words = 128B */
}
zip_dev->iq[queue].done_cnt++;
zip_dev->iq[queue].pend_cnt--;
zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx",
zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail,
zip_dev->iq[queue].hw_tail);
zip_dbg(" Got CC : pend_cnt : %d\n", zip_dev->iq[queue].pend_cnt);
spin_unlock(&zip_dev->iq[queue].lock);
}

View File

@@ -1,108 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_DEVICE_H__
#define __ZIP_DEVICE_H__
#include <linux/types.h>
#include "zip_main.h"
struct sg_info {
/*
* Pointer to the input data when scatter_gather == 0 and
* pointer to the input gather list buffer when scatter_gather == 1
*/
union zip_zptr_s *gather;
/*
* Pointer to the output data when scatter_gather == 0 and
* pointer to the output scatter list buffer when scatter_gather == 1
*/
union zip_zptr_s *scatter;
/*
* Holds size of the output buffer pointed by scatter list
* when scatter_gather == 1
*/
u64 scatter_buf_size;
/* for gather data */
u64 gather_enable;
/* for scatter data */
u64 scatter_enable;
/* Number of gather list pointers for gather data */
u32 gbuf_cnt;
/* Number of scatter list pointers for scatter data */
u32 sbuf_cnt;
/* Buffers allocation state */
u8 alloc_state;
};
/**
* struct zip_state - Structure representing the required information related
* to a command
* @zip_cmd: Pointer to zip instruction structure
* @result: Pointer to zip result structure
* @ctx: Context pointer for inflate
* @history: Decompression history pointer
* @sginfo: Scatter-gather info structure
*/
struct zip_state {
union zip_inst_s zip_cmd;
union zip_zres_s result;
union zip_zptr_s *ctx;
union zip_zptr_s *history;
struct sg_info sginfo;
};
#define ZIP_CONTEXT_SIZE 2048
#define ZIP_INFLATE_HISTORY_SIZE 32768
#define ZIP_DEFLATE_HISTORY_SIZE 32768
#endif

View File

@@ -1,223 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include <linux/delay.h>
#include <linux/sched.h>
#include "common.h"
#include "zip_inflate.h"
static int prepare_inflate_zcmd(struct zip_operation *zip_ops,
struct zip_state *s, union zip_inst_s *zip_cmd)
{
union zip_zres_s *result_ptr = &s->result;
memset(zip_cmd, 0, sizeof(s->zip_cmd));
memset(result_ptr, 0, sizeof(s->result));
/* IWORD#0 */
/* Decompression History Gather list - no gather list */
zip_cmd->s.hg = 0;
/* For decompression, CE must be 0x0. */
zip_cmd->s.ce = 0;
/* For decompression, SS must be 0x0. */
zip_cmd->s.ss = 0;
/* For decompression, SF should always be set. */
zip_cmd->s.sf = 1;
/* Begin File */
if (zip_ops->begin_file == 0)
zip_cmd->s.bf = 0;
else
zip_cmd->s.bf = 1;
zip_cmd->s.ef = 1;
/* 0: for Deflate decompression, 3: for LZS decompression */
zip_cmd->s.cc = zip_ops->ccode;
/* IWORD #1*/
/* adler checksum */
zip_cmd->s.adlercrc32 = zip_ops->csum;
/*
* HISTORYLENGTH must be 0x0 for any ZIP decompress operation.
* History data is added to a decompression operation via IWORD3.
*/
zip_cmd->s.historylength = 0;
zip_cmd->s.ds = 0;
/* IWORD # 8 and 9 - Output pointer */
zip_cmd->s.out_ptr_addr.s.addr = __pa(zip_ops->output);
zip_cmd->s.out_ptr_ctl.s.length = zip_ops->output_len;
/* Maximum number of output-stream bytes that can be written */
zip_cmd->s.totaloutputlength = zip_ops->output_len;
zip_dbg("Data Direct Input case ");
/* IWORD # 6 and 7 - input pointer */
zip_cmd->s.dg = 0;
zip_cmd->s.inp_ptr_addr.s.addr = __pa((u8 *)zip_ops->input);
zip_cmd->s.inp_ptr_ctl.s.length = zip_ops->input_len;
/* IWORD # 10 and 11 - Result pointer */
zip_cmd->s.res_ptr_addr.s.addr = __pa(result_ptr);
/* Clearing completion code */
result_ptr->s.compcode = 0;
/* Returning 0 for time being.*/
return 0;
}
/**
* zip_inflate - API to offload inflate operation to hardware
* @zip_ops: Pointer to zip operation structure
* @s: Pointer to the structure representing zip state
* @zip_dev: Pointer to zip device structure
*
* This function prepares the zip inflate command and submits it to the zip
* engine for processing.
*
* Return: 0 if successful or error code
*/
int zip_inflate(struct zip_operation *zip_ops, struct zip_state *s,
struct zip_device *zip_dev)
{
union zip_inst_s *zip_cmd = &s->zip_cmd;
union zip_zres_s *result_ptr = &s->result;
u32 queue;
/* Prepare inflate zip command */
prepare_inflate_zcmd(zip_ops, s, zip_cmd);
atomic64_add(zip_ops->input_len, &zip_dev->stats.decomp_in_bytes);
/* Load inflate command to zip queue and ring the doorbell */
queue = zip_load_instr(zip_cmd, zip_dev);
/* Decompression requests submitted stats update */
atomic64_inc(&zip_dev->stats.decomp_req_submit);
/* Wait for completion or error */
zip_poll_result(result_ptr);
/* Decompression requests completed stats update */
atomic64_inc(&zip_dev->stats.decomp_req_complete);
zip_ops->compcode = result_ptr->s.compcode;
switch (zip_ops->compcode) {
case ZIP_CMD_NOTDONE:
zip_dbg("Zip Instruction not yet completed\n");
return ZIP_ERROR;
case ZIP_CMD_SUCCESS:
zip_dbg("Zip Instruction completed successfully\n");
break;
case ZIP_CMD_DYNAMIC_STOP:
zip_dbg(" Dynamic stop Initiated\n");
break;
default:
zip_dbg("Instruction failed. Code = %d\n", zip_ops->compcode);
atomic64_inc(&zip_dev->stats.decomp_bad_reqs);
zip_update_cmd_bufs(zip_dev, queue);
return ZIP_ERROR;
}
zip_update_cmd_bufs(zip_dev, queue);
if ((zip_ops->ccode == 3) && (zip_ops->flush == 4) &&
(zip_ops->compcode != ZIP_CMD_DYNAMIC_STOP))
result_ptr->s.ef = 1;
zip_ops->csum = result_ptr->s.adler32;
atomic64_add(result_ptr->s.totalbyteswritten,
&zip_dev->stats.decomp_out_bytes);
if (zip_ops->output_len < result_ptr->s.totalbyteswritten) {
zip_err("output_len (%d) < total bytes written (%d)\n",
zip_ops->output_len, result_ptr->s.totalbyteswritten);
zip_ops->output_len = 0;
} else {
zip_ops->output_len = result_ptr->s.totalbyteswritten;
}
zip_ops->bytes_read = result_ptr->s.totalbytesread;
zip_ops->bits_processed = result_ptr->s.totalbitsprocessed;
zip_ops->end_file = result_ptr->s.ef;
if (zip_ops->end_file) {
switch (zip_ops->format) {
case RAW_FORMAT:
zip_dbg("RAW Format: %d ", zip_ops->format);
/* Get checksum from engine */
zip_ops->csum = result_ptr->s.adler32;
break;
case ZLIB_FORMAT:
zip_dbg("ZLIB Format: %d ", zip_ops->format);
zip_ops->csum = result_ptr->s.adler32;
break;
case GZIP_FORMAT:
zip_dbg("GZIP Format: %d ", zip_ops->format);
zip_ops->csum = result_ptr->s.crc32;
break;
case LZS_FORMAT:
zip_dbg("LZS Format: %d ", zip_ops->format);
break;
default:
zip_err("Format error:%d\n", zip_ops->format);
}
}
return 0;
}

View File

@@ -1,62 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_INFLATE_H__
#define __ZIP_INFLATE_H__
/**
* zip_inflate - API to offload inflate operation to hardware
* @zip_ops: Pointer to zip operation structure
* @s: Pointer to the structure representing zip state
* @zip_dev: Pointer to the structure representing zip device
*
* This function prepares the zip inflate command and submits it to the zip
* engine for processing.
*
* Return: 0 if successful or error code
*/
int zip_inflate(struct zip_operation *zip_ops, struct zip_state *s,
struct zip_device *zip_dev);
#endif

View File

@@ -1,603 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include "common.h"
#include "zip_crypto.h"
#define DRV_NAME "ThunderX-ZIP"
static struct zip_device *zip_dev[MAX_ZIP_DEVICES];
static const struct pci_device_id zip_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDERX_ZIP) },
{ 0, }
};
static void zip_debugfs_init(void);
static void zip_debugfs_exit(void);
static int zip_register_compression_device(void);
static void zip_unregister_compression_device(void);
void zip_reg_write(u64 val, u64 __iomem *addr)
{
writeq(val, addr);
}
u64 zip_reg_read(u64 __iomem *addr)
{
return readq(addr);
}
/*
* Allocates new ZIP device structure
* Returns zip_device pointer or NULL if cannot allocate memory for zip_device
*/
static struct zip_device *zip_alloc_device(struct pci_dev *pdev)
{
struct zip_device *zip = NULL;
int idx;
for (idx = 0; idx < MAX_ZIP_DEVICES; idx++) {
if (!zip_dev[idx])
break;
}
/* To ensure that the index is within the limit */
if (idx < MAX_ZIP_DEVICES)
zip = devm_kzalloc(&pdev->dev, sizeof(*zip), GFP_KERNEL);
if (!zip)
return NULL;
zip_dev[idx] = zip;
zip->index = idx;
return zip;
}
/**
* zip_get_device - Get ZIP device based on node id of cpu
*
* @node: Node id of the current cpu
* Return: Pointer to Zip device structure
*/
struct zip_device *zip_get_device(int node)
{
if ((node < MAX_ZIP_DEVICES) && (node >= 0))
return zip_dev[node];
zip_err("ZIP device not found for node id %d\n", node);
return NULL;
}
/**
* zip_get_node_id - Get the node id of the current cpu
*
* Return: Node id of the current cpu
*/
int zip_get_node_id(void)
{
return cpu_to_node(raw_smp_processor_id());
}
/* Initializes the ZIP h/w sub-system */
static int zip_init_hw(struct zip_device *zip)
{
union zip_cmd_ctl cmd_ctl;
union zip_constants constants;
union zip_que_ena que_ena;
union zip_quex_map que_map;
union zip_que_pri que_pri;
union zip_quex_sbuf_addr que_sbuf_addr;
union zip_quex_sbuf_ctl que_sbuf_ctl;
int q = 0;
/* Enable the ZIP Engine(Core) Clock */
cmd_ctl.u_reg64 = zip_reg_read(zip->reg_base + ZIP_CMD_CTL);
cmd_ctl.s.forceclk = 1;
zip_reg_write(cmd_ctl.u_reg64 & 0xFF, (zip->reg_base + ZIP_CMD_CTL));
zip_msg("ZIP_CMD_CTL : 0x%016llx",
zip_reg_read(zip->reg_base + ZIP_CMD_CTL));
constants.u_reg64 = zip_reg_read(zip->reg_base + ZIP_CONSTANTS);
zip->depth = constants.s.depth;
zip->onfsize = constants.s.onfsize;
zip->ctxsize = constants.s.ctxsize;
zip_msg("depth: 0x%016llx , onfsize : 0x%016llx , ctxsize : 0x%016llx",
zip->depth, zip->onfsize, zip->ctxsize);
/*
* Program ZIP_QUE(0..7)_SBUF_ADDR and ZIP_QUE(0..7)_SBUF_CTL to
* have the correct buffer pointer and size configured for each
* instruction queue.
*/
for (q = 0; q < ZIP_NUM_QUEUES; q++) {
que_sbuf_ctl.u_reg64 = 0ull;
que_sbuf_ctl.s.size = (ZIP_CMD_QBUF_SIZE / sizeof(u64));
que_sbuf_ctl.s.inst_be = 0;
que_sbuf_ctl.s.stream_id = 0;
zip_reg_write(que_sbuf_ctl.u_reg64,
(zip->reg_base + ZIP_QUEX_SBUF_CTL(q)));
zip_msg("QUEX_SBUF_CTL[%d]: 0x%016llx", q,
zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_CTL(q)));
}
for (q = 0; q < ZIP_NUM_QUEUES; q++) {
memset(&zip->iq[q], 0x0, sizeof(struct zip_iq));
spin_lock_init(&zip->iq[q].lock);
if (zip_cmd_qbuf_alloc(zip, q)) {
while (q != 0) {
q--;
zip_cmd_qbuf_free(zip, q);
}
return -ENOMEM;
}
/* Initialize tail ptr to head */
zip->iq[q].sw_tail = zip->iq[q].sw_head;
zip->iq[q].hw_tail = zip->iq[q].sw_head;
/* Write the physical addr to register */
que_sbuf_addr.u_reg64 = 0ull;
que_sbuf_addr.s.ptr = (__pa(zip->iq[q].sw_head) >>
ZIP_128B_ALIGN);
zip_msg("QUE[%d]_PTR(PHYS): 0x%016llx", q,
(u64)que_sbuf_addr.s.ptr);
zip_reg_write(que_sbuf_addr.u_reg64,
(zip->reg_base + ZIP_QUEX_SBUF_ADDR(q)));
zip_msg("QUEX_SBUF_ADDR[%d]: 0x%016llx", q,
zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_ADDR(q)));
zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx",
zip->iq[q].sw_head, zip->iq[q].sw_tail,
zip->iq[q].hw_tail);
zip_dbg("sw_head phy addr : 0x%lx", que_sbuf_addr.s.ptr);
}
/*
* Queue-to-ZIP core mapping
* If a queue is not mapped to a particular core, it is equivalent to
* the ZIP core being disabled.
*/
que_ena.u_reg64 = 0x0ull;
/* Enabling queues based on ZIP_NUM_QUEUES */
for (q = 0; q < ZIP_NUM_QUEUES; q++)
que_ena.s.ena |= (0x1 << q);
zip_reg_write(que_ena.u_reg64, (zip->reg_base + ZIP_QUE_ENA));
zip_msg("QUE_ENA : 0x%016llx",
zip_reg_read(zip->reg_base + ZIP_QUE_ENA));
for (q = 0; q < ZIP_NUM_QUEUES; q++) {
que_map.u_reg64 = 0ull;
/* Mapping each queue to two ZIP cores */
que_map.s.zce = 0x3;
zip_reg_write(que_map.u_reg64,
(zip->reg_base + ZIP_QUEX_MAP(q)));
zip_msg("QUE_MAP(%d) : 0x%016llx", q,
zip_reg_read(zip->reg_base + ZIP_QUEX_MAP(q)));
}
que_pri.u_reg64 = 0ull;
for (q = 0; q < ZIP_NUM_QUEUES; q++)
que_pri.s.pri |= (0x1 << q); /* Higher Priority RR */
zip_reg_write(que_pri.u_reg64, (zip->reg_base + ZIP_QUE_PRI));
zip_msg("QUE_PRI %016llx", zip_reg_read(zip->reg_base + ZIP_QUE_PRI));
return 0;
}
static void zip_reset(struct zip_device *zip)
{
union zip_cmd_ctl cmd_ctl;
cmd_ctl.u_reg64 = 0x0ull;
cmd_ctl.s.reset = 1; /* Forces ZIP cores to do reset */
zip_reg_write(cmd_ctl.u_reg64, (zip->reg_base + ZIP_CMD_CTL));
}
static int zip_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
struct zip_device *zip = NULL;
int err;
zip = zip_alloc_device(pdev);
if (!zip)
return -ENOMEM;
dev_info(dev, "Found ZIP device %d %x:%x on Node %d\n", zip->index,
pdev->vendor, pdev->device, dev_to_node(dev));
pci_set_drvdata(pdev, zip);
zip->pdev = pdev;
err = pci_enable_device(pdev);
if (err) {
dev_err(dev, "Failed to enable PCI device");
goto err_free_device;
}
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
dev_err(dev, "PCI request regions failed 0x%x", err);
goto err_disable_device;
}
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
if (err) {
dev_err(dev, "Unable to get usable 48-bit DMA configuration\n");
goto err_release_regions;
}
/* MAP configuration registers */
zip->reg_base = pci_ioremap_bar(pdev, PCI_CFG_ZIP_PF_BAR0);
if (!zip->reg_base) {
dev_err(dev, "ZIP: Cannot map BAR0 CSR memory space, aborting");
err = -ENOMEM;
goto err_release_regions;
}
/* Initialize ZIP Hardware */
err = zip_init_hw(zip);
if (err)
goto err_release_regions;
/* Register with the Kernel Crypto Interface */
err = zip_register_compression_device();
if (err < 0) {
zip_err("ZIP: Kernel Crypto Registration failed\n");
goto err_register;
}
/* comp-decomp statistics are handled with debugfs interface */
zip_debugfs_init();
return 0;
err_register:
zip_reset(zip);
err_release_regions:
if (zip->reg_base)
iounmap(zip->reg_base);
pci_release_regions(pdev);
err_disable_device:
pci_disable_device(pdev);
err_free_device:
pci_set_drvdata(pdev, NULL);
/* Remove zip_dev from zip_device list, free the zip_device memory */
zip_dev[zip->index] = NULL;
devm_kfree(dev, zip);
return err;
}
static void zip_remove(struct pci_dev *pdev)
{
struct zip_device *zip = pci_get_drvdata(pdev);
int q = 0;
if (!zip)
return;
zip_debugfs_exit();
zip_unregister_compression_device();
if (zip->reg_base) {
zip_reset(zip);
iounmap(zip->reg_base);
}
pci_release_regions(pdev);
pci_disable_device(pdev);
/*
* Free Command Queue buffers. This free should be called for all
* the enabled Queues.
*/
for (q = 0; q < ZIP_NUM_QUEUES; q++)
zip_cmd_qbuf_free(zip, q);
pci_set_drvdata(pdev, NULL);
/* remove zip device from zip device list */
zip_dev[zip->index] = NULL;
}
/* PCI Sub-System Interface */
static struct pci_driver zip_driver = {
.name = DRV_NAME,
.id_table = zip_id_table,
.probe = zip_probe,
.remove = zip_remove,
};
/* Kernel Crypto Subsystem Interface */
static struct scomp_alg zip_scomp_deflate = {
.alloc_ctx = zip_alloc_scomp_ctx_deflate,
.free_ctx = zip_free_scomp_ctx,
.compress = zip_scomp_compress,
.decompress = zip_scomp_decompress,
.base = {
.cra_name = "deflate",
.cra_driver_name = "deflate-scomp-cavium",
.cra_module = THIS_MODULE,
.cra_priority = 300,
}
};
static struct scomp_alg zip_scomp_lzs = {
.alloc_ctx = zip_alloc_scomp_ctx_lzs,
.free_ctx = zip_free_scomp_ctx,
.compress = zip_scomp_compress,
.decompress = zip_scomp_decompress,
.base = {
.cra_name = "lzs",
.cra_driver_name = "lzs-scomp-cavium",
.cra_module = THIS_MODULE,
.cra_priority = 300,
}
};
static int zip_register_compression_device(void)
{
int ret;
ret = crypto_register_scomp(&zip_scomp_deflate);
if (ret < 0) {
zip_err("Deflate scomp algorithm registration failed\n");
return ret;
}
ret = crypto_register_scomp(&zip_scomp_lzs);
if (ret < 0) {
zip_err("LZS scomp algorithm registration failed\n");
goto err_unregister_scomp_deflate;
}
return ret;
err_unregister_scomp_deflate:
crypto_unregister_scomp(&zip_scomp_deflate);
return ret;
}
static void zip_unregister_compression_device(void)
{
crypto_unregister_scomp(&zip_scomp_deflate);
crypto_unregister_scomp(&zip_scomp_lzs);
}
/*
* debugfs functions
*/
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
/* Displays ZIP device statistics */
static int zip_stats_show(struct seq_file *s, void *unused)
{
u64 val = 0ull;
u64 avg_chunk = 0ull, avg_cr = 0ull;
u32 q = 0;
int index = 0;
struct zip_device *zip;
struct zip_stats *st;
for (index = 0; index < MAX_ZIP_DEVICES; index++) {
u64 pending = 0;
if (zip_dev[index]) {
zip = zip_dev[index];
st = &zip->stats;
/* Get all the pending requests */
for (q = 0; q < ZIP_NUM_QUEUES; q++) {
val = zip_reg_read((zip->reg_base +
ZIP_DBG_QUEX_STA(q)));
pending += val >> 32 & 0xffffff;
}
val = atomic64_read(&st->comp_req_complete);
avg_chunk = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0;
val = atomic64_read(&st->comp_out_bytes);
avg_cr = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0;
seq_printf(s, " ZIP Device %d Stats\n"
"-----------------------------------\n"
"Comp Req Submitted : \t%lld\n"
"Comp Req Completed : \t%lld\n"
"Compress In Bytes : \t%lld\n"
"Compressed Out Bytes : \t%lld\n"
"Average Chunk size : \t%llu\n"
"Average Compression ratio : \t%llu\n"
"Decomp Req Submitted : \t%lld\n"
"Decomp Req Completed : \t%lld\n"
"Decompress In Bytes : \t%lld\n"
"Decompressed Out Bytes : \t%lld\n"
"Decompress Bad requests : \t%lld\n"
"Pending Req : \t%lld\n"
"---------------------------------\n",
index,
(u64)atomic64_read(&st->comp_req_submit),
(u64)atomic64_read(&st->comp_req_complete),
(u64)atomic64_read(&st->comp_in_bytes),
(u64)atomic64_read(&st->comp_out_bytes),
avg_chunk,
avg_cr,
(u64)atomic64_read(&st->decomp_req_submit),
(u64)atomic64_read(&st->decomp_req_complete),
(u64)atomic64_read(&st->decomp_in_bytes),
(u64)atomic64_read(&st->decomp_out_bytes),
(u64)atomic64_read(&st->decomp_bad_reqs),
pending);
}
}
return 0;
}
/* Clears stats data */
static int zip_clear_show(struct seq_file *s, void *unused)
{
int index = 0;
for (index = 0; index < MAX_ZIP_DEVICES; index++) {
if (zip_dev[index]) {
memset(&zip_dev[index]->stats, 0,
sizeof(struct zip_stats));
seq_printf(s, "Cleared stats for zip %d\n", index);
}
}
return 0;
}
static struct zip_registers zipregs[64] = {
{"ZIP_CMD_CTL ", 0x0000ull},
{"ZIP_THROTTLE ", 0x0010ull},
{"ZIP_CONSTANTS ", 0x00A0ull},
{"ZIP_QUE0_MAP ", 0x1400ull},
{"ZIP_QUE1_MAP ", 0x1408ull},
{"ZIP_QUE_ENA ", 0x0500ull},
{"ZIP_QUE_PRI ", 0x0508ull},
{"ZIP_QUE0_DONE ", 0x2000ull},
{"ZIP_QUE1_DONE ", 0x2008ull},
{"ZIP_QUE0_DOORBELL ", 0x4000ull},
{"ZIP_QUE1_DOORBELL ", 0x4008ull},
{"ZIP_QUE0_SBUF_ADDR ", 0x1000ull},
{"ZIP_QUE1_SBUF_ADDR ", 0x1008ull},
{"ZIP_QUE0_SBUF_CTL ", 0x1200ull},
{"ZIP_QUE1_SBUF_CTL ", 0x1208ull},
{ NULL, 0}
};
/* Prints registers' contents */
static int zip_regs_show(struct seq_file *s, void *unused)
{
u64 val = 0;
int i = 0, index = 0;
for (index = 0; index < MAX_ZIP_DEVICES; index++) {
if (zip_dev[index]) {
seq_printf(s, "--------------------------------\n"
" ZIP Device %d Registers\n"
"--------------------------------\n",
index);
i = 0;
while (zipregs[i].reg_name) {
val = zip_reg_read((zip_dev[index]->reg_base +
zipregs[i].reg_offset));
seq_printf(s, "%s: 0x%016llx\n",
zipregs[i].reg_name, val);
i++;
}
}
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(zip_stats);
DEFINE_SHOW_ATTRIBUTE(zip_clear);
DEFINE_SHOW_ATTRIBUTE(zip_regs);
/* Root directory for thunderx_zip debugfs entry */
static struct dentry *zip_debugfs_root;
static void zip_debugfs_init(void)
{
if (!debugfs_initialized())
return;
zip_debugfs_root = debugfs_create_dir("thunderx_zip", NULL);
/* Creating files for entries inside thunderx_zip directory */
debugfs_create_file("zip_stats", 0444, zip_debugfs_root, NULL,
&zip_stats_fops);
debugfs_create_file("zip_clear", 0444, zip_debugfs_root, NULL,
&zip_clear_fops);
debugfs_create_file("zip_regs", 0444, zip_debugfs_root, NULL,
&zip_regs_fops);
}
static void zip_debugfs_exit(void)
{
debugfs_remove_recursive(zip_debugfs_root);
}
#else
static void __init zip_debugfs_init(void) { }
static void __exit zip_debugfs_exit(void) { }
#endif
/* debugfs - end */
module_pci_driver(zip_driver);
MODULE_AUTHOR("Cavium Inc");
MODULE_DESCRIPTION("Cavium Inc ThunderX ZIP Driver");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(pci, zip_id_table);

View File

@@ -1,120 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_MAIN_H__
#define __ZIP_MAIN_H__
#include "zip_device.h"
#include "zip_regs.h"
/* PCI device IDs */
#define PCI_DEVICE_ID_THUNDERX_ZIP 0xA01A
/* ZIP device BARs */
#define PCI_CFG_ZIP_PF_BAR0 0 /* Base addr for normal regs */
/* Maximum available zip queues */
#define ZIP_MAX_NUM_QUEUES 8
#define ZIP_128B_ALIGN 7
/* Command queue buffer size */
#define ZIP_CMD_QBUF_SIZE (8064 + 8)
struct zip_registers {
char *reg_name;
u64 reg_offset;
};
/* ZIP Compression - Decompression stats */
struct zip_stats {
atomic64_t comp_req_submit;
atomic64_t comp_req_complete;
atomic64_t decomp_req_submit;
atomic64_t decomp_req_complete;
atomic64_t comp_in_bytes;
atomic64_t comp_out_bytes;
atomic64_t decomp_in_bytes;
atomic64_t decomp_out_bytes;
atomic64_t decomp_bad_reqs;
};
/* ZIP Instruction Queue */
struct zip_iq {
u64 *sw_head;
u64 *sw_tail;
u64 *hw_tail;
u64 done_cnt;
u64 pend_cnt;
u64 free_flag;
/* ZIP IQ lock */
spinlock_t lock;
};
/* ZIP Device */
struct zip_device {
u32 index;
void __iomem *reg_base;
struct pci_dev *pdev;
/* Different ZIP Constants */
u64 depth;
u64 onfsize;
u64 ctxsize;
struct zip_iq iq[ZIP_MAX_NUM_QUEUES];
struct zip_stats stats;
};
/* Prototypes */
struct zip_device *zip_get_device(int node_id);
int zip_get_node_id(void);
void zip_reg_write(u64 val, u64 __iomem *addr);
u64 zip_reg_read(u64 __iomem *addr);
void zip_update_cmd_bufs(struct zip_device *zip_dev, u32 queue);
u32 zip_load_instr(union zip_inst_s *instr, struct zip_device *zip_dev);
#endif /* ZIP_MAIN_H */

View File

@@ -1,114 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#include <linux/types.h>
#include <linux/vmalloc.h>
#include "common.h"
/**
* zip_cmd_qbuf_alloc - Allocates a cmd buffer for ZIP Instruction Queue
* @zip: Pointer to zip device structure
* @q: Queue number to allocate bufffer to
* Return: 0 if successful, -ENOMEM otherwise
*/
int zip_cmd_qbuf_alloc(struct zip_device *zip, int q)
{
zip->iq[q].sw_head = (u64 *)__get_free_pages((GFP_KERNEL | GFP_DMA),
get_order(ZIP_CMD_QBUF_SIZE));
if (!zip->iq[q].sw_head)
return -ENOMEM;
memset(zip->iq[q].sw_head, 0, ZIP_CMD_QBUF_SIZE);
zip_dbg("cmd_qbuf_alloc[%d] Success : %p\n", q, zip->iq[q].sw_head);
return 0;
}
/**
* zip_cmd_qbuf_free - Frees the cmd Queue buffer
* @zip: Pointer to zip device structure
* @q: Queue number to free buffer of
*/
void zip_cmd_qbuf_free(struct zip_device *zip, int q)
{
zip_dbg("Freeing cmd_qbuf 0x%lx\n", zip->iq[q].sw_tail);
free_pages((u64)zip->iq[q].sw_tail, get_order(ZIP_CMD_QBUF_SIZE));
}
/**
* zip_data_buf_alloc - Allocates memory for a data bufffer
* @size: Size of the buffer to allocate
* Returns: Pointer to the buffer allocated
*/
u8 *zip_data_buf_alloc(u64 size)
{
u8 *ptr;
ptr = (u8 *)__get_free_pages((GFP_KERNEL | GFP_DMA),
get_order(size));
if (!ptr)
return NULL;
memset(ptr, 0, size);
zip_dbg("Data buffer allocation success\n");
return ptr;
}
/**
* zip_data_buf_free - Frees the memory of a data buffer
* @ptr: Pointer to the buffer
* @size: Buffer size
*/
void zip_data_buf_free(u8 *ptr, u64 size)
{
zip_dbg("Freeing data buffer 0x%lx\n", ptr);
free_pages((u64)ptr, get_order(size));
}

View File

@@ -1,78 +0,0 @@
/***********************license start************************************
* Copyright (c) 2003-2017 Cavium, Inc.
* All rights reserved.
*
* License: one of 'Cavium License' or 'GNU General Public License Version 2'
*
* This file is provided under the terms of the Cavium License (see below)
* or under the terms of GNU General Public License, Version 2, as
* published by the Free Software Foundation. When using or redistributing
* this file, you may do so under either license.
*
* Cavium License: Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY)
* WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A
* PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
* ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE
* ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES
* WITH YOU.
***********************license end**************************************/
#ifndef __ZIP_MEM_H__
#define __ZIP_MEM_H__
/**
* zip_cmd_qbuf_free - Frees the cmd Queue buffer
* @zip: Pointer to zip device structure
* @q: Queue nmber to free buffer of
*/
void zip_cmd_qbuf_free(struct zip_device *zip, int q);
/**
* zip_cmd_qbuf_alloc - Allocates a Chunk/cmd buffer for ZIP Inst(cmd) Queue
* @zip: Pointer to zip device structure
* @q: Queue number to allocate bufffer to
* Return: 0 if successful, 1 otherwise
*/
int zip_cmd_qbuf_alloc(struct zip_device *zip, int q);
/**
* zip_data_buf_alloc - Allocates memory for a data bufffer
* @size: Size of the buffer to allocate
* Returns: Pointer to the buffer allocated
*/
u8 *zip_data_buf_alloc(u64 size);
/**
* zip_data_buf_free - Frees the memory of a data buffer
* @ptr: Pointer to the buffer
* @size: Buffer size
*/
void zip_data_buf_free(u8 *ptr, u64 size);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -130,14 +130,8 @@ struct crypto_acomp {
struct crypto_tfm base;
};
struct crypto_acomp_stream {
spinlock_t lock;
void *ctx;
};
#define COMP_ALG_COMMON { \
struct crypto_alg base; \
struct crypto_acomp_stream __percpu *stream; \
}
struct comp_alg_common COMP_ALG_COMMON;

View File

@@ -68,16 +68,17 @@ struct crypto_instance {
struct crypto_spawn *spawns;
};
struct work_struct free_work;
void *__ctx[] CRYPTO_MINALIGN_ATTR;
};
struct crypto_template {
struct list_head list;
struct hlist_head instances;
struct hlist_head dead;
struct module *module;
struct work_struct free_work;
int (*create)(struct crypto_template *tmpl, struct rtattr **tb);
char name[CRYPTO_MAX_ALG_NAME];

View File

@@ -11,6 +11,11 @@
#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>
#include <linux/workqueue_types.h>
#define ACOMP_REQUEST_ON_STACK(name, tfm) \
char __##name##_req[sizeof(struct acomp_req) + \
@@ -37,7 +42,6 @@
*
* @reqsize: Context size for (de)compression requests
* @base: Common crypto API algorithm data structure
* @stream: Per-cpu memory for algorithm
* @calg: Cmonn algorithm data structure shared with scomp
*/
struct acomp_alg {
@@ -54,6 +58,55 @@ struct acomp_alg {
};
};
struct crypto_acomp_stream {
spinlock_t lock;
void *ctx;
};
struct crypto_acomp_streams {
/* These must come first because of struct scomp_alg. */
void *(*alloc_ctx)(void);
union {
void (*free_ctx)(void *);
void (*cfree_ctx)(const void *);
};
struct crypto_acomp_stream __percpu *streams;
struct work_struct stream_work;
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.
*/
@@ -158,4 +211,27 @@ static inline bool crypto_acomp_req_chain(struct crypto_acomp *tfm)
return crypto_tfm_req_chain(&tfm->base);
}
void crypto_acomp_free_streams(struct crypto_acomp_streams *s);
int crypto_acomp_alloc_streams(struct crypto_acomp_streams *s);
struct crypto_acomp_stream *crypto_acomp_lock_stream_bh(
struct crypto_acomp_streams *s) __acquires(stream);
static inline void crypto_acomp_unlock_stream_bh(
struct crypto_acomp_stream *stream) __releases(stream)
{
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

View File

@@ -9,10 +9,7 @@
#ifndef _CRYPTO_SCOMP_INT_H
#define _CRYPTO_SCOMP_INT_H
#include <crypto/acompress.h>
#include <crypto/algapi.h>
struct acomp_req;
#include <crypto/internal/acompress.h>
struct crypto_scomp {
struct crypto_tfm base;
@@ -26,12 +23,10 @@ struct crypto_scomp {
* @compress: Function performs a compress operation
* @decompress: Function performs a de-compress operation
* @base: Common crypto API algorithm data structure
* @stream: Per-cpu memory for algorithm
* @streams: Per-cpu memory for algorithm
* @calg: Cmonn algorithm data structure shared with acomp
*/
struct scomp_alg {
void *(*alloc_ctx)(void);
void (*free_ctx)(void *ctx);
int (*compress)(struct crypto_scomp *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int *dlen,
void *ctx);
@@ -39,6 +34,14 @@ struct scomp_alg {
unsigned int slen, u8 *dst, unsigned int *dlen,
void *ctx);
union {
struct {
void *(*alloc_ctx)(void);
void (*free_ctx)(void *ctx);
};
struct crypto_acomp_streams streams;
};
union {
struct COMP_ALG_COMMON;
struct comp_alg_common calg;