All of lore.kernel.org
 help / color / mirror / Atom feed
From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
To: linux-kernel@vger.kernel.org
Cc: Fruhwirth Clemens <clemens@endorphin.org>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	cryptoapi@lists.logix.cz, James Morris <jmorris@redhat.com>,
	David Miller <davem@davemloft.net>, Andrew Morton <akpm@osdl.org>,
	Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Subject: [8/many] acrypto: crypto_dev.c
Date: Mon, 7 Mar 2005 23:37:34 +0300	[thread overview]
Message-ID: <1110227854480@2ka.mipt.ru> (raw)
In-Reply-To: <11102278542733@2ka.mipt.ru>

--- /tmp/empty/crypto_dev.c	1970-01-01 03:00:00.000000000 +0300
+++ ./acrypto/crypto_dev.c	2005-03-07 20:35:36.000000000 +0300
@@ -0,0 +1,421 @@
+/*
+ * 	crypto_dev.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#include "acrypto.h"
+
+static LIST_HEAD(cdev_list);
+static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED;
+static u32 cdev_ids;
+
+struct list_head *crypto_device_list = &cdev_list;
+spinlock_t *crypto_device_lock = &cdev_lock;
+
+static int crypto_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static int crypto_probe(struct device *dev)
+{
+	return -ENODEV;
+}
+
+static int crypto_remove(struct device *dev)
+{
+	return 0;
+}
+
+static void crypto_release(struct device *dev)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, device);
+
+	complete(&d->dev_released);
+}
+
+static void crypto_class_release(struct class *class)
+{
+}
+
+static void crypto_class_release_device(struct class_device *class_dev)
+{
+}
+
+struct class crypto_class = {
+	.name 		= "acrypto",
+	.class_release 	= crypto_class_release,
+	.release 	= crypto_class_release_device
+};
+
+struct bus_type crypto_bus_type = {
+	.name 		= "acrypto",
+	.match 		= crypto_match
+};
+
+struct device_driver crypto_driver = {
+	.name 		= "crypto_driver",
+	.bus 		= &crypto_bus_type,
+	.probe 		= crypto_probe,
+	.remove 	= crypto_remove,
+};
+
+struct device crypto_dev = {
+	.parent 	= NULL,
+	.bus 		= &crypto_bus_type,
+	.bus_id		= "Asynchronous crypto",
+	.driver 	= &crypto_driver,
+	.release 	= &crypto_release
+};
+
+static ssize_t sessions_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%d\n", atomic_read(&d->refcnt));
+}
+static ssize_t name_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%s\n", d->name);
+}
+static ssize_t devices_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d;
+	int off = 0;
+
+	spin_lock_irq(&cdev_lock);
+	list_for_each_entry(d, &cdev_list, cdev_entry) {
+		off += sprintf(buf + off, "%s ", d->name);
+	}
+	spin_unlock_irq(&cdev_lock);
+
+	if (!off)
+		off = sprintf(buf, "No devices registered yet.");
+
+	off += sprintf(buf + off, "\n");
+
+	return off;
+}
+
+static ssize_t kmem_failed_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d =  container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%llu\n", d->stat.kmem_failed);
+}
+static ssize_t sstarted_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%llu\n", d->stat.sstarted);
+}
+static ssize_t sfinished_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%llu\n", d->stat.sfinished);
+}
+static ssize_t scompleted_show(struct class_device *dev, char *buf)
+{
+	struct crypto_device *d = container_of(dev, struct crypto_device, class_device);
+
+	return sprintf(buf, "%llu\n", d->stat.scompleted);
+}
+
+static CLASS_DEVICE_ATTR(sessions, 0444, sessions_show, NULL);
+static CLASS_DEVICE_ATTR(name, 0444, name_show, NULL);
+CLASS_DEVICE_ATTR(devices, 0444, devices_show, NULL);
+static CLASS_DEVICE_ATTR(scompleted, 0444, scompleted_show, NULL);
+static CLASS_DEVICE_ATTR(sstarted, 0444, sstarted_show, NULL);
+static CLASS_DEVICE_ATTR(sfinished, 0444, sfinished_show, NULL);
+static CLASS_DEVICE_ATTR(kmem_failed, 0444, kmem_failed_show, NULL);
+
+static int compare_device(struct crypto_device *d1, struct crypto_device *d2)
+{
+	if (!strncmp(d1->name, d2->name, sizeof(d1->name)))
+		return 1;
+
+	return 0;
+}
+
+static void create_device_attributes(struct crypto_device *dev)
+{
+	class_device_create_file(&dev->class_device, &class_device_attr_sessions);
+	class_device_create_file(&dev->class_device, &class_device_attr_name);
+	class_device_create_file(&dev->class_device, &class_device_attr_scompleted);
+	class_device_create_file(&dev->class_device, &class_device_attr_sstarted);
+	class_device_create_file(&dev->class_device, &class_device_attr_sfinished);
+	class_device_create_file(&dev->class_device, &class_device_attr_kmem_failed);
+}
+
+static void remove_device_attributes(struct crypto_device *dev)
+{
+	class_device_remove_file(&dev->class_device, &class_device_attr_sessions);
+	class_device_remove_file(&dev->class_device, &class_device_attr_name);
+	class_device_remove_file(&dev->class_device, &class_device_attr_scompleted);
+	class_device_remove_file(&dev->class_device, &class_device_attr_sstarted);
+	class_device_remove_file(&dev->class_device, &class_device_attr_sfinished);
+	class_device_remove_file(&dev->class_device, &class_device_attr_kmem_failed);
+}
+
+int __match_initializer(struct crypto_capability *cap, struct crypto_session_initializer *ci)
+{
+	dprintk("Match: %04x.%04x.%04x vs. %04x.%04x.%04x.\n",
+			cap->operation, cap->type, cap->mode,
+			ci->operation, ci->type, ci->mode);
+	if (cap->operation == ci->operation && cap->type == ci->type && 
+			cap->mode == (ci->mode & 0x1fff))
+		return 1;
+
+	return 0;
+}
+
+int match_initializer(struct crypto_device *dev, struct crypto_session_initializer *ci)
+{
+	int i;
+
+	for (i = 0; i < dev->cap_number; ++i) {
+		struct crypto_capability *cap = &dev->cap[i];
+
+		if (__match_initializer(cap, ci)) {
+			if (cap->qlen >= atomic_read(&dev->refcnt) + 1) {
+				dprintk("cap->len=%u, req=%u.\n",
+					cap->qlen, atomic_read(&dev->refcnt) + 1);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void crypto_device_get(struct crypto_device *dev)
+{
+	atomic_inc(&dev->refcnt);
+}
+
+struct crypto_device *crypto_device_get_name(char *name)
+{
+	struct crypto_device *dev;
+	int found = 0;
+
+	spin_lock_irq(&cdev_lock);
+	list_for_each_entry(dev, &cdev_list, cdev_entry) {
+		if (!strcmp(dev->name, name)) {
+			found = 1;
+			crypto_device_get(dev);
+			break;
+		}
+	}
+	spin_unlock_irq(&cdev_lock);
+
+	if (!found)
+		return NULL;
+
+	return dev;
+}
+
+void crypto_device_put(struct crypto_device *dev)
+{
+	atomic_dec(&dev->refcnt);
+}
+
+static int avg_cap_qlen(struct crypto_device *dev)
+{
+	int i, max = 0;
+
+	if (!dev->cap_number)
+		return 0;
+
+	for (i=0; i<dev->cap_number; ++i) {
+		max += dev->cap[i].qlen;
+	}
+
+	return (max / dev->cap_number);
+}
+
+int __crypto_device_add(struct crypto_device *dev)
+{
+	int err, avg;
+
+	memset(&dev->stat, 0, sizeof(dev->stat));
+	spin_lock_init(&dev->stat_lock);
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->session_lock);
+	INIT_LIST_HEAD(&dev->session_list);
+	atomic_set(&dev->refcnt, 0);
+	dev->sid = 0;
+	dev->flags = 0;
+	init_completion(&dev->dev_released);
+	memcpy(&dev->device, &crypto_dev, sizeof(struct device));
+	dev->driver = &crypto_driver;
+
+	dev->session_cache = kmem_cache_create(dev->name, sizeof(struct crypto_session), 
+			0, 0, NULL, NULL);
+	if (!dev->session_cache) {
+		dprintk(KERN_ERR "Failed to create session cache for device %s.\n", dev->name);
+		return -ENOMEM;
+	}
+	
+	avg = avg_cap_qlen(dev);
+
+	if (avg) {
+		dev->session_pool = mempool_create(avg, mempool_alloc_slab, mempool_free_slab, dev->session_cache);
+		if (!dev->session_pool) {
+			dprintk(KERN_ERR "Failed to create memory pool with %d objects for device %s.\n",
+					avg, dev->name);
+			err = -ENOMEM;
+			goto err_out_cache_destroy;
+		}
+	} else
+		dev->session_pool = NULL;
+
+	snprintf(dev->device.bus_id, sizeof(dev->device.bus_id), "%s", dev->name);
+	err = device_register(&dev->device);
+	if (err) {
+		dprintk(KERN_ERR "Failed to register crypto device %s: err=%d.\n",
+			dev->name, err);
+		goto err_out_mempool_destroy;
+	}
+
+	snprintf(dev->class_device.class_id, sizeof(dev->class_device.class_id), "%s", dev->name);
+	dev->class_device.dev = &dev->device;
+	dev->class_device.class = &crypto_class;
+
+	err = class_device_register(&dev->class_device);
+	if (err) {
+		dprintk(KERN_ERR "Failed to register crypto class device %s: err=%d.\n",
+			dev->name, err);
+		goto err_out_device_unregister;
+	}
+
+	create_device_attributes(dev);
+
+	return 0;
+
+err_out_device_unregister:
+	device_unregister(&dev->device);
+err_out_mempool_destroy:
+	if (dev->session_pool)
+		mempool_destroy(dev->session_pool);
+err_out_cache_destroy:
+	kmem_cache_destroy(dev->session_cache);
+
+	return err;
+}
+
+void __crypto_device_remove(struct crypto_device *dev)
+{
+	remove_device_attributes(dev);
+	class_device_unregister(&dev->class_device);
+	device_unregister(&dev->device);
+	if (dev->session_pool)
+		mempool_destroy(dev->session_pool);
+	kmem_cache_destroy(dev->session_cache);
+}
+
+int crypto_device_add(struct crypto_device *dev)
+{
+	int err;
+
+	err = __crypto_device_add(dev);
+	if (err)
+		return err;
+
+	spin_lock_irq(&cdev_lock);
+	list_add(&dev->cdev_entry, &cdev_list);
+	dev->id = ++cdev_ids;
+	spin_unlock_irq(&cdev_lock);
+
+	printk(KERN_INFO "Crypto device %s was registered with ID=%x.\n",
+		dev->name, dev->id);
+
+	return 0;
+}
+
+void crypto_device_remove(struct crypto_device *dev)
+{
+	struct crypto_device *__dev, *n;
+
+	__crypto_device_remove(dev);
+
+	spin_lock_irq(&cdev_lock);
+	list_for_each_entry_safe(__dev, n, &cdev_list, cdev_entry) {
+		if (compare_device(__dev, dev)) {
+			list_del_init(&__dev->cdev_entry);
+			spin_unlock_irq(&cdev_lock);
+
+			/*
+			 * In test cases or when crypto device driver is not written correctly,
+			 * it's ->data_ready() method will not be callen anymore
+			 * after device is removed from crypto device list.
+			 *
+			 * For such cases we either should provide ->flush() call
+			 * or properly write ->data_ready() method.
+			 */
+
+			while (atomic_read(&__dev->refcnt)) {
+
+				dprintk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+					__dev->name, atomic_read(&dev->refcnt));
+
+				/*
+				 * Hack zone: you need to write good ->data_ready()
+				 * and crypto device driver itself.
+				 *
+				 * Driver shoud not buzz if it has pending sessions
+				 * in it's queue and it was removed from global device list.
+				 *
+				 * Although I can workaround it here, for example by
+				 * flushing the whole queue and drop all pending sessions.
+				 */
+
+				__dev->data_ready(__dev);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(HZ);
+			}
+
+			dprintk(KERN_ERR "Crypto device %s was unregistered.\n",
+				dev->name);
+			return;
+		}
+	}
+	spin_unlock_irq(&cdev_lock);
+
+	dprintk(KERN_ERR "Crypto device %s was not registered.\n", dev->name);
+}
+
+EXPORT_SYMBOL_GPL(crypto_device_add);
+EXPORT_SYMBOL_GPL(crypto_device_remove);
+EXPORT_SYMBOL_GPL(crypto_device_get);
+EXPORT_SYMBOL_GPL(crypto_device_get_name);
+EXPORT_SYMBOL_GPL(crypto_device_put);
+EXPORT_SYMBOL_GPL(match_initializer);


  reply	other threads:[~2005-03-07 22:21 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-07 20:37 [0/many] Acrypto - asynchronous crypto layer for linux kernel 2.6 Evgeniy Polyakov
2005-03-07 20:37 ` [??/many] list of files to be sent in a next couple of e-mails with small description Evgeniy Polyakov
2005-03-07 20:37   ` [??/many] acrypto benchmarks vs cryptoloop vs dm_crypt Evgeniy Polyakov
2005-03-07 20:37     ` [??/many] iok.c - simple example of the userspace acrypto usage [IOCTL] Evgeniy Polyakov
2005-03-07 20:37       ` [??/many] ucon_crypto.c - simple example of the userspace acrypto usage [DIRECT ACCESS] Evgeniy Polyakov
2005-03-07 20:37         ` [1/many] acrypto: Kconfig Evgeniy Polyakov
2005-03-07 20:37           ` [2/many] acrypto: Makefile Evgeniy Polyakov
2005-03-07 20:37             ` [3/many] acrypto: acrypto.h Evgeniy Polyakov
2005-03-07 20:37               ` [4/many] acrypto: async_provider.c Evgeniy Polyakov
2005-03-07 20:37                 ` [5/many] acrypto: crypto_conn.c Evgeniy Polyakov
2005-03-07 20:37                   ` [6/many] acrypto: crypto_conn.h Evgeniy Polyakov
2005-03-07 20:37                     ` [7/many] acrypto: crypto_def.h Evgeniy Polyakov
2005-03-07 20:37                       ` Evgeniy Polyakov [this message]
2005-03-07 20:37                         ` [9/many] acrypto: crypto_lb.c Evgeniy Polyakov
2005-03-07 20:37                           ` [10/many] acrypto: crypto_lb.h Evgeniy Polyakov
2005-03-07 20:37                             ` [11/many] acrypto: crypto_main.c Evgeniy Polyakov
2005-03-07 20:37                               ` [12/many] acrypto: crypto_route.h Evgeniy Polyakov
2005-03-07 20:37                                 ` [13/many] acrypto: crypto_stat.c Evgeniy Polyakov
2005-03-07 20:37                                   ` [14/many] acrypto: crypto_stat.h Evgeniy Polyakov
2005-03-07 20:37                                     ` [15/many] acrypto: crypto_user.c Evgeniy Polyakov
2005-03-07 20:37                                       ` [16/many] acrypto: crypto_user.h Evgeniy Polyakov
2005-03-07 20:37                                         ` [17/many] acrypto: crypto_user_direct.c Evgeniy Polyakov
2005-03-07 20:37                                           ` [18/many] acrypto: crypto_user_direct.h Evgeniy Polyakov
2005-03-07 20:37                                             ` [19/many] acrypto: crypto_user_ioctl.c Evgeniy Polyakov
2005-03-07 20:37                                               ` [20/many] acrypto: crypto_user_ioctl.h Evgeniy Polyakov
2005-03-07 20:37                                                 ` [21/many] acrypto: simple_lb.c Evgeniy Polyakov
2005-03-07 20:37                                                   ` [22/many] arch: alpha config Evgeniy Polyakov
2005-03-07 20:37                                                     ` [23/many] arch: arm config Evgeniy Polyakov
2005-03-07 20:37                                                       ` [24/many] arch: arm26 config Evgeniy Polyakov
2005-03-07 20:37                                                         ` [25/many] arch: cris config Evgeniy Polyakov
2005-03-07 20:37                                                           ` [26/many] arch: frv config Evgeniy Polyakov
2005-03-07 20:37                                                             ` [27/many] arch: h8300 config Evgeniy Polyakov
2005-03-07 20:37                                                               ` [28/many] arch: i386 config Evgeniy Polyakov
2005-03-07 20:37                                                                 ` [29/many] arch: ia64 config Evgeniy Polyakov
2005-03-07 20:37                                                                   ` [30/many] arch: m32r config Evgeniy Polyakov
2005-03-07 20:37                                                                     ` [31/many] arch: m68k config Evgeniy Polyakov
2005-03-07 20:37                                                                       ` [32/many] arch: m68knommu config Evgeniy Polyakov
2005-03-07 20:37                                                                         ` [33/many] arch: mips config Evgeniy Polyakov
2005-03-07 20:37                                                                           ` [34/many] arch: parisc config Evgeniy Polyakov
2005-03-07 20:37                                                                             ` [35/many] arch: ppc config Evgeniy Polyakov
2005-03-07 20:37                                                                               ` [36/many] arch: ppc64 config Evgeniy Polyakov
2005-03-07 20:37                                                                                 ` [37/many] arch: s390 config Evgeniy Polyakov
2005-03-07 20:37                                                                                   ` [38/many] arch: sh config Evgeniy Polyakov
2005-03-07 20:37                                                                                     ` [39/many] arch: sh64 config Evgeniy Polyakov
2005-03-07 20:37                                                                                       ` [40/many] arch: sparc config Evgeniy Polyakov
2005-03-07 20:37                                                                                         ` [41/many] arch: sparc64 config Evgeniy Polyakov
2005-03-07 20:37                                                                                           ` [42/many] arch: um config Evgeniy Polyakov
2005-03-07 20:37                                                                                             ` [43/many] arch: v850 config Evgeniy Polyakov
2005-03-07 20:37                                                                                               ` [44/many] arch: x86_64 config Evgeniy Polyakov
2005-03-07 20:37                                                                                                 ` [1/5] bd: Asynchronous block device Evgeniy Polyakov
2005-03-07 20:37                                                                                                   ` [2/5] bd: userspace utility to control asynchronous " Evgeniy Polyakov
2005-03-07 20:37                                                                                                     ` [4/5] bd: script for binding file and acrypto filters Evgeniy Polyakov
2005-03-07 20:37                                                                                                       ` [5/5] bd: script for unbinding any filters Evgeniy Polyakov
2005-03-08 15:16                                                                                                   ` [1/5] bd: Asynchronous block device Evgeniy Polyakov
2005-03-15 17:27                                         ` [16/many] acrypto: crypto_user.h Randy.Dunlap
2005-03-15 16:24                               ` [11/many] acrypto: crypto_main.c Randy.Dunlap
2005-03-16  4:58                                 ` Evgeniy Polyakov
2005-03-08 18:02                           ` [UPDATE PATCH 9/many] acrypto: crypto_lb.c Nishanth Aravamudan
2005-03-08 18:33                             ` Evgeniy Polyakov
2005-03-10 19:18                           ` [9/many] " Randy.Dunlap
2005-03-07 22:40                         ` [8/many] acrypto: crypto_dev.c Nish Aravamudan
2005-03-07 23:14                           ` Evgeniy Polyakov
2005-03-07 22:51                             ` Nish Aravamudan
2005-03-07 23:27                               ` Evgeniy Polyakov
2005-03-08  1:46                                 ` [UPDATE PATCH 8/many] " Nishanth Aravamudan
2005-03-08  9:40                                   ` Evgeniy Polyakov
2005-03-07 23:37                         ` [8/many] " Randy.Dunlap
2005-03-08  0:05                           ` Evgeniy Polyakov
2005-03-07 23:50               ` [3/many] acrypto: acrypto.h Randy.Dunlap
2005-03-08  0:34                 ` Evgeniy Polyakov
2005-03-07 23:33           ` [1/many] acrypto: Kconfig Randy.Dunlap
2005-03-08  0:03             ` Evgeniy Polyakov
2005-03-07 21:13 ` [0/many] Acrypto - asynchronous crypto layer for linux kernel 2.6 Fruhwirth Clemens
2005-03-07 21:49   ` Evgeniy Polyakov
2005-03-08 13:24     ` Joshua Jackson
2005-03-10 10:27       ` Evgeniy Polyakov
2005-03-08  5:08 ` Kyle Moffett
2005-03-08  9:37   ` Evgeniy Polyakov
2005-03-08 12:22     ` Kyle Moffett
2005-03-08 13:07       ` Evgeniy Polyakov
2005-03-08 14:46         ` Kyle Moffett
2005-03-08 15:24           ` Evgeniy Polyakov
2005-03-10 12:42   ` Christophe Saout
2005-03-08 10:30 ` Herbert Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1110227854480@2ka.mipt.ru \
    --to=johnpol@2ka.mipt.ru \
    --cc=akpm@osdl.org \
    --cc=clemens@endorphin.org \
    --cc=cryptoapi@lists.logix.cz \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=jmorris@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.