aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/crypto/nx/nx-842.c
blob: bf2823ceaf4e0593ae9fe1ee1f08d526c669c5fd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
 * Driver frontend for IBM Power 842 compression accelerator
 *
 * Copyright (C) 2015 Dan Streetman, IBM Corp
 *
 * Designer of the Power data compression engine:
 *   Bulent Abali <abali@us.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include "nx-842.h"

#define MODULE_NAME "nx-compress"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");

/* Only one driver is expected, based on the HW platform */
static struct nx842_driver *nx842_driver;
static DEFINE_SPINLOCK(nx842_driver_lock); /* protects driver pointers */

void nx842_register_driver(struct nx842_driver *driver)
{
	spin_lock(&nx842_driver_lock);

	if (nx842_driver) {
		pr_err("can't register driver %s, already using driver %s\n",
		       driver->owner->name, nx842_driver->owner->name);
	} else {
		pr_info("registering driver %s\n", driver->owner->name);
		nx842_driver = driver;
	}

	spin_unlock(&nx842_driver_lock);
}
EXPORT_SYMBOL_GPL(nx842_register_driver);

void nx842_unregister_driver(struct nx842_driver *driver)
{
	spin_lock(&nx842_driver_lock);

	if (nx842_driver == driver) {
		pr_info("unregistering driver %s\n", driver->owner->name);
		nx842_driver = NULL;
	} else if (nx842_driver) {
		pr_err("can't unregister driver %s, using driver %s\n",
		       driver->owner->name, nx842_driver->owner->name);
	} else {
		pr_err("can't unregister driver %s, no driver in use\n",
		       driver->owner->name);
	}

	spin_unlock(&nx842_driver_lock);
}
EXPORT_SYMBOL_GPL(nx842_unregister_driver);

static struct nx842_driver *get_driver(void)
{
	struct nx842_driver *driver = NULL;

	spin_lock(&nx842_driver_lock);

	driver = nx842_driver;

	if (driver && !try_module_get(driver->owner))
		driver = NULL;

	spin_unlock(&nx842_driver_lock);

	return driver;
}

static void put_driver(struct nx842_driver *driver)
{
	module_put(driver->owner);
}

/**
 * nx842_constraints
 *
 * This provides the driver's constraints.  Different nx842 implementations
 * may have varying requirements.  The constraints are:
 *   @alignment:	All buffers should be aligned to this
 *   @multiple:		All buffer lengths should be a multiple of this
 *   @minimum:		Buffer lengths must not be less than this amount
 *   @maximum:		Buffer lengths must not be more than this amount
 *
 * The constraints apply to all buffers and lengths, both input and output,
 * for both compression and decompression, except for the minimum which
 * only applies to compression input and decompression output; the
 * compressed data can be less than the minimum constraint.  It can be
 * assumed that compressed data will always adhere to the multiple
 * constraint.
 *
 * The driver may succeed even if these constraints are violated;
 * however the driver can return failure or suffer reduced performance
 * if any constraint is not met.
 */
int nx842_constraints(struct nx842_constraints *c)
{
	struct nx842_driver *driver = get_driver();
	int ret = 0;

	if (!driver)
		return -ENODEV;

	BUG_ON(!c);
	memcpy(c, driver->constraints, sizeof(*c));

	put_driver(driver);

	return ret;
}
EXPORT_SYMBOL_GPL(nx842_constraints);

int nx842_compress(const unsigned char *in, unsigned int in_len,
		   unsigned char *out, unsigned int *out_len,
		   void *wrkmem)
{
	struct nx842_driver *driver = get_driver();
	int ret;

	if (!driver)
		return -ENODEV;

	ret = driver->compress(in, in_len, out, out_len, wrkmem);

	put_driver(driver);

	return ret;
}
EXPORT_SYMBOL_GPL(nx842_compress);

int nx842_decompress(const unsigned char *in, unsigned int in_len,
		     unsigned char *out, unsigned int *out_len,
		     void *wrkmem)
{
	struct nx842_driver *driver = get_driver();
	int ret;

	if (!driver)
		return -ENODEV;

	ret = driver->decompress(in, in_len, out, out_len, wrkmem);

	put_driver(driver);

	return ret;
}
EXPORT_SYMBOL_GPL(nx842_decompress);

static __init int nx842_init(void)
{
	pr_info("loading\n");

	if (of_find_compatible_node(NULL, NULL, NX842_POWERNV_COMPAT_NAME))
		request_module_nowait(NX842_POWERNV_MODULE_NAME);
	else if (of_find_compatible_node(NULL, NULL, NX842_PSERIES_COMPAT_NAME))
		request_module_nowait(NX842_PSERIES_MODULE_NAME);
	else
		pr_err("no nx842 driver found.\n");

	pr_info("loaded\n");

	return 0;
}
module_init(nx842_init);

static void __exit nx842_exit(void)
{
	pr_info("NX842 unloaded\n");
}
module_exit(nx842_exit);