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
infiniband
hw
ipath
ipath_keys.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
3
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
4
*
5
* This software is available to you under a choice of one of two
6
* licenses. You may choose to be licensed under the terms of the GNU
7
* General Public License (GPL) Version 2, available from the file
8
* COPYING in the main directory of this source tree, or the
9
* OpenIB.org BSD license below:
10
*
11
* Redistribution and use in source and binary forms, with or
12
* without modification, are permitted provided that the following
13
* conditions are met:
14
*
15
* - Redistributions of source code must retain the above
16
* copyright notice, this list of conditions and the following
17
* disclaimer.
18
*
19
* - Redistributions in binary form must reproduce the above
20
* copyright notice, this list of conditions and the following
21
* disclaimer in the documentation and/or other materials
22
* provided with the distribution.
23
*
24
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
* SOFTWARE.
32
*/
33
34
#include <asm/io.h>
35
36
#include "
ipath_verbs.h
"
37
#include "
ipath_kernel.h
"
38
47
int
ipath_alloc_lkey
(
struct
ipath_lkey_table
*rkt,
struct
ipath_mregion
*mr)
48
{
49
unsigned
long
flags
;
50
u32
r
;
51
u32
n
;
52
int
ret
;
53
54
spin_lock_irqsave
(&rkt->
lock
, flags);
55
56
/* Find the next available LKEY */
57
r = n = rkt->
next
;
58
for
(;;) {
59
if
(rkt->
table
[r] ==
NULL
)
60
break
;
61
r = (r + 1) & (rkt->
max
- 1);
62
if
(r == n) {
63
spin_unlock_irqrestore(&rkt->
lock
, flags);
64
ipath_dbg
(
"LKEY table full\n"
);
65
ret = 0;
66
goto
bail;
67
}
68
}
69
rkt->
next
= (r + 1) & (rkt->
max
- 1);
70
/*
71
* Make sure lkey is never zero which is reserved to indicate an
72
* unrestricted LKEY.
73
*/
74
rkt->
gen
++;
75
mr->
lkey
= (r << (32 -
ib_ipath_lkey_table_size
)) |
76
((((1 << (24 -
ib_ipath_lkey_table_size
)) - 1) & rkt->
gen
)
77
<< 8);
78
if
(mr->
lkey
== 0) {
79
mr->
lkey
|= 1 << 8;
80
rkt->
gen
++;
81
}
82
rkt->
table
[
r
] = mr;
83
spin_unlock_irqrestore(&rkt->
lock
, flags);
84
85
ret = 1;
86
87
bail:
88
return
ret
;
89
}
90
96
void
ipath_free_lkey
(
struct
ipath_lkey_table
*rkt,
u32
lkey
)
97
{
98
unsigned
long
flags
;
99
u32
r
;
100
101
if
(lkey == 0)
102
return
;
103
r = lkey >> (32 -
ib_ipath_lkey_table_size
);
104
spin_lock_irqsave
(&rkt->
lock
, flags);
105
rkt->
table
[
r
] =
NULL
;
106
spin_unlock_irqrestore(&rkt->
lock
, flags);
107
}
108
121
int
ipath_lkey_ok
(
struct
ipath_qp
*qp,
struct
ipath_sge
*isge,
122
struct
ib_sge
*
sge
,
int
acc)
123
{
124
struct
ipath_lkey_table
*rkt = &to_idev(qp->
ibqp
.device)->lk_table;
125
struct
ipath_mregion
*mr;
126
unsigned
n
,
m
;
127
size_t
off;
128
int
ret
;
129
130
/*
131
* We use LKEY == zero for kernel virtual addresses
132
* (see ipath_get_dma_mr and ipath_dma.c).
133
*/
134
if
(sge->
lkey
== 0) {
135
/* always a kernel port, no locking needed */
136
struct
ipath_pd
*
pd
= to_ipd(qp->
ibqp
.pd);
137
138
if
(pd->
user
) {
139
ret = 0;
140
goto
bail;
141
}
142
isge->
mr
=
NULL
;
143
isge->
vaddr
= (
void
*) sge->
addr
;
144
isge->
length
= sge->
length
;
145
isge->
sge_length
= sge->
length
;
146
ret = 1;
147
goto
bail;
148
}
149
mr = rkt->
table
[(sge->
lkey
>> (32 -
ib_ipath_lkey_table_size
))];
150
if
(
unlikely
(mr ==
NULL
|| mr->
lkey
!= sge->
lkey
||
151
qp->
ibqp
.pd != mr->
pd
)) {
152
ret = 0;
153
goto
bail;
154
}
155
156
off = sge->
addr
- mr->
user_base
;
157
if
(
unlikely
(sge->
addr
< mr->
user_base
||
158
off + sge->
length
> mr->
length
||
159
(mr->
access_flags
& acc) != acc)) {
160
ret = 0;
161
goto
bail;
162
}
163
164
off += mr->
offset
;
165
m = 0;
166
n = 0;
167
while
(off >= mr->
map
[m]->segs[n].length) {
168
off -= mr->
map
[
m
]->segs[
n
].length;
169
n++;
170
if
(n >=
IPATH_SEGSZ
) {
171
m++;
172
n = 0;
173
}
174
}
175
isge->
mr
= mr;
176
isge->
vaddr
= mr->
map
[
m
]->segs[
n
].vaddr + off;
177
isge->
length
= mr->
map
[
m
]->segs[
n
].length - off;
178
isge->
sge_length
= sge->
length
;
179
isge->
m
=
m
;
180
isge->
n
=
n
;
181
182
ret = 1;
183
184
bail:
185
return
ret
;
186
}
187
199
int
ipath_rkey_ok
(
struct
ipath_qp
*qp,
struct
ipath_sge_state
*
ss
,
200
u32
len,
u64
vaddr
,
u32
rkey
,
int
acc)
201
{
202
struct
ipath_ibdev
*
dev
= to_idev(qp->
ibqp
.device);
203
struct
ipath_lkey_table
*rkt = &dev->
lk_table
;
204
struct
ipath_sge
*
sge
= &ss->
sge
;
205
struct
ipath_mregion
*mr;
206
unsigned
n
,
m
;
207
size_t
off;
208
int
ret
;
209
210
/*
211
* We use RKEY == zero for kernel virtual addresses
212
* (see ipath_get_dma_mr and ipath_dma.c).
213
*/
214
if
(rkey == 0) {
215
/* always a kernel port, no locking needed */
216
struct
ipath_pd
*
pd
= to_ipd(qp->
ibqp
.pd);
217
218
if
(pd->
user
) {
219
ret = 0;
220
goto
bail;
221
}
222
sge->
mr
=
NULL
;
223
sge->
vaddr
= (
void
*) vaddr;
224
sge->
length
= len;
225
sge->
sge_length
= len;
226
ss->
sg_list
=
NULL
;
227
ss->
num_sge
= 1;
228
ret = 1;
229
goto
bail;
230
}
231
232
mr = rkt->
table
[(rkey >> (32 -
ib_ipath_lkey_table_size
))];
233
if
(
unlikely
(mr ==
NULL
|| mr->
lkey
!= rkey ||
234
qp->
ibqp
.pd != mr->
pd
)) {
235
ret = 0;
236
goto
bail;
237
}
238
239
off = vaddr - mr->
iova
;
240
if
(
unlikely
(vaddr < mr->
iova
|| off + len > mr->
length
||
241
(mr->
access_flags
& acc) == 0)) {
242
ret = 0;
243
goto
bail;
244
}
245
246
off += mr->
offset
;
247
m = 0;
248
n = 0;
249
while
(off >= mr->
map
[m]->segs[n].length) {
250
off -= mr->
map
[
m
]->segs[
n
].length;
251
n++;
252
if
(n >=
IPATH_SEGSZ
) {
253
m++;
254
n = 0;
255
}
256
}
257
sge->
mr
= mr;
258
sge->
vaddr
= mr->
map
[
m
]->segs[
n
].vaddr + off;
259
sge->
length
= mr->
map
[
m
]->segs[
n
].length - off;
260
sge->
sge_length
= len;
261
sge->
m
=
m
;
262
sge->
n
=
n
;
263
ss->
sg_list
=
NULL
;
264
ss->
num_sge
= 1;
265
266
ret = 1;
267
268
bail:
269
return
ret
;
270
}
Generated on Thu Jan 10 2013 13:37:42 for Linux Kernel by
1.8.2