1225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier/*
2225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
351a379d0c8f7a6db7c9e3c9c770d90a6d2d1ef9bJack Morgenstein * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
4225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
5225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * This software is available to you under a choice of one of two
6225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * licenses.  You may choose to be licensed under the terms of the GNU
7225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * General Public License (GPL) Version 2, available from the file
8225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * COPYING in the main directory of this source tree, or the
9225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * OpenIB.org BSD license below:
10225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
11225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *     Redistribution and use in source and binary forms, with or
12225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *     without modification, are permitted provided that the following
13225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *     conditions are met:
14225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
15225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *      - Redistributions of source code must retain the above
16225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *        copyright notice, this list of conditions and the following
17225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *        disclaimer.
18225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
19225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *      - Redistributions in binary form must reproduce the above
20225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *        copyright notice, this list of conditions and the following
21225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *        disclaimer in the documentation and/or other materials
22225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *        provided with the distribution.
23225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
24225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * SOFTWARE.
32225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier */
33225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
34225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier#include <linux/string.h>
350345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin#include <linux/etherdevice.h>
36225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
37225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier#include <linux/mlx4/cmd.h>
38ee40fa0656a730491765545ff7550f3c1ceb0fbcPaul Gortmaker#include <linux/export.h>
39225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
40225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier#include "mlx4.h"
41225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
42521e575b9a7324a0bca762622139f69582a042bfRon Livne#define MGM_QPN_MASK       0x00FFFFFF
43521e575b9a7324a0bca762622139f69582a042bfRon Livne#define MGM_BLCK_LB_BIT    30
44521e575b9a7324a0bca762622139f69582a042bfRon Livne
45225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreierstatic const u8 zero_gid[16];	/* automatically initialized to 0 */
46225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
470ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstruct mlx4_mgm {
480ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	__be32			next_gid_index;
490ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	__be32			members_count;
500ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	u32			reserved[2];
510ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	u8			gid[16];
520ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	__be32			qp[MLX4_MAX_QP_PER_MGM];
530ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev};
540ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
550ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevint mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
560ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
570ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE);
580ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
590ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
600ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevint mlx4_get_qp_per_mgm(struct mlx4_dev *dev)
610ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
620ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2);
630ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
640ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
650345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinstatic int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
660345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			   struct mlx4_cmd_mailbox *mailbox)
67225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
68225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
69f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
70225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
71225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
720345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinstatic int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
730345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			    struct mlx4_cmd_mailbox *mailbox)
74225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
75225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
76f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
77225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
78225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
790ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer,
80b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			      struct mlx4_cmd_mailbox *mailbox)
81b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
82b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 in_mod;
83b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
840ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	in_mod = (u32) port << 16 | steer << 1;
85b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1,
86f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A,
87f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			MLX4_CMD_NATIVE);
88b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
89b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
900345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinstatic int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
910345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			 u16 *hash, u8 op_mod)
92225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
93225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	u64 imm;
94225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int err;
95225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
960345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
97f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			   MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A,
98f9baff509f8a05a79626defdbdf4f4aa4efd373bJack Morgenstein			   MLX4_CMD_NATIVE);
99225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
100225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (!err)
101225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		*hash = imm;
102225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
103225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return err;
104225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
105225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
106b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinstatic struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
107b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					      enum mlx4_steer_type steer,
108b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					      u32 qpn)
109b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
110b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
111b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *pqp;
112b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
113b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
114b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (pqp->qpn == qpn)
115b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			return pqp;
116b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
117b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* not found */
118b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return NULL;
119b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
120b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
121b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin/*
122b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin * Add new entry to steering data structure.
123b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin * All promisc QPs should be added as well
124b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin */
1250ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int new_steering_entry(struct mlx4_dev *dev, u8 port,
126b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			      enum mlx4_steer_type steer,
127b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			      unsigned int index, u32 qpn)
128b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
129b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
130b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_cmd_mailbox *mailbox;
131b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_mgm *mgm;
132b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 members_count;
133b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *new_entry;
134b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *pqp;
135a14b289d4614bb3b25d0455d68f72f3c7b4cc8e8Mariusz Kozlowski	struct mlx4_promisc_qp *dqp = NULL;
136b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 prot;
137b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int err;
138b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
1394c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
140b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
141b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (!new_entry)
142b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return -ENOMEM;
143b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
144b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	INIT_LIST_HEAD(&new_entry->duplicates);
145b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	new_entry->index = index;
146b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]);
147b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
148b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* If the given qpn is also a promisc qp,
149b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * it should be inserted to duplicates list
150b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 */
1510ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	pqp = get_promisc_qp(dev, 0, steer, qpn);
152b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (pqp) {
153b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
154b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (!dqp) {
155b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			err = -ENOMEM;
156b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			goto out_alloc;
157b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
158b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		dqp->qpn = qpn;
159b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		list_add_tail(&dqp->list, &new_entry->duplicates);
160b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
161b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
162b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* if no promisc qps for this vep, we are done */
163b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (list_empty(&s_steer->promisc_qps[steer]))
164b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
165b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
166b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* now need to add all the promisc qps to the new
167b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * steering entry, as they should also receive the packets
168b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * destined to this address */
169b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mailbox = mlx4_alloc_cmd_mailbox(dev);
170b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (IS_ERR(mailbox)) {
171b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = -ENOMEM;
172b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_alloc;
173b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
174b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm = mailbox->buf;
175b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
176b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	err = mlx4_READ_ENTRY(dev, index, mailbox);
177b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (err)
178b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_mailbox;
179b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
180b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
181b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	prot = be32_to_cpu(mgm->members_count) >> 30;
182b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
183b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		/* don't add already existing qpn */
184b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (pqp->qpn == qpn)
185b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			continue;
1860ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		if (members_count == dev->caps.num_qp_per_mgm) {
187b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			/* out of space */
188b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			err = -ENOMEM;
189b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			goto out_mailbox;
190b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
191b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
192b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		/* add the qpn */
193b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK);
194b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
195b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* update the qps count and update the entry with all the promisc qps*/
196b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm->members_count = cpu_to_be32(members_count | (prot << 30));
197b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	err = mlx4_WRITE_ENTRY(dev, index, mailbox);
198b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
199b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_mailbox:
200b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mlx4_free_cmd_mailbox(dev, mailbox);
201b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (!err)
202b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
203b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_alloc:
204b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (dqp) {
205b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		list_del(&dqp->list);
206a14b289d4614bb3b25d0455d68f72f3c7b4cc8e8Mariusz Kozlowski		kfree(dqp);
207b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
208b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_del(&new_entry->list);
209b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	kfree(new_entry);
210b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return err;
211b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
212b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
213b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin/* update the data structures with existing steering entry */
2140ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int existing_steering_entry(struct mlx4_dev *dev, u8 port,
215b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				   enum mlx4_steer_type steer,
216b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				   unsigned int index, u32 qpn)
217b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
218b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
219b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *tmp_entry, *entry = NULL;
220b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *pqp;
221b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *dqp;
222b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
2234c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
224b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
2250ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	pqp = get_promisc_qp(dev, 0, steer, qpn);
226b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (!pqp)
227b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0; /* nothing to do */
228b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
229b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
230b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (tmp_entry->index == index) {
231b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			entry = tmp_entry;
232b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			break;
233b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
234b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
235b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (unlikely(!entry)) {
236b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mlx4_warn(dev, "Steering entry at index %x is not registered\n", index);
237b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return -EINVAL;
238b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
239b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
240b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* the given qpn is listed as a promisc qpn
241b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * we need to add it as a duplicate to this entry
24225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * for future references */
243b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(dqp, &entry->duplicates, list) {
2440ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		if (qpn == pqp->qpn)
245b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			return 0; /* qp is already duplicated */
246b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
247b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
248b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* add the qp as a duplicate on this index */
249b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
250b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (!dqp)
251b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return -ENOMEM;
252b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	dqp->qpn = qpn;
253b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_add_tail(&dqp->list, &entry->duplicates);
254b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
255b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return 0;
256b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
257b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
258b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin/* Check whether a qpn is a duplicate on steering entry
259b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin * If so, it should not be removed from mgm */
2600ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
261b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				  enum mlx4_steer_type steer,
262b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				  unsigned int index, u32 qpn)
263b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
264b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
265b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *tmp_entry, *entry = NULL;
266b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *dqp, *tmp_dqp;
267b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
2684c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
269b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
270b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* if qp is not promisc, it cannot be duplicated */
2710ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (!get_promisc_qp(dev, 0, steer, qpn))
272b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return false;
273b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
274b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* The qp is promisc qp so it is a duplicate on this index
275b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * Find the index entry, and remove the duplicate */
276b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
277b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (tmp_entry->index == index) {
278b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			entry = tmp_entry;
279b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			break;
280b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
281b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
282b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (unlikely(!entry)) {
283b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mlx4_warn(dev, "Steering entry for index %x is not registered\n", index);
284b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return false;
285b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
286b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) {
287b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (dqp->qpn == qpn) {
288b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			list_del(&dqp->list);
289b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			kfree(dqp);
290b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
291b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
292b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return true;
293b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
294b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
295b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin/* I a steering entry contains only promisc QPs, it can be removed. */
2960ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
297b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				      enum mlx4_steer_type steer,
298b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				      unsigned int index, u32 tqpn)
299b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
300b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
301b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_cmd_mailbox *mailbox;
302b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_mgm *mgm;
303b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *entry = NULL, *tmp_entry;
304b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 qpn;
305b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 members_count;
306b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	bool ret = false;
307b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int i;
308b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
3094c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
310b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
311b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mailbox = mlx4_alloc_cmd_mailbox(dev);
312b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (IS_ERR(mailbox))
313b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return false;
314b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm = mailbox->buf;
315b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
316b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (mlx4_READ_ENTRY(dev, index, mailbox))
317b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out;
318b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
319b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	for (i = 0;  i < members_count; i++) {
320b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
3210ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) {
322b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			/* the qp is not promisc, the entry can't be removed */
323b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			goto out;
324b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
325b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
326b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 /* All the qps currently registered for this entry are promiscuous,
327b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	  * Checking for duplicates */
328b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	ret = true;
329b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
330b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (entry->index == index) {
331b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			if (list_empty(&entry->duplicates)) {
332b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				list_del(&entry->list);
333b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				kfree(entry);
334b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			} else {
335b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				/* This entry contains duplicates so it shouldn't be removed */
336b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				ret = false;
337b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				goto out;
338b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			}
339b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
340b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
341b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
342b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout:
343b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mlx4_free_cmd_mailbox(dev, mailbox);
344b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return ret;
345b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
346b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
3470ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int add_promisc_qp(struct mlx4_dev *dev, u8 port,
348b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			  enum mlx4_steer_type steer, u32 qpn)
349b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
350b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
351b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_cmd_mailbox *mailbox;
352b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_mgm *mgm;
353b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *entry;
354b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *pqp;
355b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *dqp;
356b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 members_count;
357b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 prot;
358b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int i;
359b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	bool found;
360b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int last_index;
361b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int err;
362b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_priv *priv = mlx4_priv(dev);
3630ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
3644c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
365b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
366b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mutex_lock(&priv->mcg_table.mutex);
367b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
3680ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (get_promisc_qp(dev, 0, steer, qpn)) {
369b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = 0;  /* Noting to do, already exists */
370b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_mutex;
371b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
372b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
373b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	pqp = kmalloc(sizeof *pqp, GFP_KERNEL);
374b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (!pqp) {
375b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = -ENOMEM;
376b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_mutex;
377b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
378b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	pqp->qpn = qpn;
379b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
380b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mailbox = mlx4_alloc_cmd_mailbox(dev);
381b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (IS_ERR(mailbox)) {
382b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = -ENOMEM;
383b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_alloc;
384b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
385b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm = mailbox->buf;
386b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
387b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* the promisc qp needs to be added for each one of the steering
388b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * entries, if it already exists, needs to be added as a duplicate
389b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	 * for this entry */
390b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
391b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
392b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (err)
393b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			goto out_mailbox;
394b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
395b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
396b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		prot = be32_to_cpu(mgm->members_count) >> 30;
397b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		found = false;
398b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		for (i = 0; i < members_count; i++) {
399b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
400b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				/* Entry already exists, add to duplicates */
401b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
402b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				if (!dqp)
403b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					goto out_mailbox;
404b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				dqp->qpn = qpn;
405b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				list_add_tail(&dqp->list, &entry->duplicates);
406b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				found = true;
407b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			}
408b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
409b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (!found) {
410b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			/* Need to add the qpn to mgm */
4110ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			if (members_count == dev->caps.num_qp_per_mgm) {
412b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				/* entry is full */
413b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				err = -ENOMEM;
414b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				goto out_mailbox;
415b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			}
416b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
417b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			mgm->members_count = cpu_to_be32(members_count | (prot << 30));
418b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
419b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			if (err)
420b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				goto out_mailbox;
421b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
422b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		last_index = entry->index;
423b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
424b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
425b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* add the new qpn to list of promisc qps */
426b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
427b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* now need to add all the promisc qps to default entry */
428b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	memset(mgm, 0, sizeof *mgm);
429b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	members_count = 0;
430b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
431b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
432b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
433b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
4340ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
435b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (err)
436b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_list;
437b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
438b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mlx4_free_cmd_mailbox(dev, mailbox);
439b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mutex_unlock(&priv->mcg_table.mutex);
440b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return 0;
441b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
442b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_list:
443b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_del(&pqp->list);
444b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_mailbox:
445b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mlx4_free_cmd_mailbox(dev, mailbox);
446b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_alloc:
447b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	kfree(pqp);
448b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_mutex:
449b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mutex_unlock(&priv->mcg_table.mutex);
450b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return err;
451b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
452b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
4530ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
454b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			     enum mlx4_steer_type steer, u32 qpn)
455b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
456b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_priv *priv = mlx4_priv(dev);
457b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer *s_steer;
458b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_cmd_mailbox *mailbox;
459b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_mgm *mgm;
460b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_steer_index *entry;
461b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *pqp;
462b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	struct mlx4_promisc_qp *dqp;
463b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u32 members_count;
464b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	bool found;
465b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	bool back_to_list = false;
466b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int loc, i;
467b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	int err;
468b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
4694c41b3673759d096106e68bce586f103c51d4119Eugenia Emantayev	s_steer = &mlx4_priv(dev)->steer[port - 1];
470b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mutex_lock(&priv->mcg_table.mutex);
471b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
4720ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	pqp = get_promisc_qp(dev, 0, steer, qpn);
473b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (unlikely(!pqp)) {
474b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
475b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		/* nothing to do */
476b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = 0;
477b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_mutex;
478b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
479b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
480b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/*remove from list of promisc qps */
481b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_del(&pqp->list);
482b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
483b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* set the default entry not to include the removed one */
484b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mailbox = mlx4_alloc_cmd_mailbox(dev);
485b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (IS_ERR(mailbox)) {
486b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		err = -ENOMEM;
487b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		back_to_list = true;
488b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_list;
489b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
490b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm = mailbox->buf;
4910ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	memset(mgm, 0, sizeof *mgm);
492b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	members_count = 0;
493b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
494b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
495b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
496b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
4970ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
498b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (err)
499b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out_mailbox;
500b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
501b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* remove the qp from all the steering entries*/
502b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
503b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		found = false;
504b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		list_for_each_entry(dqp, &entry->duplicates, list) {
505b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			if (dqp->qpn == qpn) {
506b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				found = true;
507b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				break;
508b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			}
509b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
510b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (found) {
511b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			/* a duplicate, no need to change the mgm,
512b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			 * only update the duplicates list */
513b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			list_del(&dqp->list);
514b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			kfree(dqp);
515b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		} else {
516b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
517b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				if (err)
518b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					goto out_mailbox;
519b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
520b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			for (loc = -1, i = 0; i < members_count; ++i)
521b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
522b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					loc = i;
523b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
524b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			mgm->members_count = cpu_to_be32(--members_count |
525b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin							 (MLX4_PROT_ETH << 30));
526b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			mgm->qp[loc] = mgm->qp[i - 1];
527b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			mgm->qp[i - 1] = 0;
528b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
529b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
530b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin				if (err)
531b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin					goto out_mailbox;
532b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
533b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
534b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
535b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
536b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_mailbox:
537b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mlx4_free_cmd_mailbox(dev, mailbox);
538b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_list:
539b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (back_to_list)
540b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
54153020092bd89b0d4ccc5368a3956f43cb43e5665Yevgeny Petrilin	else
54253020092bd89b0d4ccc5368a3956f43cb43e5665Yevgeny Petrilin		kfree(pqp);
543b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinout_mutex:
544b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mutex_unlock(&priv->mcg_table.mutex);
545b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	return err;
546b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
547b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
548225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier/*
549225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * Caller must hold MCG table semaphore.  gid and mgm parameters must
550225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * be properly aligned for command interface.
551225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
552225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *  Returns 0 unless a firmware command error occurs.
553225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
554225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
555225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * and *mgm holds MGM entry.
556225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
557225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * if GID is found in AMGM, *index = index in AMGM, *prev = index of
558225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * previous entry in hash chain and *mgm holds AMGM entry.
559225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier *
560225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * If no AMGM exists for given gid, *index = -1, *prev = index of last
561225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier * entry in hash chain and *mgm holds end of hash chain.
562225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier */
5630345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinstatic int find_entry(struct mlx4_dev *dev, u8 port,
5640345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		      u8 *gid, enum mlx4_protocol prot,
5650345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		      struct mlx4_cmd_mailbox *mgm_mailbox,
566deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev		      int *prev, int *index)
567225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
568225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_cmd_mailbox *mailbox;
569225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_mgm *mgm = mgm_mailbox->buf;
570225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	u8 *mgid;
571225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int err;
572deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev	u16 hash;
573ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz	u8 op_mod = (prot == MLX4_PROT_ETH) ?
574ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz		!!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
575225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
576225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mailbox = mlx4_alloc_cmd_mailbox(dev);
577225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (IS_ERR(mailbox))
578225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		return -ENOMEM;
579225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgid = mailbox->buf;
580225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
581225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	memcpy(mgid, gid, 16);
582225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
583deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev	err = mlx4_GID_HASH(dev, mailbox, &hash, op_mod);
584225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mlx4_free_cmd_mailbox(dev, mailbox);
585225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
586225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		return err;
587225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
588225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (0)
589deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev		mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, hash);
590225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
591deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev	*index = hash;
592225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	*prev  = -1;
593225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
594225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	do {
5950345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
596225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (err)
597225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			return err;
598225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
5990345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
600deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev			if (*index != hash) {
601225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				mlx4_err(dev, "Found zero MGID in AMGM.\n");
602225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				err = -EINVAL;
603225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			}
604225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			return err;
605225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		}
606225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
607da995a8aee044bc5d0847e19e351cd48a2cb8bccAleksey Senin		if (!memcmp(mgm->gid, gid, 16) &&
6080345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		    be32_to_cpu(mgm->members_count) >> 30 == prot)
609225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			return err;
610225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
611225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		*prev = *index;
612225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		*index = be32_to_cpu(mgm->next_gid_index) >> 6;
613225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	} while (*index);
614225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
615225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	*index = -1;
616225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return err;
617225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
618225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
6190345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinint mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
6200345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			  int block_mcast_loopback, enum mlx4_protocol prot,
6210345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			  enum mlx4_steer_type steer)
622225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
623225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_priv *priv = mlx4_priv(dev);
624225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_cmd_mailbox *mailbox;
625225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_mgm *mgm;
626225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	u32 members_count;
627225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int index, prev;
628225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int link = 0;
629225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int i;
630225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int err;
6310345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	u8 port = gid[5];
632b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	u8 new_entry = 0;
633225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
634225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mailbox = mlx4_alloc_cmd_mailbox(dev);
635225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (IS_ERR(mailbox))
636225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		return PTR_ERR(mailbox);
637225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgm = mailbox->buf;
638225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
639225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mutex_lock(&priv->mcg_table.mutex);
640deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev	err = find_entry(dev, port, gid, prot,
641deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev			 mailbox, &prev, &index);
642225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
643225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
644225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
645225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (index != -1) {
646b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
647b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin			new_entry = 1;
648225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			memcpy(mgm->gid, gid, 16);
649b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		}
650225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	} else {
651225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		link = 1;
652225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
653225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap);
654225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (index == -1) {
655225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_err(dev, "No AMGM entries left\n");
656225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			err = -ENOMEM;
657225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			goto out;
658225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		}
659225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		index += dev->caps.num_mgms;
660225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
6610ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		new_entry = 1;
662225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		memset(mgm, 0, sizeof *mgm);
663225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		memcpy(mgm->gid, gid, 16);
664225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
665225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
666da995a8aee044bc5d0847e19e351cd48a2cb8bccAleksey Senin	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
6670ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (members_count == dev->caps.num_qp_per_mgm) {
668225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		mlx4_err(dev, "MGM at index %x is full.\n", index);
669225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		err = -ENOMEM;
670225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
671225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
672225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
673225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	for (i = 0; i < members_count; ++i)
674521e575b9a7324a0bca762622139f69582a042bfRon Livne		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
675225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
676225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			err = 0;
677225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			goto out;
678225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		}
679225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
680521e575b9a7324a0bca762622139f69582a042bfRon Livne	if (block_mcast_loopback)
681521e575b9a7324a0bca762622139f69582a042bfRon Livne		mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
682e6a176228a38d74c0360ca586146bd45a2ac2d60Ingo Molnar						       (1U << MGM_BLCK_LB_BIT));
683521e575b9a7324a0bca762622139f69582a042bfRon Livne	else
684521e575b9a7324a0bca762622139f69582a042bfRon Livne		mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
685521e575b9a7324a0bca762622139f69582a042bfRon Livne
6860345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
687225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
6880345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	err = mlx4_WRITE_ENTRY(dev, index, mailbox);
689225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
690225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
691225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
692225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (!link)
693225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
694225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
6950345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	err = mlx4_READ_ENTRY(dev, prev, mailbox);
696225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
697225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
698225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
699225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgm->next_gid_index = cpu_to_be32(index << 6);
700225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
7010345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
702225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
703225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
704225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
705225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreierout:
706b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (prot == MLX4_PROT_ETH) {
707b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		/* manage the steering entry for promisc mode */
708b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		if (new_entry)
7090ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			new_steering_entry(dev, port, steer, index, qp->qpn);
710b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		else
7110ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			existing_steering_entry(dev, port, steer,
712b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin						index, qp->qpn);
713b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	}
714225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err && link && index != -1) {
715225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (index < dev->caps.num_mgms)
716225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_warn(dev, "Got AMGM index %d < %d",
717225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				  index, dev->caps.num_mgms);
718225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		else
719225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_bitmap_free(&priv->mcg_table.bitmap,
720225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier					 index - dev->caps.num_mgms);
721225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
722225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mutex_unlock(&priv->mcg_table.mutex);
723225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
724225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mlx4_free_cmd_mailbox(dev, mailbox);
725225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return err;
726225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
727225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
7280345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinint mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
7290345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			  enum mlx4_protocol prot, enum mlx4_steer_type steer)
730225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
731225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_priv *priv = mlx4_priv(dev);
732225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_cmd_mailbox *mailbox;
733225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_mgm *mgm;
734225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	u32 members_count;
735225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int prev, index;
736225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int i, loc;
737225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int err;
7380345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	u8 port = gid[5];
739b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	bool removed_entry = false;
740225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
741225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mailbox = mlx4_alloc_cmd_mailbox(dev);
742225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (IS_ERR(mailbox))
743225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		return PTR_ERR(mailbox);
744225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgm = mailbox->buf;
745225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
746225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mutex_lock(&priv->mcg_table.mutex);
747225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
748deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev	err = find_entry(dev, port, gid, prot,
749deb8b3e8494f63b05ce144a52e8c0b3f80789fedEugenia Emantayev			 mailbox, &prev, &index);
750225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
751225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
752225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
753225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (index == -1) {
7545b095d98928fdb9e3b75be20a54b7a6cbf6ca9adHarvey Harrison		mlx4_err(dev, "MGID %pI6 not found\n", gid);
755225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		err = -EINVAL;
756225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
757225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
758225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
759b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* if this pq is also a promisc qp, it shouldn't be removed */
760b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (prot == MLX4_PROT_ETH &&
7610ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	    check_duplicate_entry(dev, port, steer, index, qp->qpn))
762b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		goto out;
763b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
764da995a8aee044bc5d0847e19e351cd48a2cb8bccAleksey Senin	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
765225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	for (loc = -1, i = 0; i < members_count; ++i)
766521e575b9a7324a0bca762622139f69582a042bfRon Livne		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
767225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			loc = i;
768225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
769225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (loc == -1) {
770225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
771225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		err = -EINVAL;
772225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
773225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
774225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
775225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
7760345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
777225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgm->qp[loc]       = mgm->qp[i - 1];
778225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mgm->qp[i - 1]     = 0;
779225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
780b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (prot == MLX4_PROT_ETH)
7810ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		removed_entry = can_remove_steering_entry(dev, port, steer,
7820ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev								index, qp->qpn);
783b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
7840345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
785225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		goto out;
7864dc51b32582d45cb7e8322d750ffe0e6d82b506dEli Cohen	}
787225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
788b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	/* We are going to delete the entry, members count should be 0 */
789b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin	mgm->members_count = cpu_to_be32((u32) prot << 30);
790b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
791225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (prev == -1) {
792225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		/* Remove entry from MGM */
793225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
794225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (amgm_index) {
7950345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
796225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			if (err)
797225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				goto out;
798225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		} else
799225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			memset(mgm->gid, 0, 16);
800225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
8010345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
802225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (err)
803225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			goto out;
804225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
805225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (amgm_index) {
806225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			if (amgm_index < dev->caps.num_mgms)
807225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d",
808225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier					  index, amgm_index, dev->caps.num_mgms);
809225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			else
810225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				mlx4_bitmap_free(&priv->mcg_table.bitmap,
811225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier						 amgm_index - dev->caps.num_mgms);
812225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		}
813225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	} else {
814225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		/* Remove entry from AMGM */
815225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
8160345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		err = mlx4_READ_ENTRY(dev, prev, mailbox);
817225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (err)
818225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			goto out;
819225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
820225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
821225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
8220345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
823225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (err)
824225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			goto out;
825225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
826225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		if (index < dev->caps.num_mgms)
827225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_warn(dev, "entry %d had next AMGM index %d < %d",
828225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier				  prev, index, dev->caps.num_mgms);
829225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		else
830225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier			mlx4_bitmap_free(&priv->mcg_table.bitmap,
831225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier					 index - dev->caps.num_mgms);
832225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	}
833225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
834225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreierout:
835225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mutex_unlock(&priv->mcg_table.mutex);
836225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
837225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mlx4_free_cmd_mailbox(dev, mailbox);
838225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return err;
839225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
8400345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8410ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
8420ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			  u8 gid[16], u8 attach, u8 block_loopback,
8430ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			  enum mlx4_protocol prot)
8440ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
8450ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	struct mlx4_cmd_mailbox *mailbox;
8460ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	int err = 0;
8470ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	int qpn;
8480ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8490ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (!mlx4_is_mfunc(dev))
8500ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return -EBADF;
8510ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8520ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	mailbox = mlx4_alloc_cmd_mailbox(dev);
8530ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (IS_ERR(mailbox))
8540ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return PTR_ERR(mailbox);
8550ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8560ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	memcpy(mailbox->buf, gid, 16);
8570ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	qpn = qp->qpn;
8580ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	qpn |= (prot << 28);
8590ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (attach && block_loopback)
8600ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		qpn |= (1 << 31);
8610ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8620ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	err = mlx4_cmd(dev, mailbox->dma, qpn, attach,
8630ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		       MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A,
8640ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		       MLX4_CMD_WRAPPED);
8650ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8660ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	mlx4_free_cmd_mailbox(dev, mailbox);
8670ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return err;
8680ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
8690345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8700345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinint mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
8710345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			  int block_mcast_loopback, enum mlx4_protocol prot)
8720345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin{
873ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz	if (prot == MLX4_PROT_ETH &&
874ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
8750345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		return 0;
8760345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8770345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin	if (prot == MLX4_PROT_ETH)
878f1f75f0e2bb94674da540be9c488fe596dd55881Eugenia Emantayev		gid[7] |= (MLX4_MC_STEER << 1);
8790345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8800ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
8810ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_QP_ATTACH(dev, qp, gid, 1,
8820ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev					block_mcast_loopback, prot);
8830ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8840ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
885f1f75f0e2bb94674da540be9c488fe596dd55881Eugenia Emantayev					prot, MLX4_MC_STEER);
8860345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin}
8870345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny PetrilinEXPORT_SYMBOL_GPL(mlx4_multicast_attach);
8880345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8890345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilinint mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
8900345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin			  enum mlx4_protocol prot)
8910345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin{
892ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz	if (prot == MLX4_PROT_ETH &&
893ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
8940345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin		return 0;
8950345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
8960ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (prot == MLX4_PROT_ETH)
897f1f75f0e2bb94674da540be9c488fe596dd55881Eugenia Emantayev		gid[7] |= (MLX4_MC_STEER << 1);
8980ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
8990ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
9000ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
9010345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin
902f1f75f0e2bb94674da540be9c488fe596dd55881Eugenia Emantayev	return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_MC_STEER);
9030345584e0b8be3735a950d17c7e463db20c6ce27Yevgeny Petrilin}
904225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland DreierEXPORT_SYMBOL_GPL(mlx4_multicast_detach);
905225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
906ffe455ad04681f3fc48eef595fe526a795f809a3Eugenia Emantayevint mlx4_unicast_attach(struct mlx4_dev *dev,
9070ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			struct mlx4_qp *qp, u8 gid[16],
9080ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			int block_mcast_loopback, enum mlx4_protocol prot)
9090ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
9100ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (prot == MLX4_PROT_ETH &&
9110ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
9120ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return 0;
9130ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9140ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (prot == MLX4_PROT_ETH)
9150ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		gid[7] |= (MLX4_UC_STEER << 1);
9160ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9170ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
9180ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_QP_ATTACH(dev, qp, gid, 1,
9190ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev					block_mcast_loopback, prot);
9200ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9210ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
9220ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev					prot, MLX4_UC_STEER);
9230ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
9240ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia EmantayevEXPORT_SYMBOL_GPL(mlx4_unicast_attach);
9250ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
926ffe455ad04681f3fc48eef595fe526a795f809a3Eugenia Emantayevint mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
9270ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			       u8 gid[16], enum mlx4_protocol prot)
9280ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
9290ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (prot == MLX4_PROT_ETH &&
9300ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
9310ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return 0;
9320ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9330ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (prot == MLX4_PROT_ETH)
9340ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		gid[7] |= (MLX4_UC_STEER << 1);
9350ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9360ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
9370ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
9380ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9390ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER);
9400ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
9410ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia EmantayevEXPORT_SYMBOL_GPL(mlx4_unicast_detach);
9420ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9430ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevint mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
9440ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			 struct mlx4_vhcr *vhcr,
9450ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			 struct mlx4_cmd_mailbox *inbox,
9460ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			 struct mlx4_cmd_mailbox *outbox,
9470ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			 struct mlx4_cmd_info *cmd)
9480ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
9490ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	u32 qpn = (u32) vhcr->in_param & 0xffffffff;
9500ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	u8 port = vhcr->in_param >> 62;
9510ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	enum mlx4_steer_type steer = vhcr->in_modifier;
9520ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9530ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	/* Promiscuous unicast is not allowed in mfunc */
9540ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)
9550ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return 0;
9560ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9570ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (vhcr->op_modifier)
9580ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return add_promisc_qp(dev, port, steer, qpn);
9590ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	else
9600ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return remove_promisc_qp(dev, port, steer, qpn);
9610ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
9620ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
9630ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayevstatic int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn,
9640ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			enum mlx4_steer_type steer, u8 add, u8 port)
9650ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev{
9660ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add,
9670ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A,
9680ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev			MLX4_CMD_WRAPPED);
9690ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev}
970b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
971b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinint mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
972b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
973ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
974b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
975b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
9760ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
9770ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port);
978b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
9790ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
980b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
981b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny PetrilinEXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
982b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
983b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinint mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
984b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
985ccf863219675aa86bebdd6a2806acb8176478e37Or Gerlitz	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
986b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
987b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
9880ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
9890ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port);
990b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
9910ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
992b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
993b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny PetrilinEXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
994b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
995b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinint mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
996b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
9974df99504065fcc75c70cde0aa4a342fb32c829b8Eugenia Emantayev	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
998b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
999b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
10000ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
10010ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port);
1002b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
10030ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
1004b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
1005b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny PetrilinEXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
1006b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
1007b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilinint mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
1008b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin{
10094df99504065fcc75c70cde0aa4a342fb32c829b8Eugenia Emantayev	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
1010b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin		return 0;
1011b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
10120ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	if (mlx4_is_mfunc(dev))
10130ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev		return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port);
10140ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev
10150ec2c0f86d31ab36547307f133b0016006bdc6b5Eugenia Emantayev	return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
1016b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin}
1017b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny PetrilinEXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
1018b12d93d63c3217f0ec923ff938b12a744e242ffaYevgeny Petrilin
10193d73c2884f45f9a297cbc956cea101405a9703f2Roland Dreierint mlx4_init_mcg_table(struct mlx4_dev *dev)
1020225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
1021225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	struct mlx4_priv *priv = mlx4_priv(dev);
1022225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	int err;
1023225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
102493fc9e1bb6507dde945c2eab68c93e1066ac3691Yevgeny Petrilin	err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms,
102593fc9e1bb6507dde945c2eab68c93e1066ac3691Yevgeny Petrilin			       dev->caps.num_amgms - 1, 0, 0);
1026225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	if (err)
1027225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier		return err;
1028225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
1029225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mutex_init(&priv->mcg_table.mutex);
1030225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
1031225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	return 0;
1032225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
1033225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier
1034225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreiervoid mlx4_cleanup_mcg_table(struct mlx4_dev *dev)
1035225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier{
1036225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier	mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap);
1037225c7b1feef1b41170f7037a5b10a65cd8a42c54Roland Dreier}
1038