Blame view

crypto/scatterwalk.c 2.51 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Cryptographic API.
   *
   * Cipher operations.
   *
   * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
   *               2002 Adam J. Richter <adam@yggdrasil.com>
   *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
   *
   * 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.
   *
   */
  #include <linux/kernel.h>
  #include <linux/mm.h>
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
18
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/pagemap.h>
  #include <linux/highmem.h>
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
21
  #include <linux/scatterlist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
  #include "internal.h"
  #include "scatterwalk.h"
  
  enum km_type crypto_km_types[] = {
  	KM_USER0,
  	KM_USER1,
  	KM_SOFTIRQ0,
  	KM_SOFTIRQ1,
  };
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
31
  EXPORT_SYMBOL_GPL(crypto_km_types);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32

5c64097aa   Herbert Xu   [CRYPTO] scatterw...
33
  static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  {
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
35
36
37
38
  	void *src = out ? buf : sgdata;
  	void *dst = out ? sgdata : buf;
  
  	memcpy(dst, src, nbytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
  }
  
  void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  	walk->sg = sg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  	BUG_ON(!sg->length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
  	walk->offset = sg->offset;
  }
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
47
  EXPORT_SYMBOL_GPL(scatterwalk_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

5c64097aa   Herbert Xu   [CRYPTO] scatterw...
49
  void *scatterwalk_map(struct scatter_walk *walk, int out)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  {
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
51
52
  	return crypto_kmap(scatterwalk_page(walk), out) +
  	       offset_in_page(walk->offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  }
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
54
  EXPORT_SYMBOL_GPL(scatterwalk_map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
  
  static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
  				 unsigned int more)
  {
9f1167272   Herbert Xu   [CRYPTO] api: Flu...
59
60
61
62
63
64
  	if (out) {
  		struct page *page;
  
  		page = walk->sg->page + ((walk->offset - 1) >> PAGE_SHIFT);
  		flush_dcache_page(page);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  
  	if (more) {
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
67
68
69
  		walk->offset += PAGE_SIZE - 1;
  		walk->offset &= PAGE_MASK;
  		if (walk->offset >= walk->sg->offset + walk->sg->length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
  			scatterwalk_start(walk, sg_next(walk->sg));
  	}
  }
  
  void scatterwalk_done(struct scatter_walk *walk, int out, int more)
  {
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
76
  	if (!offset_in_page(walk->offset) || !more)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
  		scatterwalk_pagedone(walk, out, more);
  }
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
79
  EXPORT_SYMBOL_GPL(scatterwalk_done);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

5c64097aa   Herbert Xu   [CRYPTO] scatterw...
81
82
  void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
  			    size_t nbytes, int out)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  {
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
84
85
86
87
88
89
90
91
92
93
  	for (;;) {
  		unsigned int len_this_page = scatterwalk_pagelen(walk);
  		u8 *vaddr;
  
  		if (len_this_page > nbytes)
  			len_this_page = nbytes;
  
  		vaddr = scatterwalk_map(walk, out);
  		memcpy_dir(buf, vaddr, len_this_page, out);
  		scatterwalk_unmap(vaddr, out);
4ee531a3e   Herbert Xu   [CRYPTO] api: Use...
94
  		scatterwalk_advance(walk, len_this_page);
f70ee5ec8   J. Bruce Fields   [CRYPTO] api: sca...
95

5c64097aa   Herbert Xu   [CRYPTO] scatterw...
96
97
98
99
100
  		if (nbytes == len_this_page)
  			break;
  
  		buf += len_this_page;
  		nbytes -= len_this_page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  		scatterwalk_pagedone(walk, out, 1);
c774e93e2   Herbert Xu   [CRYPTO] Add plum...
103
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  }
5c64097aa   Herbert Xu   [CRYPTO] scatterw...
105
  EXPORT_SYMBOL_GPL(scatterwalk_copychunks);