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