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
amso1100
c2_vq.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2005 Ammasso, Inc. All rights reserved.
3
* Copyright (c) 2005 Open Grid Computing, 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
#include <linux/slab.h>
34
#include <
linux/spinlock.h
>
35
36
#include "
c2_vq.h
"
37
#include "
c2_provider.h
"
38
39
/*
40
* Verbs Request Objects:
41
*
42
* VQ Request Objects are allocated by the kernel verbs handlers.
43
* They contain a wait object, a refcnt, an atomic bool indicating that the
44
* adapter has replied, and a copy of the verb reply work request.
45
* A pointer to the VQ Request Object is passed down in the context
46
* field of the work request message, and reflected back by the adapter
47
* in the verbs reply message. The function handle_vq() in the interrupt
48
* path will use this pointer to:
49
* 1) append a copy of the verbs reply message
50
* 2) mark that the reply is ready
51
* 3) wake up the kernel verbs handler blocked awaiting the reply.
52
*
53
*
54
* The kernel verbs handlers do a "get" to put a 2nd reference on the
55
* VQ Request object. If the kernel verbs handler exits before the adapter
56
* can respond, this extra reference will keep the VQ Request object around
57
* until the adapter's reply can be processed. The reason we need this is
58
* because a pointer to this object is stuffed into the context field of
59
* the verbs work request message, and reflected back in the reply message.
60
* It is used in the interrupt handler (handle_vq()) to wake up the appropriate
61
* kernel verb handler that is blocked awaiting the verb reply.
62
* So handle_vq() will do a "put" on the object when it's done accessing it.
63
* NOTE: If we guarantee that the kernel verb handler will never bail before
64
* getting the reply, then we don't need these refcnts.
65
*
66
*
67
* VQ Request objects are freed by the kernel verbs handlers only
68
* after the verb has been processed, or when the adapter fails and
69
* does not reply.
70
*
71
*
72
* Verbs Reply Buffers:
73
*
74
* VQ Reply bufs are local host memory copies of a
75
* outstanding Verb Request reply
76
* message. The are always allocated by the kernel verbs handlers, and _may_ be
77
* freed by either the kernel verbs handler -or- the interrupt handler. The
78
* kernel verbs handler _must_ free the repbuf, then free the vq request object
79
* in that order.
80
*/
81
82
int
vq_init
(
struct
c2_dev
*c2dev)
83
{
84
sprintf
(c2dev->
vq_cache_name
,
"c2-vq:dev%c"
,
85
(
char
) (
'0'
+ c2dev->
devnum
));
86
c2dev->
host_msg_cache
=
87
kmem_cache_create
(c2dev->
vq_cache_name
, c2dev->
rep_vq
.msg_size, 0,
88
SLAB_HWCACHE_ALIGN
,
NULL
);
89
if
(c2dev->
host_msg_cache
==
NULL
) {
90
return
-
ENOMEM
;
91
}
92
return
0;
93
}
94
95
void
vq_term
(
struct
c2_dev
*c2dev)
96
{
97
kmem_cache_destroy
(c2dev->
host_msg_cache
);
98
}
99
100
/* vq_req_alloc - allocate a VQ Request Object and initialize it.
101
* The refcnt is set to 1.
102
*/
103
struct
c2_vq_req
*
vq_req_alloc
(
struct
c2_dev
*c2dev)
104
{
105
struct
c2_vq_req
*
r
;
106
107
r =
kmalloc
(
sizeof
(
struct
c2_vq_req
),
GFP_KERNEL
);
108
if
(r) {
109
init_waitqueue_head
(&r->
wait_object
);
110
r->
reply_msg
= 0;
111
r->
event
= 0;
112
r->
cm_id
=
NULL
;
113
r->
qp
=
NULL
;
114
atomic_set
(&r->
refcnt
, 1);
115
atomic_set
(&r->
reply_ready
, 0);
116
}
117
return
r
;
118
}
119
120
121
/* vq_req_free - free the VQ Request Object. It is assumed the verbs handler
122
* has already free the VQ Reply Buffer if it existed.
123
*/
124
void
vq_req_free
(
struct
c2_dev
*c2dev,
struct
c2_vq_req
*
r
)
125
{
126
r->
reply_msg
= 0;
127
if
(
atomic_dec_and_test
(&r->
refcnt
)) {
128
kfree
(r);
129
}
130
}
131
132
/* vq_req_get - reference a VQ Request Object. Done
133
* only in the kernel verbs handlers.
134
*/
135
void
vq_req_get
(
struct
c2_dev
*c2dev,
struct
c2_vq_req
*
r
)
136
{
137
atomic_inc
(&r->
refcnt
);
138
}
139
140
141
/* vq_req_put - dereference and potentially free a VQ Request Object.
142
*
143
* This is only called by handle_vq() on the
144
* interrupt when it is done processing
145
* a verb reply message. If the associated
146
* kernel verbs handler has already bailed,
147
* then this put will actually free the VQ
148
* Request object _and_ the VQ Reply Buffer
149
* if it exists.
150
*/
151
void
vq_req_put
(
struct
c2_dev
*c2dev,
struct
c2_vq_req
*
r
)
152
{
153
if
(
atomic_dec_and_test
(&r->
refcnt
)) {
154
if
(r->
reply_msg
!= 0)
155
vq_repbuf_free
(c2dev,
156
(
void
*) (
unsigned
long
) r->
reply_msg
);
157
kfree
(r);
158
}
159
}
160
161
162
/*
163
* vq_repbuf_alloc - allocate a VQ Reply Buffer.
164
*/
165
void
*
vq_repbuf_alloc
(
struct
c2_dev
*c2dev)
166
{
167
return
kmem_cache_alloc
(c2dev->
host_msg_cache
,
GFP_ATOMIC
);
168
}
169
170
/*
171
* vq_send_wr - post a verbs request message to the Verbs Request Queue.
172
* If a message is not available in the MQ, then block until one is available.
173
* NOTE: handle_mq() on the interrupt context will wake up threads blocked here.
174
* When the adapter drains the Verbs Request Queue,
175
* it inserts MQ index 0 in to the
176
* adapter->host activity fifo and interrupts the host.
177
*/
178
int
vq_send_wr
(
struct
c2_dev
*c2dev,
union
c2wr
*
wr
)
179
{
180
void
*
msg
;
181
wait_queue_t
__wait;
182
183
/*
184
* grab adapter vq lock
185
*/
186
spin_lock(&c2dev->
vqlock
);
187
188
/*
189
* allocate msg
190
*/
191
msg =
c2_mq_alloc
(&c2dev->
req_vq
);
192
193
/*
194
* If we cannot get a msg, then we'll wait
195
* When a messages are available, the int handler will wake_up()
196
* any waiters.
197
*/
198
while
(msg ==
NULL
) {
199
pr_debug
(
"%s:%d no available msg in VQ, waiting...\n"
,
200
__func__, __LINE__);
201
init_waitqueue_entry(&__wait,
current
);
202
add_wait_queue
(&c2dev->
req_vq_wo
, &__wait);
203
spin_unlock(&c2dev->
vqlock
);
204
for
(;;) {
205
set_current_state
(
TASK_INTERRUPTIBLE
);
206
if
(!c2_mq_full(&c2dev->
req_vq
)) {
207
break
;
208
}
209
if
(!signal_pending(
current
)) {
210
schedule_timeout
(1 *
HZ
);
/* 1 second... */
211
continue
;
212
}
213
set_current_state
(
TASK_RUNNING
);
214
remove_wait_queue
(&c2dev->
req_vq_wo
, &__wait);
215
return
-
EINTR
;
216
}
217
set_current_state
(
TASK_RUNNING
);
218
remove_wait_queue
(&c2dev->
req_vq_wo
, &__wait);
219
spin_lock(&c2dev->
vqlock
);
220
msg =
c2_mq_alloc
(&c2dev->
req_vq
);
221
}
222
223
/*
224
* copy wr into adapter msg
225
*/
226
memcpy
(msg, wr, c2dev->
req_vq
.msg_size);
227
228
/*
229
* post msg
230
*/
231
c2_mq_produce
(&c2dev->
req_vq
);
232
233
/*
234
* release adapter vq lock
235
*/
236
spin_unlock(&c2dev->
vqlock
);
237
return
0;
238
}
239
240
241
/*
242
* vq_wait_for_reply - block until the adapter posts a Verb Reply Message.
243
*/
244
int
vq_wait_for_reply
(
struct
c2_dev
*c2dev,
struct
c2_vq_req
*
req
)
245
{
246
if
(!
wait_event_timeout
(req->
wait_object
,
247
atomic_read
(&req->
reply_ready
),
248
60*
HZ
))
249
return
-
ETIMEDOUT
;
250
251
return
0;
252
}
253
254
/*
255
* vq_repbuf_free - Free a Verbs Reply Buffer.
256
*/
257
void
vq_repbuf_free
(
struct
c2_dev
*c2dev,
void
*reply)
258
{
259
kmem_cache_free
(c2dev->
host_msg_cache
, reply);
260
}
Generated on Thu Jan 10 2013 13:37:14 for Linux Kernel by
1.8.2