blob: f1f026e0b1890bd3198797ca21124ae559a719c9 [file] [log] [blame]
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001/*
Ralph Wuerthner54321142006-09-20 15:58:36 +02002 * zcrypt 2.1.0
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02003 *
Holger Dengler5e55a482012-08-28 16:45:36 +02004 * Copyright IBM Corp. 2001, 2012
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02005 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com)
7 * Cornelia Huck <cornelia.huck@de.ibm.com>
8 *
9 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
10 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
11 * Ralph Wuerthner <rwuerthn@de.ibm.com>
Holger Dengler5e55a482012-08-28 16:45:36 +020012 * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com>
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020013 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/miscdevice.h>
33#include <linux/fs.h>
34#include <linux/proc_fs.h>
Alexey Dobriyan34b92432010-02-26 22:37:50 +010035#include <linux/seq_file.h>
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020036#include <linux/compat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090037#include <linux/slab.h>
Arun Sharma600634972011-07-26 16:09:06 -070038#include <linux/atomic.h>
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020039#include <asm/uaccess.h>
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +020040#include <linux/hw_random.h>
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020041
42#include "zcrypt_api.h"
43
Felix Beck1749a812008-04-17 07:46:28 +020044/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020045 * Module description.
46 */
47MODULE_AUTHOR("IBM Corporation");
Holger Dengler5e55a482012-08-28 16:45:36 +020048MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \
49 "Copyright IBM Corp. 2001, 2012");
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020050MODULE_LICENSE("GPL");
51
52static DEFINE_SPINLOCK(zcrypt_device_lock);
53static LIST_HEAD(zcrypt_device_list);
54static int zcrypt_device_count = 0;
55static atomic_t zcrypt_open_count = ATOMIC_INIT(0);
56
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +020057static int zcrypt_rng_device_add(void);
58static void zcrypt_rng_device_remove(void);
59
Holger Dengler5e55a482012-08-28 16:45:36 +020060static DEFINE_SPINLOCK(zcrypt_ops_list_lock);
61static LIST_HEAD(zcrypt_ops_list);
62
Felix Beck1749a812008-04-17 07:46:28 +020063/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +020064 * Device attributes common for all crypto devices.
65 */
66static ssize_t zcrypt_type_show(struct device *dev,
67 struct device_attribute *attr, char *buf)
68{
69 struct zcrypt_device *zdev = to_ap_dev(dev)->private;
70 return snprintf(buf, PAGE_SIZE, "%s\n", zdev->type_string);
71}
72
73static DEVICE_ATTR(type, 0444, zcrypt_type_show, NULL);
74
75static ssize_t zcrypt_online_show(struct device *dev,
76 struct device_attribute *attr, char *buf)
77{
78 struct zcrypt_device *zdev = to_ap_dev(dev)->private;
79 return snprintf(buf, PAGE_SIZE, "%d\n", zdev->online);
80}
81
82static ssize_t zcrypt_online_store(struct device *dev,
83 struct device_attribute *attr,
84 const char *buf, size_t count)
85{
86 struct zcrypt_device *zdev = to_ap_dev(dev)->private;
87 int online;
88
89 if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
90 return -EINVAL;
91 zdev->online = online;
92 if (!online)
93 ap_flush_queue(zdev->ap_dev);
94 return count;
95}
96
97static DEVICE_ATTR(online, 0644, zcrypt_online_show, zcrypt_online_store);
98
99static struct attribute * zcrypt_device_attrs[] = {
100 &dev_attr_type.attr,
101 &dev_attr_online.attr,
102 NULL,
103};
104
105static struct attribute_group zcrypt_device_attr_group = {
106 .attrs = zcrypt_device_attrs,
107};
108
109/**
Felix Beck1749a812008-04-17 07:46:28 +0200110 * __zcrypt_increase_preference(): Increase preference of a crypto device.
111 * @zdev: Pointer the crypto device
112 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200113 * Move the device towards the head of the device list.
114 * Need to be called while holding the zcrypt device list lock.
115 * Note: cards with speed_rating of 0 are kept at the end of the list.
116 */
117static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
118{
119 struct zcrypt_device *tmp;
120 struct list_head *l;
121
122 if (zdev->speed_rating == 0)
123 return;
124 for (l = zdev->list.prev; l != &zcrypt_device_list; l = l->prev) {
125 tmp = list_entry(l, struct zcrypt_device, list);
126 if ((tmp->request_count + 1) * tmp->speed_rating <=
127 (zdev->request_count + 1) * zdev->speed_rating &&
128 tmp->speed_rating != 0)
129 break;
130 }
131 if (l == zdev->list.prev)
132 return;
133 /* Move zdev behind l */
Eric Sesterhenn1fbc9f42009-03-26 15:24:39 +0100134 list_move(&zdev->list, l);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200135}
136
137/**
Felix Beck1749a812008-04-17 07:46:28 +0200138 * __zcrypt_decrease_preference(): Decrease preference of a crypto device.
139 * @zdev: Pointer to a crypto device.
140 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200141 * Move the device towards the tail of the device list.
142 * Need to be called while holding the zcrypt device list lock.
143 * Note: cards with speed_rating of 0 are kept at the end of the list.
144 */
145static void __zcrypt_decrease_preference(struct zcrypt_device *zdev)
146{
147 struct zcrypt_device *tmp;
148 struct list_head *l;
149
150 if (zdev->speed_rating == 0)
151 return;
152 for (l = zdev->list.next; l != &zcrypt_device_list; l = l->next) {
153 tmp = list_entry(l, struct zcrypt_device, list);
154 if ((tmp->request_count + 1) * tmp->speed_rating >
155 (zdev->request_count + 1) * zdev->speed_rating ||
156 tmp->speed_rating == 0)
157 break;
158 }
159 if (l == zdev->list.next)
160 return;
161 /* Move zdev before l */
Eric Sesterhenn1fbc9f42009-03-26 15:24:39 +0100162 list_move_tail(&zdev->list, l);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200163}
164
165static void zcrypt_device_release(struct kref *kref)
166{
167 struct zcrypt_device *zdev =
168 container_of(kref, struct zcrypt_device, refcount);
169 zcrypt_device_free(zdev);
170}
171
172void zcrypt_device_get(struct zcrypt_device *zdev)
173{
174 kref_get(&zdev->refcount);
175}
176EXPORT_SYMBOL(zcrypt_device_get);
177
178int zcrypt_device_put(struct zcrypt_device *zdev)
179{
180 return kref_put(&zdev->refcount, zcrypt_device_release);
181}
182EXPORT_SYMBOL(zcrypt_device_put);
183
184struct zcrypt_device *zcrypt_device_alloc(size_t max_response_size)
185{
186 struct zcrypt_device *zdev;
187
188 zdev = kzalloc(sizeof(struct zcrypt_device), GFP_KERNEL);
189 if (!zdev)
190 return NULL;
191 zdev->reply.message = kmalloc(max_response_size, GFP_KERNEL);
192 if (!zdev->reply.message)
193 goto out_free;
194 zdev->reply.length = max_response_size;
195 spin_lock_init(&zdev->lock);
196 INIT_LIST_HEAD(&zdev->list);
197 return zdev;
198
199out_free:
200 kfree(zdev);
201 return NULL;
202}
203EXPORT_SYMBOL(zcrypt_device_alloc);
204
205void zcrypt_device_free(struct zcrypt_device *zdev)
206{
207 kfree(zdev->reply.message);
208 kfree(zdev);
209}
210EXPORT_SYMBOL(zcrypt_device_free);
211
212/**
Felix Beck1749a812008-04-17 07:46:28 +0200213 * zcrypt_device_register() - Register a crypto device.
214 * @zdev: Pointer to a crypto device
215 *
216 * Register a crypto device. Returns 0 if successful.
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200217 */
218int zcrypt_device_register(struct zcrypt_device *zdev)
219{
220 int rc;
221
Holger Dengler5e55a482012-08-28 16:45:36 +0200222 if (!zdev->ops)
223 return -ENODEV;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200224 rc = sysfs_create_group(&zdev->ap_dev->device.kobj,
225 &zcrypt_device_attr_group);
226 if (rc)
227 goto out;
228 get_device(&zdev->ap_dev->device);
229 kref_init(&zdev->refcount);
230 spin_lock_bh(&zcrypt_device_lock);
231 zdev->online = 1; /* New devices are online by default. */
232 list_add_tail(&zdev->list, &zcrypt_device_list);
233 __zcrypt_increase_preference(zdev);
234 zcrypt_device_count++;
235 spin_unlock_bh(&zcrypt_device_lock);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200236 if (zdev->ops->rng) {
237 rc = zcrypt_rng_device_add();
238 if (rc)
239 goto out_unregister;
240 }
241 return 0;
242
243out_unregister:
244 spin_lock_bh(&zcrypt_device_lock);
245 zcrypt_device_count--;
246 list_del_init(&zdev->list);
247 spin_unlock_bh(&zcrypt_device_lock);
248 sysfs_remove_group(&zdev->ap_dev->device.kobj,
249 &zcrypt_device_attr_group);
250 put_device(&zdev->ap_dev->device);
251 zcrypt_device_put(zdev);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200252out:
253 return rc;
254}
255EXPORT_SYMBOL(zcrypt_device_register);
256
257/**
Felix Beck1749a812008-04-17 07:46:28 +0200258 * zcrypt_device_unregister(): Unregister a crypto device.
259 * @zdev: Pointer to crypto device
260 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200261 * Unregister a crypto device.
262 */
263void zcrypt_device_unregister(struct zcrypt_device *zdev)
264{
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200265 if (zdev->ops->rng)
266 zcrypt_rng_device_remove();
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200267 spin_lock_bh(&zcrypt_device_lock);
268 zcrypt_device_count--;
269 list_del_init(&zdev->list);
270 spin_unlock_bh(&zcrypt_device_lock);
271 sysfs_remove_group(&zdev->ap_dev->device.kobj,
272 &zcrypt_device_attr_group);
273 put_device(&zdev->ap_dev->device);
274 zcrypt_device_put(zdev);
275}
276EXPORT_SYMBOL(zcrypt_device_unregister);
277
Holger Dengler5e55a482012-08-28 16:45:36 +0200278void zcrypt_msgtype_register(struct zcrypt_ops *zops)
279{
280 if (zops->owner) {
281 spin_lock_bh(&zcrypt_ops_list_lock);
282 list_add_tail(&zops->list, &zcrypt_ops_list);
283 spin_unlock_bh(&zcrypt_ops_list_lock);
284 }
285}
286EXPORT_SYMBOL(zcrypt_msgtype_register);
287
288void zcrypt_msgtype_unregister(struct zcrypt_ops *zops)
289{
290 spin_lock_bh(&zcrypt_ops_list_lock);
291 list_del_init(&zops->list);
292 spin_unlock_bh(&zcrypt_ops_list_lock);
293}
294EXPORT_SYMBOL(zcrypt_msgtype_unregister);
295
296static inline
297struct zcrypt_ops *__ops_lookup(unsigned char *name, int variant)
298{
299 struct zcrypt_ops *zops;
300 int found = 0;
301
302 spin_lock_bh(&zcrypt_ops_list_lock);
303 list_for_each_entry(zops, &zcrypt_ops_list, list) {
304 if ((zops->variant == variant) &&
305 (!strncmp(zops->owner->name, name, MODULE_NAME_LEN))) {
306 found = 1;
307 break;
308 }
309 }
310 spin_unlock_bh(&zcrypt_ops_list_lock);
311
312 if (!found)
313 return NULL;
314 return zops;
315}
316
317struct zcrypt_ops *zcrypt_msgtype_request(unsigned char *name, int variant)
318{
319 struct zcrypt_ops *zops = NULL;
320
321 zops = __ops_lookup(name, variant);
322 if (!zops) {
323 request_module(name);
324 zops = __ops_lookup(name, variant);
325 }
326 if ((!zops) || (!try_module_get(zops->owner)))
327 return NULL;
328 return zops;
329}
330EXPORT_SYMBOL(zcrypt_msgtype_request);
331
332void zcrypt_msgtype_release(struct zcrypt_ops *zops)
333{
334 if (zops)
335 module_put(zops->owner);
336}
337EXPORT_SYMBOL(zcrypt_msgtype_release);
338
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200339/**
Felix Beck1749a812008-04-17 07:46:28 +0200340 * zcrypt_read (): Not supported beyond zcrypt 1.3.1.
341 *
342 * This function is not supported beyond zcrypt 1.3.1.
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200343 */
344static ssize_t zcrypt_read(struct file *filp, char __user *buf,
345 size_t count, loff_t *f_pos)
346{
347 return -EPERM;
348}
349
350/**
Felix Beck1749a812008-04-17 07:46:28 +0200351 * zcrypt_write(): Not allowed.
352 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200353 * Write is is not allowed
354 */
355static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
356 size_t count, loff_t *f_pos)
357{
358 return -EPERM;
359}
360
361/**
Felix Beck1749a812008-04-17 07:46:28 +0200362 * zcrypt_open(): Count number of users.
363 *
364 * Device open function to count number of users.
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200365 */
366static int zcrypt_open(struct inode *inode, struct file *filp)
367{
368 atomic_inc(&zcrypt_open_count);
Martin Schwidefsky58ea91c2010-05-17 10:00:07 +0200369 return nonseekable_open(inode, filp);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200370}
371
Felix Beck1749a812008-04-17 07:46:28 +0200372/**
373 * zcrypt_release(): Count number of users.
374 *
375 * Device close function to count number of users.
376 */
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200377static int zcrypt_release(struct inode *inode, struct file *filp)
378{
379 atomic_dec(&zcrypt_open_count);
380 return 0;
381}
382
Felix Beck1749a812008-04-17 07:46:28 +0200383/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200384 * zcrypt ioctls.
385 */
386static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
387{
388 struct zcrypt_device *zdev;
389 int rc;
390
391 if (mex->outputdatalength < mex->inputdatalength)
392 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200393 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200394 * As long as outputdatalength is big enough, we can set the
395 * outputdatalength equal to the inputdatalength, since that is the
396 * number of bytes we will copy in any case
397 */
398 mex->outputdatalength = mex->inputdatalength;
399
400 spin_lock_bh(&zcrypt_device_lock);
401 list_for_each_entry(zdev, &zcrypt_device_list, list) {
402 if (!zdev->online ||
403 !zdev->ops->rsa_modexpo ||
404 zdev->min_mod_size > mex->inputdatalength ||
405 zdev->max_mod_size < mex->inputdatalength)
406 continue;
407 zcrypt_device_get(zdev);
408 get_device(&zdev->ap_dev->device);
409 zdev->request_count++;
410 __zcrypt_decrease_preference(zdev);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200411 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100412 spin_unlock_bh(&zcrypt_device_lock);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200413 rc = zdev->ops->rsa_modexpo(zdev, mex);
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100414 spin_lock_bh(&zcrypt_device_lock);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200415 module_put(zdev->ap_dev->drv->driver.owner);
416 }
417 else
418 rc = -EAGAIN;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200419 zdev->request_count--;
420 __zcrypt_increase_preference(zdev);
421 put_device(&zdev->ap_dev->device);
422 zcrypt_device_put(zdev);
423 spin_unlock_bh(&zcrypt_device_lock);
424 return rc;
425 }
426 spin_unlock_bh(&zcrypt_device_lock);
427 return -ENODEV;
428}
429
430static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
431{
432 struct zcrypt_device *zdev;
433 unsigned long long z1, z2, z3;
434 int rc, copied;
435
436 if (crt->outputdatalength < crt->inputdatalength ||
437 (crt->inputdatalength & 1))
438 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200439 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200440 * As long as outputdatalength is big enough, we can set the
441 * outputdatalength equal to the inputdatalength, since that is the
442 * number of bytes we will copy in any case
443 */
444 crt->outputdatalength = crt->inputdatalength;
445
446 copied = 0;
447 restart:
448 spin_lock_bh(&zcrypt_device_lock);
449 list_for_each_entry(zdev, &zcrypt_device_list, list) {
450 if (!zdev->online ||
451 !zdev->ops->rsa_modexpo_crt ||
452 zdev->min_mod_size > crt->inputdatalength ||
453 zdev->max_mod_size < crt->inputdatalength)
454 continue;
455 if (zdev->short_crt && crt->inputdatalength > 240) {
Felix Beck1749a812008-04-17 07:46:28 +0200456 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200457 * Check inputdata for leading zeros for cards
458 * that can't handle np_prime, bp_key, or
459 * u_mult_inv > 128 bytes.
460 */
461 if (copied == 0) {
Heiko Carstens0648f562010-01-13 20:44:43 +0100462 unsigned int len;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200463 spin_unlock_bh(&zcrypt_device_lock);
Felix Beck078f8ec2011-01-05 12:47:48 +0100464 /* len is max 256 / 2 - 120 = 8
465 * For bigger device just assume len of leading
466 * 0s is 8 as stated in the requirements for
467 * ica_rsa_modexpo_crt struct in zcrypt.h.
468 */
469 if (crt->inputdatalength <= 256)
470 len = crt->inputdatalength / 2 - 120;
471 else
472 len = 8;
Heiko Carstens0648f562010-01-13 20:44:43 +0100473 if (len > sizeof(z1))
474 return -EFAULT;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200475 z1 = z2 = z3 = 0;
476 if (copy_from_user(&z1, crt->np_prime, len) ||
477 copy_from_user(&z2, crt->bp_key, len) ||
478 copy_from_user(&z3, crt->u_mult_inv, len))
479 return -EFAULT;
Felix Beck078f8ec2011-01-05 12:47:48 +0100480 z1 = z2 = z3 = 0;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200481 copied = 1;
Felix Beck1749a812008-04-17 07:46:28 +0200482 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200483 * We have to restart device lookup -
484 * the device list may have changed by now.
485 */
486 goto restart;
487 }
488 if (z1 != 0ULL || z2 != 0ULL || z3 != 0ULL)
489 /* The device can't handle this request. */
490 continue;
491 }
492 zcrypt_device_get(zdev);
493 get_device(&zdev->ap_dev->device);
494 zdev->request_count++;
495 __zcrypt_decrease_preference(zdev);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200496 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100497 spin_unlock_bh(&zcrypt_device_lock);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200498 rc = zdev->ops->rsa_modexpo_crt(zdev, crt);
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100499 spin_lock_bh(&zcrypt_device_lock);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200500 module_put(zdev->ap_dev->drv->driver.owner);
501 }
502 else
503 rc = -EAGAIN;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200504 zdev->request_count--;
505 __zcrypt_increase_preference(zdev);
506 put_device(&zdev->ap_dev->device);
507 zcrypt_device_put(zdev);
508 spin_unlock_bh(&zcrypt_device_lock);
509 return rc;
510 }
511 spin_unlock_bh(&zcrypt_device_lock);
512 return -ENODEV;
513}
514
Ralph Wuerthner54321142006-09-20 15:58:36 +0200515static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
516{
517 struct zcrypt_device *zdev;
518 int rc;
519
520 spin_lock_bh(&zcrypt_device_lock);
521 list_for_each_entry(zdev, &zcrypt_device_list, list) {
522 if (!zdev->online || !zdev->ops->send_cprb ||
523 (xcRB->user_defined != AUTOSELECT &&
524 AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)
525 )
526 continue;
527 zcrypt_device_get(zdev);
528 get_device(&zdev->ap_dev->device);
529 zdev->request_count++;
530 __zcrypt_decrease_preference(zdev);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200531 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100532 spin_unlock_bh(&zcrypt_device_lock);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200533 rc = zdev->ops->send_cprb(zdev, xcRB);
Ralph Wuerthner43a867a2007-03-19 13:19:19 +0100534 spin_lock_bh(&zcrypt_device_lock);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200535 module_put(zdev->ap_dev->drv->driver.owner);
536 }
537 else
538 rc = -EAGAIN;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200539 zdev->request_count--;
540 __zcrypt_increase_preference(zdev);
541 put_device(&zdev->ap_dev->device);
542 zcrypt_device_put(zdev);
543 spin_unlock_bh(&zcrypt_device_lock);
544 return rc;
545 }
546 spin_unlock_bh(&zcrypt_device_lock);
547 return -ENODEV;
548}
549
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200550static long zcrypt_rng(char *buffer)
551{
552 struct zcrypt_device *zdev;
553 int rc;
554
555 spin_lock_bh(&zcrypt_device_lock);
556 list_for_each_entry(zdev, &zcrypt_device_list, list) {
557 if (!zdev->online || !zdev->ops->rng)
558 continue;
559 zcrypt_device_get(zdev);
560 get_device(&zdev->ap_dev->device);
561 zdev->request_count++;
562 __zcrypt_decrease_preference(zdev);
563 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
564 spin_unlock_bh(&zcrypt_device_lock);
565 rc = zdev->ops->rng(zdev, buffer);
566 spin_lock_bh(&zcrypt_device_lock);
567 module_put(zdev->ap_dev->drv->driver.owner);
568 } else
569 rc = -EAGAIN;
570 zdev->request_count--;
571 __zcrypt_increase_preference(zdev);
572 put_device(&zdev->ap_dev->device);
573 zcrypt_device_put(zdev);
574 spin_unlock_bh(&zcrypt_device_lock);
575 return rc;
576 }
577 spin_unlock_bh(&zcrypt_device_lock);
578 return -ENODEV;
579}
580
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200581static void zcrypt_status_mask(char status[AP_DEVICES])
582{
583 struct zcrypt_device *zdev;
584
585 memset(status, 0, sizeof(char) * AP_DEVICES);
586 spin_lock_bh(&zcrypt_device_lock);
587 list_for_each_entry(zdev, &zcrypt_device_list, list)
588 status[AP_QID_DEVICE(zdev->ap_dev->qid)] =
589 zdev->online ? zdev->user_space_type : 0x0d;
590 spin_unlock_bh(&zcrypt_device_lock);
591}
592
593static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES])
594{
595 struct zcrypt_device *zdev;
596
597 memset(qdepth, 0, sizeof(char) * AP_DEVICES);
598 spin_lock_bh(&zcrypt_device_lock);
599 list_for_each_entry(zdev, &zcrypt_device_list, list) {
600 spin_lock(&zdev->ap_dev->lock);
601 qdepth[AP_QID_DEVICE(zdev->ap_dev->qid)] =
602 zdev->ap_dev->pendingq_count +
603 zdev->ap_dev->requestq_count;
604 spin_unlock(&zdev->ap_dev->lock);
605 }
606 spin_unlock_bh(&zcrypt_device_lock);
607}
608
609static void zcrypt_perdev_reqcnt(int reqcnt[AP_DEVICES])
610{
611 struct zcrypt_device *zdev;
612
613 memset(reqcnt, 0, sizeof(int) * AP_DEVICES);
614 spin_lock_bh(&zcrypt_device_lock);
615 list_for_each_entry(zdev, &zcrypt_device_list, list) {
616 spin_lock(&zdev->ap_dev->lock);
617 reqcnt[AP_QID_DEVICE(zdev->ap_dev->qid)] =
618 zdev->ap_dev->total_request_count;
619 spin_unlock(&zdev->ap_dev->lock);
620 }
621 spin_unlock_bh(&zcrypt_device_lock);
622}
623
624static int zcrypt_pendingq_count(void)
625{
626 struct zcrypt_device *zdev;
627 int pendingq_count = 0;
628
629 spin_lock_bh(&zcrypt_device_lock);
630 list_for_each_entry(zdev, &zcrypt_device_list, list) {
631 spin_lock(&zdev->ap_dev->lock);
632 pendingq_count += zdev->ap_dev->pendingq_count;
633 spin_unlock(&zdev->ap_dev->lock);
634 }
635 spin_unlock_bh(&zcrypt_device_lock);
636 return pendingq_count;
637}
638
639static int zcrypt_requestq_count(void)
640{
641 struct zcrypt_device *zdev;
642 int requestq_count = 0;
643
644 spin_lock_bh(&zcrypt_device_lock);
645 list_for_each_entry(zdev, &zcrypt_device_list, list) {
646 spin_lock(&zdev->ap_dev->lock);
647 requestq_count += zdev->ap_dev->requestq_count;
648 spin_unlock(&zdev->ap_dev->lock);
649 }
650 spin_unlock_bh(&zcrypt_device_lock);
651 return requestq_count;
652}
653
654static int zcrypt_count_type(int type)
655{
656 struct zcrypt_device *zdev;
657 int device_count = 0;
658
659 spin_lock_bh(&zcrypt_device_lock);
660 list_for_each_entry(zdev, &zcrypt_device_list, list)
661 if (zdev->user_space_type == type)
662 device_count++;
663 spin_unlock_bh(&zcrypt_device_lock);
664 return device_count;
665}
666
667/**
Felix Beck1749a812008-04-17 07:46:28 +0200668 * zcrypt_ica_status(): Old, depracted combi status call.
669 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200670 * Old, deprecated combi status call.
671 */
672static long zcrypt_ica_status(struct file *filp, unsigned long arg)
673{
674 struct ica_z90_status *pstat;
675 int ret;
676
677 pstat = kzalloc(sizeof(*pstat), GFP_KERNEL);
678 if (!pstat)
679 return -ENOMEM;
680 pstat->totalcount = zcrypt_device_count;
681 pstat->leedslitecount = zcrypt_count_type(ZCRYPT_PCICA);
682 pstat->leeds2count = zcrypt_count_type(ZCRYPT_PCICC);
683 pstat->requestqWaitCount = zcrypt_requestq_count();
684 pstat->pendingqWaitCount = zcrypt_pendingq_count();
685 pstat->totalOpenCount = atomic_read(&zcrypt_open_count);
686 pstat->cryptoDomain = ap_domain_index;
687 zcrypt_status_mask(pstat->status);
688 zcrypt_qdepth_mask(pstat->qdepth);
689 ret = 0;
690 if (copy_to_user((void __user *) arg, pstat, sizeof(*pstat)))
691 ret = -EFAULT;
692 kfree(pstat);
693 return ret;
694}
695
696static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
697 unsigned long arg)
698{
699 int rc;
700
701 switch (cmd) {
702 case ICARSAMODEXPO: {
703 struct ica_rsa_modexpo __user *umex = (void __user *) arg;
704 struct ica_rsa_modexpo mex;
705 if (copy_from_user(&mex, umex, sizeof(mex)))
706 return -EFAULT;
707 do {
708 rc = zcrypt_rsa_modexpo(&mex);
709 } while (rc == -EAGAIN);
710 if (rc)
711 return rc;
712 return put_user(mex.outputdatalength, &umex->outputdatalength);
713 }
714 case ICARSACRT: {
715 struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg;
716 struct ica_rsa_modexpo_crt crt;
717 if (copy_from_user(&crt, ucrt, sizeof(crt)))
718 return -EFAULT;
719 do {
720 rc = zcrypt_rsa_crt(&crt);
721 } while (rc == -EAGAIN);
722 if (rc)
723 return rc;
724 return put_user(crt.outputdatalength, &ucrt->outputdatalength);
725 }
Ralph Wuerthner54321142006-09-20 15:58:36 +0200726 case ZSECSENDCPRB: {
727 struct ica_xcRB __user *uxcRB = (void __user *) arg;
728 struct ica_xcRB xcRB;
729 if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB)))
730 return -EFAULT;
731 do {
732 rc = zcrypt_send_cprb(&xcRB);
733 } while (rc == -EAGAIN);
734 if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
735 return -EFAULT;
736 return rc;
737 }
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200738 case Z90STAT_STATUS_MASK: {
739 char status[AP_DEVICES];
740 zcrypt_status_mask(status);
741 if (copy_to_user((char __user *) arg, status,
742 sizeof(char) * AP_DEVICES))
743 return -EFAULT;
744 return 0;
745 }
746 case Z90STAT_QDEPTH_MASK: {
747 char qdepth[AP_DEVICES];
748 zcrypt_qdepth_mask(qdepth);
749 if (copy_to_user((char __user *) arg, qdepth,
750 sizeof(char) * AP_DEVICES))
751 return -EFAULT;
752 return 0;
753 }
754 case Z90STAT_PERDEV_REQCNT: {
755 int reqcnt[AP_DEVICES];
756 zcrypt_perdev_reqcnt(reqcnt);
757 if (copy_to_user((int __user *) arg, reqcnt,
758 sizeof(int) * AP_DEVICES))
759 return -EFAULT;
760 return 0;
761 }
762 case Z90STAT_REQUESTQ_COUNT:
763 return put_user(zcrypt_requestq_count(), (int __user *) arg);
764 case Z90STAT_PENDINGQ_COUNT:
765 return put_user(zcrypt_pendingq_count(), (int __user *) arg);
766 case Z90STAT_TOTALOPEN_COUNT:
767 return put_user(atomic_read(&zcrypt_open_count),
768 (int __user *) arg);
769 case Z90STAT_DOMAIN_INDEX:
770 return put_user(ap_domain_index, (int __user *) arg);
Felix Beck1749a812008-04-17 07:46:28 +0200771 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200772 * Deprecated ioctls. Don't add another device count ioctl,
773 * you can count them yourself in the user space with the
774 * output of the Z90STAT_STATUS_MASK ioctl.
775 */
776 case ICAZ90STATUS:
777 return zcrypt_ica_status(filp, arg);
778 case Z90STAT_TOTALCOUNT:
779 return put_user(zcrypt_device_count, (int __user *) arg);
780 case Z90STAT_PCICACOUNT:
781 return put_user(zcrypt_count_type(ZCRYPT_PCICA),
782 (int __user *) arg);
783 case Z90STAT_PCICCCOUNT:
784 return put_user(zcrypt_count_type(ZCRYPT_PCICC),
785 (int __user *) arg);
786 case Z90STAT_PCIXCCMCL2COUNT:
787 return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2),
788 (int __user *) arg);
789 case Z90STAT_PCIXCCMCL3COUNT:
790 return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL3),
791 (int __user *) arg);
792 case Z90STAT_PCIXCCCOUNT:
793 return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2) +
794 zcrypt_count_type(ZCRYPT_PCIXCC_MCL3),
795 (int __user *) arg);
796 case Z90STAT_CEX2CCOUNT:
797 return put_user(zcrypt_count_type(ZCRYPT_CEX2C),
798 (int __user *) arg);
799 case Z90STAT_CEX2ACOUNT:
800 return put_user(zcrypt_count_type(ZCRYPT_CEX2A),
801 (int __user *) arg);
802 default:
803 /* unknown ioctl number */
804 return -ENOIOCTLCMD;
805 }
806}
807
808#ifdef CONFIG_COMPAT
Felix Beck1749a812008-04-17 07:46:28 +0200809/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200810 * ioctl32 conversion routines
811 */
812struct compat_ica_rsa_modexpo {
813 compat_uptr_t inputdata;
814 unsigned int inputdatalength;
815 compat_uptr_t outputdata;
816 unsigned int outputdatalength;
817 compat_uptr_t b_key;
818 compat_uptr_t n_modulus;
819};
820
821static long trans_modexpo32(struct file *filp, unsigned int cmd,
822 unsigned long arg)
823{
824 struct compat_ica_rsa_modexpo __user *umex32 = compat_ptr(arg);
825 struct compat_ica_rsa_modexpo mex32;
826 struct ica_rsa_modexpo mex64;
827 long rc;
828
829 if (copy_from_user(&mex32, umex32, sizeof(mex32)))
830 return -EFAULT;
831 mex64.inputdata = compat_ptr(mex32.inputdata);
832 mex64.inputdatalength = mex32.inputdatalength;
833 mex64.outputdata = compat_ptr(mex32.outputdata);
834 mex64.outputdatalength = mex32.outputdatalength;
835 mex64.b_key = compat_ptr(mex32.b_key);
836 mex64.n_modulus = compat_ptr(mex32.n_modulus);
837 do {
838 rc = zcrypt_rsa_modexpo(&mex64);
839 } while (rc == -EAGAIN);
840 if (!rc)
841 rc = put_user(mex64.outputdatalength,
842 &umex32->outputdatalength);
843 return rc;
844}
845
846struct compat_ica_rsa_modexpo_crt {
847 compat_uptr_t inputdata;
848 unsigned int inputdatalength;
849 compat_uptr_t outputdata;
850 unsigned int outputdatalength;
851 compat_uptr_t bp_key;
852 compat_uptr_t bq_key;
853 compat_uptr_t np_prime;
854 compat_uptr_t nq_prime;
855 compat_uptr_t u_mult_inv;
856};
857
858static long trans_modexpo_crt32(struct file *filp, unsigned int cmd,
859 unsigned long arg)
860{
861 struct compat_ica_rsa_modexpo_crt __user *ucrt32 = compat_ptr(arg);
862 struct compat_ica_rsa_modexpo_crt crt32;
863 struct ica_rsa_modexpo_crt crt64;
864 long rc;
865
866 if (copy_from_user(&crt32, ucrt32, sizeof(crt32)))
867 return -EFAULT;
868 crt64.inputdata = compat_ptr(crt32.inputdata);
869 crt64.inputdatalength = crt32.inputdatalength;
870 crt64.outputdata= compat_ptr(crt32.outputdata);
871 crt64.outputdatalength = crt32.outputdatalength;
872 crt64.bp_key = compat_ptr(crt32.bp_key);
873 crt64.bq_key = compat_ptr(crt32.bq_key);
874 crt64.np_prime = compat_ptr(crt32.np_prime);
875 crt64.nq_prime = compat_ptr(crt32.nq_prime);
876 crt64.u_mult_inv = compat_ptr(crt32.u_mult_inv);
877 do {
878 rc = zcrypt_rsa_crt(&crt64);
879 } while (rc == -EAGAIN);
880 if (!rc)
881 rc = put_user(crt64.outputdatalength,
882 &ucrt32->outputdatalength);
883 return rc;
884}
885
Ralph Wuerthner54321142006-09-20 15:58:36 +0200886struct compat_ica_xcRB {
887 unsigned short agent_ID;
888 unsigned int user_defined;
889 unsigned short request_ID;
890 unsigned int request_control_blk_length;
891 unsigned char padding1[16 - sizeof (compat_uptr_t)];
892 compat_uptr_t request_control_blk_addr;
893 unsigned int request_data_length;
894 char padding2[16 - sizeof (compat_uptr_t)];
895 compat_uptr_t request_data_address;
896 unsigned int reply_control_blk_length;
897 char padding3[16 - sizeof (compat_uptr_t)];
898 compat_uptr_t reply_control_blk_addr;
899 unsigned int reply_data_length;
900 char padding4[16 - sizeof (compat_uptr_t)];
901 compat_uptr_t reply_data_addr;
902 unsigned short priority_window;
903 unsigned int status;
904} __attribute__((packed));
905
906static long trans_xcRB32(struct file *filp, unsigned int cmd,
907 unsigned long arg)
908{
909 struct compat_ica_xcRB __user *uxcRB32 = compat_ptr(arg);
910 struct compat_ica_xcRB xcRB32;
911 struct ica_xcRB xcRB64;
912 long rc;
913
914 if (copy_from_user(&xcRB32, uxcRB32, sizeof(xcRB32)))
915 return -EFAULT;
916 xcRB64.agent_ID = xcRB32.agent_ID;
917 xcRB64.user_defined = xcRB32.user_defined;
918 xcRB64.request_ID = xcRB32.request_ID;
919 xcRB64.request_control_blk_length =
920 xcRB32.request_control_blk_length;
921 xcRB64.request_control_blk_addr =
922 compat_ptr(xcRB32.request_control_blk_addr);
923 xcRB64.request_data_length =
924 xcRB32.request_data_length;
925 xcRB64.request_data_address =
926 compat_ptr(xcRB32.request_data_address);
927 xcRB64.reply_control_blk_length =
928 xcRB32.reply_control_blk_length;
929 xcRB64.reply_control_blk_addr =
930 compat_ptr(xcRB32.reply_control_blk_addr);
931 xcRB64.reply_data_length = xcRB32.reply_data_length;
932 xcRB64.reply_data_addr =
933 compat_ptr(xcRB32.reply_data_addr);
934 xcRB64.priority_window = xcRB32.priority_window;
935 xcRB64.status = xcRB32.status;
936 do {
937 rc = zcrypt_send_cprb(&xcRB64);
938 } while (rc == -EAGAIN);
939 xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length;
940 xcRB32.reply_data_length = xcRB64.reply_data_length;
941 xcRB32.status = xcRB64.status;
942 if (copy_to_user(uxcRB32, &xcRB32, sizeof(xcRB32)))
943 return -EFAULT;
944 return rc;
945}
946
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100947static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200948 unsigned long arg)
949{
950 if (cmd == ICARSAMODEXPO)
951 return trans_modexpo32(filp, cmd, arg);
952 if (cmd == ICARSACRT)
953 return trans_modexpo_crt32(filp, cmd, arg);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200954 if (cmd == ZSECSENDCPRB)
955 return trans_xcRB32(filp, cmd, arg);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200956 return zcrypt_unlocked_ioctl(filp, cmd, arg);
957}
958#endif
959
Felix Beck1749a812008-04-17 07:46:28 +0200960/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200961 * Misc device file operations.
962 */
Arjan van de Vend54b1fd2007-02-12 00:55:34 -0800963static const struct file_operations zcrypt_fops = {
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200964 .owner = THIS_MODULE,
965 .read = zcrypt_read,
966 .write = zcrypt_write,
967 .unlocked_ioctl = zcrypt_unlocked_ioctl,
968#ifdef CONFIG_COMPAT
969 .compat_ioctl = zcrypt_compat_ioctl,
970#endif
971 .open = zcrypt_open,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200972 .release = zcrypt_release,
973 .llseek = no_llseek,
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200974};
975
Felix Beck1749a812008-04-17 07:46:28 +0200976/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200977 * Misc device.
978 */
979static struct miscdevice zcrypt_misc_device = {
980 .minor = MISC_DYNAMIC_MINOR,
981 .name = "z90crypt",
982 .fops = &zcrypt_fops,
983};
984
Felix Beck1749a812008-04-17 07:46:28 +0200985/*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200986 * Deprecated /proc entry support.
987 */
988static struct proc_dir_entry *zcrypt_entry;
989
Alexey Dobriyan34b92432010-02-26 22:37:50 +0100990static void sprintcl(struct seq_file *m, unsigned char *addr, unsigned int len)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200991{
Alexey Dobriyan34b92432010-02-26 22:37:50 +0100992 int i;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200993
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200994 for (i = 0; i < len; i++)
Alexey Dobriyan34b92432010-02-26 22:37:50 +0100995 seq_printf(m, "%01x", (unsigned int) addr[i]);
996 seq_putc(m, ' ');
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +0200997}
998
Alexey Dobriyan34b92432010-02-26 22:37:50 +0100999static void sprintrw(struct seq_file *m, unsigned char *addr, unsigned int len)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001000{
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001001 int inl, c, cx;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001002
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001003 seq_printf(m, " ");
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001004 inl = 0;
1005 for (c = 0; c < (len / 16); c++) {
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001006 sprintcl(m, addr+inl, 16);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001007 inl += 16;
1008 }
1009 cx = len%16;
1010 if (cx) {
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001011 sprintcl(m, addr+inl, cx);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001012 inl += cx;
1013 }
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001014 seq_putc(m, '\n');
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001015}
1016
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001017static void sprinthx(unsigned char *title, struct seq_file *m,
1018 unsigned char *addr, unsigned int len)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001019{
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001020 int inl, r, rx;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001021
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001022 seq_printf(m, "\n%s\n", title);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001023 inl = 0;
1024 for (r = 0; r < (len / 64); r++) {
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001025 sprintrw(m, addr+inl, 64);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001026 inl += 64;
1027 }
1028 rx = len % 64;
1029 if (rx) {
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001030 sprintrw(m, addr+inl, rx);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001031 inl += rx;
1032 }
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001033 seq_putc(m, '\n');
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001034}
1035
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001036static void sprinthx4(unsigned char *title, struct seq_file *m,
1037 unsigned int *array, unsigned int len)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001038{
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001039 int r;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001040
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001041 seq_printf(m, "\n%s\n", title);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001042 for (r = 0; r < len; r++) {
1043 if ((r % 8) == 0)
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001044 seq_printf(m, " ");
1045 seq_printf(m, "%08X ", array[r]);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001046 if ((r % 8) == 7)
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001047 seq_putc(m, '\n');
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001048 }
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001049 seq_putc(m, '\n');
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001050}
1051
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001052static int zcrypt_proc_show(struct seq_file *m, void *v)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001053{
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001054 char workarea[sizeof(int) * AP_DEVICES];
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001055
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001056 seq_printf(m, "\nzcrypt version: %d.%d.%d\n",
1057 ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT);
1058 seq_printf(m, "Cryptographic domain: %d\n", ap_domain_index);
1059 seq_printf(m, "Total device count: %d\n", zcrypt_device_count);
1060 seq_printf(m, "PCICA count: %d\n", zcrypt_count_type(ZCRYPT_PCICA));
1061 seq_printf(m, "PCICC count: %d\n", zcrypt_count_type(ZCRYPT_PCICC));
1062 seq_printf(m, "PCIXCC MCL2 count: %d\n",
1063 zcrypt_count_type(ZCRYPT_PCIXCC_MCL2));
1064 seq_printf(m, "PCIXCC MCL3 count: %d\n",
1065 zcrypt_count_type(ZCRYPT_PCIXCC_MCL3));
1066 seq_printf(m, "CEX2C count: %d\n", zcrypt_count_type(ZCRYPT_CEX2C));
1067 seq_printf(m, "CEX2A count: %d\n", zcrypt_count_type(ZCRYPT_CEX2A));
1068 seq_printf(m, "CEX3C count: %d\n", zcrypt_count_type(ZCRYPT_CEX3C));
1069 seq_printf(m, "CEX3A count: %d\n", zcrypt_count_type(ZCRYPT_CEX3A));
1070 seq_printf(m, "requestq count: %d\n", zcrypt_requestq_count());
1071 seq_printf(m, "pendingq count: %d\n", zcrypt_pendingq_count());
1072 seq_printf(m, "Total open handles: %d\n\n",
1073 atomic_read(&zcrypt_open_count));
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001074 zcrypt_status_mask(workarea);
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001075 sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
1076 "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A 7=CEX3C 8=CEX3A",
1077 m, workarea, AP_DEVICES);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001078 zcrypt_qdepth_mask(workarea);
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001079 sprinthx("Waiting work element counts", m, workarea, AP_DEVICES);
Heiko Carstens2b67fc42007-02-05 21:16:47 +01001080 zcrypt_perdev_reqcnt((int *) workarea);
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001081 sprinthx4("Per-device successfully completed request counts",
1082 m, (unsigned int *) workarea, AP_DEVICES);
1083 return 0;
1084}
1085
1086static int zcrypt_proc_open(struct inode *inode, struct file *file)
1087{
1088 return single_open(file, zcrypt_proc_show, NULL);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001089}
1090
1091static void zcrypt_disable_card(int index)
1092{
1093 struct zcrypt_device *zdev;
1094
1095 spin_lock_bh(&zcrypt_device_lock);
1096 list_for_each_entry(zdev, &zcrypt_device_list, list)
1097 if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) {
1098 zdev->online = 0;
1099 ap_flush_queue(zdev->ap_dev);
1100 break;
1101 }
1102 spin_unlock_bh(&zcrypt_device_lock);
1103}
1104
1105static void zcrypt_enable_card(int index)
1106{
1107 struct zcrypt_device *zdev;
1108
1109 spin_lock_bh(&zcrypt_device_lock);
1110 list_for_each_entry(zdev, &zcrypt_device_list, list)
1111 if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) {
1112 zdev->online = 1;
1113 break;
1114 }
1115 spin_unlock_bh(&zcrypt_device_lock);
1116}
1117
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001118static ssize_t zcrypt_proc_write(struct file *file, const char __user *buffer,
1119 size_t count, loff_t *pos)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001120{
1121 unsigned char *lbuf, *ptr;
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001122 size_t local_count;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001123 int j;
1124
1125 if (count <= 0)
1126 return 0;
1127
1128#define LBUFSIZE 1200UL
1129 lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
Felix Beck1a89dd82008-07-14 09:59:27 +02001130 if (!lbuf)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001131 return 0;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001132
1133 local_count = min(LBUFSIZE - 1, count);
1134 if (copy_from_user(lbuf, buffer, local_count) != 0) {
1135 kfree(lbuf);
1136 return -EFAULT;
1137 }
1138 lbuf[local_count] = '\0';
1139
1140 ptr = strstr(lbuf, "Online devices");
Felix Beck1a89dd82008-07-14 09:59:27 +02001141 if (!ptr)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001142 goto out;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001143 ptr = strstr(ptr, "\n");
Felix Beck1a89dd82008-07-14 09:59:27 +02001144 if (!ptr)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001145 goto out;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001146 ptr++;
1147
Felix Beck1a89dd82008-07-14 09:59:27 +02001148 if (strstr(ptr, "Waiting work element counts") == NULL)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001149 goto out;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001150
1151 for (j = 0; j < 64 && *ptr; ptr++) {
Felix Beck1749a812008-04-17 07:46:28 +02001152 /*
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001153 * '0' for no device, '1' for PCICA, '2' for PCICC,
1154 * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3,
1155 * '5' for CEX2C and '6' for CEX2A'
Felix Beckffda4f72009-12-07 12:51:56 +01001156 * '7' for CEX3C and '8' for CEX3A
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001157 */
Felix Beckffda4f72009-12-07 12:51:56 +01001158 if (*ptr >= '0' && *ptr <= '8')
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001159 j++;
1160 else if (*ptr == 'd' || *ptr == 'D')
1161 zcrypt_disable_card(j++);
1162 else if (*ptr == 'e' || *ptr == 'E')
1163 zcrypt_enable_card(j++);
1164 else if (*ptr != ' ' && *ptr != '\t')
1165 break;
1166 }
1167out:
1168 kfree(lbuf);
1169 return count;
1170}
1171
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001172static const struct file_operations zcrypt_proc_fops = {
1173 .owner = THIS_MODULE,
1174 .open = zcrypt_proc_open,
1175 .read = seq_read,
1176 .llseek = seq_lseek,
1177 .release = single_release,
1178 .write = zcrypt_proc_write,
1179};
1180
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001181static int zcrypt_rng_device_count;
1182static u32 *zcrypt_rng_buffer;
1183static int zcrypt_rng_buffer_index;
1184static DEFINE_MUTEX(zcrypt_rng_mutex);
1185
1186static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
1187{
1188 int rc;
1189
Felix Beck1749a812008-04-17 07:46:28 +02001190 /*
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001191 * We don't need locking here because the RNG API guarantees serialized
1192 * read method calls.
1193 */
1194 if (zcrypt_rng_buffer_index == 0) {
1195 rc = zcrypt_rng((char *) zcrypt_rng_buffer);
1196 if (rc < 0)
1197 return -EIO;
1198 zcrypt_rng_buffer_index = rc / sizeof *data;
1199 }
1200 *data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index];
1201 return sizeof *data;
1202}
1203
1204static struct hwrng zcrypt_rng_dev = {
1205 .name = "zcrypt",
1206 .data_read = zcrypt_rng_data_read,
1207};
1208
1209static int zcrypt_rng_device_add(void)
1210{
1211 int rc = 0;
1212
1213 mutex_lock(&zcrypt_rng_mutex);
1214 if (zcrypt_rng_device_count == 0) {
1215 zcrypt_rng_buffer = (u32 *) get_zeroed_page(GFP_KERNEL);
1216 if (!zcrypt_rng_buffer) {
1217 rc = -ENOMEM;
1218 goto out;
1219 }
1220 zcrypt_rng_buffer_index = 0;
1221 rc = hwrng_register(&zcrypt_rng_dev);
1222 if (rc)
1223 goto out_free;
1224 zcrypt_rng_device_count = 1;
1225 } else
1226 zcrypt_rng_device_count++;
1227 mutex_unlock(&zcrypt_rng_mutex);
1228 return 0;
1229
1230out_free:
1231 free_page((unsigned long) zcrypt_rng_buffer);
1232out:
1233 mutex_unlock(&zcrypt_rng_mutex);
1234 return rc;
1235}
1236
1237static void zcrypt_rng_device_remove(void)
1238{
1239 mutex_lock(&zcrypt_rng_mutex);
1240 zcrypt_rng_device_count--;
1241 if (zcrypt_rng_device_count == 0) {
1242 hwrng_unregister(&zcrypt_rng_dev);
1243 free_page((unsigned long) zcrypt_rng_buffer);
1244 }
1245 mutex_unlock(&zcrypt_rng_mutex);
1246}
1247
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001248/**
Felix Beck1749a812008-04-17 07:46:28 +02001249 * zcrypt_api_init(): Module initialization.
1250 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001251 * The module initialization code.
1252 */
1253int __init zcrypt_api_init(void)
1254{
1255 int rc;
1256
1257 /* Register the request sprayer. */
1258 rc = misc_register(&zcrypt_misc_device);
Felix Beck1a89dd82008-07-14 09:59:27 +02001259 if (rc < 0)
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001260 goto out;
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001261
1262 /* Set up the proc file system */
Alexey Dobriyan34b92432010-02-26 22:37:50 +01001263 zcrypt_entry = proc_create("driver/z90crypt", 0644, NULL, &zcrypt_proc_fops);
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001264 if (!zcrypt_entry) {
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001265 rc = -ENOMEM;
1266 goto out_misc;
1267 }
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001268
1269 return 0;
1270
1271out_misc:
1272 misc_deregister(&zcrypt_misc_device);
1273out:
1274 return rc;
1275}
1276
1277/**
Felix Beck1749a812008-04-17 07:46:28 +02001278 * zcrypt_api_exit(): Module termination.
1279 *
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001280 * The module termination code.
1281 */
1282void zcrypt_api_exit(void)
1283{
1284 remove_proc_entry("driver/z90crypt", NULL);
1285 misc_deregister(&zcrypt_misc_device);
1286}
1287
Martin Schwidefsky2dbc2412006-09-20 15:58:27 +02001288module_init(zcrypt_api_init);
1289module_exit(zcrypt_api_exit);