OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [mlx4/] [mcg.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
3
 *
4
 * This software is available to you under a choice of one of two
5
 * licenses.  You may choose to be licensed under the terms of the GNU
6
 * General Public License (GPL) Version 2, available from the file
7
 * COPYING in the main directory of this source tree, or the
8
 * OpenIB.org BSD license below:
9
 *
10
 *     Redistribution and use in source and binary forms, with or
11
 *     without modification, are permitted provided that the following
12
 *     conditions are met:
13
 *
14
 *      - Redistributions of source code must retain the above
15
 *        copyright notice, this list of conditions and the following
16
 *        disclaimer.
17
 *
18
 *      - Redistributions in binary form must reproduce the above
19
 *        copyright notice, this list of conditions and the following
20
 *        disclaimer in the documentation and/or other materials
21
 *        provided with the distribution.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
 * SOFTWARE.
31
 */
32
 
33
#include <linux/init.h>
34
#include <linux/string.h>
35
#include <linux/slab.h>
36
 
37
#include <linux/mlx4/cmd.h>
38
 
39
#include "mlx4.h"
40
 
41
struct mlx4_mgm {
42
        __be32                  next_gid_index;
43
        __be32                  members_count;
44
        u32                     reserved[2];
45
        u8                      gid[16];
46
        __be32                  qp[MLX4_QP_PER_MGM];
47
};
48
 
49
static const u8 zero_gid[16];   /* automatically initialized to 0 */
50
 
51
static int mlx4_READ_MCG(struct mlx4_dev *dev, int index,
52
                         struct mlx4_cmd_mailbox *mailbox)
53
{
54
        return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
55
                            MLX4_CMD_TIME_CLASS_A);
56
}
57
 
58
static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index,
59
                          struct mlx4_cmd_mailbox *mailbox)
60
{
61
        return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
62
                        MLX4_CMD_TIME_CLASS_A);
63
}
64
 
65
static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
66
                          u16 *hash)
67
{
68
        u64 imm;
69
        int err;
70
 
71
        err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH,
72
                           MLX4_CMD_TIME_CLASS_A);
73
 
74
        if (!err)
75
                *hash = imm;
76
 
77
        return err;
78
}
79
 
80
/*
81
 * Caller must hold MCG table semaphore.  gid and mgm parameters must
82
 * be properly aligned for command interface.
83
 *
84
 *  Returns 0 unless a firmware command error occurs.
85
 *
86
 * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
87
 * and *mgm holds MGM entry.
88
 *
89
 * if GID is found in AMGM, *index = index in AMGM, *prev = index of
90
 * previous entry in hash chain and *mgm holds AMGM entry.
91
 *
92
 * If no AMGM exists for given gid, *index = -1, *prev = index of last
93
 * entry in hash chain and *mgm holds end of hash chain.
94
 */
95
static int find_mgm(struct mlx4_dev *dev,
96
                    u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox,
97
                    u16 *hash, int *prev, int *index)
98
{
99
        struct mlx4_cmd_mailbox *mailbox;
100
        struct mlx4_mgm *mgm = mgm_mailbox->buf;
101
        u8 *mgid;
102
        int err;
103
 
104
        mailbox = mlx4_alloc_cmd_mailbox(dev);
105
        if (IS_ERR(mailbox))
106
                return -ENOMEM;
107
        mgid = mailbox->buf;
108
 
109
        memcpy(mgid, gid, 16);
110
 
111
        err = mlx4_MGID_HASH(dev, mailbox, hash);
112
        mlx4_free_cmd_mailbox(dev, mailbox);
113
        if (err)
114
                return err;
115
 
116
        if (0)
117
                mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
118
                          "%04x:%04x:%04x:%04x is %04x\n",
119
                          be16_to_cpu(((__be16 *) gid)[0]),
120
                          be16_to_cpu(((__be16 *) gid)[1]),
121
                          be16_to_cpu(((__be16 *) gid)[2]),
122
                          be16_to_cpu(((__be16 *) gid)[3]),
123
                          be16_to_cpu(((__be16 *) gid)[4]),
124
                          be16_to_cpu(((__be16 *) gid)[5]),
125
                          be16_to_cpu(((__be16 *) gid)[6]),
126
                          be16_to_cpu(((__be16 *) gid)[7]),
127
                          *hash);
128
 
129
        *index = *hash;
130
        *prev  = -1;
131
 
132
        do {
133
                err = mlx4_READ_MCG(dev, *index, mgm_mailbox);
134
                if (err)
135
                        return err;
136
 
137
                if (!memcmp(mgm->gid, zero_gid, 16)) {
138
                        if (*index != *hash) {
139
                                mlx4_err(dev, "Found zero MGID in AMGM.\n");
140
                                err = -EINVAL;
141
                        }
142
                        return err;
143
                }
144
 
145
                if (!memcmp(mgm->gid, gid, 16))
146
                        return err;
147
 
148
                *prev = *index;
149
                *index = be32_to_cpu(mgm->next_gid_index) >> 6;
150
        } while (*index);
151
 
152
        *index = -1;
153
        return err;
154
}
155
 
156
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
157
{
158
        struct mlx4_priv *priv = mlx4_priv(dev);
159
        struct mlx4_cmd_mailbox *mailbox;
160
        struct mlx4_mgm *mgm;
161
        u32 members_count;
162
        u16 hash;
163
        int index, prev;
164
        int link = 0;
165
        int i;
166
        int err;
167
 
168
        mailbox = mlx4_alloc_cmd_mailbox(dev);
169
        if (IS_ERR(mailbox))
170
                return PTR_ERR(mailbox);
171
        mgm = mailbox->buf;
172
 
173
        mutex_lock(&priv->mcg_table.mutex);
174
 
175
        err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
176
        if (err)
177
                goto out;
178
 
179
        if (index != -1) {
180
                if (!memcmp(mgm->gid, zero_gid, 16))
181
                        memcpy(mgm->gid, gid, 16);
182
        } else {
183
                link = 1;
184
 
185
                index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap);
186
                if (index == -1) {
187
                        mlx4_err(dev, "No AMGM entries left\n");
188
                        err = -ENOMEM;
189
                        goto out;
190
                }
191
                index += dev->caps.num_mgms;
192
 
193
                err = mlx4_READ_MCG(dev, index, mailbox);
194
                if (err)
195
                        goto out;
196
 
197
                memset(mgm, 0, sizeof *mgm);
198
                memcpy(mgm->gid, gid, 16);
199
        }
200
 
201
        members_count = be32_to_cpu(mgm->members_count);
202
        if (members_count == MLX4_QP_PER_MGM) {
203
                mlx4_err(dev, "MGM at index %x is full.\n", index);
204
                err = -ENOMEM;
205
                goto out;
206
        }
207
 
208
        for (i = 0; i < members_count; ++i)
209
                if (mgm->qp[i] == cpu_to_be32(qp->qpn)) {
210
                        mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
211
                        err = 0;
212
                        goto out;
213
                }
214
 
215
        mgm->qp[members_count++] = cpu_to_be32(qp->qpn);
216
        mgm->members_count       = cpu_to_be32(members_count);
217
 
218
        err = mlx4_WRITE_MCG(dev, index, mailbox);
219
        if (err)
220
                goto out;
221
 
222
        if (!link)
223
                goto out;
224
 
225
        err = mlx4_READ_MCG(dev, prev, mailbox);
226
        if (err)
227
                goto out;
228
 
229
        mgm->next_gid_index = cpu_to_be32(index << 6);
230
 
231
        err = mlx4_WRITE_MCG(dev, prev, mailbox);
232
        if (err)
233
                goto out;
234
 
235
out:
236
        if (err && link && index != -1) {
237
                if (index < dev->caps.num_mgms)
238
                        mlx4_warn(dev, "Got AMGM index %d < %d",
239
                                  index, dev->caps.num_mgms);
240
                else
241
                        mlx4_bitmap_free(&priv->mcg_table.bitmap,
242
                                         index - dev->caps.num_mgms);
243
        }
244
        mutex_unlock(&priv->mcg_table.mutex);
245
 
246
        mlx4_free_cmd_mailbox(dev, mailbox);
247
        return err;
248
}
249
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
250
 
251
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
252
{
253
        struct mlx4_priv *priv = mlx4_priv(dev);
254
        struct mlx4_cmd_mailbox *mailbox;
255
        struct mlx4_mgm *mgm;
256
        u32 members_count;
257
        u16 hash;
258
        int prev, index;
259
        int i, loc;
260
        int err;
261
 
262
        mailbox = mlx4_alloc_cmd_mailbox(dev);
263
        if (IS_ERR(mailbox))
264
                return PTR_ERR(mailbox);
265
        mgm = mailbox->buf;
266
 
267
        mutex_lock(&priv->mcg_table.mutex);
268
 
269
        err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
270
        if (err)
271
                goto out;
272
 
273
        if (index == -1) {
274
                mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
275
                          "not found\n",
276
                          be16_to_cpu(((__be16 *) gid)[0]),
277
                          be16_to_cpu(((__be16 *) gid)[1]),
278
                          be16_to_cpu(((__be16 *) gid)[2]),
279
                          be16_to_cpu(((__be16 *) gid)[3]),
280
                          be16_to_cpu(((__be16 *) gid)[4]),
281
                          be16_to_cpu(((__be16 *) gid)[5]),
282
                          be16_to_cpu(((__be16 *) gid)[6]),
283
                          be16_to_cpu(((__be16 *) gid)[7]));
284
                err = -EINVAL;
285
                goto out;
286
        }
287
 
288
        members_count = be32_to_cpu(mgm->members_count);
289
        for (loc = -1, i = 0; i < members_count; ++i)
290
                if (mgm->qp[i] == cpu_to_be32(qp->qpn))
291
                        loc = i;
292
 
293
        if (loc == -1) {
294
                mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
295
                err = -EINVAL;
296
                goto out;
297
        }
298
 
299
 
300
        mgm->members_count = cpu_to_be32(--members_count);
301
        mgm->qp[loc]       = mgm->qp[i - 1];
302
        mgm->qp[i - 1]     = 0;
303
 
304
        err = mlx4_WRITE_MCG(dev, index, mailbox);
305
        if (err)
306
                goto out;
307
 
308
        if (i != 1)
309
                goto out;
310
 
311
        if (prev == -1) {
312
                /* Remove entry from MGM */
313
                int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
314
                if (amgm_index) {
315
                        err = mlx4_READ_MCG(dev, amgm_index, mailbox);
316
                        if (err)
317
                                goto out;
318
                } else
319
                        memset(mgm->gid, 0, 16);
320
 
321
                err = mlx4_WRITE_MCG(dev, index, mailbox);
322
                if (err)
323
                        goto out;
324
 
325
                if (amgm_index) {
326
                        if (amgm_index < dev->caps.num_mgms)
327
                                mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d",
328
                                          index, amgm_index, dev->caps.num_mgms);
329
                        else
330
                                mlx4_bitmap_free(&priv->mcg_table.bitmap,
331
                                                 amgm_index - dev->caps.num_mgms);
332
                }
333
        } else {
334
                /* Remove entry from AMGM */
335
                int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
336
                err = mlx4_READ_MCG(dev, prev, mailbox);
337
                if (err)
338
                        goto out;
339
 
340
                mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
341
 
342
                err = mlx4_WRITE_MCG(dev, prev, mailbox);
343
                if (err)
344
                        goto out;
345
 
346
                if (index < dev->caps.num_mgms)
347
                        mlx4_warn(dev, "entry %d had next AMGM index %d < %d",
348
                                  prev, index, dev->caps.num_mgms);
349
                else
350
                        mlx4_bitmap_free(&priv->mcg_table.bitmap,
351
                                         index - dev->caps.num_mgms);
352
        }
353
 
354
out:
355
        mutex_unlock(&priv->mcg_table.mutex);
356
 
357
        mlx4_free_cmd_mailbox(dev, mailbox);
358
        return err;
359
}
360
EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
361
 
362
int mlx4_init_mcg_table(struct mlx4_dev *dev)
363
{
364
        struct mlx4_priv *priv = mlx4_priv(dev);
365
        int err;
366
 
367
        err = mlx4_bitmap_init(&priv->mcg_table.bitmap,
368
                               dev->caps.num_amgms, dev->caps.num_amgms - 1, 0);
369
        if (err)
370
                return err;
371
 
372
        mutex_init(&priv->mcg_table.mutex);
373
 
374
        return 0;
375
}
376
 
377
void mlx4_cleanup_mcg_table(struct mlx4_dev *dev)
378
{
379
        mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap);
380
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.