~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to drivers/infiniband/hw/amso1100/c2_mm.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
35
#include "c2.h"
 
36
#include "c2_vq.h"
 
37
 
 
38
#define PBL_VIRT 1
 
39
#define PBL_PHYS 2
 
40
 
 
41
/*
 
42
 * Send all the PBL messages to convey the remainder of the PBL
 
43
 * Wait for the adapter's reply on the last one.
 
44
 * This is indicated by setting the MEM_PBL_COMPLETE in the flags.
 
45
 *
 
46
 * NOTE:  vq_req is _not_ freed by this function.  The VQ Host
 
47
 *        Reply buffer _is_ freed by this function.
 
48
 */
 
49
static int
 
50
send_pbl_messages(struct c2_dev *c2dev, __be32 stag_index,
 
51
                  unsigned long va, u32 pbl_depth,
 
52
                  struct c2_vq_req *vq_req, int pbl_type)
 
53
{
 
54
        u32 pbe_count;          /* amt that fits in a PBL msg */
 
55
        u32 count;              /* amt in this PBL MSG. */
 
56
        struct c2wr_nsmr_pbl_req *wr;   /* PBL WR ptr */
 
57
        struct c2wr_nsmr_pbl_rep *reply;        /* reply ptr */
 
58
        int err, pbl_virt, pbl_index, i;
 
59
 
 
60
        switch (pbl_type) {
 
61
        case PBL_VIRT:
 
62
                pbl_virt = 1;
 
63
                break;
 
64
        case PBL_PHYS:
 
65
                pbl_virt = 0;
 
66
                break;
 
67
        default:
 
68
                return -EINVAL;
 
69
                break;
 
70
        }
 
71
 
 
72
        pbe_count = (c2dev->req_vq.msg_size -
 
73
                     sizeof(struct c2wr_nsmr_pbl_req)) / sizeof(u64);
 
74
        wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL);
 
75
        if (!wr) {
 
76
                return -ENOMEM;
 
77
        }
 
78
        c2_wr_set_id(wr, CCWR_NSMR_PBL);
 
79
 
 
80
        /*
 
81
         * Only the last PBL message will generate a reply from the verbs,
 
82
         * so we set the context to 0 indicating there is no kernel verbs
 
83
         * handler blocked awaiting this reply.
 
84
         */
 
85
        wr->hdr.context = 0;
 
86
        wr->rnic_handle = c2dev->adapter_handle;
 
87
        wr->stag_index = stag_index;    /* already swapped */
 
88
        wr->flags = 0;
 
89
        pbl_index = 0;
 
90
        while (pbl_depth) {
 
91
                count = min(pbe_count, pbl_depth);
 
92
                wr->addrs_length = cpu_to_be32(count);
 
93
 
 
94
                /*
 
95
                 *  If this is the last message, then reference the
 
96
                 *  vq request struct cuz we're gonna wait for a reply.
 
97
                 *  also make this PBL msg as the last one.
 
98
                 */
 
99
                if (count == pbl_depth) {
 
100
                        /*
 
101
                         * reference the request struct.  dereferenced in the
 
102
                         * int handler.
 
103
                         */
 
104
                        vq_req_get(c2dev, vq_req);
 
105
                        wr->flags = cpu_to_be32(MEM_PBL_COMPLETE);
 
106
 
 
107
                        /*
 
108
                         * This is the last PBL message.
 
109
                         * Set the context to our VQ Request Object so we can
 
110
                         * wait for the reply.
 
111
                         */
 
112
                        wr->hdr.context = (unsigned long) vq_req;
 
113
                }
 
114
 
 
115
                /*
 
116
                 * If pbl_virt is set then va is a virtual address
 
117
                 * that describes a virtually contiguous memory
 
118
                 * allocation. The wr needs the start of each virtual page
 
119
                 * to be converted to the corresponding physical address
 
120
                 * of the page. If pbl_virt is not set then va is an array
 
121
                 * of physical addresses and there is no conversion to do.
 
122
                 * Just fill in the wr with what is in the array.
 
123
                 */
 
124
                for (i = 0; i < count; i++) {
 
125
                        if (pbl_virt) {
 
126
                                va += PAGE_SIZE;
 
127
                        } else {
 
128
                                wr->paddrs[i] =
 
129
                                    cpu_to_be64(((u64 *)va)[pbl_index + i]);
 
130
                        }
 
131
                }
 
132
 
 
133
                /*
 
134
                 * Send WR to adapter
 
135
                 */
 
136
                err = vq_send_wr(c2dev, (union c2wr *) wr);
 
137
                if (err) {
 
138
                        if (count <= pbe_count) {
 
139
                                vq_req_put(c2dev, vq_req);
 
140
                        }
 
141
                        goto bail0;
 
142
                }
 
143
                pbl_depth -= count;
 
144
                pbl_index += count;
 
145
        }
 
146
 
 
147
        /*
 
148
         *  Now wait for the reply...
 
149
         */
 
150
        err = vq_wait_for_reply(c2dev, vq_req);
 
151
        if (err) {
 
152
                goto bail0;
 
153
        }
 
154
 
 
155
        /*
 
156
         * Process reply
 
157
         */
 
158
        reply = (struct c2wr_nsmr_pbl_rep *) (unsigned long) vq_req->reply_msg;
 
159
        if (!reply) {
 
160
                err = -ENOMEM;
 
161
                goto bail0;
 
162
        }
 
163
 
 
164
        err = c2_errno(reply);
 
165
 
 
166
        vq_repbuf_free(c2dev, reply);
 
167
      bail0:
 
168
        kfree(wr);
 
169
        return err;
 
170
}
 
171
 
 
172
#define C2_PBL_MAX_DEPTH 131072
 
173
int
 
174
c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list,
 
175
                           int page_size, int pbl_depth, u32 length,
 
176
                           u32 offset, u64 *va, enum c2_acf acf,
 
177
                           struct c2_mr *mr)
 
178
{
 
179
        struct c2_vq_req *vq_req;
 
180
        struct c2wr_nsmr_register_req *wr;
 
181
        struct c2wr_nsmr_register_rep *reply;
 
182
        u16 flags;
 
183
        int i, pbe_count, count;
 
184
        int err;
 
185
 
 
186
        if (!va || !length || !addr_list || !pbl_depth)
 
187
                return -EINTR;
 
188
 
 
189
        /*
 
190
         * Verify PBL depth is within rnic max
 
191
         */
 
192
        if (pbl_depth > C2_PBL_MAX_DEPTH) {
 
193
                return -EINTR;
 
194
        }
 
195
 
 
196
        /*
 
197
         * allocate verbs request object
 
198
         */
 
199
        vq_req = vq_req_alloc(c2dev);
 
200
        if (!vq_req)
 
201
                return -ENOMEM;
 
202
 
 
203
        wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL);
 
204
        if (!wr) {
 
205
                err = -ENOMEM;
 
206
                goto bail0;
 
207
        }
 
208
 
 
209
        /*
 
210
         * build the WR
 
211
         */
 
212
        c2_wr_set_id(wr, CCWR_NSMR_REGISTER);
 
213
        wr->hdr.context = (unsigned long) vq_req;
 
214
        wr->rnic_handle = c2dev->adapter_handle;
 
215
 
 
216
        flags = (acf | MEM_VA_BASED | MEM_REMOTE);
 
217
 
 
218
        /*
 
219
         * compute how many pbes can fit in the message
 
220
         */
 
221
        pbe_count = (c2dev->req_vq.msg_size -
 
222
                     sizeof(struct c2wr_nsmr_register_req)) / sizeof(u64);
 
223
 
 
224
        if (pbl_depth <= pbe_count) {
 
225
                flags |= MEM_PBL_COMPLETE;
 
226
        }
 
227
        wr->flags = cpu_to_be16(flags);
 
228
        wr->stag_key = 0;       //stag_key;
 
229
        wr->va = cpu_to_be64(*va);
 
230
        wr->pd_id = mr->pd->pd_id;
 
231
        wr->pbe_size = cpu_to_be32(page_size);
 
232
        wr->length = cpu_to_be32(length);
 
233
        wr->pbl_depth = cpu_to_be32(pbl_depth);
 
234
        wr->fbo = cpu_to_be32(offset);
 
235
        count = min(pbl_depth, pbe_count);
 
236
        wr->addrs_length = cpu_to_be32(count);
 
237
 
 
238
        /*
 
239
         * fill out the PBL for this message
 
240
         */
 
241
        for (i = 0; i < count; i++) {
 
242
                wr->paddrs[i] = cpu_to_be64(addr_list[i]);
 
243
        }
 
244
 
 
245
        /*
 
246
         * regerence the request struct
 
247
         */
 
248
        vq_req_get(c2dev, vq_req);
 
249
 
 
250
        /*
 
251
         * send the WR to the adapter
 
252
         */
 
253
        err = vq_send_wr(c2dev, (union c2wr *) wr);
 
254
        if (err) {
 
255
                vq_req_put(c2dev, vq_req);
 
256
                goto bail1;
 
257
        }
 
258
 
 
259
        /*
 
260
         * wait for reply from adapter
 
261
         */
 
262
        err = vq_wait_for_reply(c2dev, vq_req);
 
263
        if (err) {
 
264
                goto bail1;
 
265
        }
 
266
 
 
267
        /*
 
268
         * process reply
 
269
         */
 
270
        reply =
 
271
            (struct c2wr_nsmr_register_rep *) (unsigned long) (vq_req->reply_msg);
 
272
        if (!reply) {
 
273
                err = -ENOMEM;
 
274
                goto bail1;
 
275
        }
 
276
        if ((err = c2_errno(reply))) {
 
277
                goto bail2;
 
278
        }
 
279
        //*p_pb_entries = be32_to_cpu(reply->pbl_depth);
 
280
        mr->ibmr.lkey = mr->ibmr.rkey = be32_to_cpu(reply->stag_index);
 
281
        vq_repbuf_free(c2dev, reply);
 
282
 
 
283
        /*
 
284
         * if there are still more PBEs we need to send them to
 
285
         * the adapter and wait for a reply on the final one.
 
286
         * reuse vq_req for this purpose.
 
287
         */
 
288
        pbl_depth -= count;
 
289
        if (pbl_depth) {
 
290
 
 
291
                vq_req->reply_msg = (unsigned long) NULL;
 
292
                atomic_set(&vq_req->reply_ready, 0);
 
293
                err = send_pbl_messages(c2dev,
 
294
                                        cpu_to_be32(mr->ibmr.lkey),
 
295
                                        (unsigned long) &addr_list[i],
 
296
                                        pbl_depth, vq_req, PBL_PHYS);
 
297
                if (err) {
 
298
                        goto bail1;
 
299
                }
 
300
        }
 
301
 
 
302
        vq_req_free(c2dev, vq_req);
 
303
        kfree(wr);
 
304
 
 
305
        return err;
 
306
 
 
307
      bail2:
 
308
        vq_repbuf_free(c2dev, reply);
 
309
      bail1:
 
310
        kfree(wr);
 
311
      bail0:
 
312
        vq_req_free(c2dev, vq_req);
 
313
        return err;
 
314
}
 
315
 
 
316
int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index)
 
317
{
 
318
        struct c2_vq_req *vq_req;       /* verbs request object */
 
319
        struct c2wr_stag_dealloc_req wr;        /* work request */
 
320
        struct c2wr_stag_dealloc_rep *reply;    /* WR reply  */
 
321
        int err;
 
322
 
 
323
 
 
324
        /*
 
325
         * allocate verbs request object
 
326
         */
 
327
        vq_req = vq_req_alloc(c2dev);
 
328
        if (!vq_req) {
 
329
                return -ENOMEM;
 
330
        }
 
331
 
 
332
        /*
 
333
         * Build the WR
 
334
         */
 
335
        c2_wr_set_id(&wr, CCWR_STAG_DEALLOC);
 
336
        wr.hdr.context = (u64) (unsigned long) vq_req;
 
337
        wr.rnic_handle = c2dev->adapter_handle;
 
338
        wr.stag_index = cpu_to_be32(stag_index);
 
339
 
 
340
        /*
 
341
         * reference the request struct.  dereferenced in the int handler.
 
342
         */
 
343
        vq_req_get(c2dev, vq_req);
 
344
 
 
345
        /*
 
346
         * Send WR to adapter
 
347
         */
 
348
        err = vq_send_wr(c2dev, (union c2wr *) & wr);
 
349
        if (err) {
 
350
                vq_req_put(c2dev, vq_req);
 
351
                goto bail0;
 
352
        }
 
353
 
 
354
        /*
 
355
         * Wait for reply from adapter
 
356
         */
 
357
        err = vq_wait_for_reply(c2dev, vq_req);
 
358
        if (err) {
 
359
                goto bail0;
 
360
        }
 
361
 
 
362
        /*
 
363
         * Process reply
 
364
         */
 
365
        reply = (struct c2wr_stag_dealloc_rep *) (unsigned long) vq_req->reply_msg;
 
366
        if (!reply) {
 
367
                err = -ENOMEM;
 
368
                goto bail0;
 
369
        }
 
370
 
 
371
        err = c2_errno(reply);
 
372
 
 
373
        vq_repbuf_free(c2dev, reply);
 
374
      bail0:
 
375
        vq_req_free(c2dev, vq_req);
 
376
        return err;
 
377
}