Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
rtl8192u
ieee80211
scatterwalk.c
Go to the documentation of this file.
1
/*
2
* Cryptographic API.
3
*
4
* Cipher operations.
5
*
6
* Copyright (c) 2002 James Morris <
[email protected]
>
7
* 2002 Adam J. Richter <
[email protected]
>
8
* 2004 Jean-Luc Cooke <
[email protected]
>
9
*
10
* This program is free software; you can redistribute it and/or modify it
11
* under the terms of the GNU General Public License as published by the Free
12
* Software Foundation; either version 2 of the License, or (at your option)
13
* any later version.
14
*
15
*/
16
#include <linux/kernel.h>
17
#include <
linux/mm.h
>
18
#include <
linux/pagemap.h
>
19
#include <
linux/highmem.h
>
20
#include <asm/scatterlist.h>
21
#include "
internal.h
"
22
#include "
scatterwalk.h
"
23
24
void
*
scatterwalk_whichbuf
(
struct
scatter_walk
*walk,
unsigned
int
nbytes
,
void
*
scratch
)
25
{
26
if
(nbytes <= walk->
len_this_page
&&
27
(((
unsigned
long
)walk->
data
) & (
PAGE_CACHE_SIZE
- 1)) + nbytes <=
28
PAGE_CACHE_SIZE
)
29
return
walk->
data
;
30
else
31
return
scratch
;
32
}
33
34
static
void
memcpy_dir(
void
*
buf
,
void
*sgdata,
size_t
nbytes
,
int
out
)
35
{
36
if
(out)
37
memcpy
(sgdata, buf, nbytes);
38
else
39
memcpy
(buf, sgdata, nbytes);
40
}
41
42
void
scatterwalk_start
(
struct
scatter_walk
*walk,
struct
scatterlist
*
sg
)
43
{
44
unsigned
int
rest_of_page;
45
46
walk->
sg
=
sg
;
47
48
walk->
page
= sg->page;
49
walk->
len_this_segment
= sg->
length
;
50
51
rest_of_page =
PAGE_CACHE_SIZE
- (sg->
offset
& (
PAGE_CACHE_SIZE
- 1));
52
walk->
len_this_page
=
min
(sg->
length
, rest_of_page);
53
walk->
offset
= sg->
offset
;
54
}
55
56
void
scatterwalk_map
(
struct
scatter_walk
*walk)
57
{
58
walk->
data
=
kmap_atomic
(walk->
page
) + walk->
offset
;
59
}
60
61
static
void
scatterwalk_pagedone(
struct
scatter_walk
*walk,
int
out,
62
unsigned
int
more)
63
{
64
/* walk->data may be pointing the first byte of the next page;
65
however, we know we transferred at least one byte. So,
66
walk->data - 1 will be a virtual address in the mapped page. */
67
68
if
(out)
69
flush_dcache_page
(walk->
page
);
70
71
if
(more) {
72
walk->
len_this_segment
-= walk->
len_this_page
;
73
74
if
(walk->
len_this_segment
) {
75
walk->
page
++;
76
walk->
len_this_page
=
min
(walk->
len_this_segment
,
77
(
unsigned
)
PAGE_CACHE_SIZE
);
78
walk->
offset
= 0;
79
}
80
else
81
scatterwalk_start
(walk,
sg_next
(walk->
sg
));
82
}
83
}
84
85
void
scatterwalk_done
(
struct
scatter_walk
*walk,
int
out,
int
more)
86
{
87
crypto_kunmap(walk->
data
, out);
88
if
(walk->
len_this_page
== 0 || !more)
89
scatterwalk_pagedone(walk, out, more);
90
}
91
92
/*
93
* Do not call this unless the total length of all of the fragments
94
* has been verified as multiple of the block size.
95
*/
96
int
scatterwalk_copychunks
(
void
*buf,
struct
scatter_walk
*walk,
97
size_t
nbytes)
98
{
99
if
(buf != walk->
data
) {
100
while
(nbytes > walk->
len_this_page
) {
101
memcpy_dir(buf, walk->
data
, walk->
len_this_page
, out);
102
buf += walk->
len_this_page
;
103
nbytes -= walk->
len_this_page
;
104
105
kunmap_atomic
(walk->
data
);
106
scatterwalk_pagedone(walk, out, 1);
107
scatterwalk_map
(walk);
108
}
109
110
memcpy_dir(buf, walk->
data
, nbytes, out);
111
}
112
113
walk->
offset
+=
nbytes
;
114
walk->
len_this_page
-=
nbytes
;
115
walk->
len_this_segment
-=
nbytes
;
116
return
0;
117
}
Generated on Thu Jan 10 2013 13:23:07 for Linux Kernel by
1.8.2