xref: /OK3568_Linux_fs/kernel/include/crypto/scatterwalk.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Cryptographic scatter and gather helpers.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
6*4882a593Smuzhiyun  * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
7*4882a593Smuzhiyun  * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
8*4882a593Smuzhiyun  * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #ifndef _CRYPTO_SCATTERWALK_H
12*4882a593Smuzhiyun #define _CRYPTO_SCATTERWALK_H
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <crypto/algapi.h>
15*4882a593Smuzhiyun #include <linux/highmem.h>
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/scatterlist.h>
18*4882a593Smuzhiyun 
scatterwalk_crypto_chain(struct scatterlist * head,struct scatterlist * sg,int num)19*4882a593Smuzhiyun static inline void scatterwalk_crypto_chain(struct scatterlist *head,
20*4882a593Smuzhiyun 					    struct scatterlist *sg, int num)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	if (sg)
23*4882a593Smuzhiyun 		sg_chain(head, num, sg);
24*4882a593Smuzhiyun 	else
25*4882a593Smuzhiyun 		sg_mark_end(head);
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun 
scatterwalk_pagelen(struct scatter_walk * walk)28*4882a593Smuzhiyun static inline unsigned int scatterwalk_pagelen(struct scatter_walk *walk)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun 	unsigned int len = walk->sg->offset + walk->sg->length - walk->offset;
31*4882a593Smuzhiyun 	unsigned int len_this_page = offset_in_page(~walk->offset) + 1;
32*4882a593Smuzhiyun 	return len_this_page > len ? len : len_this_page;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
scatterwalk_clamp(struct scatter_walk * walk,unsigned int nbytes)35*4882a593Smuzhiyun static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk,
36*4882a593Smuzhiyun 					     unsigned int nbytes)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	unsigned int len_this_page = scatterwalk_pagelen(walk);
39*4882a593Smuzhiyun 	return nbytes > len_this_page ? len_this_page : nbytes;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
scatterwalk_advance(struct scatter_walk * walk,unsigned int nbytes)42*4882a593Smuzhiyun static inline void scatterwalk_advance(struct scatter_walk *walk,
43*4882a593Smuzhiyun 				       unsigned int nbytes)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	walk->offset += nbytes;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
scatterwalk_aligned(struct scatter_walk * walk,unsigned int alignmask)48*4882a593Smuzhiyun static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk,
49*4882a593Smuzhiyun 					       unsigned int alignmask)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	return !(walk->offset & alignmask);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
scatterwalk_page(struct scatter_walk * walk)54*4882a593Smuzhiyun static inline struct page *scatterwalk_page(struct scatter_walk *walk)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
scatterwalk_unmap(void * vaddr)59*4882a593Smuzhiyun static inline void scatterwalk_unmap(void *vaddr)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	kunmap_atomic(vaddr);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
scatterwalk_start(struct scatter_walk * walk,struct scatterlist * sg)64*4882a593Smuzhiyun static inline void scatterwalk_start(struct scatter_walk *walk,
65*4882a593Smuzhiyun 				     struct scatterlist *sg)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	walk->sg = sg;
68*4882a593Smuzhiyun 	walk->offset = sg->offset;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
scatterwalk_map(struct scatter_walk * walk)71*4882a593Smuzhiyun static inline void *scatterwalk_map(struct scatter_walk *walk)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	return kmap_atomic(scatterwalk_page(walk)) +
74*4882a593Smuzhiyun 	       offset_in_page(walk->offset);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
scatterwalk_pagedone(struct scatter_walk * walk,int out,unsigned int more)77*4882a593Smuzhiyun static inline void scatterwalk_pagedone(struct scatter_walk *walk, int out,
78*4882a593Smuzhiyun 					unsigned int more)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	if (out) {
81*4882a593Smuzhiyun 		struct page *page;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 		page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT);
84*4882a593Smuzhiyun 		/* Test ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE first as
85*4882a593Smuzhiyun 		 * PageSlab cannot be optimised away per se due to
86*4882a593Smuzhiyun 		 * use of volatile pointer.
87*4882a593Smuzhiyun 		 */
88*4882a593Smuzhiyun 		if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE && !PageSlab(page))
89*4882a593Smuzhiyun 			flush_dcache_page(page);
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	if (more && walk->offset >= walk->sg->offset + walk->sg->length)
93*4882a593Smuzhiyun 		scatterwalk_start(walk, sg_next(walk->sg));
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
scatterwalk_done(struct scatter_walk * walk,int out,int more)96*4882a593Smuzhiyun static inline void scatterwalk_done(struct scatter_walk *walk, int out,
97*4882a593Smuzhiyun 				    int more)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	if (!more || walk->offset >= walk->sg->offset + walk->sg->length ||
100*4882a593Smuzhiyun 	    !(walk->offset & (PAGE_SIZE - 1)))
101*4882a593Smuzhiyun 		scatterwalk_pagedone(walk, out, more);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
105*4882a593Smuzhiyun 			    size_t nbytes, int out);
106*4882a593Smuzhiyun void *scatterwalk_map(struct scatter_walk *walk);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
109*4882a593Smuzhiyun 			      unsigned int start, unsigned int nbytes, int out);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
112*4882a593Smuzhiyun 				     struct scatterlist *src,
113*4882a593Smuzhiyun 				     unsigned int len);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #endif  /* _CRYPTO_SCATTERWALK_H */
116