132e091a6SHaren Myneni // SPDX-License-Identifier: GPL-2.0-or-later
232e091a6SHaren Myneni /*
332e091a6SHaren Myneni * Driver for IBM PowerNV compression accelerator
432e091a6SHaren Myneni *
532e091a6SHaren Myneni * Copyright (C) 2015 Dan Streetman, IBM Corp
632e091a6SHaren Myneni */
732e091a6SHaren Myneni
832e091a6SHaren Myneni #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
932e091a6SHaren Myneni
1032e091a6SHaren Myneni #include "nx-842.h"
1132e091a6SHaren Myneni
1232e091a6SHaren Myneni #include <linux/timer.h>
1332e091a6SHaren Myneni
1432e091a6SHaren Myneni #include <asm/prom.h>
1532e091a6SHaren Myneni #include <asm/icswx.h>
1632e091a6SHaren Myneni #include <asm/vas.h>
1732e091a6SHaren Myneni #include <asm/reg.h>
1832e091a6SHaren Myneni #include <asm/opal-api.h>
1932e091a6SHaren Myneni #include <asm/opal.h>
2032e091a6SHaren Myneni
2132e091a6SHaren Myneni MODULE_LICENSE("GPL");
2232e091a6SHaren Myneni MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
2332e091a6SHaren Myneni MODULE_DESCRIPTION("H/W Compression driver for IBM PowerNV processors");
2432e091a6SHaren Myneni MODULE_ALIAS_CRYPTO("842");
2532e091a6SHaren Myneni MODULE_ALIAS_CRYPTO("842-nx");
2632e091a6SHaren Myneni
2732e091a6SHaren Myneni #define WORKMEM_ALIGN (CRB_ALIGN)
2832e091a6SHaren Myneni #define CSB_WAIT_MAX (5000) /* ms */
2932e091a6SHaren Myneni #define VAS_RETRIES (10)
3032e091a6SHaren Myneni
3132e091a6SHaren Myneni struct nx842_workmem {
3232e091a6SHaren Myneni /* Below fields must be properly aligned */
3332e091a6SHaren Myneni struct coprocessor_request_block crb; /* CRB_ALIGN align */
3432e091a6SHaren Myneni struct data_descriptor_entry ddl_in[DDL_LEN_MAX]; /* DDE_ALIGN align */
3532e091a6SHaren Myneni struct data_descriptor_entry ddl_out[DDL_LEN_MAX]; /* DDE_ALIGN align */
3632e091a6SHaren Myneni /* Above fields must be properly aligned */
3732e091a6SHaren Myneni
3832e091a6SHaren Myneni ktime_t start;
3932e091a6SHaren Myneni
4032e091a6SHaren Myneni char padding[WORKMEM_ALIGN]; /* unused, to allow alignment */
4132e091a6SHaren Myneni } __packed __aligned(WORKMEM_ALIGN);
4232e091a6SHaren Myneni
434aebf3ceSHaren Myneni struct nx_coproc {
4432e091a6SHaren Myneni unsigned int chip_id;
454aebf3ceSHaren Myneni unsigned int ct; /* Can be 842 or GZIP high/normal*/
4632e091a6SHaren Myneni unsigned int ci; /* Coprocessor instance, used with icswx */
4732e091a6SHaren Myneni struct {
4832e091a6SHaren Myneni struct vas_window *rxwin;
4932e091a6SHaren Myneni int id;
5032e091a6SHaren Myneni } vas;
5132e091a6SHaren Myneni struct list_head list;
5232e091a6SHaren Myneni };
5332e091a6SHaren Myneni
5432e091a6SHaren Myneni /*
5532e091a6SHaren Myneni * Send the request to NX engine on the chip for the corresponding CPU
5632e091a6SHaren Myneni * where the process is executing. Use with VAS function.
5732e091a6SHaren Myneni */
5832e091a6SHaren Myneni static DEFINE_PER_CPU(struct vas_window *, cpu_txwin);
5932e091a6SHaren Myneni
6032e091a6SHaren Myneni /* no cpu hotplug on powernv, so this list never changes after init */
614aebf3ceSHaren Myneni static LIST_HEAD(nx_coprocs);
6232e091a6SHaren Myneni static unsigned int nx842_ct; /* used in icswx function */
6332e091a6SHaren Myneni
644aebf3ceSHaren Myneni /*
654aebf3ceSHaren Myneni * Using same values as in skiboot or coprocessor type representing
664aebf3ceSHaren Myneni * in NX workbook.
674aebf3ceSHaren Myneni */
681af11ae2SHaren Myneni #define NX_CT_GZIP (2) /* on P9 and later */
694aebf3ceSHaren Myneni #define NX_CT_842 (3)
704aebf3ceSHaren Myneni
7132e091a6SHaren Myneni static int (*nx842_powernv_exec)(const unsigned char *in,
7232e091a6SHaren Myneni unsigned int inlen, unsigned char *out,
7332e091a6SHaren Myneni unsigned int *outlenp, void *workmem, int fc);
7432e091a6SHaren Myneni
75*6084466eSHerbert Xu /*
7632e091a6SHaren Myneni * setup_indirect_dde - Setup an indirect DDE
7732e091a6SHaren Myneni *
7854a8b680SJiang Jian * The DDE is setup with the DDE count, byte count, and address of
7932e091a6SHaren Myneni * first direct DDE in the list.
8032e091a6SHaren Myneni */
setup_indirect_dde(struct data_descriptor_entry * dde,struct data_descriptor_entry * ddl,unsigned int dde_count,unsigned int byte_count)8132e091a6SHaren Myneni static void setup_indirect_dde(struct data_descriptor_entry *dde,
8232e091a6SHaren Myneni struct data_descriptor_entry *ddl,
8332e091a6SHaren Myneni unsigned int dde_count, unsigned int byte_count)
8432e091a6SHaren Myneni {
8532e091a6SHaren Myneni dde->flags = 0;
8632e091a6SHaren Myneni dde->count = dde_count;
8732e091a6SHaren Myneni dde->index = 0;
8832e091a6SHaren Myneni dde->length = cpu_to_be32(byte_count);
8932e091a6SHaren Myneni dde->address = cpu_to_be64(nx842_get_pa(ddl));
9032e091a6SHaren Myneni }
9132e091a6SHaren Myneni
92*6084466eSHerbert Xu /*
9332e091a6SHaren Myneni * setup_direct_dde - Setup single DDE from buffer
9432e091a6SHaren Myneni *
9532e091a6SHaren Myneni * The DDE is setup with the buffer and length. The buffer must be properly
9632e091a6SHaren Myneni * aligned. The used length is returned.
9732e091a6SHaren Myneni * Returns:
9832e091a6SHaren Myneni * N Successfully set up DDE with N bytes
9932e091a6SHaren Myneni */
setup_direct_dde(struct data_descriptor_entry * dde,unsigned long pa,unsigned int len)10032e091a6SHaren Myneni static unsigned int setup_direct_dde(struct data_descriptor_entry *dde,
10132e091a6SHaren Myneni unsigned long pa, unsigned int len)
10232e091a6SHaren Myneni {
10332e091a6SHaren Myneni unsigned int l = min_t(unsigned int, len, LEN_ON_PAGE(pa));
10432e091a6SHaren Myneni
10532e091a6SHaren Myneni dde->flags = 0;
10632e091a6SHaren Myneni dde->count = 0;
10732e091a6SHaren Myneni dde->index = 0;
10832e091a6SHaren Myneni dde->length = cpu_to_be32(l);
10932e091a6SHaren Myneni dde->address = cpu_to_be64(pa);
11032e091a6SHaren Myneni
11132e091a6SHaren Myneni return l;
11232e091a6SHaren Myneni }
11332e091a6SHaren Myneni
114*6084466eSHerbert Xu /*
11532e091a6SHaren Myneni * setup_ddl - Setup DDL from buffer
11632e091a6SHaren Myneni *
11732e091a6SHaren Myneni * Returns:
11832e091a6SHaren Myneni * 0 Successfully set up DDL
11932e091a6SHaren Myneni */
setup_ddl(struct data_descriptor_entry * dde,struct data_descriptor_entry * ddl,unsigned char * buf,unsigned int len,bool in)12032e091a6SHaren Myneni static int setup_ddl(struct data_descriptor_entry *dde,
12132e091a6SHaren Myneni struct data_descriptor_entry *ddl,
12232e091a6SHaren Myneni unsigned char *buf, unsigned int len,
12332e091a6SHaren Myneni bool in)
12432e091a6SHaren Myneni {
12532e091a6SHaren Myneni unsigned long pa = nx842_get_pa(buf);
12632e091a6SHaren Myneni int i, ret, total_len = len;
12732e091a6SHaren Myneni
12832e091a6SHaren Myneni if (!IS_ALIGNED(pa, DDE_BUFFER_ALIGN)) {
12932e091a6SHaren Myneni pr_debug("%s buffer pa 0x%lx not 0x%x-byte aligned\n",
13032e091a6SHaren Myneni in ? "input" : "output", pa, DDE_BUFFER_ALIGN);
13132e091a6SHaren Myneni return -EINVAL;
13232e091a6SHaren Myneni }
13332e091a6SHaren Myneni
13432e091a6SHaren Myneni /* only need to check last mult; since buffer must be
13532e091a6SHaren Myneni * DDE_BUFFER_ALIGN aligned, and that is a multiple of
13632e091a6SHaren Myneni * DDE_BUFFER_SIZE_MULT, and pre-last page DDE buffers
13732e091a6SHaren Myneni * are guaranteed a multiple of DDE_BUFFER_SIZE_MULT.
13832e091a6SHaren Myneni */
13932e091a6SHaren Myneni if (len % DDE_BUFFER_LAST_MULT) {
14032e091a6SHaren Myneni pr_debug("%s buffer len 0x%x not a multiple of 0x%x\n",
14132e091a6SHaren Myneni in ? "input" : "output", len, DDE_BUFFER_LAST_MULT);
14232e091a6SHaren Myneni if (in)
14332e091a6SHaren Myneni return -EINVAL;
14432e091a6SHaren Myneni len = round_down(len, DDE_BUFFER_LAST_MULT);
14532e091a6SHaren Myneni }
14632e091a6SHaren Myneni
14732e091a6SHaren Myneni /* use a single direct DDE */
14832e091a6SHaren Myneni if (len <= LEN_ON_PAGE(pa)) {
14932e091a6SHaren Myneni ret = setup_direct_dde(dde, pa, len);
15032e091a6SHaren Myneni WARN_ON(ret < len);
15132e091a6SHaren Myneni return 0;
15232e091a6SHaren Myneni }
15332e091a6SHaren Myneni
15432e091a6SHaren Myneni /* use the DDL */
15532e091a6SHaren Myneni for (i = 0; i < DDL_LEN_MAX && len > 0; i++) {
15632e091a6SHaren Myneni ret = setup_direct_dde(&ddl[i], pa, len);
15732e091a6SHaren Myneni buf += ret;
15832e091a6SHaren Myneni len -= ret;
15932e091a6SHaren Myneni pa = nx842_get_pa(buf);
16032e091a6SHaren Myneni }
16132e091a6SHaren Myneni
16232e091a6SHaren Myneni if (len > 0) {
16332e091a6SHaren Myneni pr_debug("0x%x total %s bytes 0x%x too many for DDL.\n",
16432e091a6SHaren Myneni total_len, in ? "input" : "output", len);
16532e091a6SHaren Myneni if (in)
16632e091a6SHaren Myneni return -EMSGSIZE;
16732e091a6SHaren Myneni total_len -= len;
16832e091a6SHaren Myneni }
16932e091a6SHaren Myneni setup_indirect_dde(dde, ddl, i, total_len);
17032e091a6SHaren Myneni
17132e091a6SHaren Myneni return 0;
17232e091a6SHaren Myneni }
17332e091a6SHaren Myneni
17432e091a6SHaren Myneni #define CSB_ERR(csb, msg, ...) \
17532e091a6SHaren Myneni pr_err("ERROR: " msg " : %02x %02x %02x %02x %08x\n", \
17632e091a6SHaren Myneni ##__VA_ARGS__, (csb)->flags, \
17732e091a6SHaren Myneni (csb)->cs, (csb)->cc, (csb)->ce, \
17832e091a6SHaren Myneni be32_to_cpu((csb)->count))
17932e091a6SHaren Myneni
18032e091a6SHaren Myneni #define CSB_ERR_ADDR(csb, msg, ...) \
18132e091a6SHaren Myneni CSB_ERR(csb, msg " at %lx", ##__VA_ARGS__, \
18232e091a6SHaren Myneni (unsigned long)be64_to_cpu((csb)->address))
18332e091a6SHaren Myneni
wait_for_csb(struct nx842_workmem * wmem,struct coprocessor_status_block * csb)18432e091a6SHaren Myneni static int wait_for_csb(struct nx842_workmem *wmem,
18532e091a6SHaren Myneni struct coprocessor_status_block *csb)
18632e091a6SHaren Myneni {
18732e091a6SHaren Myneni ktime_t start = wmem->start, now = ktime_get();
18832e091a6SHaren Myneni ktime_t timeout = ktime_add_ms(start, CSB_WAIT_MAX);
18932e091a6SHaren Myneni
19032e091a6SHaren Myneni while (!(READ_ONCE(csb->flags) & CSB_V)) {
19132e091a6SHaren Myneni cpu_relax();
19232e091a6SHaren Myneni now = ktime_get();
19332e091a6SHaren Myneni if (ktime_after(now, timeout))
19432e091a6SHaren Myneni break;
19532e091a6SHaren Myneni }
19632e091a6SHaren Myneni
19732e091a6SHaren Myneni /* hw has updated csb and output buffer */
19832e091a6SHaren Myneni barrier();
19932e091a6SHaren Myneni
20032e091a6SHaren Myneni /* check CSB flags */
20132e091a6SHaren Myneni if (!(csb->flags & CSB_V)) {
20232e091a6SHaren Myneni CSB_ERR(csb, "CSB still not valid after %ld us, giving up",
20332e091a6SHaren Myneni (long)ktime_us_delta(now, start));
20432e091a6SHaren Myneni return -ETIMEDOUT;
20532e091a6SHaren Myneni }
20632e091a6SHaren Myneni if (csb->flags & CSB_F) {
20732e091a6SHaren Myneni CSB_ERR(csb, "Invalid CSB format");
20832e091a6SHaren Myneni return -EPROTO;
20932e091a6SHaren Myneni }
21032e091a6SHaren Myneni if (csb->flags & CSB_CH) {
21132e091a6SHaren Myneni CSB_ERR(csb, "Invalid CSB chaining state");
21232e091a6SHaren Myneni return -EPROTO;
21332e091a6SHaren Myneni }
21432e091a6SHaren Myneni
21532e091a6SHaren Myneni /* verify CSB completion sequence is 0 */
21632e091a6SHaren Myneni if (csb->cs) {
21732e091a6SHaren Myneni CSB_ERR(csb, "Invalid CSB completion sequence");
21832e091a6SHaren Myneni return -EPROTO;
21932e091a6SHaren Myneni }
22032e091a6SHaren Myneni
22132e091a6SHaren Myneni /* check CSB Completion Code */
22232e091a6SHaren Myneni switch (csb->cc) {
22332e091a6SHaren Myneni /* no error */
22432e091a6SHaren Myneni case CSB_CC_SUCCESS:
22532e091a6SHaren Myneni break;
22632e091a6SHaren Myneni case CSB_CC_TPBC_GT_SPBC:
22732e091a6SHaren Myneni /* not an error, but the compressed data is
22832e091a6SHaren Myneni * larger than the uncompressed data :(
22932e091a6SHaren Myneni */
23032e091a6SHaren Myneni break;
23132e091a6SHaren Myneni
23232e091a6SHaren Myneni /* input data errors */
23332e091a6SHaren Myneni case CSB_CC_OPERAND_OVERLAP:
23432e091a6SHaren Myneni /* input and output buffers overlap */
23532e091a6SHaren Myneni CSB_ERR(csb, "Operand Overlap error");
23632e091a6SHaren Myneni return -EINVAL;
23732e091a6SHaren Myneni case CSB_CC_INVALID_OPERAND:
23832e091a6SHaren Myneni CSB_ERR(csb, "Invalid operand");
23932e091a6SHaren Myneni return -EINVAL;
24032e091a6SHaren Myneni case CSB_CC_NOSPC:
24132e091a6SHaren Myneni /* output buffer too small */
24232e091a6SHaren Myneni return -ENOSPC;
24332e091a6SHaren Myneni case CSB_CC_ABORT:
24432e091a6SHaren Myneni CSB_ERR(csb, "Function aborted");
24532e091a6SHaren Myneni return -EINTR;
24632e091a6SHaren Myneni case CSB_CC_CRC_MISMATCH:
24732e091a6SHaren Myneni CSB_ERR(csb, "CRC mismatch");
24832e091a6SHaren Myneni return -EINVAL;
24932e091a6SHaren Myneni case CSB_CC_TEMPL_INVALID:
25032e091a6SHaren Myneni CSB_ERR(csb, "Compressed data template invalid");
25132e091a6SHaren Myneni return -EINVAL;
25232e091a6SHaren Myneni case CSB_CC_TEMPL_OVERFLOW:
25332e091a6SHaren Myneni CSB_ERR(csb, "Compressed data template shows data past end");
25432e091a6SHaren Myneni return -EINVAL;
25532e091a6SHaren Myneni case CSB_CC_EXCEED_BYTE_COUNT: /* P9 or later */
25632e091a6SHaren Myneni /*
25732e091a6SHaren Myneni * DDE byte count exceeds the limit specified in Maximum
25832e091a6SHaren Myneni * byte count register.
25932e091a6SHaren Myneni */
26032e091a6SHaren Myneni CSB_ERR(csb, "DDE byte count exceeds the limit");
26132e091a6SHaren Myneni return -EINVAL;
26232e091a6SHaren Myneni
26332e091a6SHaren Myneni /* these should not happen */
26432e091a6SHaren Myneni case CSB_CC_INVALID_ALIGN:
26532e091a6SHaren Myneni /* setup_ddl should have detected this */
26632e091a6SHaren Myneni CSB_ERR_ADDR(csb, "Invalid alignment");
26732e091a6SHaren Myneni return -EINVAL;
26832e091a6SHaren Myneni case CSB_CC_DATA_LENGTH:
26932e091a6SHaren Myneni /* setup_ddl should have detected this */
27032e091a6SHaren Myneni CSB_ERR(csb, "Invalid data length");
27132e091a6SHaren Myneni return -EINVAL;
27232e091a6SHaren Myneni case CSB_CC_WR_TRANSLATION:
27332e091a6SHaren Myneni case CSB_CC_TRANSLATION:
27432e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP1:
27532e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP2:
27632e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP3:
27732e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP4:
27832e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP5:
27932e091a6SHaren Myneni case CSB_CC_TRANSLATION_DUP6:
28032e091a6SHaren Myneni /* should not happen, we use physical addrs */
28132e091a6SHaren Myneni CSB_ERR_ADDR(csb, "Translation error");
28232e091a6SHaren Myneni return -EPROTO;
28332e091a6SHaren Myneni case CSB_CC_WR_PROTECTION:
28432e091a6SHaren Myneni case CSB_CC_PROTECTION:
28532e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP1:
28632e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP2:
28732e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP3:
28832e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP4:
28932e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP5:
29032e091a6SHaren Myneni case CSB_CC_PROTECTION_DUP6:
29132e091a6SHaren Myneni /* should not happen, we use physical addrs */
29232e091a6SHaren Myneni CSB_ERR_ADDR(csb, "Protection error");
29332e091a6SHaren Myneni return -EPROTO;
29432e091a6SHaren Myneni case CSB_CC_PRIVILEGE:
29532e091a6SHaren Myneni /* shouldn't happen, we're in HYP mode */
29632e091a6SHaren Myneni CSB_ERR(csb, "Insufficient Privilege error");
29732e091a6SHaren Myneni return -EPROTO;
29832e091a6SHaren Myneni case CSB_CC_EXCESSIVE_DDE:
29932e091a6SHaren Myneni /* shouldn't happen, setup_ddl doesn't use many dde's */
30032e091a6SHaren Myneni CSB_ERR(csb, "Too many DDEs in DDL");
30132e091a6SHaren Myneni return -EINVAL;
30232e091a6SHaren Myneni case CSB_CC_TRANSPORT:
30332e091a6SHaren Myneni case CSB_CC_INVALID_CRB: /* P9 or later */
30432e091a6SHaren Myneni /* shouldn't happen, we setup CRB correctly */
30532e091a6SHaren Myneni CSB_ERR(csb, "Invalid CRB");
30632e091a6SHaren Myneni return -EINVAL;
30732e091a6SHaren Myneni case CSB_CC_INVALID_DDE: /* P9 or later */
30832e091a6SHaren Myneni /*
30932e091a6SHaren Myneni * shouldn't happen, setup_direct/indirect_dde creates
31032e091a6SHaren Myneni * DDE right
31132e091a6SHaren Myneni */
31232e091a6SHaren Myneni CSB_ERR(csb, "Invalid DDE");
31332e091a6SHaren Myneni return -EINVAL;
31432e091a6SHaren Myneni case CSB_CC_SEGMENTED_DDL:
31532e091a6SHaren Myneni /* shouldn't happen, setup_ddl creates DDL right */
31632e091a6SHaren Myneni CSB_ERR(csb, "Segmented DDL error");
31732e091a6SHaren Myneni return -EINVAL;
31832e091a6SHaren Myneni case CSB_CC_DDE_OVERFLOW:
31932e091a6SHaren Myneni /* shouldn't happen, setup_ddl creates DDL right */
32032e091a6SHaren Myneni CSB_ERR(csb, "DDE overflow error");
32132e091a6SHaren Myneni return -EINVAL;
32232e091a6SHaren Myneni case CSB_CC_SESSION:
32332e091a6SHaren Myneni /* should not happen with ICSWX */
32432e091a6SHaren Myneni CSB_ERR(csb, "Session violation error");
32532e091a6SHaren Myneni return -EPROTO;
32632e091a6SHaren Myneni case CSB_CC_CHAIN:
32732e091a6SHaren Myneni /* should not happen, we don't use chained CRBs */
32832e091a6SHaren Myneni CSB_ERR(csb, "Chained CRB error");
32932e091a6SHaren Myneni return -EPROTO;
33032e091a6SHaren Myneni case CSB_CC_SEQUENCE:
33132e091a6SHaren Myneni /* should not happen, we don't use chained CRBs */
33232e091a6SHaren Myneni CSB_ERR(csb, "CRB sequence number error");
33332e091a6SHaren Myneni return -EPROTO;
33432e091a6SHaren Myneni case CSB_CC_UNKNOWN_CODE:
33532e091a6SHaren Myneni CSB_ERR(csb, "Unknown subfunction code");
33632e091a6SHaren Myneni return -EPROTO;
33732e091a6SHaren Myneni
33832e091a6SHaren Myneni /* hardware errors */
33932e091a6SHaren Myneni case CSB_CC_RD_EXTERNAL:
34032e091a6SHaren Myneni case CSB_CC_RD_EXTERNAL_DUP1:
34132e091a6SHaren Myneni case CSB_CC_RD_EXTERNAL_DUP2:
34232e091a6SHaren Myneni case CSB_CC_RD_EXTERNAL_DUP3:
34332e091a6SHaren Myneni CSB_ERR_ADDR(csb, "Read error outside coprocessor");
34432e091a6SHaren Myneni return -EPROTO;
34532e091a6SHaren Myneni case CSB_CC_WR_EXTERNAL:
34632e091a6SHaren Myneni CSB_ERR_ADDR(csb, "Write error outside coprocessor");
34732e091a6SHaren Myneni return -EPROTO;
34832e091a6SHaren Myneni case CSB_CC_INTERNAL:
34932e091a6SHaren Myneni CSB_ERR(csb, "Internal error in coprocessor");
35032e091a6SHaren Myneni return -EPROTO;
35132e091a6SHaren Myneni case CSB_CC_PROVISION:
35232e091a6SHaren Myneni CSB_ERR(csb, "Storage provision error");
35332e091a6SHaren Myneni return -EPROTO;
35432e091a6SHaren Myneni case CSB_CC_HW:
35532e091a6SHaren Myneni CSB_ERR(csb, "Correctable hardware error");
35632e091a6SHaren Myneni return -EPROTO;
35732e091a6SHaren Myneni case CSB_CC_HW_EXPIRED_TIMER: /* P9 or later */
35832e091a6SHaren Myneni CSB_ERR(csb, "Job did not finish within allowed time");
35932e091a6SHaren Myneni return -EPROTO;
36032e091a6SHaren Myneni
36132e091a6SHaren Myneni default:
36232e091a6SHaren Myneni CSB_ERR(csb, "Invalid CC %d", csb->cc);
36332e091a6SHaren Myneni return -EPROTO;
36432e091a6SHaren Myneni }
36532e091a6SHaren Myneni
36632e091a6SHaren Myneni /* check Completion Extension state */
36732e091a6SHaren Myneni if (csb->ce & CSB_CE_TERMINATION) {
36832e091a6SHaren Myneni CSB_ERR(csb, "CSB request was terminated");
36932e091a6SHaren Myneni return -EPROTO;
37032e091a6SHaren Myneni }
37132e091a6SHaren Myneni if (csb->ce & CSB_CE_INCOMPLETE) {
37232e091a6SHaren Myneni CSB_ERR(csb, "CSB request not complete");
37332e091a6SHaren Myneni return -EPROTO;
37432e091a6SHaren Myneni }
37532e091a6SHaren Myneni if (!(csb->ce & CSB_CE_TPBC)) {
37632e091a6SHaren Myneni CSB_ERR(csb, "TPBC not provided, unknown target length");
37732e091a6SHaren Myneni return -EPROTO;
37832e091a6SHaren Myneni }
37932e091a6SHaren Myneni
38032e091a6SHaren Myneni /* successful completion */
38132e091a6SHaren Myneni pr_debug_ratelimited("Processed %u bytes in %lu us\n",
38232e091a6SHaren Myneni be32_to_cpu(csb->count),
38332e091a6SHaren Myneni (unsigned long)ktime_us_delta(now, start));
38432e091a6SHaren Myneni
38532e091a6SHaren Myneni return 0;
38632e091a6SHaren Myneni }
38732e091a6SHaren Myneni
nx842_config_crb(const unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int outlen,struct nx842_workmem * wmem)38832e091a6SHaren Myneni static int nx842_config_crb(const unsigned char *in, unsigned int inlen,
38932e091a6SHaren Myneni unsigned char *out, unsigned int outlen,
39032e091a6SHaren Myneni struct nx842_workmem *wmem)
39132e091a6SHaren Myneni {
39232e091a6SHaren Myneni struct coprocessor_request_block *crb;
39332e091a6SHaren Myneni struct coprocessor_status_block *csb;
39432e091a6SHaren Myneni u64 csb_addr;
39532e091a6SHaren Myneni int ret;
39632e091a6SHaren Myneni
39732e091a6SHaren Myneni crb = &wmem->crb;
39832e091a6SHaren Myneni csb = &crb->csb;
39932e091a6SHaren Myneni
40032e091a6SHaren Myneni /* Clear any previous values */
40132e091a6SHaren Myneni memset(crb, 0, sizeof(*crb));
40232e091a6SHaren Myneni
40332e091a6SHaren Myneni /* set up DDLs */
40432e091a6SHaren Myneni ret = setup_ddl(&crb->source, wmem->ddl_in,
40532e091a6SHaren Myneni (unsigned char *)in, inlen, true);
40632e091a6SHaren Myneni if (ret)
40732e091a6SHaren Myneni return ret;
40832e091a6SHaren Myneni
40932e091a6SHaren Myneni ret = setup_ddl(&crb->target, wmem->ddl_out,
41032e091a6SHaren Myneni out, outlen, false);
41132e091a6SHaren Myneni if (ret)
41232e091a6SHaren Myneni return ret;
41332e091a6SHaren Myneni
41432e091a6SHaren Myneni /* set up CRB's CSB addr */
41532e091a6SHaren Myneni csb_addr = nx842_get_pa(csb) & CRB_CSB_ADDRESS;
41632e091a6SHaren Myneni csb_addr |= CRB_CSB_AT; /* Addrs are phys */
41732e091a6SHaren Myneni crb->csb_addr = cpu_to_be64(csb_addr);
41832e091a6SHaren Myneni
41932e091a6SHaren Myneni return 0;
42032e091a6SHaren Myneni }
42132e091a6SHaren Myneni
42232e091a6SHaren Myneni /**
42332e091a6SHaren Myneni * nx842_exec_icswx - compress/decompress data using the 842 algorithm
42432e091a6SHaren Myneni *
42532e091a6SHaren Myneni * (De)compression provided by the NX842 coprocessor on IBM PowerNV systems.
42632e091a6SHaren Myneni * This compresses or decompresses the provided input buffer into the provided
42732e091a6SHaren Myneni * output buffer.
42832e091a6SHaren Myneni *
42932e091a6SHaren Myneni * Upon return from this function @outlen contains the length of the
43032e091a6SHaren Myneni * output data. If there is an error then @outlen will be 0 and an
43132e091a6SHaren Myneni * error will be specified by the return code from this function.
43232e091a6SHaren Myneni *
43332e091a6SHaren Myneni * The @workmem buffer should only be used by one function call at a time.
43432e091a6SHaren Myneni *
43532e091a6SHaren Myneni * @in: input buffer pointer
43632e091a6SHaren Myneni * @inlen: input buffer size
43732e091a6SHaren Myneni * @out: output buffer pointer
43832e091a6SHaren Myneni * @outlenp: output buffer size pointer
43932e091a6SHaren Myneni * @workmem: working memory buffer pointer, size determined by
44032e091a6SHaren Myneni * nx842_powernv_driver.workmem_size
44132e091a6SHaren Myneni * @fc: function code, see CCW Function Codes in nx-842.h
44232e091a6SHaren Myneni *
44332e091a6SHaren Myneni * Returns:
44432e091a6SHaren Myneni * 0 Success, output of length @outlenp stored in the buffer at @out
44532e091a6SHaren Myneni * -ENODEV Hardware unavailable
44632e091a6SHaren Myneni * -ENOSPC Output buffer is to small
44732e091a6SHaren Myneni * -EMSGSIZE Input buffer too large
44832e091a6SHaren Myneni * -EINVAL buffer constraints do not fix nx842_constraints
44932e091a6SHaren Myneni * -EPROTO hardware error during operation
45032e091a6SHaren Myneni * -ETIMEDOUT hardware did not complete operation in reasonable time
45132e091a6SHaren Myneni * -EINTR operation was aborted
45232e091a6SHaren Myneni */
nx842_exec_icswx(const unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int * outlenp,void * workmem,int fc)45332e091a6SHaren Myneni static int nx842_exec_icswx(const unsigned char *in, unsigned int inlen,
45432e091a6SHaren Myneni unsigned char *out, unsigned int *outlenp,
45532e091a6SHaren Myneni void *workmem, int fc)
45632e091a6SHaren Myneni {
45732e091a6SHaren Myneni struct coprocessor_request_block *crb;
45832e091a6SHaren Myneni struct coprocessor_status_block *csb;
45932e091a6SHaren Myneni struct nx842_workmem *wmem;
46032e091a6SHaren Myneni int ret;
46132e091a6SHaren Myneni u32 ccw;
46232e091a6SHaren Myneni unsigned int outlen = *outlenp;
46332e091a6SHaren Myneni
46432e091a6SHaren Myneni wmem = PTR_ALIGN(workmem, WORKMEM_ALIGN);
46532e091a6SHaren Myneni
46632e091a6SHaren Myneni *outlenp = 0;
46732e091a6SHaren Myneni
46832e091a6SHaren Myneni /* shoudn't happen, we don't load without a coproc */
46932e091a6SHaren Myneni if (!nx842_ct) {
47032e091a6SHaren Myneni pr_err_ratelimited("coprocessor CT is 0");
47132e091a6SHaren Myneni return -ENODEV;
47232e091a6SHaren Myneni }
47332e091a6SHaren Myneni
47432e091a6SHaren Myneni ret = nx842_config_crb(in, inlen, out, outlen, wmem);
47532e091a6SHaren Myneni if (ret)
47632e091a6SHaren Myneni return ret;
47732e091a6SHaren Myneni
47832e091a6SHaren Myneni crb = &wmem->crb;
47932e091a6SHaren Myneni csb = &crb->csb;
48032e091a6SHaren Myneni
48132e091a6SHaren Myneni /* set up CCW */
48232e091a6SHaren Myneni ccw = 0;
48332e091a6SHaren Myneni ccw = SET_FIELD(CCW_CT, ccw, nx842_ct);
48432e091a6SHaren Myneni ccw = SET_FIELD(CCW_CI_842, ccw, 0); /* use 0 for hw auto-selection */
48532e091a6SHaren Myneni ccw = SET_FIELD(CCW_FC_842, ccw, fc);
48632e091a6SHaren Myneni
48732e091a6SHaren Myneni wmem->start = ktime_get();
48832e091a6SHaren Myneni
48932e091a6SHaren Myneni /* do ICSWX */
49032e091a6SHaren Myneni ret = icswx(cpu_to_be32(ccw), crb);
49132e091a6SHaren Myneni
49232e091a6SHaren Myneni pr_debug_ratelimited("icswx CR %x ccw %x crb->ccw %x\n", ret,
49332e091a6SHaren Myneni (unsigned int)ccw,
49432e091a6SHaren Myneni (unsigned int)be32_to_cpu(crb->ccw));
49532e091a6SHaren Myneni
49632e091a6SHaren Myneni /*
49732e091a6SHaren Myneni * NX842 coprocessor sets 3rd bit in CR register with XER[S0].
49832e091a6SHaren Myneni * XER[S0] is the integer summary overflow bit which is nothing
49932e091a6SHaren Myneni * to do NX. Since this bit can be set with other return values,
50032e091a6SHaren Myneni * mask this bit.
50132e091a6SHaren Myneni */
50232e091a6SHaren Myneni ret &= ~ICSWX_XERS0;
50332e091a6SHaren Myneni
50432e091a6SHaren Myneni switch (ret) {
50532e091a6SHaren Myneni case ICSWX_INITIATED:
50632e091a6SHaren Myneni ret = wait_for_csb(wmem, csb);
50732e091a6SHaren Myneni break;
50832e091a6SHaren Myneni case ICSWX_BUSY:
50932e091a6SHaren Myneni pr_debug_ratelimited("842 Coprocessor busy\n");
51032e091a6SHaren Myneni ret = -EBUSY;
51132e091a6SHaren Myneni break;
51232e091a6SHaren Myneni case ICSWX_REJECTED:
51332e091a6SHaren Myneni pr_err_ratelimited("ICSWX rejected\n");
51432e091a6SHaren Myneni ret = -EPROTO;
51532e091a6SHaren Myneni break;
51632e091a6SHaren Myneni }
51732e091a6SHaren Myneni
51832e091a6SHaren Myneni if (!ret)
51932e091a6SHaren Myneni *outlenp = be32_to_cpu(csb->count);
52032e091a6SHaren Myneni
52132e091a6SHaren Myneni return ret;
52232e091a6SHaren Myneni }
52332e091a6SHaren Myneni
52432e091a6SHaren Myneni /**
52532e091a6SHaren Myneni * nx842_exec_vas - compress/decompress data using the 842 algorithm
52632e091a6SHaren Myneni *
52732e091a6SHaren Myneni * (De)compression provided by the NX842 coprocessor on IBM PowerNV systems.
52832e091a6SHaren Myneni * This compresses or decompresses the provided input buffer into the provided
52932e091a6SHaren Myneni * output buffer.
53032e091a6SHaren Myneni *
53132e091a6SHaren Myneni * Upon return from this function @outlen contains the length of the
53232e091a6SHaren Myneni * output data. If there is an error then @outlen will be 0 and an
53332e091a6SHaren Myneni * error will be specified by the return code from this function.
53432e091a6SHaren Myneni *
53532e091a6SHaren Myneni * The @workmem buffer should only be used by one function call at a time.
53632e091a6SHaren Myneni *
53732e091a6SHaren Myneni * @in: input buffer pointer
53832e091a6SHaren Myneni * @inlen: input buffer size
53932e091a6SHaren Myneni * @out: output buffer pointer
54032e091a6SHaren Myneni * @outlenp: output buffer size pointer
54132e091a6SHaren Myneni * @workmem: working memory buffer pointer, size determined by
54232e091a6SHaren Myneni * nx842_powernv_driver.workmem_size
54332e091a6SHaren Myneni * @fc: function code, see CCW Function Codes in nx-842.h
54432e091a6SHaren Myneni *
54532e091a6SHaren Myneni * Returns:
54632e091a6SHaren Myneni * 0 Success, output of length @outlenp stored in the buffer
54732e091a6SHaren Myneni * at @out
54832e091a6SHaren Myneni * -ENODEV Hardware unavailable
54932e091a6SHaren Myneni * -ENOSPC Output buffer is to small
55032e091a6SHaren Myneni * -EMSGSIZE Input buffer too large
55132e091a6SHaren Myneni * -EINVAL buffer constraints do not fix nx842_constraints
55232e091a6SHaren Myneni * -EPROTO hardware error during operation
55332e091a6SHaren Myneni * -ETIMEDOUT hardware did not complete operation in reasonable time
55432e091a6SHaren Myneni * -EINTR operation was aborted
55532e091a6SHaren Myneni */
nx842_exec_vas(const unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int * outlenp,void * workmem,int fc)55632e091a6SHaren Myneni static int nx842_exec_vas(const unsigned char *in, unsigned int inlen,
55732e091a6SHaren Myneni unsigned char *out, unsigned int *outlenp,
55832e091a6SHaren Myneni void *workmem, int fc)
55932e091a6SHaren Myneni {
56032e091a6SHaren Myneni struct coprocessor_request_block *crb;
56132e091a6SHaren Myneni struct coprocessor_status_block *csb;
56232e091a6SHaren Myneni struct nx842_workmem *wmem;
56332e091a6SHaren Myneni struct vas_window *txwin;
56432e091a6SHaren Myneni int ret, i = 0;
56532e091a6SHaren Myneni u32 ccw;
56632e091a6SHaren Myneni unsigned int outlen = *outlenp;
56732e091a6SHaren Myneni
56832e091a6SHaren Myneni wmem = PTR_ALIGN(workmem, WORKMEM_ALIGN);
56932e091a6SHaren Myneni
57032e091a6SHaren Myneni *outlenp = 0;
57132e091a6SHaren Myneni
57232e091a6SHaren Myneni crb = &wmem->crb;
57332e091a6SHaren Myneni csb = &crb->csb;
57432e091a6SHaren Myneni
57532e091a6SHaren Myneni ret = nx842_config_crb(in, inlen, out, outlen, wmem);
57632e091a6SHaren Myneni if (ret)
57732e091a6SHaren Myneni return ret;
57832e091a6SHaren Myneni
57932e091a6SHaren Myneni ccw = 0;
58032e091a6SHaren Myneni ccw = SET_FIELD(CCW_FC_842, ccw, fc);
58132e091a6SHaren Myneni crb->ccw = cpu_to_be32(ccw);
58232e091a6SHaren Myneni
58332e091a6SHaren Myneni do {
58432e091a6SHaren Myneni wmem->start = ktime_get();
58532e091a6SHaren Myneni preempt_disable();
58632e091a6SHaren Myneni txwin = this_cpu_read(cpu_txwin);
58732e091a6SHaren Myneni
58832e091a6SHaren Myneni /*
58932e091a6SHaren Myneni * VAS copy CRB into L2 cache. Refer <asm/vas.h>.
59032e091a6SHaren Myneni * @crb and @offset.
59132e091a6SHaren Myneni */
59232e091a6SHaren Myneni vas_copy_crb(crb, 0);
59332e091a6SHaren Myneni
59432e091a6SHaren Myneni /*
59532e091a6SHaren Myneni * VAS paste previously copied CRB to NX.
59632e091a6SHaren Myneni * @txwin, @offset and @last (must be true).
59732e091a6SHaren Myneni */
59832e091a6SHaren Myneni ret = vas_paste_crb(txwin, 0, 1);
59932e091a6SHaren Myneni preempt_enable();
60032e091a6SHaren Myneni /*
60132e091a6SHaren Myneni * Retry copy/paste function for VAS failures.
60232e091a6SHaren Myneni */
60332e091a6SHaren Myneni } while (ret && (i++ < VAS_RETRIES));
60432e091a6SHaren Myneni
60532e091a6SHaren Myneni if (ret) {
60632e091a6SHaren Myneni pr_err_ratelimited("VAS copy/paste failed\n");
60732e091a6SHaren Myneni return ret;
60832e091a6SHaren Myneni }
60932e091a6SHaren Myneni
61032e091a6SHaren Myneni ret = wait_for_csb(wmem, csb);
61132e091a6SHaren Myneni if (!ret)
61232e091a6SHaren Myneni *outlenp = be32_to_cpu(csb->count);
61332e091a6SHaren Myneni
61432e091a6SHaren Myneni return ret;
61532e091a6SHaren Myneni }
61632e091a6SHaren Myneni
61732e091a6SHaren Myneni /**
61832e091a6SHaren Myneni * nx842_powernv_compress - Compress data using the 842 algorithm
61932e091a6SHaren Myneni *
62032e091a6SHaren Myneni * Compression provided by the NX842 coprocessor on IBM PowerNV systems.
62132e091a6SHaren Myneni * The input buffer is compressed and the result is stored in the
62232e091a6SHaren Myneni * provided output buffer.
62332e091a6SHaren Myneni *
62432e091a6SHaren Myneni * Upon return from this function @outlen contains the length of the
62532e091a6SHaren Myneni * compressed data. If there is an error then @outlen will be 0 and an
62632e091a6SHaren Myneni * error will be specified by the return code from this function.
62732e091a6SHaren Myneni *
62832e091a6SHaren Myneni * @in: input buffer pointer
62932e091a6SHaren Myneni * @inlen: input buffer size
63032e091a6SHaren Myneni * @out: output buffer pointer
63132e091a6SHaren Myneni * @outlenp: output buffer size pointer
632*6084466eSHerbert Xu * @wmem: working memory buffer pointer, size determined by
63332e091a6SHaren Myneni * nx842_powernv_driver.workmem_size
63432e091a6SHaren Myneni *
63532e091a6SHaren Myneni * Returns: see @nx842_powernv_exec()
63632e091a6SHaren Myneni */
nx842_powernv_compress(const unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int * outlenp,void * wmem)63732e091a6SHaren Myneni static int nx842_powernv_compress(const unsigned char *in, unsigned int inlen,
63832e091a6SHaren Myneni unsigned char *out, unsigned int *outlenp,
63932e091a6SHaren Myneni void *wmem)
64032e091a6SHaren Myneni {
64132e091a6SHaren Myneni return nx842_powernv_exec(in, inlen, out, outlenp,
64232e091a6SHaren Myneni wmem, CCW_FC_842_COMP_CRC);
64332e091a6SHaren Myneni }
64432e091a6SHaren Myneni
64532e091a6SHaren Myneni /**
64632e091a6SHaren Myneni * nx842_powernv_decompress - Decompress data using the 842 algorithm
64732e091a6SHaren Myneni *
64832e091a6SHaren Myneni * Decompression provided by the NX842 coprocessor on IBM PowerNV systems.
64932e091a6SHaren Myneni * The input buffer is decompressed and the result is stored in the
65032e091a6SHaren Myneni * provided output buffer.
65132e091a6SHaren Myneni *
65232e091a6SHaren Myneni * Upon return from this function @outlen contains the length of the
65332e091a6SHaren Myneni * decompressed data. If there is an error then @outlen will be 0 and an
65432e091a6SHaren Myneni * error will be specified by the return code from this function.
65532e091a6SHaren Myneni *
65632e091a6SHaren Myneni * @in: input buffer pointer
65732e091a6SHaren Myneni * @inlen: input buffer size
65832e091a6SHaren Myneni * @out: output buffer pointer
65932e091a6SHaren Myneni * @outlenp: output buffer size pointer
6603f4a8567SShaokun Zhang * @wmem: working memory buffer pointer, size determined by
66132e091a6SHaren Myneni * nx842_powernv_driver.workmem_size
66232e091a6SHaren Myneni *
66332e091a6SHaren Myneni * Returns: see @nx842_powernv_exec()
66432e091a6SHaren Myneni */
nx842_powernv_decompress(const unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int * outlenp,void * wmem)66532e091a6SHaren Myneni static int nx842_powernv_decompress(const unsigned char *in, unsigned int inlen,
66632e091a6SHaren Myneni unsigned char *out, unsigned int *outlenp,
66732e091a6SHaren Myneni void *wmem)
66832e091a6SHaren Myneni {
66932e091a6SHaren Myneni return nx842_powernv_exec(in, inlen, out, outlenp,
67032e091a6SHaren Myneni wmem, CCW_FC_842_DECOMP_CRC);
67132e091a6SHaren Myneni }
67232e091a6SHaren Myneni
nx_add_coprocs_list(struct nx_coproc * coproc,int chipid)6734aebf3ceSHaren Myneni static inline void nx_add_coprocs_list(struct nx_coproc *coproc,
67432e091a6SHaren Myneni int chipid)
67532e091a6SHaren Myneni {
67632e091a6SHaren Myneni coproc->chip_id = chipid;
67732e091a6SHaren Myneni INIT_LIST_HEAD(&coproc->list);
6784aebf3ceSHaren Myneni list_add(&coproc->list, &nx_coprocs);
67932e091a6SHaren Myneni }
68032e091a6SHaren Myneni
nx_alloc_txwin(struct nx_coproc * coproc)6814aebf3ceSHaren Myneni static struct vas_window *nx_alloc_txwin(struct nx_coproc *coproc)
68232e091a6SHaren Myneni {
68332e091a6SHaren Myneni struct vas_window *txwin = NULL;
68432e091a6SHaren Myneni struct vas_tx_win_attr txattr;
68532e091a6SHaren Myneni
68632e091a6SHaren Myneni /*
68732e091a6SHaren Myneni * Kernel requests will be high priority. So open send
68832e091a6SHaren Myneni * windows only for high priority RxFIFO entries.
68932e091a6SHaren Myneni */
69032e091a6SHaren Myneni vas_init_tx_win_attr(&txattr, coproc->ct);
69132e091a6SHaren Myneni txattr.lpid = 0; /* lpid is 0 for kernel requests */
69232e091a6SHaren Myneni
69332e091a6SHaren Myneni /*
69432e091a6SHaren Myneni * Open a VAS send window which is used to send request to NX.
69532e091a6SHaren Myneni */
69632e091a6SHaren Myneni txwin = vas_tx_win_open(coproc->vas.id, coproc->ct, &txattr);
69732e091a6SHaren Myneni if (IS_ERR(txwin))
69832e091a6SHaren Myneni pr_err("ibm,nx-842: Can not open TX window: %ld\n",
69932e091a6SHaren Myneni PTR_ERR(txwin));
70032e091a6SHaren Myneni
70132e091a6SHaren Myneni return txwin;
70232e091a6SHaren Myneni }
70332e091a6SHaren Myneni
70432e091a6SHaren Myneni /*
70532e091a6SHaren Myneni * Identify chip ID for each CPU, open send wndow for the corresponding NX
70632e091a6SHaren Myneni * engine and save txwin in percpu cpu_txwin.
70732e091a6SHaren Myneni * cpu_txwin is used in copy/paste operation for each compression /
70832e091a6SHaren Myneni * decompression request.
70932e091a6SHaren Myneni */
nx_open_percpu_txwins(void)7104aebf3ceSHaren Myneni static int nx_open_percpu_txwins(void)
71132e091a6SHaren Myneni {
7124aebf3ceSHaren Myneni struct nx_coproc *coproc, *n;
71332e091a6SHaren Myneni unsigned int i, chip_id;
71432e091a6SHaren Myneni
71532e091a6SHaren Myneni for_each_possible_cpu(i) {
71632e091a6SHaren Myneni struct vas_window *txwin = NULL;
71732e091a6SHaren Myneni
71832e091a6SHaren Myneni chip_id = cpu_to_chip_id(i);
71932e091a6SHaren Myneni
7204aebf3ceSHaren Myneni list_for_each_entry_safe(coproc, n, &nx_coprocs, list) {
72132e091a6SHaren Myneni /*
72232e091a6SHaren Myneni * Kernel requests use only high priority FIFOs. So
72332e091a6SHaren Myneni * open send windows for these FIFOs.
7244aebf3ceSHaren Myneni * GZIP is not supported in kernel right now.
72532e091a6SHaren Myneni */
72632e091a6SHaren Myneni
72732e091a6SHaren Myneni if (coproc->ct != VAS_COP_TYPE_842_HIPRI)
72832e091a6SHaren Myneni continue;
72932e091a6SHaren Myneni
73032e091a6SHaren Myneni if (coproc->chip_id == chip_id) {
7314aebf3ceSHaren Myneni txwin = nx_alloc_txwin(coproc);
73232e091a6SHaren Myneni if (IS_ERR(txwin))
73332e091a6SHaren Myneni return PTR_ERR(txwin);
73432e091a6SHaren Myneni
73532e091a6SHaren Myneni per_cpu(cpu_txwin, i) = txwin;
73632e091a6SHaren Myneni break;
73732e091a6SHaren Myneni }
73832e091a6SHaren Myneni }
73932e091a6SHaren Myneni
74032e091a6SHaren Myneni if (!per_cpu(cpu_txwin, i)) {
74132e091a6SHaren Myneni /* shouldn't happen, Each chip will have NX engine */
74232e091a6SHaren Myneni pr_err("NX engine is not available for CPU %d\n", i);
74332e091a6SHaren Myneni return -EINVAL;
74432e091a6SHaren Myneni }
74532e091a6SHaren Myneni }
74632e091a6SHaren Myneni
74732e091a6SHaren Myneni return 0;
74832e091a6SHaren Myneni }
74932e091a6SHaren Myneni
nx_set_ct(struct nx_coproc * coproc,const char * priority,int high,int normal)7504aebf3ceSHaren Myneni static int __init nx_set_ct(struct nx_coproc *coproc, const char *priority,
7514aebf3ceSHaren Myneni int high, int normal)
7524aebf3ceSHaren Myneni {
7534aebf3ceSHaren Myneni if (!strcmp(priority, "High"))
7544aebf3ceSHaren Myneni coproc->ct = high;
7554aebf3ceSHaren Myneni else if (!strcmp(priority, "Normal"))
7564aebf3ceSHaren Myneni coproc->ct = normal;
7574aebf3ceSHaren Myneni else {
7584aebf3ceSHaren Myneni pr_err("Invalid RxFIFO priority value\n");
7594aebf3ceSHaren Myneni return -EINVAL;
7604aebf3ceSHaren Myneni }
7614aebf3ceSHaren Myneni
7624aebf3ceSHaren Myneni return 0;
7634aebf3ceSHaren Myneni }
7644aebf3ceSHaren Myneni
vas_cfg_coproc_info(struct device_node * dn,int chip_id,int vasid,int type,int * ct)76532e091a6SHaren Myneni static int __init vas_cfg_coproc_info(struct device_node *dn, int chip_id,
7664aebf3ceSHaren Myneni int vasid, int type, int *ct)
76732e091a6SHaren Myneni {
76832e091a6SHaren Myneni struct vas_window *rxwin = NULL;
76932e091a6SHaren Myneni struct vas_rx_win_attr rxattr;
77032e091a6SHaren Myneni u32 lpid, pid, tid, fifo_size;
7714aebf3ceSHaren Myneni struct nx_coproc *coproc;
77232e091a6SHaren Myneni u64 rx_fifo;
77332e091a6SHaren Myneni const char *priority;
77432e091a6SHaren Myneni int ret;
77532e091a6SHaren Myneni
77632e091a6SHaren Myneni ret = of_property_read_u64(dn, "rx-fifo-address", &rx_fifo);
77732e091a6SHaren Myneni if (ret) {
77832e091a6SHaren Myneni pr_err("Missing rx-fifo-address property\n");
77932e091a6SHaren Myneni return ret;
78032e091a6SHaren Myneni }
78132e091a6SHaren Myneni
78232e091a6SHaren Myneni ret = of_property_read_u32(dn, "rx-fifo-size", &fifo_size);
78332e091a6SHaren Myneni if (ret) {
78432e091a6SHaren Myneni pr_err("Missing rx-fifo-size property\n");
78532e091a6SHaren Myneni return ret;
78632e091a6SHaren Myneni }
78732e091a6SHaren Myneni
78832e091a6SHaren Myneni ret = of_property_read_u32(dn, "lpid", &lpid);
78932e091a6SHaren Myneni if (ret) {
79032e091a6SHaren Myneni pr_err("Missing lpid property\n");
79132e091a6SHaren Myneni return ret;
79232e091a6SHaren Myneni }
79332e091a6SHaren Myneni
79432e091a6SHaren Myneni ret = of_property_read_u32(dn, "pid", &pid);
79532e091a6SHaren Myneni if (ret) {
79632e091a6SHaren Myneni pr_err("Missing pid property\n");
79732e091a6SHaren Myneni return ret;
79832e091a6SHaren Myneni }
79932e091a6SHaren Myneni
80032e091a6SHaren Myneni ret = of_property_read_u32(dn, "tid", &tid);
80132e091a6SHaren Myneni if (ret) {
80232e091a6SHaren Myneni pr_err("Missing tid property\n");
80332e091a6SHaren Myneni return ret;
80432e091a6SHaren Myneni }
80532e091a6SHaren Myneni
80632e091a6SHaren Myneni ret = of_property_read_string(dn, "priority", &priority);
80732e091a6SHaren Myneni if (ret) {
80832e091a6SHaren Myneni pr_err("Missing priority property\n");
80932e091a6SHaren Myneni return ret;
81032e091a6SHaren Myneni }
81132e091a6SHaren Myneni
81232e091a6SHaren Myneni coproc = kzalloc(sizeof(*coproc), GFP_KERNEL);
81332e091a6SHaren Myneni if (!coproc)
81432e091a6SHaren Myneni return -ENOMEM;
81532e091a6SHaren Myneni
8164aebf3ceSHaren Myneni if (type == NX_CT_842)
8174aebf3ceSHaren Myneni ret = nx_set_ct(coproc, priority, VAS_COP_TYPE_842_HIPRI,
8184aebf3ceSHaren Myneni VAS_COP_TYPE_842);
8191af11ae2SHaren Myneni else if (type == NX_CT_GZIP)
8201af11ae2SHaren Myneni ret = nx_set_ct(coproc, priority, VAS_COP_TYPE_GZIP_HIPRI,
8211af11ae2SHaren Myneni VAS_COP_TYPE_GZIP);
8224aebf3ceSHaren Myneni
8234aebf3ceSHaren Myneni if (ret)
82432e091a6SHaren Myneni goto err_out;
82532e091a6SHaren Myneni
82632e091a6SHaren Myneni vas_init_rx_win_attr(&rxattr, coproc->ct);
827c127d130SHaren Myneni rxattr.rx_fifo = rx_fifo;
82832e091a6SHaren Myneni rxattr.rx_fifo_size = fifo_size;
82932e091a6SHaren Myneni rxattr.lnotify_lpid = lpid;
83032e091a6SHaren Myneni rxattr.lnotify_pid = pid;
83132e091a6SHaren Myneni rxattr.lnotify_tid = tid;
83232e091a6SHaren Myneni /*
83332e091a6SHaren Myneni * Maximum RX window credits can not be more than #CRBs in
83432e091a6SHaren Myneni * RxFIFO. Otherwise, can get checkstop if RxFIFO overruns.
83532e091a6SHaren Myneni */
83632e091a6SHaren Myneni rxattr.wcreds_max = fifo_size / CRB_SIZE;
83732e091a6SHaren Myneni
83832e091a6SHaren Myneni /*
83932e091a6SHaren Myneni * Open a VAS receice window which is used to configure RxFIFO
84032e091a6SHaren Myneni * for NX.
84132e091a6SHaren Myneni */
84232e091a6SHaren Myneni rxwin = vas_rx_win_open(vasid, coproc->ct, &rxattr);
84332e091a6SHaren Myneni if (IS_ERR(rxwin)) {
84432e091a6SHaren Myneni ret = PTR_ERR(rxwin);
84532e091a6SHaren Myneni pr_err("setting RxFIFO with VAS failed: %d\n",
84632e091a6SHaren Myneni ret);
84732e091a6SHaren Myneni goto err_out;
84832e091a6SHaren Myneni }
84932e091a6SHaren Myneni
85032e091a6SHaren Myneni coproc->vas.rxwin = rxwin;
85132e091a6SHaren Myneni coproc->vas.id = vasid;
8524aebf3ceSHaren Myneni nx_add_coprocs_list(coproc, chip_id);
85332e091a6SHaren Myneni
85432e091a6SHaren Myneni /*
85532e091a6SHaren Myneni * (lpid, pid, tid) combination has to be unique for each
85632e091a6SHaren Myneni * coprocessor instance in the system. So to make it
85732e091a6SHaren Myneni * unique, skiboot uses coprocessor type such as 842 or
85832e091a6SHaren Myneni * GZIP for pid and provides this value to kernel in pid
85932e091a6SHaren Myneni * device-tree property.
86032e091a6SHaren Myneni */
86132e091a6SHaren Myneni *ct = pid;
86232e091a6SHaren Myneni
86332e091a6SHaren Myneni return 0;
86432e091a6SHaren Myneni
86532e091a6SHaren Myneni err_out:
86632e091a6SHaren Myneni kfree(coproc);
86732e091a6SHaren Myneni return ret;
86832e091a6SHaren Myneni }
86932e091a6SHaren Myneni
nx_coproc_init(int chip_id,int ct_842,int ct_gzip)8701af11ae2SHaren Myneni static int __init nx_coproc_init(int chip_id, int ct_842, int ct_gzip)
87132e091a6SHaren Myneni {
8724aebf3ceSHaren Myneni int ret = 0;
8734aebf3ceSHaren Myneni
8744aebf3ceSHaren Myneni if (opal_check_token(OPAL_NX_COPROC_INIT)) {
8754aebf3ceSHaren Myneni ret = opal_nx_coproc_init(chip_id, ct_842);
8761af11ae2SHaren Myneni
8771af11ae2SHaren Myneni if (!ret)
8781af11ae2SHaren Myneni ret = opal_nx_coproc_init(chip_id, ct_gzip);
8791af11ae2SHaren Myneni
8804aebf3ceSHaren Myneni if (ret) {
8814aebf3ceSHaren Myneni ret = opal_error_code(ret);
8824aebf3ceSHaren Myneni pr_err("Failed to initialize NX for chip(%d): %d\n",
8834aebf3ceSHaren Myneni chip_id, ret);
8844aebf3ceSHaren Myneni }
8854aebf3ceSHaren Myneni } else
8864aebf3ceSHaren Myneni pr_warn("Firmware doesn't support NX initialization\n");
8874aebf3ceSHaren Myneni
8884aebf3ceSHaren Myneni return ret;
8894aebf3ceSHaren Myneni }
8904aebf3ceSHaren Myneni
find_nx_device_tree(struct device_node * dn,int chip_id,int vasid,int type,char * devname,int * ct)8914aebf3ceSHaren Myneni static int __init find_nx_device_tree(struct device_node *dn, int chip_id,
8924aebf3ceSHaren Myneni int vasid, int type, char *devname,
8934aebf3ceSHaren Myneni int *ct)
8944aebf3ceSHaren Myneni {
8954aebf3ceSHaren Myneni int ret = 0;
8964aebf3ceSHaren Myneni
8974aebf3ceSHaren Myneni if (of_device_is_compatible(dn, devname)) {
8984aebf3ceSHaren Myneni ret = vas_cfg_coproc_info(dn, chip_id, vasid, type, ct);
8994aebf3ceSHaren Myneni if (ret)
9004aebf3ceSHaren Myneni of_node_put(dn);
9014aebf3ceSHaren Myneni }
9024aebf3ceSHaren Myneni
9034aebf3ceSHaren Myneni return ret;
9044aebf3ceSHaren Myneni }
9054aebf3ceSHaren Myneni
nx_powernv_probe_vas(struct device_node * pn)9064aebf3ceSHaren Myneni static int __init nx_powernv_probe_vas(struct device_node *pn)
9074aebf3ceSHaren Myneni {
90832e091a6SHaren Myneni int chip_id, vasid, ret = 0;
9091af11ae2SHaren Myneni int ct_842 = 0, ct_gzip = 0;
9104aebf3ceSHaren Myneni struct device_node *dn;
91132e091a6SHaren Myneni
91232e091a6SHaren Myneni chip_id = of_get_ibm_chip_id(pn);
91332e091a6SHaren Myneni if (chip_id < 0) {
91432e091a6SHaren Myneni pr_err("ibm,chip-id missing\n");
91532e091a6SHaren Myneni return -EINVAL;
91632e091a6SHaren Myneni }
91732e091a6SHaren Myneni
91832e091a6SHaren Myneni vasid = chip_to_vas_id(chip_id);
91932e091a6SHaren Myneni if (vasid < 0) {
92032e091a6SHaren Myneni pr_err("Unable to map chip_id %d to vasid\n", chip_id);
92132e091a6SHaren Myneni return -EINVAL;
92232e091a6SHaren Myneni }
92332e091a6SHaren Myneni
92432e091a6SHaren Myneni for_each_child_of_node(pn, dn) {
9254aebf3ceSHaren Myneni ret = find_nx_device_tree(dn, chip_id, vasid, NX_CT_842,
9264aebf3ceSHaren Myneni "ibm,p9-nx-842", &ct_842);
9271af11ae2SHaren Myneni
9281af11ae2SHaren Myneni if (!ret)
9291af11ae2SHaren Myneni ret = find_nx_device_tree(dn, chip_id, vasid,
9301af11ae2SHaren Myneni NX_CT_GZIP, "ibm,p9-nx-gzip", &ct_gzip);
9311af11ae2SHaren Myneni
9321406f0f3SYang Li if (ret) {
9331406f0f3SYang Li of_node_put(dn);
93432e091a6SHaren Myneni return ret;
93532e091a6SHaren Myneni }
9361406f0f3SYang Li }
93732e091a6SHaren Myneni
9381af11ae2SHaren Myneni if (!ct_842 || !ct_gzip) {
9391af11ae2SHaren Myneni pr_err("NX FIFO nodes are missing\n");
94032e091a6SHaren Myneni return -EINVAL;
94132e091a6SHaren Myneni }
94232e091a6SHaren Myneni
94332e091a6SHaren Myneni /*
94432e091a6SHaren Myneni * Initialize NX instance for both high and normal priority FIFOs.
94532e091a6SHaren Myneni */
9461af11ae2SHaren Myneni ret = nx_coproc_init(chip_id, ct_842, ct_gzip);
94732e091a6SHaren Myneni
94832e091a6SHaren Myneni return ret;
94932e091a6SHaren Myneni }
95032e091a6SHaren Myneni
nx842_powernv_probe(struct device_node * dn)95132e091a6SHaren Myneni static int __init nx842_powernv_probe(struct device_node *dn)
95232e091a6SHaren Myneni {
9534aebf3ceSHaren Myneni struct nx_coproc *coproc;
95432e091a6SHaren Myneni unsigned int ct, ci;
95532e091a6SHaren Myneni int chip_id;
95632e091a6SHaren Myneni
95732e091a6SHaren Myneni chip_id = of_get_ibm_chip_id(dn);
95832e091a6SHaren Myneni if (chip_id < 0) {
95932e091a6SHaren Myneni pr_err("ibm,chip-id missing\n");
96032e091a6SHaren Myneni return -EINVAL;
96132e091a6SHaren Myneni }
96232e091a6SHaren Myneni
96332e091a6SHaren Myneni if (of_property_read_u32(dn, "ibm,842-coprocessor-type", &ct)) {
96432e091a6SHaren Myneni pr_err("ibm,842-coprocessor-type missing\n");
96532e091a6SHaren Myneni return -EINVAL;
96632e091a6SHaren Myneni }
96732e091a6SHaren Myneni
96832e091a6SHaren Myneni if (of_property_read_u32(dn, "ibm,842-coprocessor-instance", &ci)) {
96932e091a6SHaren Myneni pr_err("ibm,842-coprocessor-instance missing\n");
97032e091a6SHaren Myneni return -EINVAL;
97132e091a6SHaren Myneni }
97232e091a6SHaren Myneni
97332e091a6SHaren Myneni coproc = kzalloc(sizeof(*coproc), GFP_KERNEL);
97432e091a6SHaren Myneni if (!coproc)
97532e091a6SHaren Myneni return -ENOMEM;
97632e091a6SHaren Myneni
97732e091a6SHaren Myneni coproc->ct = ct;
97832e091a6SHaren Myneni coproc->ci = ci;
9794aebf3ceSHaren Myneni nx_add_coprocs_list(coproc, chip_id);
98032e091a6SHaren Myneni
98132e091a6SHaren Myneni pr_info("coprocessor found on chip %d, CT %d CI %d\n", chip_id, ct, ci);
98232e091a6SHaren Myneni
98332e091a6SHaren Myneni if (!nx842_ct)
98432e091a6SHaren Myneni nx842_ct = ct;
98532e091a6SHaren Myneni else if (nx842_ct != ct)
98632e091a6SHaren Myneni pr_err("NX842 chip %d, CT %d != first found CT %d\n",
98732e091a6SHaren Myneni chip_id, ct, nx842_ct);
98832e091a6SHaren Myneni
98932e091a6SHaren Myneni return 0;
99032e091a6SHaren Myneni }
99132e091a6SHaren Myneni
nx_delete_coprocs(void)9924aebf3ceSHaren Myneni static void nx_delete_coprocs(void)
99332e091a6SHaren Myneni {
9944aebf3ceSHaren Myneni struct nx_coproc *coproc, *n;
99532e091a6SHaren Myneni struct vas_window *txwin;
99632e091a6SHaren Myneni int i;
99732e091a6SHaren Myneni
99832e091a6SHaren Myneni /*
99932e091a6SHaren Myneni * close percpu txwins that are opened for the corresponding coproc.
100032e091a6SHaren Myneni */
100132e091a6SHaren Myneni for_each_possible_cpu(i) {
100232e091a6SHaren Myneni txwin = per_cpu(cpu_txwin, i);
100332e091a6SHaren Myneni if (txwin)
100432e091a6SHaren Myneni vas_win_close(txwin);
100532e091a6SHaren Myneni
10064aebf3ceSHaren Myneni per_cpu(cpu_txwin, i) = NULL;
100732e091a6SHaren Myneni }
100832e091a6SHaren Myneni
10094aebf3ceSHaren Myneni list_for_each_entry_safe(coproc, n, &nx_coprocs, list) {
101032e091a6SHaren Myneni if (coproc->vas.rxwin)
101132e091a6SHaren Myneni vas_win_close(coproc->vas.rxwin);
101232e091a6SHaren Myneni
101332e091a6SHaren Myneni list_del(&coproc->list);
101432e091a6SHaren Myneni kfree(coproc);
101532e091a6SHaren Myneni }
101632e091a6SHaren Myneni }
101732e091a6SHaren Myneni
101832e091a6SHaren Myneni static struct nx842_constraints nx842_powernv_constraints = {
101932e091a6SHaren Myneni .alignment = DDE_BUFFER_ALIGN,
102032e091a6SHaren Myneni .multiple = DDE_BUFFER_LAST_MULT,
102132e091a6SHaren Myneni .minimum = DDE_BUFFER_LAST_MULT,
102232e091a6SHaren Myneni .maximum = (DDL_LEN_MAX - 1) * PAGE_SIZE,
102332e091a6SHaren Myneni };
102432e091a6SHaren Myneni
102532e091a6SHaren Myneni static struct nx842_driver nx842_powernv_driver = {
102632e091a6SHaren Myneni .name = KBUILD_MODNAME,
102732e091a6SHaren Myneni .owner = THIS_MODULE,
102832e091a6SHaren Myneni .workmem_size = sizeof(struct nx842_workmem),
102932e091a6SHaren Myneni .constraints = &nx842_powernv_constraints,
103032e091a6SHaren Myneni .compress = nx842_powernv_compress,
103132e091a6SHaren Myneni .decompress = nx842_powernv_decompress,
103232e091a6SHaren Myneni };
103332e091a6SHaren Myneni
nx842_powernv_crypto_init(struct crypto_tfm * tfm)103432e091a6SHaren Myneni static int nx842_powernv_crypto_init(struct crypto_tfm *tfm)
103532e091a6SHaren Myneni {
103632e091a6SHaren Myneni return nx842_crypto_init(tfm, &nx842_powernv_driver);
103732e091a6SHaren Myneni }
103832e091a6SHaren Myneni
103932e091a6SHaren Myneni static struct crypto_alg nx842_powernv_alg = {
104032e091a6SHaren Myneni .cra_name = "842",
104132e091a6SHaren Myneni .cra_driver_name = "842-nx",
104232e091a6SHaren Myneni .cra_priority = 300,
104332e091a6SHaren Myneni .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
104432e091a6SHaren Myneni .cra_ctxsize = sizeof(struct nx842_crypto_ctx),
104532e091a6SHaren Myneni .cra_module = THIS_MODULE,
104632e091a6SHaren Myneni .cra_init = nx842_powernv_crypto_init,
104732e091a6SHaren Myneni .cra_exit = nx842_crypto_exit,
104832e091a6SHaren Myneni .cra_u = { .compress = {
104932e091a6SHaren Myneni .coa_compress = nx842_crypto_compress,
105032e091a6SHaren Myneni .coa_decompress = nx842_crypto_decompress } }
105132e091a6SHaren Myneni };
105232e091a6SHaren Myneni
nx_compress_powernv_init(void)10534aebf3ceSHaren Myneni static __init int nx_compress_powernv_init(void)
105432e091a6SHaren Myneni {
105532e091a6SHaren Myneni struct device_node *dn;
105632e091a6SHaren Myneni int ret;
105732e091a6SHaren Myneni
105832e091a6SHaren Myneni /* verify workmem size/align restrictions */
105932e091a6SHaren Myneni BUILD_BUG_ON(WORKMEM_ALIGN % CRB_ALIGN);
106032e091a6SHaren Myneni BUILD_BUG_ON(CRB_ALIGN % DDE_ALIGN);
106132e091a6SHaren Myneni BUILD_BUG_ON(CRB_SIZE % DDE_ALIGN);
106232e091a6SHaren Myneni /* verify buffer size/align restrictions */
106332e091a6SHaren Myneni BUILD_BUG_ON(PAGE_SIZE % DDE_BUFFER_ALIGN);
106432e091a6SHaren Myneni BUILD_BUG_ON(DDE_BUFFER_ALIGN % DDE_BUFFER_SIZE_MULT);
106532e091a6SHaren Myneni BUILD_BUG_ON(DDE_BUFFER_SIZE_MULT % DDE_BUFFER_LAST_MULT);
106632e091a6SHaren Myneni
106732e091a6SHaren Myneni for_each_compatible_node(dn, NULL, "ibm,power9-nx") {
10684aebf3ceSHaren Myneni ret = nx_powernv_probe_vas(dn);
106932e091a6SHaren Myneni if (ret) {
10704aebf3ceSHaren Myneni nx_delete_coprocs();
107132e091a6SHaren Myneni of_node_put(dn);
107232e091a6SHaren Myneni return ret;
107332e091a6SHaren Myneni }
107432e091a6SHaren Myneni }
107532e091a6SHaren Myneni
10764aebf3ceSHaren Myneni if (list_empty(&nx_coprocs)) {
107732e091a6SHaren Myneni for_each_compatible_node(dn, NULL, "ibm,power-nx")
107832e091a6SHaren Myneni nx842_powernv_probe(dn);
107932e091a6SHaren Myneni
108032e091a6SHaren Myneni if (!nx842_ct)
108132e091a6SHaren Myneni return -ENODEV;
108232e091a6SHaren Myneni
108332e091a6SHaren Myneni nx842_powernv_exec = nx842_exec_icswx;
108432e091a6SHaren Myneni } else {
10854aebf3ceSHaren Myneni /*
10861af11ae2SHaren Myneni * Register VAS user space API for NX GZIP so
10871af11ae2SHaren Myneni * that user space can use GZIP engine.
10881af11ae2SHaren Myneni * Using high FIFO priority for kernel requests and
10891af11ae2SHaren Myneni * normal FIFO priority is assigned for userspace.
10901af11ae2SHaren Myneni * 842 compression is supported only in kernel.
10911af11ae2SHaren Myneni */
109206c6fad9SHaren Myneni ret = vas_register_api_powernv(THIS_MODULE, VAS_COP_TYPE_GZIP,
10931af11ae2SHaren Myneni "nx-gzip");
10941af11ae2SHaren Myneni
10951af11ae2SHaren Myneni /*
10964aebf3ceSHaren Myneni * GZIP is not supported in kernel right now.
10974aebf3ceSHaren Myneni * So open tx windows only for 842.
10984aebf3ceSHaren Myneni */
10991af11ae2SHaren Myneni if (!ret)
11004aebf3ceSHaren Myneni ret = nx_open_percpu_txwins();
11011af11ae2SHaren Myneni
110232e091a6SHaren Myneni if (ret) {
11034aebf3ceSHaren Myneni nx_delete_coprocs();
110432e091a6SHaren Myneni return ret;
110532e091a6SHaren Myneni }
110632e091a6SHaren Myneni
110732e091a6SHaren Myneni nx842_powernv_exec = nx842_exec_vas;
110832e091a6SHaren Myneni }
110932e091a6SHaren Myneni
111032e091a6SHaren Myneni ret = crypto_register_alg(&nx842_powernv_alg);
111132e091a6SHaren Myneni if (ret) {
11124aebf3ceSHaren Myneni nx_delete_coprocs();
111332e091a6SHaren Myneni return ret;
111432e091a6SHaren Myneni }
111532e091a6SHaren Myneni
111632e091a6SHaren Myneni return 0;
111732e091a6SHaren Myneni }
11184aebf3ceSHaren Myneni module_init(nx_compress_powernv_init);
111932e091a6SHaren Myneni
nx_compress_powernv_exit(void)11204aebf3ceSHaren Myneni static void __exit nx_compress_powernv_exit(void)
112132e091a6SHaren Myneni {
11221af11ae2SHaren Myneni /*
11231af11ae2SHaren Myneni * GZIP engine is supported only in power9 or later and nx842_ct
11241af11ae2SHaren Myneni * is used on power8 (icswx).
11251af11ae2SHaren Myneni * VAS API for NX GZIP is registered during init for user space
11261af11ae2SHaren Myneni * use. So delete this API use for GZIP engine.
11271af11ae2SHaren Myneni */
11281af11ae2SHaren Myneni if (!nx842_ct)
112906c6fad9SHaren Myneni vas_unregister_api_powernv();
11301af11ae2SHaren Myneni
113132e091a6SHaren Myneni crypto_unregister_alg(&nx842_powernv_alg);
113232e091a6SHaren Myneni
11334aebf3ceSHaren Myneni nx_delete_coprocs();
113432e091a6SHaren Myneni }
11354aebf3ceSHaren Myneni module_exit(nx_compress_powernv_exit);
1136