Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.8 654 lines 18 kB view raw
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 /* 446 * NX842 coprocessor sets 3rd bit in CR register with XER[S0]. 447 * XER[S0] is the integer summary overflow bit which is nothing 448 * to do NX. Since this bit can be set with other return values, 449 * mask this bit. 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 * nx842_powernv_compress - Compress data using the 842 algorithm 475 * 476 * Compression provided by the NX842 coprocessor on IBM PowerNV systems. 477 * The input buffer is compressed and the result is stored in the 478 * provided output buffer. 479 * 480 * Upon return from this function @outlen contains the length of the 481 * compressed data. If there is an error then @outlen will be 0 and an 482 * error will be specified by the return code from this function. 483 * 484 * @in: input buffer pointer 485 * @inlen: input buffer size 486 * @out: output buffer pointer 487 * @outlenp: output buffer size pointer 488 * @workmem: working memory buffer pointer, size determined by 489 * nx842_powernv_driver.workmem_size 490 * 491 * Returns: see @nx842_powernv_function() 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 * nx842_powernv_decompress - Decompress data using the 842 algorithm 503 * 504 * Decompression provided by the NX842 coprocessor on IBM PowerNV systems. 505 * The input buffer is decompressed and the result is stored in the 506 * provided output buffer. 507 * 508 * Upon return from this function @outlen contains the length of the 509 * decompressed data. If there is an error then @outlen will be 0 and an 510 * error will be specified by the return code from this function. 511 * 512 * @in: input buffer pointer 513 * @inlen: input buffer size 514 * @out: output buffer pointer 515 * @outlenp: output buffer size pointer 516 * @workmem: working memory buffer pointer, size determined by 517 * nx842_powernv_driver.workmem_size 518 * 519 * Returns: see @nx842_powernv_function() 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 /* verify workmem size/align restrictions */ 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 /* verify buffer size/align restrictions */ 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);