]>
Commit | Line | Data |
---|---|---|
ed70b479 DS |
1 | /* |
2 | * Cryptographic API for the NX-842 hardware compression. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * Copyright (C) IBM Corporation, 2011-2015 | |
15 | * | |
16 | * Original Authors: Robert Jennings <rcj@linux.vnet.ibm.com> | |
17 | * Seth Jennings <sjenning@linux.vnet.ibm.com> | |
18 | * | |
19 | * Rewrite: Dan Streetman <ddstreet@ieee.org> | |
20 | * | |
21 | * This is an interface to the NX-842 compression hardware in PowerPC | |
22 | * processors. Most of the complexity of this drvier is due to the fact that | |
23 | * the NX-842 compression hardware requires the input and output data buffers | |
24 | * to be specifically aligned, to be a specific multiple in length, and within | |
25 | * specific minimum and maximum lengths. Those restrictions, provided by the | |
26 | * nx-842 driver via nx842_constraints, mean this driver must use bounce | |
27 | * buffers and headers to correct misaligned in or out buffers, and to split | |
28 | * input buffers that are too large. | |
29 | * | |
30 | * This driver will fall back to software decompression if the hardware | |
31 | * decompression fails, so this driver's decompression should never fail as | |
32 | * long as the provided compressed buffer is valid. Any compressed buffer | |
33 | * created by this driver will have a header (except ones where the input | |
34 | * perfectly matches the constraints); so users of this driver cannot simply | |
35 | * pass a compressed buffer created by this driver over to the 842 software | |
36 | * decompression library. Instead, users must use this driver to decompress; | |
37 | * if the hardware fails or is unavailable, the compressed buffer will be | |
38 | * parsed and the header removed, and the raw 842 buffer(s) passed to the 842 | |
39 | * software decompression library. | |
40 | * | |
41 | * This does not fall back to software compression, however, since the caller | |
42 | * of this function is specifically requesting hardware compression; if the | |
43 | * hardware compression fails, the caller can fall back to software | |
44 | * compression, and the raw 842 compressed buffer that the software compressor | |
45 | * creates can be passed to this driver for hardware decompression; any | |
46 | * buffer without our specific header magic is assumed to be a raw 842 buffer | |
47 | * and passed directly to the hardware. Note that the software compression | |
48 | * library will produce a compressed buffer that is incompatible with the | |
49 | * hardware decompressor if the original input buffer length is not a multiple | |
50 | * of 8; if such a compressed buffer is passed to this driver for | |
51 | * decompression, the hardware will reject it and this driver will then pass | |
52 | * it over to the software library for decompression. | |
53 | */ | |
54 | ||
55 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
56 | ||
57 | #include <linux/init.h> | |
58 | #include <linux/module.h> | |
59 | #include <linux/crypto.h> | |
60 | #include <linux/vmalloc.h> | |
ed70b479 DS |
61 | #include <linux/sw842.h> |
62 | #include <linux/ratelimit.h> | |
63 | ||
32be6d3e DS |
64 | #include "nx-842.h" |
65 | ||
ed70b479 DS |
66 | /* The first 5 bits of this magic are 0x1f, which is an invalid 842 5-bit |
67 | * template (see lib/842/842.h), so this magic number will never appear at | |
68 | * the start of a raw 842 compressed buffer. That is important, as any buffer | |
69 | * passed to us without this magic is assumed to be a raw 842 compressed | |
70 | * buffer, and passed directly to the hardware to decompress. | |
71 | */ | |
72 | #define NX842_CRYPTO_MAGIC (0xf842) | |
73 | #define NX842_CRYPTO_GROUP_MAX (0x20) | |
74 | #define NX842_CRYPTO_HEADER_SIZE(g) \ | |
75 | (sizeof(struct nx842_crypto_header) + \ | |
76 | sizeof(struct nx842_crypto_header_group) * (g)) | |
77 | #define NX842_CRYPTO_HEADER_MAX_SIZE \ | |
78 | NX842_CRYPTO_HEADER_SIZE(NX842_CRYPTO_GROUP_MAX) | |
79 | ||
80 | /* bounce buffer size */ | |
81 | #define BOUNCE_BUFFER_ORDER (2) | |
82 | #define BOUNCE_BUFFER_SIZE \ | |
83 | ((unsigned int)(PAGE_SIZE << BOUNCE_BUFFER_ORDER)) | |
84 | ||
85 | /* try longer on comp because we can fallback to sw decomp if hw is busy */ | |
86 | #define COMP_BUSY_TIMEOUT (250) /* ms */ | |
87 | #define DECOMP_BUSY_TIMEOUT (50) /* ms */ | |
88 | ||
89 | struct nx842_crypto_header_group { | |
90 | __be16 padding; /* unused bytes at start of group */ | |
91 | __be32 compressed_length; /* compressed bytes in group */ | |
92 | __be32 uncompressed_length; /* bytes after decompression */ | |
93 | } __packed; | |
94 | ||
95 | struct nx842_crypto_header { | |
96 | __be16 magic; /* NX842_CRYPTO_MAGIC */ | |
97 | __be16 ignore; /* decompressed end bytes to ignore */ | |
98 | u8 groups; /* total groups in this header */ | |
99 | struct nx842_crypto_header_group group[]; | |
100 | } __packed; | |
101 | ||
102 | struct nx842_crypto_param { | |
103 | u8 *in; | |
104 | unsigned int iremain; | |
105 | u8 *out; | |
106 | unsigned int oremain; | |
107 | unsigned int ototal; | |
108 | }; | |
109 | ||
110 | static int update_param(struct nx842_crypto_param *p, | |
111 | unsigned int slen, unsigned int dlen) | |
112 | { | |
113 | if (p->iremain < slen) | |
114 | return -EOVERFLOW; | |
115 | if (p->oremain < dlen) | |
116 | return -ENOSPC; | |
117 | ||
118 | p->in += slen; | |
119 | p->iremain -= slen; | |
120 | p->out += dlen; | |
121 | p->oremain -= dlen; | |
122 | p->ototal += dlen; | |
123 | ||
124 | return 0; | |
125 | } | |
126 | ||
127 | struct nx842_crypto_ctx { | |
128 | u8 *wmem; | |
129 | u8 *sbounce, *dbounce; | |
130 | ||
131 | struct nx842_crypto_header header; | |
132 | struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX]; | |
133 | }; | |
134 | ||
135 | static int nx842_crypto_init(struct crypto_tfm *tfm) | |
136 | { | |
137 | struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); | |
138 | ||
139 | ctx->wmem = kmalloc(NX842_MEM_COMPRESS, GFP_KERNEL); | |
140 | ctx->sbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); | |
141 | ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); | |
142 | if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) { | |
143 | kfree(ctx->wmem); | |
144 | free_page((unsigned long)ctx->sbounce); | |
145 | free_page((unsigned long)ctx->dbounce); | |
146 | return -ENOMEM; | |
147 | } | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | static void nx842_crypto_exit(struct crypto_tfm *tfm) | |
153 | { | |
154 | struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); | |
155 | ||
156 | kfree(ctx->wmem); | |
157 | free_page((unsigned long)ctx->sbounce); | |
158 | free_page((unsigned long)ctx->dbounce); | |
159 | } | |
160 | ||
161 | static int read_constraints(struct nx842_constraints *c) | |
162 | { | |
163 | int ret; | |
164 | ||
165 | ret = nx842_constraints(c); | |
166 | if (ret) { | |
167 | pr_err_ratelimited("could not get nx842 constraints : %d\n", | |
168 | ret); | |
169 | return ret; | |
170 | } | |
171 | ||
172 | /* limit maximum, to always have enough bounce buffer to decompress */ | |
173 | if (c->maximum > BOUNCE_BUFFER_SIZE) { | |
174 | c->maximum = BOUNCE_BUFFER_SIZE; | |
175 | pr_info_once("limiting nx842 maximum to %x\n", c->maximum); | |
176 | } | |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
181 | static int nx842_crypto_add_header(struct nx842_crypto_header *hdr, u8 *buf) | |
182 | { | |
183 | int s = NX842_CRYPTO_HEADER_SIZE(hdr->groups); | |
184 | ||
185 | /* compress should have added space for header */ | |
186 | if (s > be16_to_cpu(hdr->group[0].padding)) { | |
187 | pr_err("Internal error: no space for header\n"); | |
188 | return -EINVAL; | |
189 | } | |
190 | ||
191 | memcpy(buf, hdr, s); | |
192 | ||
193 | print_hex_dump_debug("header ", DUMP_PREFIX_OFFSET, 16, 1, buf, s, 0); | |
194 | ||
195 | return 0; | |
196 | } | |
197 | ||
198 | static int compress(struct nx842_crypto_ctx *ctx, | |
199 | struct nx842_crypto_param *p, | |
200 | struct nx842_crypto_header_group *g, | |
201 | struct nx842_constraints *c, | |
202 | u16 *ignore, | |
203 | unsigned int hdrsize) | |
204 | { | |
205 | unsigned int slen = p->iremain, dlen = p->oremain, tmplen; | |
206 | unsigned int adj_slen = slen; | |
207 | u8 *src = p->in, *dst = p->out; | |
208 | int ret, dskip = 0; | |
209 | ktime_t timeout; | |
210 | ||
211 | if (p->iremain == 0) | |
212 | return -EOVERFLOW; | |
213 | ||
214 | if (p->oremain == 0 || hdrsize + c->minimum > dlen) | |
215 | return -ENOSPC; | |
216 | ||
217 | if (slen % c->multiple) | |
218 | adj_slen = round_up(slen, c->multiple); | |
219 | if (slen < c->minimum) | |
220 | adj_slen = c->minimum; | |
221 | if (slen > c->maximum) | |
222 | adj_slen = slen = c->maximum; | |
223 | if (adj_slen > slen || (u64)src % c->alignment) { | |
224 | adj_slen = min(adj_slen, BOUNCE_BUFFER_SIZE); | |
225 | slen = min(slen, BOUNCE_BUFFER_SIZE); | |
226 | if (adj_slen > slen) | |
227 | memset(ctx->sbounce + slen, 0, adj_slen - slen); | |
228 | memcpy(ctx->sbounce, src, slen); | |
229 | src = ctx->sbounce; | |
230 | slen = adj_slen; | |
231 | pr_debug("using comp sbounce buffer, len %x\n", slen); | |
232 | } | |
233 | ||
234 | dst += hdrsize; | |
235 | dlen -= hdrsize; | |
236 | ||
237 | if ((u64)dst % c->alignment) { | |
238 | dskip = (int)(PTR_ALIGN(dst, c->alignment) - dst); | |
239 | dst += dskip; | |
240 | dlen -= dskip; | |
241 | } | |
242 | if (dlen % c->multiple) | |
243 | dlen = round_down(dlen, c->multiple); | |
244 | if (dlen < c->minimum) { | |
245 | nospc: | |
246 | dst = ctx->dbounce; | |
247 | dlen = min(p->oremain, BOUNCE_BUFFER_SIZE); | |
248 | dlen = round_down(dlen, c->multiple); | |
249 | dskip = 0; | |
250 | pr_debug("using comp dbounce buffer, len %x\n", dlen); | |
251 | } | |
252 | if (dlen > c->maximum) | |
253 | dlen = c->maximum; | |
254 | ||
255 | tmplen = dlen; | |
256 | timeout = ktime_add_ms(ktime_get(), COMP_BUSY_TIMEOUT); | |
257 | do { | |
258 | dlen = tmplen; /* reset dlen, if we're retrying */ | |
259 | ret = nx842_compress(src, slen, dst, &dlen, ctx->wmem); | |
260 | /* possibly we should reduce the slen here, instead of | |
261 | * retrying with the dbounce buffer? | |
262 | */ | |
263 | if (ret == -ENOSPC && dst != ctx->dbounce) | |
264 | goto nospc; | |
265 | } while (ret == -EBUSY && ktime_before(ktime_get(), timeout)); | |
266 | if (ret) | |
267 | return ret; | |
268 | ||
269 | dskip += hdrsize; | |
270 | ||
271 | if (dst == ctx->dbounce) | |
272 | memcpy(p->out + dskip, dst, dlen); | |
273 | ||
274 | g->padding = cpu_to_be16(dskip); | |
275 | g->compressed_length = cpu_to_be32(dlen); | |
276 | g->uncompressed_length = cpu_to_be32(slen); | |
277 | ||
278 | if (p->iremain < slen) { | |
279 | *ignore = slen - p->iremain; | |
280 | slen = p->iremain; | |
281 | } | |
282 | ||
283 | pr_debug("compress slen %x ignore %x dlen %x padding %x\n", | |
284 | slen, *ignore, dlen, dskip); | |
285 | ||
286 | return update_param(p, slen, dskip + dlen); | |
287 | } | |
288 | ||
289 | static int nx842_crypto_compress(struct crypto_tfm *tfm, | |
290 | const u8 *src, unsigned int slen, | |
291 | u8 *dst, unsigned int *dlen) | |
292 | { | |
293 | struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); | |
294 | struct nx842_crypto_header *hdr = &ctx->header; | |
295 | struct nx842_crypto_param p; | |
296 | struct nx842_constraints c; | |
297 | unsigned int groups, hdrsize, h; | |
298 | int ret, n; | |
299 | bool add_header; | |
300 | u16 ignore = 0; | |
301 | ||
ed70b479 DS |
302 | p.in = (u8 *)src; |
303 | p.iremain = slen; | |
304 | p.out = dst; | |
305 | p.oremain = *dlen; | |
306 | p.ototal = 0; | |
307 | ||
308 | *dlen = 0; | |
309 | ||
310 | ret = read_constraints(&c); | |
311 | if (ret) | |
312 | return ret; | |
313 | ||
314 | groups = min_t(unsigned int, NX842_CRYPTO_GROUP_MAX, | |
315 | DIV_ROUND_UP(p.iremain, c.maximum)); | |
316 | hdrsize = NX842_CRYPTO_HEADER_SIZE(groups); | |
317 | ||
318 | /* skip adding header if the buffers meet all constraints */ | |
319 | add_header = (p.iremain % c.multiple || | |
320 | p.iremain < c.minimum || | |
321 | p.iremain > c.maximum || | |
322 | (u64)p.in % c.alignment || | |
323 | p.oremain % c.multiple || | |
324 | p.oremain < c.minimum || | |
325 | p.oremain > c.maximum || | |
326 | (u64)p.out % c.alignment); | |
327 | ||
328 | hdr->magic = cpu_to_be16(NX842_CRYPTO_MAGIC); | |
329 | hdr->groups = 0; | |
330 | hdr->ignore = 0; | |
331 | ||
332 | while (p.iremain > 0) { | |
333 | n = hdr->groups++; | |
334 | if (hdr->groups > NX842_CRYPTO_GROUP_MAX) | |
335 | return -ENOSPC; | |
336 | ||
337 | /* header goes before first group */ | |
338 | h = !n && add_header ? hdrsize : 0; | |
339 | ||
340 | if (ignore) | |
341 | pr_warn("interal error, ignore is set %x\n", ignore); | |
342 | ||
343 | ret = compress(ctx, &p, &hdr->group[n], &c, &ignore, h); | |
344 | if (ret) | |
345 | return ret; | |
346 | } | |
347 | ||
348 | if (!add_header && hdr->groups > 1) { | |
349 | pr_err("Internal error: No header but multiple groups\n"); | |
350 | return -EINVAL; | |
351 | } | |
352 | ||
353 | /* ignore indicates the input stream needed to be padded */ | |
354 | hdr->ignore = cpu_to_be16(ignore); | |
355 | if (ignore) | |
356 | pr_debug("marked %d bytes as ignore\n", ignore); | |
357 | ||
358 | if (add_header) | |
359 | ret = nx842_crypto_add_header(hdr, dst); | |
360 | if (ret) | |
361 | return ret; | |
362 | ||
363 | *dlen = p.ototal; | |
364 | ||
365 | pr_debug("compress total slen %x dlen %x\n", slen, *dlen); | |
366 | ||
367 | return 0; | |
368 | } | |
369 | ||
370 | static int decompress(struct nx842_crypto_ctx *ctx, | |
371 | struct nx842_crypto_param *p, | |
372 | struct nx842_crypto_header_group *g, | |
373 | struct nx842_constraints *c, | |
374 | u16 ignore, | |
375 | bool usehw) | |
376 | { | |
377 | unsigned int slen = be32_to_cpu(g->compressed_length); | |
378 | unsigned int required_len = be32_to_cpu(g->uncompressed_length); | |
379 | unsigned int dlen = p->oremain, tmplen; | |
380 | unsigned int adj_slen = slen; | |
381 | u8 *src = p->in, *dst = p->out; | |
382 | u16 padding = be16_to_cpu(g->padding); | |
383 | int ret, spadding = 0, dpadding = 0; | |
384 | ktime_t timeout; | |
385 | ||
386 | if (!slen || !required_len) | |
387 | return -EINVAL; | |
388 | ||
389 | if (p->iremain <= 0 || padding + slen > p->iremain) | |
390 | return -EOVERFLOW; | |
391 | ||
392 | if (p->oremain <= 0 || required_len - ignore > p->oremain) | |
393 | return -ENOSPC; | |
394 | ||
395 | src += padding; | |
396 | ||
397 | if (!usehw) | |
398 | goto usesw; | |
399 | ||
400 | if (slen % c->multiple) | |
401 | adj_slen = round_up(slen, c->multiple); | |
402 | if (slen < c->minimum) | |
403 | adj_slen = c->minimum; | |
404 | if (slen > c->maximum) | |
405 | goto usesw; | |
406 | if (slen < adj_slen || (u64)src % c->alignment) { | |
407 | /* we can append padding bytes because the 842 format defines | |
408 | * an "end" template (see lib/842/842_decompress.c) and will | |
409 | * ignore any bytes following it. | |
410 | */ | |
411 | if (slen < adj_slen) | |
412 | memset(ctx->sbounce + slen, 0, adj_slen - slen); | |
413 | memcpy(ctx->sbounce, src, slen); | |
414 | src = ctx->sbounce; | |
415 | spadding = adj_slen - slen; | |
416 | slen = adj_slen; | |
417 | pr_debug("using decomp sbounce buffer, len %x\n", slen); | |
418 | } | |
419 | ||
420 | if (dlen % c->multiple) | |
421 | dlen = round_down(dlen, c->multiple); | |
422 | if (dlen < required_len || (u64)dst % c->alignment) { | |
423 | dst = ctx->dbounce; | |
424 | dlen = min(required_len, BOUNCE_BUFFER_SIZE); | |
425 | pr_debug("using decomp dbounce buffer, len %x\n", dlen); | |
426 | } | |
427 | if (dlen < c->minimum) | |
428 | goto usesw; | |
429 | if (dlen > c->maximum) | |
430 | dlen = c->maximum; | |
431 | ||
432 | tmplen = dlen; | |
433 | timeout = ktime_add_ms(ktime_get(), DECOMP_BUSY_TIMEOUT); | |
434 | do { | |
435 | dlen = tmplen; /* reset dlen, if we're retrying */ | |
436 | ret = nx842_decompress(src, slen, dst, &dlen, ctx->wmem); | |
437 | } while (ret == -EBUSY && ktime_before(ktime_get(), timeout)); | |
438 | if (ret) { | |
439 | usesw: | |
440 | /* reset everything, sw doesn't have constraints */ | |
441 | src = p->in + padding; | |
442 | slen = be32_to_cpu(g->compressed_length); | |
443 | spadding = 0; | |
444 | dst = p->out; | |
445 | dlen = p->oremain; | |
446 | dpadding = 0; | |
447 | if (dlen < required_len) { /* have ignore bytes */ | |
448 | dst = ctx->dbounce; | |
449 | dlen = BOUNCE_BUFFER_SIZE; | |
450 | } | |
451 | pr_info_ratelimited("using software 842 decompression\n"); | |
452 | ret = sw842_decompress(src, slen, dst, &dlen); | |
453 | } | |
454 | if (ret) | |
455 | return ret; | |
456 | ||
457 | slen -= spadding; | |
458 | ||
459 | dlen -= ignore; | |
460 | if (ignore) | |
461 | pr_debug("ignoring last %x bytes\n", ignore); | |
462 | ||
463 | if (dst == ctx->dbounce) | |
464 | memcpy(p->out, dst, dlen); | |
465 | ||
466 | pr_debug("decompress slen %x padding %x dlen %x ignore %x\n", | |
467 | slen, padding, dlen, ignore); | |
468 | ||
469 | return update_param(p, slen + padding, dlen); | |
470 | } | |
471 | ||
472 | static int nx842_crypto_decompress(struct crypto_tfm *tfm, | |
473 | const u8 *src, unsigned int slen, | |
474 | u8 *dst, unsigned int *dlen) | |
475 | { | |
476 | struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); | |
477 | struct nx842_crypto_header *hdr; | |
478 | struct nx842_crypto_param p; | |
479 | struct nx842_constraints c; | |
480 | int n, ret, hdr_len; | |
481 | u16 ignore = 0; | |
482 | bool usehw = true; | |
483 | ||
ed70b479 DS |
484 | p.in = (u8 *)src; |
485 | p.iremain = slen; | |
486 | p.out = dst; | |
487 | p.oremain = *dlen; | |
488 | p.ototal = 0; | |
489 | ||
490 | *dlen = 0; | |
491 | ||
492 | if (read_constraints(&c)) | |
493 | usehw = false; | |
494 | ||
495 | hdr = (struct nx842_crypto_header *)src; | |
496 | ||
497 | /* If it doesn't start with our header magic number, assume it's a raw | |
498 | * 842 compressed buffer and pass it directly to the hardware driver | |
499 | */ | |
500 | if (be16_to_cpu(hdr->magic) != NX842_CRYPTO_MAGIC) { | |
501 | struct nx842_crypto_header_group g = { | |
502 | .padding = 0, | |
503 | .compressed_length = cpu_to_be32(p.iremain), | |
504 | .uncompressed_length = cpu_to_be32(p.oremain), | |
505 | }; | |
506 | ||
507 | ret = decompress(ctx, &p, &g, &c, 0, usehw); | |
508 | if (ret) | |
509 | return ret; | |
510 | ||
511 | *dlen = p.ototal; | |
512 | ||
513 | return 0; | |
514 | } | |
515 | ||
516 | if (!hdr->groups) { | |
517 | pr_err("header has no groups\n"); | |
518 | return -EINVAL; | |
519 | } | |
520 | if (hdr->groups > NX842_CRYPTO_GROUP_MAX) { | |
521 | pr_err("header has too many groups %x, max %x\n", | |
522 | hdr->groups, NX842_CRYPTO_GROUP_MAX); | |
523 | return -EINVAL; | |
524 | } | |
525 | ||
526 | hdr_len = NX842_CRYPTO_HEADER_SIZE(hdr->groups); | |
527 | if (hdr_len > slen) | |
528 | return -EOVERFLOW; | |
529 | ||
530 | memcpy(&ctx->header, src, hdr_len); | |
531 | hdr = &ctx->header; | |
532 | ||
533 | for (n = 0; n < hdr->groups; n++) { | |
534 | /* ignore applies to last group */ | |
535 | if (n + 1 == hdr->groups) | |
536 | ignore = be16_to_cpu(hdr->ignore); | |
537 | ||
538 | ret = decompress(ctx, &p, &hdr->group[n], &c, ignore, usehw); | |
539 | if (ret) | |
540 | return ret; | |
541 | } | |
542 | ||
543 | *dlen = p.ototal; | |
544 | ||
545 | pr_debug("decompress total slen %x dlen %x\n", slen, *dlen); | |
546 | ||
547 | return 0; | |
548 | } | |
549 | ||
550 | static struct crypto_alg alg = { | |
551 | .cra_name = "842", | |
552 | .cra_driver_name = "842-nx", | |
553 | .cra_priority = 300, | |
554 | .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, | |
555 | .cra_ctxsize = sizeof(struct nx842_crypto_ctx), | |
556 | .cra_module = THIS_MODULE, | |
557 | .cra_init = nx842_crypto_init, | |
558 | .cra_exit = nx842_crypto_exit, | |
559 | .cra_u = { .compress = { | |
560 | .coa_compress = nx842_crypto_compress, | |
561 | .coa_decompress = nx842_crypto_decompress } } | |
562 | }; | |
563 | ||
564 | static int __init nx842_crypto_mod_init(void) | |
565 | { | |
566 | return crypto_register_alg(&alg); | |
567 | } | |
568 | module_init(nx842_crypto_mod_init); | |
569 | ||
570 | static void __exit nx842_crypto_mod_exit(void) | |
571 | { | |
572 | crypto_unregister_alg(&alg); | |
573 | } | |
574 | module_exit(nx842_crypto_mod_exit); | |
575 | ||
576 | MODULE_LICENSE("GPL"); | |
577 | MODULE_DESCRIPTION("IBM PowerPC Nest (NX) 842 Hardware Compression Interface"); | |
578 | MODULE_ALIAS_CRYPTO("842"); | |
579 | MODULE_ALIAS_CRYPTO("842-nx"); | |
580 | MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>"); |