Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  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
 39#include "mlx4.h"
 40
 41#define MGM_QPN_MASK       0x00FFFFFF
 42#define MGM_BLCK_LB_BIT    30
 43
 44static const u8 zero_gid[16];	/* automatically initialized to 0 */
 45
 46static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
 47			   struct mlx4_cmd_mailbox *mailbox)
 48{
 49	return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
 50			    MLX4_CMD_TIME_CLASS_A);
 51}
 52
 53static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
 54			    struct mlx4_cmd_mailbox *mailbox)
 55{
 56	return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
 57			MLX4_CMD_TIME_CLASS_A);
 58}
 59
 60static 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
 70static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
 71			 u16 *hash, u8 op_mod)
 72{
 73	u64 imm;
 74	int err;
 75
 76	err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
 77			   MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A);
 78
 79	if (!err)
 80		*hash = imm;
 81
 82	return err;
 83}
 84
 85static 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 */
104static 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
180out_mailbox:
181	mlx4_free_cmd_mailbox(dev, mailbox);
182	if (!err)
183		return 0;
184out_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 */
195static 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 */
243static 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. */
281static 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
329out:
330	mlx4_free_cmd_mailbox(dev, mailbox);
331	return ret;
332}
333
334static 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
430out_list:
431	list_del(&pqp->list);
432out_mailbox:
433	mlx4_free_cmd_mailbox(dev, mailbox);
434out_alloc:
435	kfree(pqp);
436out_mutex:
437	mutex_unlock(&priv->mcg_table.mutex);
438	return err;
439}
440
441static 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
525out_mailbox:
526	mlx4_free_cmd_mailbox(dev, mailbox);
527out_list:
528	if (back_to_list)
529		list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
530	else
531		kfree(pqp);
532out_mutex:
533	mutex_unlock(&priv->mcg_table.mutex);
534	return err;
535}
536
537/*
538 * Caller must hold MCG table semaphore.  gid and mgm parameters must
539 * be properly aligned for command interface.
540 *
541 *  Returns 0 unless a firmware command error occurs.
542 *
543 * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
544 * and *mgm holds MGM entry.
545 *
546 * if GID is found in AMGM, *index = index in AMGM, *prev = index of
547 * previous entry in hash chain and *mgm holds AMGM entry.
548 *
549 * If no AMGM exists for given gid, *index = -1, *prev = index of last
550 * entry in hash chain and *mgm holds end of hash chain.
551 */
552static 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)
557{
558	struct mlx4_cmd_mailbox *mailbox;
559	struct mlx4_mgm *mgm = mgm_mailbox->buf;
560	u8 *mgid;
561	int err;
562	u8 op_mod = (prot == MLX4_PROT_ETH) ?
563		!!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
564
565	mailbox = mlx4_alloc_cmd_mailbox(dev);
566	if (IS_ERR(mailbox))
567		return -ENOMEM;
568	mgid = mailbox->buf;
569
570	memcpy(mgid, gid, 16);
571
572	err = mlx4_GID_HASH(dev, mailbox, hash, op_mod);
573	mlx4_free_cmd_mailbox(dev, mailbox);
574	if (err)
575		return err;
576
577	if (0)
578		mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
579
580	*index = *hash;
581	*prev  = -1;
582
583	do {
584		err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
585		if (err)
586			return err;
587
588		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
589			if (*index != *hash) {
590				mlx4_err(dev, "Found zero MGID in AMGM.\n");
591				err = -EINVAL;
592			}
593			return err;
594		}
595
596		if (!memcmp(mgm->gid, gid, 16) &&
597		    be32_to_cpu(mgm->members_count) >> 30 == prot)
598			return err;
599
600		*prev = *index;
601		*index = be32_to_cpu(mgm->next_gid_index) >> 6;
602	} while (*index);
603
604	*index = -1;
605	return err;
606}
607
608int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
609			  int block_mcast_loopback, enum mlx4_protocol prot,
610			  enum mlx4_steer_type steer)
611{
612	struct mlx4_priv *priv = mlx4_priv(dev);
613	struct mlx4_cmd_mailbox *mailbox;
614	struct mlx4_mgm *mgm;
615	u32 members_count;
616	u16 hash;
617	int index, prev;
618	int link = 0;
619	int i;
620	int err;
621	u8 port = gid[5];
622	u8 new_entry = 0;
623
624	mailbox = mlx4_alloc_cmd_mailbox(dev);
625	if (IS_ERR(mailbox))
626		return PTR_ERR(mailbox);
627	mgm = mailbox->buf;
628
629	mutex_lock(&priv->mcg_table.mutex);
630	err = find_entry(dev, port, gid, prot, steer,
631			 mailbox, &hash, &prev, &index);
632	if (err)
633		goto out;
634
635	if (index != -1) {
636		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
637			new_entry = 1;
638			memcpy(mgm->gid, gid, 16);
639		}
640	} else {
641		link = 1;
642
643		index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap);
644		if (index == -1) {
645			mlx4_err(dev, "No AMGM entries left\n");
646			err = -ENOMEM;
647			goto out;
648		}
649		index += dev->caps.num_mgms;
650
651		memset(mgm, 0, sizeof *mgm);
652		memcpy(mgm->gid, gid, 16);
653	}
654
655	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
656	if (members_count == MLX4_QP_PER_MGM) {
657		mlx4_err(dev, "MGM at index %x is full.\n", index);
658		err = -ENOMEM;
659		goto out;
660	}
661
662	for (i = 0; i < members_count; ++i)
663		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
664			mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
665			err = 0;
666			goto out;
667		}
668
669	if (block_mcast_loopback)
670		mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
671						       (1U << MGM_BLCK_LB_BIT));
672	else
673		mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
674
675	mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
676
677	err = mlx4_WRITE_ENTRY(dev, index, mailbox);
678	if (err)
679		goto out;
680
681	if (!link)
682		goto out;
683
684	err = mlx4_READ_ENTRY(dev, prev, mailbox);
685	if (err)
686		goto out;
687
688	mgm->next_gid_index = cpu_to_be32(index << 6);
689
690	err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
691	if (err)
692		goto out;
693
694out:
695	if (prot == MLX4_PROT_ETH) {
696		/* manage the steering entry for promisc mode */
697		if (new_entry)
698			new_steering_entry(dev, 0, port, steer, index, qp->qpn);
699		else
700			existing_steering_entry(dev, 0, port, steer,
701						index, qp->qpn);
702	}
703	if (err && link && index != -1) {
704		if (index < dev->caps.num_mgms)
705			mlx4_warn(dev, "Got AMGM index %d < %d",
706				  index, dev->caps.num_mgms);
707		else
708			mlx4_bitmap_free(&priv->mcg_table.bitmap,
709					 index - dev->caps.num_mgms);
710	}
711	mutex_unlock(&priv->mcg_table.mutex);
712
713	mlx4_free_cmd_mailbox(dev, mailbox);
714	return err;
715}
716
717int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
718			  enum mlx4_protocol prot, enum mlx4_steer_type steer)
719{
720	struct mlx4_priv *priv = mlx4_priv(dev);
721	struct mlx4_cmd_mailbox *mailbox;
722	struct mlx4_mgm *mgm;
723	u32 members_count;
724	u16 hash;
725	int prev, index;
726	int i, loc;
727	int err;
728	u8 port = gid[5];
729	bool removed_entry = false;
730
731	mailbox = mlx4_alloc_cmd_mailbox(dev);
732	if (IS_ERR(mailbox))
733		return PTR_ERR(mailbox);
734	mgm = mailbox->buf;
735
736	mutex_lock(&priv->mcg_table.mutex);
737
738	err = find_entry(dev, port, gid, prot, steer,
739			 mailbox, &hash, &prev, &index);
740	if (err)
741		goto out;
742
743	if (index == -1) {
744		mlx4_err(dev, "MGID %pI6 not found\n", gid);
745		err = -EINVAL;
746		goto out;
747	}
748
749	/* if this pq is also a promisc qp, it shouldn't be removed */
750	if (prot == MLX4_PROT_ETH &&
751	    check_duplicate_entry(dev, 0, port, steer, index, qp->qpn))
752		goto out;
753
754	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
755	for (loc = -1, i = 0; i < members_count; ++i)
756		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
757			loc = i;
758
759	if (loc == -1) {
760		mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
761		err = -EINVAL;
762		goto out;
763	}
764
765
766	mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
767	mgm->qp[loc]       = mgm->qp[i - 1];
768	mgm->qp[i - 1]     = 0;
769
770	if (prot == MLX4_PROT_ETH)
771		removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn);
772	if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
773		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
774		goto out;
775	}
776
777	/* We are going to delete the entry, members count should be 0 */
778	mgm->members_count = cpu_to_be32((u32) prot << 30);
779
780	if (prev == -1) {
781		/* Remove entry from MGM */
782		int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
783		if (amgm_index) {
784			err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
785			if (err)
786				goto out;
787		} else
788			memset(mgm->gid, 0, 16);
789
790		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
791		if (err)
792			goto out;
793
794		if (amgm_index) {
795			if (amgm_index < dev->caps.num_mgms)
796				mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d",
797					  index, amgm_index, dev->caps.num_mgms);
798			else
799				mlx4_bitmap_free(&priv->mcg_table.bitmap,
800						 amgm_index - dev->caps.num_mgms);
801		}
802	} else {
803		/* Remove entry from AMGM */
804		int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
805		err = mlx4_READ_ENTRY(dev, prev, mailbox);
806		if (err)
807			goto out;
808
809		mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
810
811		err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
812		if (err)
813			goto out;
814
815		if (index < dev->caps.num_mgms)
816			mlx4_warn(dev, "entry %d had next AMGM index %d < %d",
817				  prev, index, dev->caps.num_mgms);
818		else
819			mlx4_bitmap_free(&priv->mcg_table.bitmap,
820					 index - dev->caps.num_mgms);
821	}
822
823out:
824	mutex_unlock(&priv->mcg_table.mutex);
825
826	mlx4_free_cmd_mailbox(dev, mailbox);
827	return err;
828}
829
830
831int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
832			  int block_mcast_loopback, enum mlx4_protocol prot)
833{
834	enum mlx4_steer_type steer;
835
836	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
837
838	if (prot == MLX4_PROT_ETH &&
839			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
840		return 0;
841
842	if (prot == MLX4_PROT_ETH)
843		gid[7] |= (steer << 1);
844
845	return mlx4_qp_attach_common(dev, qp, gid,
846				     block_mcast_loopback, prot,
847				     steer);
848}
849EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
850
851int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
852			  enum mlx4_protocol prot)
853{
854	enum mlx4_steer_type steer;
855
856	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
857
858	if (prot == MLX4_PROT_ETH &&
859			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
860		return 0;
861
862	if (prot == MLX4_PROT_ETH) {
863		gid[7] |= (steer << 1);
864	}
865
866	return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
867}
868EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
869
870
871int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
872{
873	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
874		return 0;
875
876
877	return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
878}
879EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
880
881int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
882{
883	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
884		return 0;
885
886
887	return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
888}
889EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
890
891int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
892{
893	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
894		return 0;
895
896
897	return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
898}
899EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
900
901int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
902{
903	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
904		return 0;
905
906	return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
907}
908EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
909
910int mlx4_init_mcg_table(struct mlx4_dev *dev)
911{
912	struct mlx4_priv *priv = mlx4_priv(dev);
913	int err;
914
915	err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms,
916			       dev->caps.num_amgms - 1, 0, 0);
917	if (err)
918		return err;
919
920	mutex_init(&priv->mcg_table.mutex);
921
922	return 0;
923}
924
925void mlx4_cleanup_mcg_table(struct mlx4_dev *dev)
926{
927	mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap);
928}