1/* 2 * Driver for IBM PowerNV 842 compression accelerator 3 * 4 * Copyright (C) 2015 Dan Streetman, IBM Corp 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 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) /* ms */ 34 35struct nx842_workmem { 36 /* Below fields must be properly aligned */ 37 struct coprocessor_request_block crb; /* CRB_ALIGN align */ 38 struct data_descriptor_entry ddl_in[DDL_LEN_MAX]; /* DDE_ALIGN align */ 39 struct data_descriptor_entry ddl_out[DDL_LEN_MAX]; /* DDE_ALIGN align */ 40 /* Above fields must be properly aligned */ 41 42 ktime_t start; 43 44 char padding[WORKMEM_ALIGN]; /* unused, to allow alignment */ 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/* no cpu hotplug on powernv, so this list never changes after init */ 55static LIST_HEAD(nx842_coprocs); 56static unsigned int nx842_ct; 57 58/** 59 * setup_indirect_dde - Setup an indirect DDE 60 * 61 * The DDE is setup with the the DDE count, byte count, and address of 62 * first direct DDE in the list. 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 * setup_direct_dde - Setup single DDE from buffer 77 * 78 * The DDE is setup with the buffer and length. The buffer must be properly 79 * aligned. The used length is returned. 80 * Returns: 81 * N Successfully set up DDE with N bytes 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 * setup_ddl - Setup DDL from buffer 99 * 100 * Returns: 101 * 0 Successfully set up DDL 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 /* only need to check last mult; since buffer must be 118 * DDE_BUFFER_ALIGN aligned, and that is a multiple of 119 * DDE_BUFFER_SIZE_MULT, and pre-last page DDE buffers 120 * are guaranteed a multiple of DDE_BUFFER_SIZE_MULT. 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 /* use a single direct DDE */ 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 /* use the DDL */ 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 * wait_for_csb 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 /* hw has updated csb and output buffer */ 184 barrier(); 185 186 /* check CSB flags */ 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 /* verify CSB completion sequence is 0 */ 202 if (csb->cs) { 203 CSB_ERR(csb, "Invalid CSB completion sequence"); 204 return -EPROTO; 205 } 206 207 /* check CSB Completion Code */ 208 switch (csb->cc) { 209 /* no error */ 210 case CSB_CC_SUCCESS: 211 break; 212 case CSB_CC_TPBC_GT_SPBC: 213 /* not an error, but the compressed data is 214 * larger than the uncompressed data :( 215 */ 216 break; 217 218 /* input data errors */ 219 case CSB_CC_OPERAND_OVERLAP: 220 /* input and output buffers overlap */ 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 /* output buffer too small */ 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 /* these should not happen */ 243 case CSB_CC_INVALID_ALIGN: 244 /* setup_ddl should have detected this */ 245 CSB_ERR_ADDR(csb, "Invalid alignment"); 246 return -EINVAL; 247 case CSB_CC_DATA_LENGTH: 248 /* setup_ddl should have detected this */ 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 /* should not happen, we use physical addrs */ 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 /* should not happen, we use physical addrs */ 271 CSB_ERR_ADDR(csb, "Protection error"); 272 return -EPROTO; 273 case CSB_CC_PRIVILEGE: 274 /* shouldn't happen, we're in HYP mode */ 275 CSB_ERR(csb, "Insufficient Privilege error"); 276 return -EPROTO; 277 case CSB_CC_EXCESSIVE_DDE: 278 /* shouldn't happen, setup_ddl doesn't use many dde's */ 279 CSB_ERR(csb, "Too many DDEs in DDL"); 280 return -EINVAL; 281 case CSB_CC_TRANSPORT: 282 /* shouldn't happen, we setup CRB correctly */ 283 CSB_ERR(csb, "Invalid CRB"); 284 return -EINVAL; 285 case CSB_CC_SEGMENTED_DDL: 286 /* shouldn't happen, setup_ddl creates DDL right */ 287 CSB_ERR(csb, "Segmented DDL error"); 288 return -EINVAL; 289 case CSB_CC_DDE_OVERFLOW: 290 /* shouldn't happen, setup_ddl creates DDL right */ 291 CSB_ERR(csb, "DDE overflow error"); 292 return -EINVAL; 293 case CSB_CC_SESSION: 294 /* should not happen with ICSWX */ 295 CSB_ERR(csb, "Session violation error"); 296 return -EPROTO; 297 case CSB_CC_CHAIN: 298 /* should not happen, we don't use chained CRBs */ 299 CSB_ERR(csb, "Chained CRB error"); 300 return -EPROTO; 301 case CSB_CC_SEQUENCE: 302 /* should not happen, we don't use chained CRBs */ 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 /* hardware errors */ 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 /* check Completion Extension state */ 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 /* successful completion */ 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 * nx842_powernv_function - compress/decompress data using the 842 algorithm 358 * 359 * (De)compression provided by the NX842 coprocessor on IBM PowerNV systems. 360 * This compresses or decompresses the provided input buffer into the provided 361 * output buffer. 362 * 363 * Upon return from this function @outlen contains the length of the 364 * output data. If there is an error then @outlen will be 0 and an 365 * error will be specified by the return code from this function. 366 * 367 * The @workmem buffer should only be used by one function call at a time. 368 * 369 * @in: input buffer pointer 370 * @inlen: input buffer size 371 * @out: output buffer pointer 372 * @outlenp: output buffer size pointer 373 * @workmem: working memory buffer pointer, size determined by 374 * nx842_powernv_driver.workmem_size 375 * @fc: function code, see CCW Function Codes in nx-842.h 376 * 377 * Returns: 378 * 0 Success, output of length @outlenp stored in the buffer at @out 379 * -ENODEV Hardware unavailable 380 * -ENOSPC Output buffer is to small 381 * -EMSGSIZE Input buffer too large 382 * -EINVAL buffer constraints do not fix nx842_constraints 383 * -EPROTO hardware error during operation 384 * -ETIMEDOUT hardware did not complete operation in reasonable time 385 * -EINTR operation was aborted 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 /* shoudn't happen, we don't load without a coproc */ 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 /* Clear any previous values */ 413 memset(crb, 0, sizeof(*crb)); 414 415 /* set up DDLs */ 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 /* set up CCW */ 426 ccw = 0; 427 ccw = SET_FIELD(ccw, CCW_CT, nx842_ct); 428 ccw = SET_FIELD(ccw, CCW_CI_842, 0); /* use 0 for hw auto-selection */ 429 ccw = SET_FIELD(ccw, CCW_FC_842, fc); 430 431 /* set up CRB's CSB addr */ 432 csb_addr = nx842_get_pa(csb) & CRB_CSB_ADDRESS; 433 csb_addr |= CRB_CSB_AT; /* Addrs are phys */ 434 crb->csb_addr = cpu_to_be64(csb_addr); 435 436 wmem->start = ktime_get(); 437 438 /* do ICSWX */ 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 switch (ret) { 446 case ICSWX_INITIATED: 447 ret = wait_for_csb(wmem, csb); 448 break; 449 case ICSWX_BUSY: 450 pr_debug_ratelimited("842 Coprocessor busy\n"); 451 ret = -EBUSY; 452 break; 453 case ICSWX_REJECTED: 454 pr_err_ratelimited("ICSWX rejected\n"); 455 ret = -EPROTO; 456 break; 457 default: 458 pr_err_ratelimited("Invalid ICSWX return code %x\n", ret); 459 ret = -EPROTO; 460 break; 461 } 462 463 if (!ret) 464 *outlenp = be32_to_cpu(csb->count); 465 466 return ret; 467} 468 469/** 470 * nx842_powernv_compress - Compress data using the 842 algorithm 471 * 472 * Compression provided by the NX842 coprocessor on IBM PowerNV systems. 473 * The input buffer is compressed and the result is stored in the 474 * provided output buffer. 475 * 476 * Upon return from this function @outlen contains the length of the 477 * compressed data. If there is an error then @outlen will be 0 and an 478 * error will be specified by the return code from this function. 479 * 480 * @in: input buffer pointer 481 * @inlen: input buffer size 482 * @out: output buffer pointer 483 * @outlenp: output buffer size pointer 484 * @workmem: working memory buffer pointer, size determined by 485 * nx842_powernv_driver.workmem_size 486 * 487 * Returns: see @nx842_powernv_function() 488 */ 489static int nx842_powernv_compress(const unsigned char *in, unsigned int inlen, 490 unsigned char *out, unsigned int *outlenp, 491 void *wmem) 492{ 493 return nx842_powernv_function(in, inlen, out, outlenp, 494 wmem, CCW_FC_842_COMP_CRC); 495} 496 497/** 498 * nx842_powernv_decompress - Decompress data using the 842 algorithm 499 * 500 * Decompression provided by the NX842 coprocessor on IBM PowerNV systems. 501 * The input buffer is decompressed and the result is stored in the 502 * provided output buffer. 503 * 504 * Upon return from this function @outlen contains the length of the 505 * decompressed data. If there is an error then @outlen will be 0 and an 506 * error will be specified by the return code from this function. 507 * 508 * @in: input buffer pointer 509 * @inlen: input buffer size 510 * @out: output buffer pointer 511 * @outlenp: output buffer size pointer 512 * @workmem: working memory buffer pointer, size determined by 513 * nx842_powernv_driver.workmem_size 514 * 515 * Returns: see @nx842_powernv_function() 516 */ 517static int nx842_powernv_decompress(const unsigned char *in, unsigned int inlen, 518 unsigned char *out, unsigned int *outlenp, 519 void *wmem) 520{ 521 return nx842_powernv_function(in, inlen, out, outlenp, 522 wmem, CCW_FC_842_DECOMP_CRC); 523} 524 525static int __init nx842_powernv_probe(struct device_node *dn) 526{ 527 struct nx842_coproc *coproc; 528 struct property *ct_prop, *ci_prop; 529 unsigned int ct, ci; 530 int chip_id; 531 532 chip_id = of_get_ibm_chip_id(dn); 533 if (chip_id < 0) { 534 pr_err("ibm,chip-id missing\n"); 535 return -EINVAL; 536 } 537 ct_prop = of_find_property(dn, "ibm,842-coprocessor-type", NULL); 538 if (!ct_prop) { 539 pr_err("ibm,842-coprocessor-type missing\n"); 540 return -EINVAL; 541 } 542 ct = be32_to_cpu(*(unsigned int *)ct_prop->value); 543 ci_prop = of_find_property(dn, "ibm,842-coprocessor-instance", NULL); 544 if (!ci_prop) { 545 pr_err("ibm,842-coprocessor-instance missing\n"); 546 return -EINVAL; 547 } 548 ci = be32_to_cpu(*(unsigned int *)ci_prop->value); 549 550 coproc = kmalloc(sizeof(*coproc), GFP_KERNEL); 551 if (!coproc) 552 return -ENOMEM; 553 554 coproc->chip_id = chip_id; 555 coproc->ct = ct; 556 coproc->ci = ci; 557 INIT_LIST_HEAD(&coproc->list); 558 list_add(&coproc->list, &nx842_coprocs); 559 560 pr_info("coprocessor found on chip %d, CT %d CI %d\n", chip_id, ct, ci); 561 562 if (!nx842_ct) 563 nx842_ct = ct; 564 else if (nx842_ct != ct) 565 pr_err("NX842 chip %d, CT %d != first found CT %d\n", 566 chip_id, ct, nx842_ct); 567 568 return 0; 569} 570 571static struct nx842_constraints nx842_powernv_constraints = { 572 .alignment = DDE_BUFFER_ALIGN, 573 .multiple = DDE_BUFFER_LAST_MULT, 574 .minimum = DDE_BUFFER_LAST_MULT, 575 .maximum = (DDL_LEN_MAX - 1) * PAGE_SIZE, 576}; 577 578static struct nx842_driver nx842_powernv_driver = { 579 .name = KBUILD_MODNAME, 580 .owner = THIS_MODULE, 581 .workmem_size = sizeof(struct nx842_workmem), 582 .constraints = &nx842_powernv_constraints, 583 .compress = nx842_powernv_compress, 584 .decompress = nx842_powernv_decompress, 585}; 586 587static int nx842_powernv_crypto_init(struct crypto_tfm *tfm) 588{ 589 return nx842_crypto_init(tfm, &nx842_powernv_driver); 590} 591 592static struct crypto_alg nx842_powernv_alg = { 593 .cra_name = "842", 594 .cra_driver_name = "842-nx", 595 .cra_priority = 300, 596 .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 597 .cra_ctxsize = sizeof(struct nx842_crypto_ctx), 598 .cra_module = THIS_MODULE, 599 .cra_init = nx842_powernv_crypto_init, 600 .cra_exit = nx842_crypto_exit, 601 .cra_u = { .compress = { 602 .coa_compress = nx842_crypto_compress, 603 .coa_decompress = nx842_crypto_decompress } } 604}; 605 606static __init int nx842_powernv_init(void) 607{ 608 struct device_node *dn; 609 int ret; 610 611 /* verify workmem size/align restrictions */ 612 BUILD_BUG_ON(WORKMEM_ALIGN % CRB_ALIGN); 613 BUILD_BUG_ON(CRB_ALIGN % DDE_ALIGN); 614 BUILD_BUG_ON(CRB_SIZE % DDE_ALIGN); 615 /* verify buffer size/align restrictions */ 616 BUILD_BUG_ON(PAGE_SIZE % DDE_BUFFER_ALIGN); 617 BUILD_BUG_ON(DDE_BUFFER_ALIGN % DDE_BUFFER_SIZE_MULT); 618 BUILD_BUG_ON(DDE_BUFFER_SIZE_MULT % DDE_BUFFER_LAST_MULT); 619 620 for_each_compatible_node(dn, NULL, "ibm,power-nx") 621 nx842_powernv_probe(dn); 622 623 if (!nx842_ct) 624 return -ENODEV; 625 626 ret = crypto_register_alg(&nx842_powernv_alg); 627 if (ret) { 628 struct nx842_coproc *coproc, *n; 629 630 list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) { 631 list_del(&coproc->list); 632 kfree(coproc); 633 } 634 635 return ret; 636 } 637 638 return 0; 639} 640module_init(nx842_powernv_init); 641 642static void __exit nx842_powernv_exit(void) 643{ 644 struct nx842_coproc *coproc, *n; 645 646 crypto_unregister_alg(&nx842_powernv_alg); 647 648 list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) { 649 list_del(&coproc->list); 650 kfree(coproc); 651 } 652} 653module_exit(nx842_powernv_exit); 654