xref: /OK3568_Linux_fs/kernel/drivers/crypto/rockchip/cryptodev_linux/util.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2011 Maxim Levitsky
3  *
4  * This file is part of linux cryptodev.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #include <crypto/scatterwalk.h>
23 #include <linux/scatterlist.h>
24 #include "util.h"
25 
26 /* These were taken from Maxim Levitsky's patch to lkml.
27  */
cryptodev_sg_advance(struct scatterlist * sg,int consumed)28 struct scatterlist *cryptodev_sg_advance(struct scatterlist *sg, int consumed)
29 {
30 	while (consumed >= sg->length) {
31 		consumed -= sg->length;
32 
33 		sg = sg_next(sg);
34 		if (!sg)
35 			break;
36 	}
37 
38 	WARN_ON(!sg && consumed);
39 
40 	if (!sg)
41 		return NULL;
42 
43 	sg->offset += consumed;
44 	sg->length -= consumed;
45 
46 	if (sg->offset >= PAGE_SIZE) {
47 		struct page *page =
48 			nth_page(sg_page(sg), sg->offset / PAGE_SIZE);
49 		sg_set_page(sg, page, sg->length, sg->offset % PAGE_SIZE);
50 	}
51 
52 	return sg;
53 }
54 
55 /**
56  * cryptodev_sg_copy - copies sg entries from sg_from to sg_to, such
57  * as sg_to covers first 'len' bytes from sg_from.
58  */
cryptodev_sg_copy(struct scatterlist * sg_from,struct scatterlist * sg_to,int len)59 int cryptodev_sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to, int len)
60 {
61 	while (len > sg_from->length) {
62 		len -= sg_from->length;
63 
64 		sg_set_page(sg_to, sg_page(sg_from),
65 				sg_from->length, sg_from->offset);
66 
67 		sg_to = sg_next(sg_to);
68 		sg_from = sg_next(sg_from);
69 
70 		if (len && (!sg_from || !sg_to))
71 			return -ENOMEM;
72 	}
73 
74 	if (len)
75 		sg_set_page(sg_to, sg_page(sg_from),
76 				len, sg_from->offset);
77 	sg_mark_end(sg_to);
78 	return 0;
79 }
80 
81