aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-03-22 18:38:24 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:22 -0400
commitb12d93d63c3217f0ec923ff938b12a744e242ffa (patch)
treebecc9b94ecf1f9d664c0e137c54383786a27be45
parent0345584e0b8be3735a950d17c7e463db20c6ce27 (diff)
mlx4: Add support for promiscuous mode in the new steering model.
For Ethernet mode only, When we want to register QP as promiscuous, it must be added to all the existing steering entries and also to the default one. The promiscuous QP might also be on of "real" QPs, which means we need to monitor every entry to avoid duplicates and ensure we close an entry when all it has is promiscuous QPs. Same mechanism both for unicast and multicast. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/mlx4/main.c63
-rw-r--r--drivers/net/mlx4/mcg.c535
-rw-r--r--drivers/net/mlx4/mlx4.h33
3 files changed, 620 insertions, 11 deletions
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index da0da281d830..c8e276138f81 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -1063,6 +1063,59 @@ static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
1063 device_remove_file(&info->dev->pdev->dev, &info->port_attr); 1063 device_remove_file(&info->dev->pdev->dev, &info->port_attr);
1064} 1064}
1065 1065
1066static int mlx4_init_steering(struct mlx4_dev *dev)
1067{
1068 struct mlx4_priv *priv = mlx4_priv(dev);
1069 int num_entries = dev->caps.num_ports;
1070 int i, j;
1071
1072 priv->steer = kzalloc(sizeof(struct mlx4_steer) * num_entries, GFP_KERNEL);
1073 if (!priv->steer)
1074 return -ENOMEM;
1075
1076 for (i = 0; i < num_entries; i++) {
1077 for (j = 0; j < MLX4_NUM_STEERS; j++) {
1078 INIT_LIST_HEAD(&priv->steer[i].promisc_qps[j]);
1079 INIT_LIST_HEAD(&priv->steer[i].steer_entries[j]);
1080 }
1081 INIT_LIST_HEAD(&priv->steer[i].high_prios);
1082 }
1083 return 0;
1084}
1085
1086static void mlx4_clear_steering(struct mlx4_dev *dev)
1087{
1088 struct mlx4_priv *priv = mlx4_priv(dev);
1089 struct mlx4_steer_index *entry, *tmp_entry;
1090 struct mlx4_promisc_qp *pqp, *tmp_pqp;
1091 int num_entries = dev->caps.num_ports;
1092 int i, j;
1093
1094 for (i = 0; i < num_entries; i++) {
1095 for (j = 0; j < MLX4_NUM_STEERS; j++) {
1096 list_for_each_entry_safe(pqp, tmp_pqp,
1097 &priv->steer[i].promisc_qps[j],
1098 list) {
1099 list_del(&pqp->list);
1100 kfree(pqp);
1101 }
1102 list_for_each_entry_safe(entry, tmp_entry,
1103 &priv->steer[i].steer_entries[j],
1104 list) {
1105 list_del(&entry->list);
1106 list_for_each_entry_safe(pqp, tmp_pqp,
1107 &entry->duplicates,
1108 list) {
1109 list_del(&pqp->list);
1110 kfree(pqp);
1111 }
1112 kfree(entry);
1113 }
1114 }
1115 }
1116 kfree(priv->steer);
1117}
1118
1066static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 1119static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1067{ 1120{
1068 struct mlx4_priv *priv; 1121 struct mlx4_priv *priv;
@@ -1172,6 +1225,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1172 1225
1173 mlx4_enable_msi_x(dev); 1226 mlx4_enable_msi_x(dev);
1174 1227
1228 err = mlx4_init_steering(dev);
1229 if (err)
1230 goto err_free_eq;
1231
1175 err = mlx4_setup_hca(dev); 1232 err = mlx4_setup_hca(dev);
1176 if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) { 1233 if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) {
1177 dev->flags &= ~MLX4_FLAG_MSI_X; 1234 dev->flags &= ~MLX4_FLAG_MSI_X;
@@ -1180,7 +1237,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1180 } 1237 }
1181 1238
1182 if (err) 1239 if (err)
1183 goto err_free_eq; 1240 goto err_steer;
1184 1241
1185 for (port = 1; port <= dev->caps.num_ports; port++) { 1242 for (port = 1; port <= dev->caps.num_ports; port++) {
1186 err = mlx4_init_port_info(dev, port); 1243 err = mlx4_init_port_info(dev, port);
@@ -1213,6 +1270,9 @@ err_port:
1213 mlx4_cleanup_pd_table(dev); 1270 mlx4_cleanup_pd_table(dev);
1214 mlx4_cleanup_uar_table(dev); 1271 mlx4_cleanup_uar_table(dev);
1215 1272
1273err_steer:
1274 mlx4_clear_steering(dev);
1275
1216err_free_eq: 1276err_free_eq:
1217 mlx4_free_eq_table(dev); 1277 mlx4_free_eq_table(dev);
1218 1278
@@ -1272,6 +1332,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
1272 iounmap(priv->kar); 1332 iounmap(priv->kar);
1273 mlx4_uar_free(dev, &priv->driver_uar); 1333 mlx4_uar_free(dev, &priv->driver_uar);
1274 mlx4_cleanup_uar_table(dev); 1334 mlx4_cleanup_uar_table(dev);
1335 mlx4_clear_steering(dev);
1275 mlx4_free_eq_table(dev); 1336 mlx4_free_eq_table(dev);
1276 mlx4_close_hca(dev); 1337 mlx4_close_hca(dev);
1277 mlx4_cmd_cleanup(dev); 1338 mlx4_cmd_cleanup(dev);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index b103ad23bd84..e71372aa9cc4 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -41,14 +41,6 @@
41#define MGM_QPN_MASK 0x00FFFFFF 41#define MGM_QPN_MASK 0x00FFFFFF
42#define MGM_BLCK_LB_BIT 30 42#define MGM_BLCK_LB_BIT 30
43 43
44struct mlx4_mgm {
45 __be32 next_gid_index;
46 __be32 members_count;
47 u32 reserved[2];
48 u8 gid[16];
49 __be32 qp[MLX4_QP_PER_MGM];
50};
51
52static const u8 zero_gid[16]; /* automatically initialized to 0 */ 44static const u8 zero_gid[16]; /* automatically initialized to 0 */
53 45
54static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, 46static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
@@ -65,6 +57,16 @@ static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
65 MLX4_CMD_TIME_CLASS_A); 57 MLX4_CMD_TIME_CLASS_A);
66} 58}
67 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
68static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, 70static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
69 u16 *hash, u8 op_mod) 71 u16 *hash, u8 op_mod)
70{ 72{
@@ -80,6 +82,457 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
80 return err; 82 return err;
81} 83}
82 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;
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 refernce */
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 kfree(pqp);
473
474 /* set the default entry not to include the removed one */
475 mailbox = mlx4_alloc_cmd_mailbox(dev);
476 if (IS_ERR(mailbox)) {
477 err = -ENOMEM;
478 back_to_list = true;
479 goto out_list;
480 }
481 mgm = mailbox->buf;
482 members_count = 0;
483 list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
484 mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
485 mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
486
487 err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
488 if (err)
489 goto out_mailbox;
490
491 /* remove the qp from all the steering entries*/
492 list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
493 found = false;
494 list_for_each_entry(dqp, &entry->duplicates, list) {
495 if (dqp->qpn == qpn) {
496 found = true;
497 break;
498 }
499 }
500 if (found) {
501 /* a duplicate, no need to change the mgm,
502 * only update the duplicates list */
503 list_del(&dqp->list);
504 kfree(dqp);
505 } else {
506 err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
507 if (err)
508 goto out_mailbox;
509 members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
510 for (loc = -1, i = 0; i < members_count; ++i)
511 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
512 loc = i;
513
514 mgm->members_count = cpu_to_be32(--members_count |
515 (MLX4_PROT_ETH << 30));
516 mgm->qp[loc] = mgm->qp[i - 1];
517 mgm->qp[i - 1] = 0;
518
519 err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
520 if (err)
521 goto out_mailbox;
522 }
523
524 }
525
526out_mailbox:
527 mlx4_free_cmd_mailbox(dev, mailbox);
528out_list:
529 if (back_to_list)
530 list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
531out_mutex:
532 mutex_unlock(&priv->mcg_table.mutex);
533 return err;
534}
535
83/* 536/*
84 * Caller must hold MCG table semaphore. gid and mgm parameters must 537 * Caller must hold MCG table semaphore. gid and mgm parameters must
85 * be properly aligned for command interface. 538 * be properly aligned for command interface.
@@ -164,6 +617,7 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
164 int i; 617 int i;
165 int err; 618 int err;
166 u8 port = gid[5]; 619 u8 port = gid[5];
620 u8 new_entry = 0;
167 621
168 mailbox = mlx4_alloc_cmd_mailbox(dev); 622 mailbox = mlx4_alloc_cmd_mailbox(dev);
169 if (IS_ERR(mailbox)) 623 if (IS_ERR(mailbox))
@@ -177,8 +631,10 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
177 goto out; 631 goto out;
178 632
179 if (index != -1) { 633 if (index != -1) {
180 if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) 634 if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
635 new_entry = 1;
181 memcpy(mgm->gid, gid, 16); 636 memcpy(mgm->gid, gid, 16);
637 }
182 } else { 638 } else {
183 link = 1; 639 link = 1;
184 640
@@ -234,6 +690,14 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
234 goto out; 690 goto out;
235 691
236out: 692out:
693 if (prot == MLX4_PROT_ETH) {
694 /* manage the steering entry for promisc mode */
695 if (new_entry)
696 new_steering_entry(dev, 0, port, steer, index, qp->qpn);
697 else
698 existing_steering_entry(dev, 0, port, steer,
699 index, qp->qpn);
700 }
237 if (err && link && index != -1) { 701 if (err && link && index != -1) {
238 if (index < dev->caps.num_mgms) 702 if (index < dev->caps.num_mgms)
239 mlx4_warn(dev, "Got AMGM index %d < %d", 703 mlx4_warn(dev, "Got AMGM index %d < %d",
@@ -260,6 +724,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
260 int i, loc; 724 int i, loc;
261 int err; 725 int err;
262 u8 port = gid[5]; 726 u8 port = gid[5];
727 bool removed_entry = false;
263 728
264 mailbox = mlx4_alloc_cmd_mailbox(dev); 729 mailbox = mlx4_alloc_cmd_mailbox(dev);
265 if (IS_ERR(mailbox)) 730 if (IS_ERR(mailbox))
@@ -279,6 +744,11 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
279 goto out; 744 goto out;
280 } 745 }
281 746
747 /* if this pq is also a promisc qp, it shouldn't be removed */
748 if (prot == MLX4_PROT_ETH &&
749 check_duplicate_entry(dev, 0, port, steer, index, qp->qpn))
750 goto out;
751
282 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 752 members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
283 for (loc = -1, i = 0; i < members_count; ++i) 753 for (loc = -1, i = 0; i < members_count; ++i)
284 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) 754 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
@@ -295,11 +765,16 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
295 mgm->qp[loc] = mgm->qp[i - 1]; 765 mgm->qp[loc] = mgm->qp[i - 1];
296 mgm->qp[i - 1] = 0; 766 mgm->qp[i - 1] = 0;
297 767
298 if (i != 1) { 768 if (prot == MLX4_PROT_ETH)
769 removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn);
770 if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
299 err = mlx4_WRITE_ENTRY(dev, index, mailbox); 771 err = mlx4_WRITE_ENTRY(dev, index, mailbox);
300 goto out; 772 goto out;
301 } 773 }
302 774
775 /* We are going to delete the entry, members count should be 0 */
776 mgm->members_count = cpu_to_be32((u32) prot << 30);
777
303 if (prev == -1) { 778 if (prev == -1) {
304 /* Remove entry from MGM */ 779 /* Remove entry from MGM */
305 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 780 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
@@ -388,6 +863,46 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
388} 863}
389EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 864EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
390 865
866
867int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
868{
869 if (!dev->caps.vep_mc_steering)
870 return 0;
871
872
873 return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
874}
875EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
876
877int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
878{
879 if (!dev->caps.vep_mc_steering)
880 return 0;
881
882
883 return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
884}
885EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
886
887int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
888{
889 if (!dev->caps.vep_mc_steering)
890 return 0;
891
892
893 return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
894}
895EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
896
897int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
898{
899 if (!dev->caps.vep_mc_steering)
900 return 0;
901
902 return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
903}
904EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
905
391int mlx4_init_mcg_table(struct mlx4_dev *dev) 906int mlx4_init_mcg_table(struct mlx4_dev *dev)
392{ 907{
393 struct mlx4_priv *priv = mlx4_priv(dev); 908 struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 67ee8dacae79..1513a91b4bd4 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -162,6 +162,27 @@ struct mlx4_fw {
162 u8 catas_bar; 162 u8 catas_bar;
163}; 163};
164 164
165#define MGM_QPN_MASK 0x00FFFFFF
166#define MGM_BLCK_LB_BIT 30
167
168struct mlx4_promisc_qp {
169 struct list_head list;
170 u32 qpn;
171};
172
173struct mlx4_steer_index {
174 struct list_head list;
175 unsigned int index;
176 struct list_head duplicates;
177};
178
179struct mlx4_mgm {
180 __be32 next_gid_index;
181 __be32 members_count;
182 u32 reserved[2];
183 u8 gid[16];
184 __be32 qp[MLX4_QP_PER_MGM];
185};
165struct mlx4_cmd { 186struct mlx4_cmd {
166 struct pci_pool *pool; 187 struct pci_pool *pool;
167 void __iomem *hcr; 188 void __iomem *hcr;
@@ -287,6 +308,12 @@ struct mlx4_msix_ctl {
287 spinlock_t pool_lock; 308 spinlock_t pool_lock;
288}; 309};
289 310
311struct mlx4_steer {
312 struct list_head promisc_qps[MLX4_NUM_STEERS];
313 struct list_head steer_entries[MLX4_NUM_STEERS];
314 struct list_head high_prios;
315};
316
290struct mlx4_priv { 317struct mlx4_priv {
291 struct mlx4_dev dev; 318 struct mlx4_dev dev;
292 319
@@ -319,6 +346,7 @@ struct mlx4_priv {
319 struct mlx4_sense sense; 346 struct mlx4_sense sense;
320 struct mutex port_mutex; 347 struct mutex port_mutex;
321 struct mlx4_msix_ctl msix_ctl; 348 struct mlx4_msix_ctl msix_ctl;
349 struct mlx4_steer *steer;
322}; 350};
323 351
324static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) 352static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
@@ -409,4 +437,9 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
409int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); 437int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
410int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); 438int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
411 439
440int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
441 enum mlx4_protocol prot, enum mlx4_steer_type steer);
442int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
443 int block_mcast_loopback, enum mlx4_protocol prot,
444 enum mlx4_steer_type steer);
412#endif /* MLX4_H */ 445#endif /* MLX4_H */