~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/mlx4/mcg.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 */
33
33
 
34
34
#include <linux/string.h>
 
35
#include <linux/etherdevice.h>
35
36
 
36
37
#include <linux/mlx4/cmd.h>
37
38
 
40
41
#define MGM_QPN_MASK       0x00FFFFFF
41
42
#define MGM_BLCK_LB_BIT    30
42
43
 
43
 
struct mlx4_mgm {
44
 
        __be32                  next_gid_index;
45
 
        __be32                  members_count;
46
 
        u32                     reserved[2];
47
 
        u8                      gid[16];
48
 
        __be32                  qp[MLX4_QP_PER_MGM];
49
 
};
50
 
 
51
44
static const u8 zero_gid[16];   /* automatically initialized to 0 */
52
45
 
53
 
static int mlx4_READ_MCG(struct mlx4_dev *dev, int index,
54
 
                         struct mlx4_cmd_mailbox *mailbox)
 
46
static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
 
47
                           struct mlx4_cmd_mailbox *mailbox)
55
48
{
56
49
        return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
57
50
                            MLX4_CMD_TIME_CLASS_A);
58
51
}
59
52
 
60
 
static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index,
61
 
                          struct mlx4_cmd_mailbox *mailbox)
 
53
static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
 
54
                            struct mlx4_cmd_mailbox *mailbox)
62
55
{
63
56
        return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
64
57
                        MLX4_CMD_TIME_CLASS_A);
65
58
}
66
59
 
67
 
static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
68
 
                          u16 *hash)
 
60
static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 vep_num, u8 port, u8 steer,
 
61
                              struct mlx4_cmd_mailbox *mailbox)
 
62
{
 
63
        u32 in_mod;
 
64
 
 
65
        in_mod = (u32) vep_num << 24 | (u32) port << 16 | steer << 1;
 
66
        return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1,
 
67
                        MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A);
 
68
}
 
69
 
 
70
static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
 
71
                         u16 *hash, u8 op_mod)
69
72
{
70
73
        u64 imm;
71
74
        int err;
72
75
 
73
 
        err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH,
74
 
                           MLX4_CMD_TIME_CLASS_A);
 
76
        err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
 
77
                           MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A);
75
78
 
76
79
        if (!err)
77
80
                *hash = imm;
79
82
        return err;
80
83
}
81
84
 
 
85
static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
 
86
                                              enum mlx4_steer_type steer,
 
87
                                              u32 qpn)
 
88
{
 
89
        struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
 
90
        struct mlx4_promisc_qp *pqp;
 
91
 
 
92
        list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
 
93
                if (pqp->qpn == qpn)
 
94
                        return pqp;
 
95
        }
 
96
        /* not found */
 
97
        return NULL;
 
98
}
 
99
 
 
100
/*
 
101
 * Add new entry to steering data structure.
 
102
 * All promisc QPs should be added as well
 
103
 */
 
104
static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
105
                              enum mlx4_steer_type steer,
 
106
                              unsigned int index, u32 qpn)
 
107
{
 
108
        struct mlx4_steer *s_steer;
 
109
        struct mlx4_cmd_mailbox *mailbox;
 
110
        struct mlx4_mgm *mgm;
 
111
        u32 members_count;
 
112
        struct mlx4_steer_index *new_entry;
 
113
        struct mlx4_promisc_qp *pqp;
 
114
        struct mlx4_promisc_qp *dqp = NULL;
 
115
        u32 prot;
 
116
        int err;
 
117
        u8 pf_num;
 
118
 
 
119
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
120
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
121
        new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
 
122
        if (!new_entry)
 
123
                return -ENOMEM;
 
124
 
 
125
        INIT_LIST_HEAD(&new_entry->duplicates);
 
126
        new_entry->index = index;
 
127
        list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]);
 
128
 
 
129
        /* If the given qpn is also a promisc qp,
 
130
         * it should be inserted to duplicates list
 
131
         */
 
132
        pqp = get_promisc_qp(dev, pf_num, steer, qpn);
 
133
        if (pqp) {
 
134
                dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
 
135
                if (!dqp) {
 
136
                        err = -ENOMEM;
 
137
                        goto out_alloc;
 
138
                }
 
139
                dqp->qpn = qpn;
 
140
                list_add_tail(&dqp->list, &new_entry->duplicates);
 
141
        }
 
142
 
 
143
        /* if no promisc qps for this vep, we are done */
 
144
        if (list_empty(&s_steer->promisc_qps[steer]))
 
145
                return 0;
 
146
 
 
147
        /* now need to add all the promisc qps to the new
 
148
         * steering entry, as they should also receive the packets
 
149
         * destined to this address */
 
150
        mailbox = mlx4_alloc_cmd_mailbox(dev);
 
151
        if (IS_ERR(mailbox)) {
 
152
                err = -ENOMEM;
 
153
                goto out_alloc;
 
154
        }
 
155
        mgm = mailbox->buf;
 
156
 
 
157
        err = mlx4_READ_ENTRY(dev, index, mailbox);
 
158
        if (err)
 
159
                goto out_mailbox;
 
160
 
 
161
        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 
162
        prot = be32_to_cpu(mgm->members_count) >> 30;
 
163
        list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
 
164
                /* don't add already existing qpn */
 
165
                if (pqp->qpn == qpn)
 
166
                        continue;
 
167
                if (members_count == MLX4_QP_PER_MGM) {
 
168
                        /* out of space */
 
169
                        err = -ENOMEM;
 
170
                        goto out_mailbox;
 
171
                }
 
172
 
 
173
                /* add the qpn */
 
174
                mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK);
 
175
        }
 
176
        /* update the qps count and update the entry with all the promisc qps*/
 
177
        mgm->members_count = cpu_to_be32(members_count | (prot << 30));
 
178
        err = mlx4_WRITE_ENTRY(dev, index, mailbox);
 
179
 
 
180
out_mailbox:
 
181
        mlx4_free_cmd_mailbox(dev, mailbox);
 
182
        if (!err)
 
183
                return 0;
 
184
out_alloc:
 
185
        if (dqp) {
 
186
                list_del(&dqp->list);
 
187
                kfree(dqp);
 
188
        }
 
189
        list_del(&new_entry->list);
 
190
        kfree(new_entry);
 
191
        return err;
 
192
}
 
193
 
 
194
/* update the data structures with existing steering entry */
 
195
static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
196
                                   enum mlx4_steer_type steer,
 
197
                                   unsigned int index, u32 qpn)
 
198
{
 
199
        struct mlx4_steer *s_steer;
 
200
        struct mlx4_steer_index *tmp_entry, *entry = NULL;
 
201
        struct mlx4_promisc_qp *pqp;
 
202
        struct mlx4_promisc_qp *dqp;
 
203
        u8 pf_num;
 
204
 
 
205
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
206
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
207
 
 
208
        pqp = get_promisc_qp(dev, pf_num, steer, qpn);
 
209
        if (!pqp)
 
210
                return 0; /* nothing to do */
 
211
 
 
212
        list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
 
213
                if (tmp_entry->index == index) {
 
214
                        entry = tmp_entry;
 
215
                        break;
 
216
                }
 
217
        }
 
218
        if (unlikely(!entry)) {
 
219
                mlx4_warn(dev, "Steering entry at index %x is not registered\n", index);
 
220
                return -EINVAL;
 
221
        }
 
222
 
 
223
        /* the given qpn is listed as a promisc qpn
 
224
         * we need to add it as a duplicate to this entry
 
225
         * for future references */
 
226
        list_for_each_entry(dqp, &entry->duplicates, list) {
 
227
                if (qpn == dqp->qpn)
 
228
                        return 0; /* qp is already duplicated */
 
229
        }
 
230
 
 
231
        /* add the qp as a duplicate on this index */
 
232
        dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
 
233
        if (!dqp)
 
234
                return -ENOMEM;
 
235
        dqp->qpn = qpn;
 
236
        list_add_tail(&dqp->list, &entry->duplicates);
 
237
 
 
238
        return 0;
 
239
}
 
240
 
 
241
/* Check whether a qpn is a duplicate on steering entry
 
242
 * If so, it should not be removed from mgm */
 
243
static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
244
                                  enum mlx4_steer_type steer,
 
245
                                  unsigned int index, u32 qpn)
 
246
{
 
247
        struct mlx4_steer *s_steer;
 
248
        struct mlx4_steer_index *tmp_entry, *entry = NULL;
 
249
        struct mlx4_promisc_qp *dqp, *tmp_dqp;
 
250
        u8 pf_num;
 
251
 
 
252
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
253
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
254
 
 
255
        /* if qp is not promisc, it cannot be duplicated */
 
256
        if (!get_promisc_qp(dev, pf_num, steer, qpn))
 
257
                return false;
 
258
 
 
259
        /* The qp is promisc qp so it is a duplicate on this index
 
260
         * Find the index entry, and remove the duplicate */
 
261
        list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
 
262
                if (tmp_entry->index == index) {
 
263
                        entry = tmp_entry;
 
264
                        break;
 
265
                }
 
266
        }
 
267
        if (unlikely(!entry)) {
 
268
                mlx4_warn(dev, "Steering entry for index %x is not registered\n", index);
 
269
                return false;
 
270
        }
 
271
        list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) {
 
272
                if (dqp->qpn == qpn) {
 
273
                        list_del(&dqp->list);
 
274
                        kfree(dqp);
 
275
                }
 
276
        }
 
277
        return true;
 
278
}
 
279
 
 
280
/* I a steering entry contains only promisc QPs, it can be removed. */
 
281
static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
282
                                      enum mlx4_steer_type steer,
 
283
                                      unsigned int index, u32 tqpn)
 
284
{
 
285
        struct mlx4_steer *s_steer;
 
286
        struct mlx4_cmd_mailbox *mailbox;
 
287
        struct mlx4_mgm *mgm;
 
288
        struct mlx4_steer_index *entry = NULL, *tmp_entry;
 
289
        u32 qpn;
 
290
        u32 members_count;
 
291
        bool ret = false;
 
292
        int i;
 
293
        u8 pf_num;
 
294
 
 
295
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
296
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
297
 
 
298
        mailbox = mlx4_alloc_cmd_mailbox(dev);
 
299
        if (IS_ERR(mailbox))
 
300
                return false;
 
301
        mgm = mailbox->buf;
 
302
 
 
303
        if (mlx4_READ_ENTRY(dev, index, mailbox))
 
304
                goto out;
 
305
        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 
306
        for (i = 0;  i < members_count; i++) {
 
307
                qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
 
308
                if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) {
 
309
                        /* the qp is not promisc, the entry can't be removed */
 
310
                        goto out;
 
311
                }
 
312
        }
 
313
         /* All the qps currently registered for this entry are promiscuous,
 
314
          * Checking for duplicates */
 
315
        ret = true;
 
316
        list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
 
317
                if (entry->index == index) {
 
318
                        if (list_empty(&entry->duplicates)) {
 
319
                                list_del(&entry->list);
 
320
                                kfree(entry);
 
321
                        } else {
 
322
                                /* This entry contains duplicates so it shouldn't be removed */
 
323
                                ret = false;
 
324
                                goto out;
 
325
                        }
 
326
                }
 
327
        }
 
328
 
 
329
out:
 
330
        mlx4_free_cmd_mailbox(dev, mailbox);
 
331
        return ret;
 
332
}
 
333
 
 
334
static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
335
                          enum mlx4_steer_type steer, u32 qpn)
 
336
{
 
337
        struct mlx4_steer *s_steer;
 
338
        struct mlx4_cmd_mailbox *mailbox;
 
339
        struct mlx4_mgm *mgm;
 
340
        struct mlx4_steer_index *entry;
 
341
        struct mlx4_promisc_qp *pqp;
 
342
        struct mlx4_promisc_qp *dqp;
 
343
        u32 members_count;
 
344
        u32 prot;
 
345
        int i;
 
346
        bool found;
 
347
        int last_index;
 
348
        int err;
 
349
        u8 pf_num;
 
350
        struct mlx4_priv *priv = mlx4_priv(dev);
 
351
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
352
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
353
 
 
354
        mutex_lock(&priv->mcg_table.mutex);
 
355
 
 
356
        if (get_promisc_qp(dev, pf_num, steer, qpn)) {
 
357
                err = 0;  /* Noting to do, already exists */
 
358
                goto out_mutex;
 
359
        }
 
360
 
 
361
        pqp = kmalloc(sizeof *pqp, GFP_KERNEL);
 
362
        if (!pqp) {
 
363
                err = -ENOMEM;
 
364
                goto out_mutex;
 
365
        }
 
366
        pqp->qpn = qpn;
 
367
 
 
368
        mailbox = mlx4_alloc_cmd_mailbox(dev);
 
369
        if (IS_ERR(mailbox)) {
 
370
                err = -ENOMEM;
 
371
                goto out_alloc;
 
372
        }
 
373
        mgm = mailbox->buf;
 
374
 
 
375
        /* the promisc qp needs to be added for each one of the steering
 
376
         * entries, if it already exists, needs to be added as a duplicate
 
377
         * for this entry */
 
378
        list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
 
379
                err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
 
380
                if (err)
 
381
                        goto out_mailbox;
 
382
 
 
383
                members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 
384
                prot = be32_to_cpu(mgm->members_count) >> 30;
 
385
                found = false;
 
386
                for (i = 0; i < members_count; i++) {
 
387
                        if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
 
388
                                /* Entry already exists, add to duplicates */
 
389
                                dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
 
390
                                if (!dqp)
 
391
                                        goto out_mailbox;
 
392
                                dqp->qpn = qpn;
 
393
                                list_add_tail(&dqp->list, &entry->duplicates);
 
394
                                found = true;
 
395
                        }
 
396
                }
 
397
                if (!found) {
 
398
                        /* Need to add the qpn to mgm */
 
399
                        if (members_count == MLX4_QP_PER_MGM) {
 
400
                                /* entry is full */
 
401
                                err = -ENOMEM;
 
402
                                goto out_mailbox;
 
403
                        }
 
404
                        mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
 
405
                        mgm->members_count = cpu_to_be32(members_count | (prot << 30));
 
406
                        err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
 
407
                        if (err)
 
408
                                goto out_mailbox;
 
409
                }
 
410
                last_index = entry->index;
 
411
        }
 
412
 
 
413
        /* add the new qpn to list of promisc qps */
 
414
        list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
 
415
        /* now need to add all the promisc qps to default entry */
 
416
        memset(mgm, 0, sizeof *mgm);
 
417
        members_count = 0;
 
418
        list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
 
419
                mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
 
420
        mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
 
421
 
 
422
        err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
 
423
        if (err)
 
424
                goto out_list;
 
425
 
 
426
        mlx4_free_cmd_mailbox(dev, mailbox);
 
427
        mutex_unlock(&priv->mcg_table.mutex);
 
428
        return 0;
 
429
 
 
430
out_list:
 
431
        list_del(&pqp->list);
 
432
out_mailbox:
 
433
        mlx4_free_cmd_mailbox(dev, mailbox);
 
434
out_alloc:
 
435
        kfree(pqp);
 
436
out_mutex:
 
437
        mutex_unlock(&priv->mcg_table.mutex);
 
438
        return err;
 
439
}
 
440
 
 
441
static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
 
442
                             enum mlx4_steer_type steer, u32 qpn)
 
443
{
 
444
        struct mlx4_priv *priv = mlx4_priv(dev);
 
445
        struct mlx4_steer *s_steer;
 
446
        struct mlx4_cmd_mailbox *mailbox;
 
447
        struct mlx4_mgm *mgm;
 
448
        struct mlx4_steer_index *entry;
 
449
        struct mlx4_promisc_qp *pqp;
 
450
        struct mlx4_promisc_qp *dqp;
 
451
        u32 members_count;
 
452
        bool found;
 
453
        bool back_to_list = false;
 
454
        int loc, i;
 
455
        int err;
 
456
        u8 pf_num;
 
457
 
 
458
        pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
 
459
        s_steer = &mlx4_priv(dev)->steer[pf_num];
 
460
        mutex_lock(&priv->mcg_table.mutex);
 
461
 
 
462
        pqp = get_promisc_qp(dev, pf_num, steer, qpn);
 
463
        if (unlikely(!pqp)) {
 
464
                mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
 
465
                /* nothing to do */
 
466
                err = 0;
 
467
                goto out_mutex;
 
468
        }
 
469
 
 
470
        /*remove from list of promisc qps */
 
471
        list_del(&pqp->list);
 
472
 
 
473
        /* set the default entry not to include the removed one */
 
474
        mailbox = mlx4_alloc_cmd_mailbox(dev);
 
475
        if (IS_ERR(mailbox)) {
 
476
                err = -ENOMEM;
 
477
                back_to_list = true;
 
478
                goto out_list;
 
479
        }
 
480
        mgm = mailbox->buf;
 
481
        members_count = 0;
 
482
        list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
 
483
                mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
 
484
        mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
 
485
 
 
486
        err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
 
487
        if (err)
 
488
                goto out_mailbox;
 
489
 
 
490
        /* remove the qp from all the steering entries*/
 
491
        list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
 
492
                found = false;
 
493
                list_for_each_entry(dqp, &entry->duplicates, list) {
 
494
                        if (dqp->qpn == qpn) {
 
495
                                found = true;
 
496
                                break;
 
497
                        }
 
498
                }
 
499
                if (found) {
 
500
                        /* a duplicate, no need to change the mgm,
 
501
                         * only update the duplicates list */
 
502
                        list_del(&dqp->list);
 
503
                        kfree(dqp);
 
504
                } else {
 
505
                        err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
 
506
                                if (err)
 
507
                                        goto out_mailbox;
 
508
                        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 
509
                        for (loc = -1, i = 0; i < members_count; ++i)
 
510
                                if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
 
511
                                        loc = i;
 
512
 
 
513
                        mgm->members_count = cpu_to_be32(--members_count |
 
514
                                                         (MLX4_PROT_ETH << 30));
 
515
                        mgm->qp[loc] = mgm->qp[i - 1];
 
516
                        mgm->qp[i - 1] = 0;
 
517
 
 
518
                        err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
 
519
                                if (err)
 
520
                                        goto out_mailbox;
 
521
                }
 
522
 
 
523
        }
 
524
 
 
525
out_mailbox:
 
526
        mlx4_free_cmd_mailbox(dev, mailbox);
 
527
out_list:
 
528
        if (back_to_list)
 
529
                list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
 
530
        else
 
531
                kfree(pqp);
 
532
out_mutex:
 
533
        mutex_unlock(&priv->mcg_table.mutex);
 
534
        return err;
 
535
}
 
536
 
82
537
/*
83
538
 * Caller must hold MCG table semaphore.  gid and mgm parameters must
84
539
 * be properly aligned for command interface.
94
549
 * If no AMGM exists for given gid, *index = -1, *prev = index of last
95
550
 * entry in hash chain and *mgm holds end of hash chain.
96
551
 */
97
 
static int find_mgm(struct mlx4_dev *dev,
98
 
                    u8 *gid, enum mlx4_protocol protocol,
99
 
                    struct mlx4_cmd_mailbox *mgm_mailbox,
100
 
                    u16 *hash, int *prev, int *index)
 
552
static int find_entry(struct mlx4_dev *dev, u8 port,
 
553
                      u8 *gid, enum mlx4_protocol prot,
 
554
                      enum mlx4_steer_type steer,
 
555
                      struct mlx4_cmd_mailbox *mgm_mailbox,
 
556
                      u16 *hash, int *prev, int *index)
101
557
{
102
558
        struct mlx4_cmd_mailbox *mailbox;
103
559
        struct mlx4_mgm *mgm = mgm_mailbox->buf;
104
560
        u8 *mgid;
105
561
        int err;
 
562
        u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0;
106
563
 
107
564
        mailbox = mlx4_alloc_cmd_mailbox(dev);
108
565
        if (IS_ERR(mailbox))
111
568
 
112
569
        memcpy(mgid, gid, 16);
113
570
 
114
 
        err = mlx4_MGID_HASH(dev, mailbox, hash);
 
571
        err = mlx4_GID_HASH(dev, mailbox, hash, op_mod);
115
572
        mlx4_free_cmd_mailbox(dev, mailbox);
116
573
        if (err)
117
574
                return err;
123
580
        *prev  = -1;
124
581
 
125
582
        do {
126
 
                err = mlx4_READ_MCG(dev, *index, mgm_mailbox);
 
583
                err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
127
584
                if (err)
128
585
                        return err;
129
586
 
130
 
                if (!memcmp(mgm->gid, zero_gid, 16)) {
 
587
                if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
131
588
                        if (*index != *hash) {
132
589
                                mlx4_err(dev, "Found zero MGID in AMGM.\n");
133
590
                                err = -EINVAL;
136
593
                }
137
594
 
138
595
                if (!memcmp(mgm->gid, gid, 16) &&
139
 
                    be32_to_cpu(mgm->members_count) >> 30 == protocol)
 
596
                    be32_to_cpu(mgm->members_count) >> 30 == prot)
140
597
                        return err;
141
598
 
142
599
                *prev = *index;
147
604
        return err;
148
605
}
149
606
 
150
 
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
151
 
                          int block_mcast_loopback, enum mlx4_protocol protocol)
 
607
int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
608
                          int block_mcast_loopback, enum mlx4_protocol prot,
 
609
                          enum mlx4_steer_type steer)
152
610
{
153
611
        struct mlx4_priv *priv = mlx4_priv(dev);
154
612
        struct mlx4_cmd_mailbox *mailbox;
159
617
        int link = 0;
160
618
        int i;
161
619
        int err;
 
620
        u8 port = gid[5];
 
621
        u8 new_entry = 0;
162
622
 
163
623
        mailbox = mlx4_alloc_cmd_mailbox(dev);
164
624
        if (IS_ERR(mailbox))
166
626
        mgm = mailbox->buf;
167
627
 
168
628
        mutex_lock(&priv->mcg_table.mutex);
169
 
 
170
 
        err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
 
629
        err = find_entry(dev, port, gid, prot, steer,
 
630
                         mailbox, &hash, &prev, &index);
171
631
        if (err)
172
632
                goto out;
173
633
 
174
634
        if (index != -1) {
175
 
                if (!memcmp(mgm->gid, zero_gid, 16))
 
635
                if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
 
636
                        new_entry = 1;
176
637
                        memcpy(mgm->gid, gid, 16);
 
638
                }
177
639
        } else {
178
640
                link = 1;
179
641
 
209
671
        else
210
672
                mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
211
673
 
212
 
        mgm->members_count = cpu_to_be32(members_count | (u32) protocol << 30);
 
674
        mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
213
675
 
214
 
        err = mlx4_WRITE_MCG(dev, index, mailbox);
 
676
        err = mlx4_WRITE_ENTRY(dev, index, mailbox);
215
677
        if (err)
216
678
                goto out;
217
679
 
218
680
        if (!link)
219
681
                goto out;
220
682
 
221
 
        err = mlx4_READ_MCG(dev, prev, mailbox);
 
683
        err = mlx4_READ_ENTRY(dev, prev, mailbox);
222
684
        if (err)
223
685
                goto out;
224
686
 
225
687
        mgm->next_gid_index = cpu_to_be32(index << 6);
226
688
 
227
 
        err = mlx4_WRITE_MCG(dev, prev, mailbox);
 
689
        err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
228
690
        if (err)
229
691
                goto out;
230
692
 
231
693
out:
 
694
        if (prot == MLX4_PROT_ETH) {
 
695
                /* manage the steering entry for promisc mode */
 
696
                if (new_entry)
 
697
                        new_steering_entry(dev, 0, port, steer, index, qp->qpn);
 
698
                else
 
699
                        existing_steering_entry(dev, 0, port, steer,
 
700
                                                index, qp->qpn);
 
701
        }
232
702
        if (err && link && index != -1) {
233
703
                if (index < dev->caps.num_mgms)
234
704
                        mlx4_warn(dev, "Got AMGM index %d < %d",
242
712
        mlx4_free_cmd_mailbox(dev, mailbox);
243
713
        return err;
244
714
}
245
 
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
246
715
 
247
 
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
248
 
                          enum mlx4_protocol protocol)
 
716
int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
717
                          enum mlx4_protocol prot, enum mlx4_steer_type steer)
249
718
{
250
719
        struct mlx4_priv *priv = mlx4_priv(dev);
251
720
        struct mlx4_cmd_mailbox *mailbox;
255
724
        int prev, index;
256
725
        int i, loc;
257
726
        int err;
 
727
        u8 port = gid[5];
 
728
        bool removed_entry = false;
258
729
 
259
730
        mailbox = mlx4_alloc_cmd_mailbox(dev);
260
731
        if (IS_ERR(mailbox))
263
734
 
264
735
        mutex_lock(&priv->mcg_table.mutex);
265
736
 
266
 
        err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
 
737
        err = find_entry(dev, port, gid, prot, steer,
 
738
                         mailbox, &hash, &prev, &index);
267
739
        if (err)
268
740
                goto out;
269
741
 
273
745
                goto out;
274
746
        }
275
747
 
 
748
        /* if this pq is also a promisc qp, it shouldn't be removed */
 
749
        if (prot == MLX4_PROT_ETH &&
 
750
            check_duplicate_entry(dev, 0, port, steer, index, qp->qpn))
 
751
                goto out;
 
752
 
276
753
        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
277
754
        for (loc = -1, i = 0; i < members_count; ++i)
278
755
                if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
285
762
        }
286
763
 
287
764
 
288
 
        mgm->members_count = cpu_to_be32(--members_count | (u32) protocol << 30);
 
765
        mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
289
766
        mgm->qp[loc]       = mgm->qp[i - 1];
290
767
        mgm->qp[i - 1]     = 0;
291
768
 
292
 
        if (i != 1) {
293
 
                err = mlx4_WRITE_MCG(dev, index, mailbox);
 
769
        if (prot == MLX4_PROT_ETH)
 
770
                removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn);
 
771
        if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
 
772
                err = mlx4_WRITE_ENTRY(dev, index, mailbox);
294
773
                goto out;
295
774
        }
296
775
 
 
776
        /* We are going to delete the entry, members count should be 0 */
 
777
        mgm->members_count = cpu_to_be32((u32) prot << 30);
 
778
 
297
779
        if (prev == -1) {
298
780
                /* Remove entry from MGM */
299
781
                int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
300
782
                if (amgm_index) {
301
 
                        err = mlx4_READ_MCG(dev, amgm_index, mailbox);
 
783
                        err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
302
784
                        if (err)
303
785
                                goto out;
304
786
                } else
305
787
                        memset(mgm->gid, 0, 16);
306
788
 
307
 
                err = mlx4_WRITE_MCG(dev, index, mailbox);
 
789
                err = mlx4_WRITE_ENTRY(dev, index, mailbox);
308
790
                if (err)
309
791
                        goto out;
310
792
 
319
801
        } else {
320
802
                /* Remove entry from AMGM */
321
803
                int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
322
 
                err = mlx4_READ_MCG(dev, prev, mailbox);
 
804
                err = mlx4_READ_ENTRY(dev, prev, mailbox);
323
805
                if (err)
324
806
                        goto out;
325
807
 
326
808
                mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
327
809
 
328
 
                err = mlx4_WRITE_MCG(dev, prev, mailbox);
 
810
                err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
329
811
                if (err)
330
812
                        goto out;
331
813
 
343
825
        mlx4_free_cmd_mailbox(dev, mailbox);
344
826
        return err;
345
827
}
 
828
 
 
829
 
 
830
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
831
                          int block_mcast_loopback, enum mlx4_protocol prot)
 
832
{
 
833
        enum mlx4_steer_type steer;
 
834
 
 
835
        steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
 
836
 
 
837
        if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
 
838
                return 0;
 
839
 
 
840
        if (prot == MLX4_PROT_ETH)
 
841
                gid[7] |= (steer << 1);
 
842
 
 
843
        return mlx4_qp_attach_common(dev, qp, gid,
 
844
                                     block_mcast_loopback, prot,
 
845
                                     steer);
 
846
}
 
847
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
 
848
 
 
849
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
850
                          enum mlx4_protocol prot)
 
851
{
 
852
        enum mlx4_steer_type steer;
 
853
 
 
854
        steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
 
855
 
 
856
        if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
 
857
                return 0;
 
858
 
 
859
        if (prot == MLX4_PROT_ETH) {
 
860
                gid[7] |= (steer << 1);
 
861
        }
 
862
 
 
863
        return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
 
864
}
346
865
EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
347
866
 
 
867
 
 
868
int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
 
869
{
 
870
        if (!dev->caps.vep_mc_steering)
 
871
                return 0;
 
872
 
 
873
 
 
874
        return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
 
875
}
 
876
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
 
877
 
 
878
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
 
879
{
 
880
        if (!dev->caps.vep_mc_steering)
 
881
                return 0;
 
882
 
 
883
 
 
884
        return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
 
885
}
 
886
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
 
887
 
 
888
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
 
889
{
 
890
        if (!dev->caps.vep_mc_steering)
 
891
                return 0;
 
892
 
 
893
 
 
894
        return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
 
895
}
 
896
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
 
897
 
 
898
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
 
899
{
 
900
        if (!dev->caps.vep_mc_steering)
 
901
                return 0;
 
902
 
 
903
        return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
 
904
}
 
905
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
 
906
 
348
907
int mlx4_init_mcg_table(struct mlx4_dev *dev)
349
908
{
350
909
        struct mlx4_priv *priv = mlx4_priv(dev);