From 6421de4d84558d90cb6918add0656763ba3363fa Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Thu, 23 Feb 2012 23:44:17 +0100
Subject: [PATCH 184/291] cryptodev: Adapted

---
 drivers/staging/crypto/cryptodev/Makefile        |  2 +-
 drivers/staging/crypto/cryptodev/authenc.c       | 27 ++++++++++++----------
 drivers/staging/crypto/cryptodev/cryptodev_int.h |  7 ++++--
 drivers/staging/crypto/cryptodev/main.c          |  6 ++---
 drivers/staging/crypto/cryptodev/tests/Makefile  |  3 +++
 drivers/staging/crypto/cryptodev/zc.c            | 29 ++++++++++++++++--------
 drivers/staging/crypto/cryptodev/zc.h            |  5 ++--
 7 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/drivers/staging/crypto/cryptodev/Makefile b/drivers/staging/crypto/cryptodev/Makefile
index 1da4633cd77d..6b75711132d8 100644
--- a/drivers/staging/crypto/cryptodev/Makefile
+++ b/drivers/staging/crypto/cryptodev/Makefile
@@ -1,6 +1,6 @@
 KBUILD_CFLAGS += -I$(src)
 KERNEL_DIR = /lib/modules/$(shell uname -r)/build
-VERSION = 1.1
+VERSION = 1.2
 
 cryptodev-objs = ioctl.o main.o cryptlib.o authenc.o zc.o util.o
 
diff --git a/drivers/staging/crypto/cryptodev/authenc.c b/drivers/staging/crypto/cryptodev/authenc.c
index 80757035a8e3..ae04de2b1e35 100644
--- a/drivers/staging/crypto/cryptodev/authenc.c
+++ b/drivers/staging/crypto/cryptodev/authenc.c
@@ -52,8 +52,7 @@
  * (caop->src is assumed to be equal to caop->dst)
  */
 static int get_userbuf_tls(struct csession *ses, struct kernel_crypt_auth_op *kcaop,
-			struct scatterlist **dst_sg, 
-			int *tot_pages)
+			struct scatterlist **dst_sg)
 {
 	int pagecount = 0;
 	struct crypt_auth_op *caop = &kcaop->caop;
@@ -75,7 +74,8 @@ static int get_userbuf_tls(struct csession *ses, struct kernel_crypt_auth_op *kc
 
 	pagecount = PAGECOUNT(caop->dst, kcaop->dst_len);
 
-	(*tot_pages) = pagecount;
+	ses->used_pages = pagecount;
+	ses->readable_pages = 0;
 
 	rc = adjust_sg_array(ses, pagecount);
 	if (rc)
@@ -104,8 +104,7 @@ static int get_userbuf_tls(struct csession *ses, struct kernel_crypt_auth_op *kc
  * returns error.
  */
 static int get_userbuf_srtp(struct csession *ses, struct kernel_crypt_auth_op *kcaop,
-			struct scatterlist **auth_sg, struct scatterlist **dst_sg, 
-			int *tot_pages)
+			struct scatterlist **auth_sg, struct scatterlist **dst_sg)
 {
 	int pagecount, diff;
 	int auth_pagecount = 0;
@@ -141,7 +140,7 @@ static int get_userbuf_srtp(struct csession *ses, struct kernel_crypt_auth_op *k
 		return -EINVAL;
 	}
 
-	(*tot_pages) = pagecount = auth_pagecount;
+	pagecount = auth_pagecount;
 
 	rc = adjust_sg_array(ses, pagecount*2); /* double pages to have pages for dst(=auth_src) */
 	if (rc) {
@@ -156,6 +155,10 @@ static int get_userbuf_srtp(struct csession *ses, struct kernel_crypt_auth_op *k
 			"failed to get user pages for data input\n");
 		return -EINVAL;
 	}
+
+	ses->used_pages = pagecount;
+	ses->readable_pages = 0;
+
 	(*auth_sg) = ses->sg;
 
 	(*dst_sg) = ses->sg + auth_pagecount;
@@ -163,7 +166,7 @@ static int get_userbuf_srtp(struct csession *ses, struct kernel_crypt_auth_op *k
 	sg_copy(ses->sg, (*dst_sg), caop->auth_len);
 	(*dst_sg) = sg_advance(*dst_sg, diff);
 	if (*dst_sg == NULL) {
-		release_user_pages(ses->pages, pagecount);
+		release_user_pages(ses);
 		dprintk(1, KERN_ERR,
 			"failed to get enough pages for auth data\n");
 		return -EINVAL;
@@ -594,7 +597,7 @@ __crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcao
 {
 	struct scatterlist *dst_sg, *auth_sg, *src_sg;
 	struct crypt_auth_op *caop = &kcaop->caop;
-	int ret = 0, pagecount = 0;
+	int ret = 0;
 
 	if (caop->flags & COP_FLAG_AEAD_SRTP_TYPE) {
 		if (unlikely(ses_ptr->cdata.init != 0 && 
@@ -604,7 +607,7 @@ __crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcao
 			return -EINVAL;
 		}
 
-		ret = get_userbuf_srtp(ses_ptr, kcaop, &auth_sg, &dst_sg, &pagecount);
+		ret = get_userbuf_srtp(ses_ptr, kcaop, &auth_sg, &dst_sg);
 		if (unlikely(ret)) {
 			dprintk(1, KERN_ERR, "get_userbuf_srtp(): Error getting user pages.\n");
 			return ret;
@@ -644,7 +647,7 @@ __crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcao
 		}
 
 		if (caop->flags & COP_FLAG_AEAD_TLS_TYPE && ses_ptr->cdata.aead == 0) {
-			ret = get_userbuf_tls(ses_ptr, kcaop, &dst_sg, &pagecount);
+			ret = get_userbuf_tls(ses_ptr, kcaop, &dst_sg);
 			if (unlikely(ret)) {
 				dprintk(1, KERN_ERR, "get_userbuf_tls(): Error getting user pages.\n");
 				goto fail;
@@ -667,7 +670,7 @@ __crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcao
 			else dst_len = caop->len - cryptodev_cipher_get_tag_size(&ses_ptr->cdata);
 			
 			ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, dst_len,
-					  kcaop->task, kcaop->mm, &src_sg, &dst_sg, &pagecount);
+					  kcaop->task, kcaop->mm, &src_sg, &dst_sg);
 			if (unlikely(ret)) {
 				dprintk(1, KERN_ERR, "get_userbuf(): Error getting user pages.\n");
 				goto fail;
@@ -681,7 +684,7 @@ fail:
 		free_page((unsigned long)auth_buf);
 	}
 
-	release_user_pages(ses_ptr->pages, pagecount);
+	release_user_pages(ses_ptr);
 	return ret;
 }
 
diff --git a/drivers/staging/crypto/cryptodev/cryptodev_int.h b/drivers/staging/crypto/cryptodev/cryptodev_int.h
index e4a8974c59fe..c1d327f01fee 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev_int.h
+++ b/drivers/staging/crypto/cryptodev/cryptodev_int.h
@@ -26,7 +26,6 @@
 
 extern int cryptodev_verbosity;
 
-
 struct fcrypt {
 	struct list_head list;
 	struct mutex sem;
@@ -115,7 +114,11 @@ struct csession {
 	struct hash_data hdata;
 	uint32_t sid;
 	uint32_t alignmask;
-	int array_size;
+
+	unsigned int array_size;
+	unsigned int used_pages; /* the number of pages that are used */
+	/* the number of pages marked as writable (first are the readable) */
+	unsigned int readable_pages; 
 	struct page **pages;
 	struct scatterlist *sg;
 };
diff --git a/drivers/staging/crypto/cryptodev/main.c b/drivers/staging/crypto/cryptodev/main.c
index 0302f3ca0429..d8d7ee00eaa6 100644
--- a/drivers/staging/crypto/cryptodev/main.c
+++ b/drivers/staging/crypto/cryptodev/main.c
@@ -166,10 +166,10 @@ __crypto_run_zc(struct csession *ses_ptr, struct kernel_crypt_op *kcop)
 {
 	struct scatterlist *src_sg, *dst_sg;
 	struct crypt_op *cop = &kcop->cop;
-	int ret = 0, pagecount;
+	int ret = 0;
 
 	ret = get_userbuf(ses_ptr, cop->src, cop->len, cop->dst, cop->len, 
-	                  kcop->task, kcop->mm, &src_sg, &dst_sg, &pagecount);
+	                  kcop->task, kcop->mm, &src_sg, &dst_sg);
 	if (unlikely(ret)) {
 		dprintk(1, KERN_ERR, "Error getting user pages. "
 					"Falling back to non zero copy.\n");
@@ -178,7 +178,7 @@ __crypto_run_zc(struct csession *ses_ptr, struct kernel_crypt_op *kcop)
 
 	ret = hash_n_crypt(ses_ptr, cop, src_sg, dst_sg, cop->len);
 
-	release_user_pages(ses_ptr->pages, pagecount);
+	release_user_pages(ses_ptr);
 	return ret;
 }
 
diff --git a/drivers/staging/crypto/cryptodev/tests/Makefile b/drivers/staging/crypto/cryptodev/tests/Makefile
index 9a367d3043d3..baefbd706de4 100644
--- a/drivers/staging/crypto/cryptodev/tests/Makefile
+++ b/drivers/staging/crypto/cryptodev/tests/Makefile
@@ -21,6 +21,9 @@ check: $(hostprogs)
 	./hmac
 	./async_cipher
 	./async_hmac
+	./cipher-aead-srtp
+	./cipher-gcm
+	./cipher-aead
 
 clean:
 	rm -f *.o *~ $(hostprogs)
diff --git a/drivers/staging/crypto/cryptodev/zc.c b/drivers/staging/crypto/cryptodev/zc.c
index 778593fbc2e6..11491dc87bf5 100644
--- a/drivers/staging/crypto/cryptodev/zc.c
+++ b/drivers/staging/crypto/cryptodev/zc.c
@@ -102,13 +102,22 @@ int array_size;
 	return 0;
 }
 
-void release_user_pages(struct page **pg, int pagecount)
+void release_user_pages(struct csession *ses)
 {
-	while (pagecount--) {
-		if (!PageReserved(pg[pagecount]))
-			SetPageDirty(pg[pagecount]);
-		page_cache_release(pg[pagecount]);
+unsigned int i;
+
+	for (i=0;i<ses->used_pages;i++) {
+		if (!PageReserved(ses->pages[i]))
+			SetPageDirty(ses->pages[i]);
+                
+                if (ses->readable_pages == 0)
+                        flush_dcache_page(ses->pages[i]);
+                else
+                        ses->readable_pages--;
+                
+		page_cache_release(ses->pages[i]);
 	}
+	ses->used_pages = 0;
 }
 
 /* make src and dst available in scatterlists.
@@ -118,8 +127,7 @@ int get_userbuf(struct csession *ses, void* __user src, int src_len,
                 void* __user dst, int dst_len,
 		struct task_struct *task, struct mm_struct *mm,
                 struct scatterlist **src_sg, 
-                struct scatterlist **dst_sg,
-                int *tot_pages)
+                struct scatterlist **dst_sg)
 {
 	int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1;
 	int rc;
@@ -153,7 +161,10 @@ int get_userbuf(struct csession *ses, void* __user src, int src_len,
 					__func__, (unsigned long)dst, ses->alignmask + 1);
 		}
         }
-	(*tot_pages) = pagecount = src_pagecount + dst_pagecount;
+	ses->used_pages = pagecount = src_pagecount + dst_pagecount;
+
+	if (write_src) ses->readable_pages = 0;
+	else ses->readable_pages = src_pagecount;
 
 	if (pagecount > ses->array_size) {
 		rc = adjust_sg_array(ses, pagecount);
@@ -181,7 +192,7 @@ int get_userbuf(struct csession *ses, void* __user src, int src_len,
 	if (unlikely(rc)) {
 		dprintk(1, KERN_ERR,
 		        "failed to get user pages for data output\n");
-		release_user_pages(ses->pages, src_pagecount);
+		release_user_pages(ses);
 		return -EINVAL;
 	}
 	return 0;
diff --git a/drivers/staging/crypto/cryptodev/zc.h b/drivers/staging/crypto/cryptodev/zc.h
index e914f0f6d27f..f8e8727370d5 100644
--- a/drivers/staging/crypto/cryptodev/zc.h
+++ b/drivers/staging/crypto/cryptodev/zc.h
@@ -7,14 +7,13 @@
 int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
 		int pgcount, struct page **pg, struct scatterlist *sg,
 		struct task_struct *task, struct mm_struct *mm);
-void release_user_pages(struct page **pg, int pagecount);
+void release_user_pages(struct csession* ses);
 
 int get_userbuf(struct csession *ses, void* __user src, int src_len,
                 void* __user dst, int dst_len,
 		struct task_struct *task, struct mm_struct *mm,
                 struct scatterlist **src_sg, 
-                struct scatterlist **dst_sg,
-                int *tot_pages);
+                struct scatterlist **dst_sg);
 
 /* last page - first page + 1 */
 #define PAGECOUNT(buf, buflen) \
-- 
2.1.0

