--- a/drivers/md/dm-crypt.c	2005-06-17 22:48:29.000000000 +0300
+++ b/drivers/md/dm-crypt.c	2005-09-05 17:51:15.625958672 +0300
@@ -18,6 +18,19 @@
 #include <asm/scatterlist.h>
 #include <asm/page.h>
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+
+#undef DM_DEBUG
+#ifdef DM_DEBUG
+#define dmprintk printk
+#else
+#define dmprintk(fmt,args...) 
+#endif
+
+#include <linux/cryptodev.h>
+
+#endif /* CONFIG_OCF_DM_CRYPT */
+
 #include "dm.h"
 
 #define PFX	"crypt: "
@@ -82,7 +95,19 @@
 	sector_t iv_offset;
 	unsigned int iv_size;
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+	struct cryptoini 	cr_dm;    		/* OCF session */
+	char  			ocf_alg_name[CRYPTO_MAX_ALG_NAME];
+	uint64_t 	 	ocf_cryptoid;		/* OCF sesssion ID */
+	u32 		 	dm_ocf_rd_completed;	/* Num of rd completions */
+	u32 		 	dm_ocf_rd_pending;	/* Num of rd pendings */
+	wait_queue_head_t	dm_ocf_rd_queue;	/* waiting Q, for rd completion */
+	u32 		 	dm_ocf_wr_completed;	/* Num of wr completions */
+	u32 		 	dm_ocf_wr_pending;	/* Num of wr pendings */
+	wait_queue_head_t	dm_ocf_wr_queue;	/* waiting Q, for wr completion */
+#else
 	struct crypto_tfm *tfm;
+#endif
 	unsigned int key_size;
 	u8 key[0];
 };
@@ -158,6 +183,7 @@
 
 	saltsize = crypto_tfm_alg_digestsize(hash_tfm);
 	salt = kmalloc(saltsize, GFP_KERNEL);
+	
 	if (salt == NULL) {
 		ti->error = PFX "Error kmallocing salt storage in ESSIV";
 		crypto_free_tfm(hash_tfm);
@@ -171,15 +197,24 @@
 	crypto_free_tfm(hash_tfm);
 
 	/* Setup the essiv_tfm with the given salt */
+#if defined(CONFIG_OCF_DM_CRYPT)
+	essiv_tfm = crypto_alloc_tfm(cc->ocf_alg_name,
+	                             CRYPTO_TFM_MODE_ECB);
+#else
 	essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm),
 	                             CRYPTO_TFM_MODE_ECB);
+#endif
 	if (essiv_tfm == NULL) {
 		ti->error = PFX "Error allocating crypto tfm for ESSIV";
 		kfree(salt);
 		return -EINVAL;
 	}
+#if  defined(CONFIG_OCF_DM_CRYPT)
+	if (crypto_tfm_alg_blocksize(essiv_tfm) != cc->iv_size) {
+#else
 	if (crypto_tfm_alg_blocksize(essiv_tfm)
 	    != crypto_tfm_alg_ivsize(cc->tfm)) {
+#endif
 		ti->error = PFX "Block size of ESSIV cipher does "
 			        "not match IV size of block cipher";
 		crypto_free_tfm(essiv_tfm);
@@ -231,6 +266,122 @@
 };
 
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+static int dm_ocf_wr_cb(struct cryptop *crp)
+{
+	struct  crypt_config *cc = (struct crypt_config *)crp->crp_opaque;
+
+	dmprintk("cw %x \n",cc->dm_ocf_wr_completed);
+
+	if(crp == NULL) {
+		printk("dm_ocf_cb: crp is NULL!! \n");
+	}
+
+	cc->dm_ocf_wr_completed++;
+	
+	/* if no more pending for read, wake up the read task. */
+	if(cc->dm_ocf_wr_completed == cc->dm_ocf_wr_pending)
+		wake_up(&cc->dm_ocf_wr_queue);
+
+	crypto_freereq(crp);
+	return 0;
+}
+
+static int dm_ocf_rd_cb(struct cryptop *crp)
+{
+	struct  crypt_config *cc = (struct crypt_config *)crp->crp_opaque;
+
+	dmprintk("cr %x \n",cc->dm_ocf_rd_completed);
+
+	if(crp == NULL) {
+		printk("dm_ocf_cb: crp is NULL!! \n");
+	}
+
+	cc->dm_ocf_rd_completed++;
+	
+	/* if no more pending for read, wake up the read task. */
+	if(cc->dm_ocf_rd_completed == cc->dm_ocf_rd_pending)
+		wake_up(&cc->dm_ocf_rd_queue);
+
+	crypto_freereq(crp);
+	return 0;
+}
+
+u32 stam = 0;
+
+static inline int dm_ocf_process(struct crypt_config *cc, struct scatterlist *out, 
+		struct scatterlist *in, unsigned int len, u8 *iv, int iv_size, int write)
+{
+	struct cryptop *crp;
+	struct cryptodesc *crda = NULL;
+	int    err = 0;
+
+	crp = crypto_getreq(1);	 /* only encryption */
+	if (!crp) {
+		err = -ENOMEM;
+		printk("crypto_getreq failed!!\n");
+		goto err_out_exit;
+	}
+	
+	crda = crp->crp_desc;
+
+	crda->crd_flags  = (write)? CRD_F_ENCRYPT: 0;	
+	crda->crd_alg    = cc->cr_dm.cri_alg;
+	crda->crd_skip   = 0;
+	crda->crd_len    = len;
+	crda->crd_inject = 0; /* NA */
+	crda->crd_klen   = cc->cr_dm.cri_klen;
+	crda->crd_key    = cc->cr_dm.cri_key;
+
+	if (iv) {
+		crda->crd_flags |= (CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT);
+		if( iv_size > EALG_MAX_BLOCK_LEN ) {
+			printk("dm_ocf_process: iv is too big!!\n");
+		}
+		memcpy(&crda->crd_iv, iv, iv_size);		
+	}
+	else {
+		printk(" goto err_out_free \n");
+		goto err_out_free;
+	}
+
+	/* according to the current implementation the in and the out are the same buffer for read, and different for write*/
+	if((page_address(out->page) + out->offset) != (page_address(in->page) + in->offset)) {
+		memcpy((page_address(out->page) + out->offset) , (page_address(in->page) + in->offset) , len);
+		dmprintk("OCF: dm_crypt copy buffers!! \n");
+	}
+
+	dmprintk("len: %d",len);
+	crp->crp_ilen = len; /* Total input length */
+        crp->crp_flags = CRYPTO_F_CBIMM | CRYPTO_F_BATCH;
+        crp->crp_buf = page_address(out->page) + out->offset;
+	if(write) {
+        	crp->crp_callback = dm_ocf_wr_cb;
+	}
+	else {
+		crp->crp_callback = dm_ocf_rd_cb;
+	}
+        crp->crp_sid = cc->ocf_cryptoid;
+        crp->crp_opaque = (void *)cc;
+        if(crypto_dispatch(crp) != 0) {
+		printk("crypto_dispatch failed!!\n");
+	}
+
+	return 0;
+	
+err_out_free:
+	crypto_freereq(crp); 
+err_out_exit:
+	if(write) {
+		cc->dm_ocf_wr_completed++;
+	}
+	else {
+		cc->dm_ocf_rd_completed++;
+	}
+	return err;
+}
+#endif
+
 static inline int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                           struct scatterlist *in, unsigned int length,
@@ -243,16 +394,27 @@
 		r = cc->iv_gen_ops->generator(cc, iv, sector);
 		if (r < 0)
 			return r;
-
+#if defined(CONFIG_OCF_DM_CRYPT)
+		r = dm_ocf_process(cc, out, in, length, iv, cc->iv_size, write);
+		if (r == 0)
+			return r;
+#else
 		if (write)
 			r = crypto_cipher_encrypt_iv(cc->tfm, out, in, length, iv);
 		else
 			r = crypto_cipher_decrypt_iv(cc->tfm, out, in, length, iv);
+#endif
 	} else {
+#if defined(CONFIG_OCF_DM_CRYPT)
+		r = dm_ocf_process(cc, out, in, length, NULL, 0, write);
+		if (r == 0)
+			return r;
+#else
 		if (write)
 			r = crypto_cipher_encrypt(cc->tfm, out, in, length);
 		else
 			r = crypto_cipher_decrypt(cc->tfm, out, in, length);
+#endif
 	}
 
 	return r;
@@ -281,6 +443,17 @@
 {
 	int r = 0;
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+	if(ctx->write) {	
+		cc->dm_ocf_wr_completed = 0;
+		cc->dm_ocf_wr_pending = 0;		
+	}
+	else {
+		cc->dm_ocf_rd_completed = 0;
+		cc->dm_ocf_rd_pending = 0;
+	}	
+#endif
+
 	while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
 	      ctx->idx_out < ctx->bio_out->bi_vcnt) {
 		struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
@@ -308,6 +481,16 @@
 			ctx->idx_out++;
 		}
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+		if(ctx->write) {
+			cc->dm_ocf_wr_pending++;
+			dmprintk("w %x ",cc->dm_ocf_wr_pending);
+		}
+		else{
+			cc->dm_ocf_rd_pending++;
+			dmprintk("r %x ",cc->dm_ocf_rd_pending);
+		}
+#endif
 		r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length,
 		                              ctx->write, ctx->sector);
 		if (r < 0)
@@ -316,6 +499,29 @@
 		ctx->sector++;
 	}
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+	{
+		long timeout = 1000;
+		long tm;
+
+		if(ctx->write) {
+			tm = wait_event_timeout(cc->dm_ocf_wr_queue, (cc->dm_ocf_wr_pending == cc->dm_ocf_wr_completed)
+									, msecs_to_jiffies(timeout));
+			if (!tm)
+				printk("%s: bug: wr work was not finished in %ld msecs, %d pending %d completed.\n", 
+					__func__, timeout, cc->dm_ocf_wr_pending, cc->dm_ocf_wr_completed);
+		}
+		else {
+			tm = wait_event_timeout(cc->dm_ocf_rd_queue, (cc->dm_ocf_rd_pending == cc->dm_ocf_rd_completed)
+									, msecs_to_jiffies(timeout));
+			if (!tm)
+				printk("%s: bug: rd work was not finished in %ld msecs, %d pending %d completed.\n", 
+					__func__, timeout, cc->dm_ocf_rd_pending, cc->dm_ocf_rd_completed);
+		}
+
+	}
+#endif
+
 	return r;
 }
 
@@ -527,13 +733,17 @@
 static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	struct crypt_config *cc;
+	unsigned int crypto_flags;
+#if defined(CONFIG_OCF_DM_CRYPT)
+	struct cryptoini cr_dm;
+#else
 	struct crypto_tfm *tfm;
+#endif
 	char *tmp;
 	char *cipher;
 	char *chainmode;
 	char *ivmode;
 	char *ivopts;
-	unsigned int crypto_flags;
 	unsigned int key_size;
 
 	if (argc != 5) {
@@ -587,6 +797,37 @@
 		goto bad1;
 	}
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+	/* prepare a new OCF session */
+        memset(&cc->cr_dm, 0, sizeof(cr_dm));
+
+	if((strcmp(cipher,"aes") == 0) && (strcmp(chainmode, "cbc") == 0))
+        	cc->cr_dm.cri_alg  = CRYPTO_AES_CBC;
+	else if((strcmp(cipher,"des") == 0) && (strcmp(chainmode, "cbc") == 0))
+        	cc->cr_dm.cri_alg  = CRYPTO_DES_CBC;
+	else if((strcmp(cipher,"3des") == 0) && (strcmp(chainmode, "cbc") == 0))
+        	cc->cr_dm.cri_alg  = CRYPTO_3DES_CBC; 
+	else {
+		ti->error = PFX "using OCF: unknown cipher or bad chain mode";
+		goto bad1;
+	}
+
+	strcpy(cc->ocf_alg_name, cipher);
+	dmprintk("key size is %d\n",cc->key_size);
+        cc->cr_dm.cri_klen = cc->key_size*8;
+        cc->cr_dm.cri_key  = cc->key;
+        cc->cr_dm.cri_next = NULL;
+
+        if(crypto_newsession(&cc->ocf_cryptoid, &cc->cr_dm, 0)){
+		dmprintk("crypt_ctr: crypto_newsession failed\n");
+                ti->error = PFX "crypto_newsession failed";
+                goto bad2;
+        }
+
+	/* init waiting queue for read worker. */	
+	init_waitqueue_head(&cc->dm_ocf_rd_queue);
+	init_waitqueue_head(&cc->dm_ocf_wr_queue);
+#else
 	tfm = crypto_alloc_tfm(cipher, crypto_flags);
 	if (!tfm) {
 		ti->error = PFX "Error allocating crypto tfm";
@@ -598,7 +839,7 @@
 	}
 
 	cc->tfm = tfm;
-
+#endif
 	/*
 	 * Choose ivmode. Valid modes: "plain", "essiv:<esshash>".
 	 * See comments at iv code
@@ -619,10 +860,21 @@
 	    cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0)
 		goto bad2;
 
+#if defined(CONFIG_OCF_DM_CRYPT)
+	switch (cr_dm.cri_alg) {
+		case CRYPTO_AES_CBC:
+			cc->iv_size = 16;
+			break;
+		default:
+			cc->iv_size = 8;
+			break;
+	}
+#else
 	if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv)
 		/* at least a 64 bit sector number should fit in our buffer */
 		cc->iv_size = max(crypto_tfm_alg_ivsize(tfm),
 		                  (unsigned int)(sizeof(u64) / sizeof(u8)));
+
 	else {
 		cc->iv_size = 0;
 		if (cc->iv_gen_ops) {
@@ -632,6 +884,7 @@
 			cc->iv_gen_ops = NULL;
 		}
 	}
+#endif
 
 	cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
 				     mempool_free_slab, _crypt_io_pool);
@@ -647,10 +900,12 @@
 		goto bad4;
 	}
 
+#if !defined(CONFIG_OCF_DM_CRYPT)
 	if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
 		ti->error = PFX "Error setting key";
 		goto bad5;
 	}
+#endif
 
 	if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
 		ti->error = PFX "Invalid iv_offset sector";
@@ -691,7 +946,11 @@
 	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
 		cc->iv_gen_ops->dtr(cc);
 bad2:
+#if defined(CONFIG_OCF_DM_CRYPT)
+	crypto_freesession(cc->ocf_cryptoid);
+#else
 	crypto_free_tfm(tfm);
+#endif
 bad1:
 	kfree(cc);
 	return -EINVAL;
@@ -708,7 +967,11 @@
 		kfree(cc->iv_mode);
 	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
 		cc->iv_gen_ops->dtr(cc);
+#if defined(CONFIG_OCF_DM_CRYPT)
+	crypto_freesession(cc->ocf_cryptoid);
+#else
 	crypto_free_tfm(cc->tfm);
+#endif
 	dm_put_device(ti, cc->dev);
 	kfree(cc);
 }
@@ -870,6 +1133,12 @@
 		break;
 
 	case STATUSTYPE_TABLE:
+
+#if  defined(CONFIG_OCF_DM_CRYPT)
+		cipher = cc->ocf_alg_name;
+		chainmode = "cbc";
+		DMEMIT("OCF ");
+#else
 		cipher = crypto_tfm_alg_name(cc->tfm);
 
 		switch(cc->tfm->crt_cipher.cit_mode) {
@@ -882,6 +1151,7 @@
 		default:
 			BUG();
 		}
+#endif
 
 		if (cc->iv_mode)
 			DMEMIT("%s-%s-%s ", cipher, chainmode, cc->iv_mode);
--- a/crypto/ocf/Kconfig	2005-06-14 03:42:51.000000000 +0300
+++ b/crypto/ocf/Kconfig	2005-09-05 15:30:58.969484944 +0300
@@ -25,6 +25,16 @@
 	  A software driver for the OCF framework that uses
 	  the kernel CryptoAPI.
 
+config OCF_DM_CRYPT
+	bool "OCF dm_crypt"
+	depends on OCF_OCF && DM_CRYPT
+	help
+	  The dm_crypt device mapper will use the OCF for encryption/decryption,
+	  in case of essiv, the essiv generation will use the kernel crypto APIs.
+	  When using the OCF dm_crypt, only the following encryption algorithms 
+	  are supported:
+		DES-CBC, 3DES-CBC and AES-CBC.
+
 config OCF_SAFE
 	tristate "safenet (HW crypto engine)"
 	depends on OCF_OCF
