1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19#include "nx-842.h"
20
21#include <linux/timer.h>
22
23#include <asm/prom.h>
24#include <asm/icswx.h>
25
26MODULE_LICENSE("GPL");
27MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
28MODULE_DESCRIPTION("842 H/W Compression driver for IBM PowerNV processors");
29MODULE_ALIAS_CRYPTO("842");
30MODULE_ALIAS_CRYPTO("842-nx");
31
32#define WORKMEM_ALIGN (CRB_ALIGN)
33#define CSB_WAIT_MAX (5000)
34
35struct nx842_workmem {
36
37 struct coprocessor_request_block crb;
38 struct data_descriptor_entry ddl_in[DDL_LEN_MAX];
39 struct data_descriptor_entry ddl_out[DDL_LEN_MAX];
40
41
42 ktime_t start;
43
44 char padding[WORKMEM_ALIGN];
45} __packed __aligned(WORKMEM_ALIGN);
46
47struct nx842_coproc {
48 unsigned int chip_id;
49 unsigned int ct;
50 unsigned int ci;
51 struct list_head list;
52};
53
54
55static LIST_HEAD(nx842_coprocs);
56static unsigned int nx842_ct;
57
58
59
60
61
62
63
64static void setup_indirect_dde(struct data_descriptor_entry *dde,
65 struct data_descriptor_entry *ddl,
66 unsigned int dde_count, unsigned int byte_count)
67{
68 dde->flags = 0;
69 dde->count = dde_count;
70 dde->index = 0;
71 dde->length = cpu_to_be32(byte_count);
72 dde->address = cpu_to_be64(nx842_get_pa(ddl));
73}
74
75
76
77
78
79
80
81
82
83static unsigned int setup_direct_dde(struct data_descriptor_entry *dde,
84 unsigned long pa, unsigned int len)
85{
86 unsigned int l = min_t(unsigned int, len, LEN_ON_PAGE(pa));
87
88 dde->flags = 0;
89 dde->count = 0;
90 dde->index = 0;
91 dde->length = cpu_to_be32(l);
92 dde->address = cpu_to_be64(pa);
93
94 return l;
95}
96
97
98
99
100
101
102
103static int setup_ddl(struct data_descriptor_entry *dde,
104 struct data_descriptor_entry *ddl,
105 unsigned char *buf, unsigned int len,
106 bool in)
107{
108 unsigned long pa = nx842_get_pa(buf);
109 int i, ret, total_len = len;
110
111 if (!IS_ALIGNED(pa, DDE_BUFFER_ALIGN)) {
112 pr_debug("%s buffer pa 0x%lx not 0x%x-byte aligned\n",
113 in ? "input" : "output", pa, DDE_BUFFER_ALIGN);
114 return -EINVAL;
115 }
116
117
118
119
120
121
122 if (len % DDE_BUFFER_LAST_MULT) {
123 pr_debug("%s buffer len 0x%x not a multiple of 0x%x\n",
124 in ? "input" : "output", len, DDE_BUFFER_LAST_MULT);
125 if (in)
126 return -EINVAL;
127 len = round_down(len, DDE_BUFFER_LAST_MULT);
128 }
129
130
131 if (len <= LEN_ON_PAGE(pa)) {
132 ret = setup_direct_dde(dde, pa, len);
133 WARN_ON(ret < len);
134 return 0;
135 }
136
137
138 for (i = 0; i < DDL_LEN_MAX && len > 0; i++) {
139 ret = setup_direct_dde(&ddl[i], pa, len);
140 buf += ret;
141 len -= ret;
142 pa = nx842_get_pa(buf);
143 }
144
145 if (len > 0) {
146 pr_debug("0x%x total %s bytes 0x%x too many for DDL.\n",
147 total_len, in ? "input" : "output", len);
148 if (in)
149 return -EMSGSIZE;
150 total_len -= len;
151 }
152 setup_indirect_dde(dde, ddl, i, total_len);
153
154 return 0;
155}
156
157#define CSB_ERR(csb, msg, ...) \
158 pr_err("ERROR: " msg " : %02x %02x %02x %02x %08x\n", \
159 ##__VA_ARGS__, (csb)->flags, \
160 (csb)->cs, (csb)->cc, (csb)->ce, \
161 be32_to_cpu((csb)->count))
162
163#define CSB_ERR_ADDR(csb, msg, ...) \
164 CSB_ERR(csb, msg " at %lx", ##__VA_ARGS__, \
165 (unsigned long)be64_to_cpu((csb)->address))
166
167
168
169
170static int wait_for_csb(struct nx842_workmem *wmem,
171 struct coprocessor_status_block *csb)
172{
173 ktime_t start = wmem->start, now = ktime_get();
174 ktime_t timeout = ktime_add_ms(start, CSB_WAIT_MAX);
175
176 while (!(ACCESS_ONCE(csb->flags) & CSB_V)) {
177 cpu_relax();
178 now = ktime_get();
179 if (ktime_after(now, timeout))
180 break;
181 }
182
183
184 barrier();
185
186
187 if (!(csb->flags & CSB_V)) {
188 CSB_ERR(csb, "CSB still not valid after %ld us, giving up",
189 (long)ktime_us_delta(now, start));
190 return -ETIMEDOUT;
191 }
192 if (csb->flags & CSB_F) {
193 CSB_ERR(csb, "Invalid CSB format");
194 return -EPROTO;
195 }
196 if (csb->flags & CSB_CH) {
197 CSB_ERR(csb, "Invalid CSB chaining state");
198 return -EPROTO;
199 }
200
201
202 if (csb->cs) {
203 CSB_ERR(csb, "Invalid CSB completion sequence");
204 return -EPROTO;
205 }
206
207
208 switch (csb->cc) {
209
210 case CSB_CC_SUCCESS:
211 break;
212 case CSB_CC_TPBC_GT_SPBC:
213
214
215
216 break;
217
218
219 case CSB_CC_OPERAND_OVERLAP:
220
221 CSB_ERR(csb, "Operand Overlap error");
222 return -EINVAL;
223 case CSB_CC_INVALID_OPERAND:
224 CSB_ERR(csb, "Invalid operand");
225 return -EINVAL;
226 case CSB_CC_NOSPC:
227
228 return -ENOSPC;
229 case CSB_CC_ABORT:
230 CSB_ERR(csb, "Function aborted");
231 return -EINTR;
232 case CSB_CC_CRC_MISMATCH:
233 CSB_ERR(csb, "CRC mismatch");
234 return -EINVAL;
235 case CSB_CC_TEMPL_INVALID:
236 CSB_ERR(csb, "Compressed data template invalid");
237 return -EINVAL;
238 case CSB_CC_TEMPL_OVERFLOW:
239 CSB_ERR(csb, "Compressed data template shows data past end");
240 return -EINVAL;
241
242
243 case CSB_CC_INVALID_ALIGN:
244
245 CSB_ERR_ADDR(csb, "Invalid alignment");
246 return -EINVAL;
247 case CSB_CC_DATA_LENGTH:
248
249 CSB_ERR(csb, "Invalid data length");
250 return -EINVAL;
251 case CSB_CC_WR_TRANSLATION:
252 case CSB_CC_TRANSLATION:
253 case CSB_CC_TRANSLATION_DUP1:
254 case CSB_CC_TRANSLATION_DUP2:
255 case CSB_CC_TRANSLATION_DUP3:
256 case CSB_CC_TRANSLATION_DUP4:
257 case CSB_CC_TRANSLATION_DUP5:
258 case CSB_CC_TRANSLATION_DUP6:
259
260 CSB_ERR_ADDR(csb, "Translation error");
261 return -EPROTO;
262 case CSB_CC_WR_PROTECTION:
263 case CSB_CC_PROTECTION:
264 case CSB_CC_PROTECTION_DUP1:
265 case CSB_CC_PROTECTION_DUP2:
266 case CSB_CC_PROTECTION_DUP3:
267 case CSB_CC_PROTECTION_DUP4:
268 case CSB_CC_PROTECTION_DUP5:
269 case CSB_CC_PROTECTION_DUP6:
270
271 CSB_ERR_ADDR(csb, "Protection error");
272 return -EPROTO;
273 case CSB_CC_PRIVILEGE:
274
275 CSB_ERR(csb, "Insufficient Privilege error");
276 return -EPROTO;
277 case CSB_CC_EXCESSIVE_DDE:
278
279 CSB_ERR(csb, "Too many DDEs in DDL");
280 return -EINVAL;
281 case CSB_CC_TRANSPORT:
282
283 CSB_ERR(csb, "Invalid CRB");
284 return -EINVAL;
285 case CSB_CC_SEGMENTED_DDL:
286
287 CSB_ERR(csb, "Segmented DDL error");
288 return -EINVAL;
289 case CSB_CC_DDE_OVERFLOW:
290
291 CSB_ERR(csb, "DDE overflow error");
292 return -EINVAL;
293 case CSB_CC_SESSION:
294
295 CSB_ERR(csb, "Session violation error");
296 return -EPROTO;
297 case CSB_CC_CHAIN:
298
299 CSB_ERR(csb, "Chained CRB error");
300 return -EPROTO;
301 case CSB_CC_SEQUENCE:
302
303 CSB_ERR(csb, "CRB seqeunce number error");
304 return -EPROTO;
305 case CSB_CC_UNKNOWN_CODE:
306 CSB_ERR(csb, "Unknown subfunction code");
307 return -EPROTO;
308
309
310 case CSB_CC_RD_EXTERNAL:
311 case CSB_CC_RD_EXTERNAL_DUP1:
312 case CSB_CC_RD_EXTERNAL_DUP2:
313 case CSB_CC_RD_EXTERNAL_DUP3:
314 CSB_ERR_ADDR(csb, "Read error outside coprocessor");
315 return -EPROTO;
316 case CSB_CC_WR_EXTERNAL:
317 CSB_ERR_ADDR(csb, "Write error outside coprocessor");
318 return -EPROTO;
319 case CSB_CC_INTERNAL:
320 CSB_ERR(csb, "Internal error in coprocessor");
321 return -EPROTO;
322 case CSB_CC_PROVISION:
323 CSB_ERR(csb, "Storage provision error");
324 return -EPROTO;
325 case CSB_CC_HW:
326 CSB_ERR(csb, "Correctable hardware error");
327 return -EPROTO;
328
329 default:
330 CSB_ERR(csb, "Invalid CC %d", csb->cc);
331 return -EPROTO;
332 }
333
334
335 if (csb->ce & CSB_CE_TERMINATION) {
336 CSB_ERR(csb, "CSB request was terminated");
337 return -EPROTO;
338 }
339 if (csb->ce & CSB_CE_INCOMPLETE) {
340 CSB_ERR(csb, "CSB request not complete");
341 return -EPROTO;
342 }
343 if (!(csb->ce & CSB_CE_TPBC)) {
344 CSB_ERR(csb, "TPBC not provided, unknown target length");
345 return -EPROTO;
346 }
347
348
349 pr_debug_ratelimited("Processed %u bytes in %lu us\n",
350 be32_to_cpu(csb->count),
351 (unsigned long)ktime_us_delta(now, start));
352
353 return 0;
354}
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387static int nx842_powernv_function(const unsigned char *in, unsigned int inlen,
388 unsigned char *out, unsigned int *outlenp,
389 void *workmem, int fc)
390{
391 struct coprocessor_request_block *crb;
392 struct coprocessor_status_block *csb;
393 struct nx842_workmem *wmem;
394 int ret;
395 u64 csb_addr;
396 u32 ccw;
397 unsigned int outlen = *outlenp;
398
399 wmem = PTR_ALIGN(workmem, WORKMEM_ALIGN);
400
401 *outlenp = 0;
402
403
404 if (!nx842_ct) {
405 pr_err_ratelimited("coprocessor CT is 0");
406 return -ENODEV;
407 }
408
409 crb = &wmem->crb;
410 csb = &crb->csb;
411
412
413 memset(crb, 0, sizeof(*crb));
414
415
416 ret = setup_ddl(&crb->source, wmem->ddl_in,
417 (unsigned char *)in, inlen, true);
418 if (ret)
419 return ret;
420 ret = setup_ddl(&crb->target, wmem->ddl_out,
421 out, outlen, false);
422 if (ret)
423 return ret;
424
425
426 ccw = 0;
427 ccw = SET_FIELD(ccw, CCW_CT, nx842_ct);
428 ccw = SET_FIELD(ccw, CCW_CI_842, 0);
429 ccw = SET_FIELD(ccw, CCW_FC_842, fc);
430
431
432 csb_addr = nx842_get_pa(csb) & CRB_CSB_ADDRESS;
433 csb_addr |= CRB_CSB_AT;
434 crb->csb_addr = cpu_to_be64(csb_addr);
435
436 wmem->start = ktime_get();
437
438
439 ret = icswx(cpu_to_be32(ccw), crb);
440
441 pr_debug_ratelimited("icswx CR %x ccw %x crb->ccw %x\n", ret,
442 (unsigned int)ccw,
443 (unsigned int)be32_to_cpu(crb->ccw));
444
445
446
447
448
449
450
451 ret &= ~ICSWX_XERS0;
452
453 switch (ret) {
454 case ICSWX_INITIATED:
455 ret = wait_for_csb(wmem, csb);
456 break;
457 case ICSWX_BUSY:
458 pr_debug_ratelimited("842 Coprocessor busy\n");
459 ret = -EBUSY;
460 break;
461 case ICSWX_REJECTED:
462 pr_err_ratelimited("ICSWX rejected\n");
463 ret = -EPROTO;
464 break;
465 }
466
467 if (!ret)
468 *outlenp = be32_to_cpu(csb->count);
469
470 return ret;
471}
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493static int nx842_powernv_compress(const unsigned char *in, unsigned int inlen,
494 unsigned char *out, unsigned int *outlenp,
495 void *wmem)
496{
497 return nx842_powernv_function(in, inlen, out, outlenp,
498 wmem, CCW_FC_842_COMP_CRC);
499}
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521static int nx842_powernv_decompress(const unsigned char *in, unsigned int inlen,
522 unsigned char *out, unsigned int *outlenp,
523 void *wmem)
524{
525 return nx842_powernv_function(in, inlen, out, outlenp,
526 wmem, CCW_FC_842_DECOMP_CRC);
527}
528
529static int __init nx842_powernv_probe(struct device_node *dn)
530{
531 struct nx842_coproc *coproc;
532 unsigned int ct, ci;
533 int chip_id;
534
535 chip_id = of_get_ibm_chip_id(dn);
536 if (chip_id < 0) {
537 pr_err("ibm,chip-id missing\n");
538 return -EINVAL;
539 }
540
541 if (of_property_read_u32(dn, "ibm,842-coprocessor-type", &ct)) {
542 pr_err("ibm,842-coprocessor-type missing\n");
543 return -EINVAL;
544 }
545
546 if (of_property_read_u32(dn, "ibm,842-coprocessor-instance", &ci)) {
547 pr_err("ibm,842-coprocessor-instance missing\n");
548 return -EINVAL;
549 }
550
551 coproc = kmalloc(sizeof(*coproc), GFP_KERNEL);
552 if (!coproc)
553 return -ENOMEM;
554
555 coproc->chip_id = chip_id;
556 coproc->ct = ct;
557 coproc->ci = ci;
558 INIT_LIST_HEAD(&coproc->list);
559 list_add(&coproc->list, &nx842_coprocs);
560
561 pr_info("coprocessor found on chip %d, CT %d CI %d\n", chip_id, ct, ci);
562
563 if (!nx842_ct)
564 nx842_ct = ct;
565 else if (nx842_ct != ct)
566 pr_err("NX842 chip %d, CT %d != first found CT %d\n",
567 chip_id, ct, nx842_ct);
568
569 return 0;
570}
571
572static struct nx842_constraints nx842_powernv_constraints = {
573 .alignment = DDE_BUFFER_ALIGN,
574 .multiple = DDE_BUFFER_LAST_MULT,
575 .minimum = DDE_BUFFER_LAST_MULT,
576 .maximum = (DDL_LEN_MAX - 1) * PAGE_SIZE,
577};
578
579static struct nx842_driver nx842_powernv_driver = {
580 .name = KBUILD_MODNAME,
581 .owner = THIS_MODULE,
582 .workmem_size = sizeof(struct nx842_workmem),
583 .constraints = &nx842_powernv_constraints,
584 .compress = nx842_powernv_compress,
585 .decompress = nx842_powernv_decompress,
586};
587
588static int nx842_powernv_crypto_init(struct crypto_tfm *tfm)
589{
590 return nx842_crypto_init(tfm, &nx842_powernv_driver);
591}
592
593static struct crypto_alg nx842_powernv_alg = {
594 .cra_name = "842",
595 .cra_driver_name = "842-nx",
596 .cra_priority = 300,
597 .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
598 .cra_ctxsize = sizeof(struct nx842_crypto_ctx),
599 .cra_module = THIS_MODULE,
600 .cra_init = nx842_powernv_crypto_init,
601 .cra_exit = nx842_crypto_exit,
602 .cra_u = { .compress = {
603 .coa_compress = nx842_crypto_compress,
604 .coa_decompress = nx842_crypto_decompress } }
605};
606
607static __init int nx842_powernv_init(void)
608{
609 struct device_node *dn;
610 int ret;
611
612
613 BUILD_BUG_ON(WORKMEM_ALIGN % CRB_ALIGN);
614 BUILD_BUG_ON(CRB_ALIGN % DDE_ALIGN);
615 BUILD_BUG_ON(CRB_SIZE % DDE_ALIGN);
616
617 BUILD_BUG_ON(PAGE_SIZE % DDE_BUFFER_ALIGN);
618 BUILD_BUG_ON(DDE_BUFFER_ALIGN % DDE_BUFFER_SIZE_MULT);
619 BUILD_BUG_ON(DDE_BUFFER_SIZE_MULT % DDE_BUFFER_LAST_MULT);
620
621 for_each_compatible_node(dn, NULL, "ibm,power-nx")
622 nx842_powernv_probe(dn);
623
624 if (!nx842_ct)
625 return -ENODEV;
626
627 ret = crypto_register_alg(&nx842_powernv_alg);
628 if (ret) {
629 struct nx842_coproc *coproc, *n;
630
631 list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) {
632 list_del(&coproc->list);
633 kfree(coproc);
634 }
635
636 return ret;
637 }
638
639 return 0;
640}
641module_init(nx842_powernv_init);
642
643static void __exit nx842_powernv_exit(void)
644{
645 struct nx842_coproc *coproc, *n;
646
647 crypto_unregister_alg(&nx842_powernv_alg);
648
649 list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) {
650 list_del(&coproc->list);
651 kfree(coproc);
652 }
653}
654module_exit(nx842_powernv_exit);
655