blob: bf2823ceaf4e0593ae9fe1ee1f08d526c669c5fd [file] [log] [blame]
Dan Streetman7011a122015-05-07 13:49:17 -04001/*
2 * Driver frontend for IBM Power 842 compression accelerator
3 *
4 * Copyright (C) 2015 Dan Streetman, IBM Corp
5 *
6 * Designer of the Power data compression engine:
7 * Bulent Abali <abali@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22#include "nx-842.h"
23
24#define MODULE_NAME "nx-compress"
25MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
27MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
28
29/* Only one driver is expected, based on the HW platform */
30static struct nx842_driver *nx842_driver;
31static DEFINE_SPINLOCK(nx842_driver_lock); /* protects driver pointers */
32
33void nx842_register_driver(struct nx842_driver *driver)
34{
35 spin_lock(&nx842_driver_lock);
36
37 if (nx842_driver) {
38 pr_err("can't register driver %s, already using driver %s\n",
39 driver->owner->name, nx842_driver->owner->name);
40 } else {
41 pr_info("registering driver %s\n", driver->owner->name);
42 nx842_driver = driver;
43 }
44
45 spin_unlock(&nx842_driver_lock);
46}
47EXPORT_SYMBOL_GPL(nx842_register_driver);
48
49void nx842_unregister_driver(struct nx842_driver *driver)
50{
51 spin_lock(&nx842_driver_lock);
52
53 if (nx842_driver == driver) {
54 pr_info("unregistering driver %s\n", driver->owner->name);
55 nx842_driver = NULL;
56 } else if (nx842_driver) {
57 pr_err("can't unregister driver %s, using driver %s\n",
58 driver->owner->name, nx842_driver->owner->name);
59 } else {
60 pr_err("can't unregister driver %s, no driver in use\n",
61 driver->owner->name);
62 }
63
64 spin_unlock(&nx842_driver_lock);
65}
66EXPORT_SYMBOL_GPL(nx842_unregister_driver);
67
68static struct nx842_driver *get_driver(void)
69{
70 struct nx842_driver *driver = NULL;
71
72 spin_lock(&nx842_driver_lock);
73
74 driver = nx842_driver;
75
76 if (driver && !try_module_get(driver->owner))
77 driver = NULL;
78
79 spin_unlock(&nx842_driver_lock);
80
81 return driver;
82}
83
84static void put_driver(struct nx842_driver *driver)
85{
86 module_put(driver->owner);
87}
88
Dan Streetman959e6652015-05-07 13:49:18 -040089/**
90 * nx842_constraints
91 *
92 * This provides the driver's constraints. Different nx842 implementations
93 * may have varying requirements. The constraints are:
94 * @alignment: All buffers should be aligned to this
95 * @multiple: All buffer lengths should be a multiple of this
96 * @minimum: Buffer lengths must not be less than this amount
97 * @maximum: Buffer lengths must not be more than this amount
98 *
99 * The constraints apply to all buffers and lengths, both input and output,
100 * for both compression and decompression, except for the minimum which
101 * only applies to compression input and decompression output; the
102 * compressed data can be less than the minimum constraint. It can be
103 * assumed that compressed data will always adhere to the multiple
104 * constraint.
105 *
106 * The driver may succeed even if these constraints are violated;
107 * however the driver can return failure or suffer reduced performance
108 * if any constraint is not met.
109 */
110int nx842_constraints(struct nx842_constraints *c)
111{
112 struct nx842_driver *driver = get_driver();
113 int ret = 0;
114
115 if (!driver)
116 return -ENODEV;
117
118 BUG_ON(!c);
119 memcpy(c, driver->constraints, sizeof(*c));
120
121 put_driver(driver);
122
123 return ret;
124}
125EXPORT_SYMBOL_GPL(nx842_constraints);
126
Dan Streetman7011a122015-05-07 13:49:17 -0400127int nx842_compress(const unsigned char *in, unsigned int in_len,
128 unsigned char *out, unsigned int *out_len,
129 void *wrkmem)
130{
131 struct nx842_driver *driver = get_driver();
132 int ret;
133
134 if (!driver)
135 return -ENODEV;
136
137 ret = driver->compress(in, in_len, out, out_len, wrkmem);
138
139 put_driver(driver);
140
141 return ret;
142}
143EXPORT_SYMBOL_GPL(nx842_compress);
144
145int nx842_decompress(const unsigned char *in, unsigned int in_len,
146 unsigned char *out, unsigned int *out_len,
147 void *wrkmem)
148{
149 struct nx842_driver *driver = get_driver();
150 int ret;
151
152 if (!driver)
153 return -ENODEV;
154
155 ret = driver->decompress(in, in_len, out, out_len, wrkmem);
156
157 put_driver(driver);
158
159 return ret;
160}
161EXPORT_SYMBOL_GPL(nx842_decompress);
162
163static __init int nx842_init(void)
164{
165 pr_info("loading\n");
166
Dan Streetman99182a422015-05-07 13:49:19 -0400167 if (of_find_compatible_node(NULL, NULL, NX842_POWERNV_COMPAT_NAME))
168 request_module_nowait(NX842_POWERNV_MODULE_NAME);
169 else if (of_find_compatible_node(NULL, NULL, NX842_PSERIES_COMPAT_NAME))
Dan Streetman7011a122015-05-07 13:49:17 -0400170 request_module_nowait(NX842_PSERIES_MODULE_NAME);
171 else
172 pr_err("no nx842 driver found.\n");
173
174 pr_info("loaded\n");
175
176 return 0;
177}
178module_init(nx842_init);
179
180static void __exit nx842_exit(void)
181{
182 pr_info("NX842 unloaded\n");
183}
184module_exit(nx842_exit);