aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaeed Mahameed <saeedm@mellanox.com>2014-07-16 04:57:51 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-17 02:26:25 -0400
commit1645a54082ec8bf3fc0147c6d1ced273549ac1a2 (patch)
tree4d1a8c066ace55cd5d41e81ac1ae64883762ab97
parent816e59846bb683e8d5c91e35df5f8fabac20494f (diff)
net/mlx4_core: Remove MCG in case it is attached to promiscuous QPs only
In B0 steering mode if promiscuous QP asks to be detached from MCG entry, and it is the only one in this entry then the entry will never be deleted. This is a wrong behavior since we don't want to keep those entries after the promiscuous QP becomes non-promiscuous. Therefore remove steering entry containing only promiscuous QP. Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c88
1 files changed, 62 insertions, 26 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 9d92bc22b9e5..d80e7a6fac74 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -270,7 +270,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
270 * we need to add it as a duplicate to this entry 270 * we need to add it as a duplicate to this entry
271 * for future references */ 271 * for future references */
272 list_for_each_entry(dqp, &entry->duplicates, list) { 272 list_for_each_entry(dqp, &entry->duplicates, list) {
273 if (qpn == pqp->qpn) 273 if (qpn == dqp->qpn)
274 return 0; /* qp is already duplicated */ 274 return 0; /* qp is already duplicated */
275 } 275 }
276 276
@@ -324,24 +324,22 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
324 return true; 324 return true;
325} 325}
326 326
327/* I a steering entry contains only promisc QPs, it can be removed. */ 327/* Returns true if all the QPs != tqpn contained in this entry
328static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, 328 * are Promisc QPs. Returns false otherwise.
329 enum mlx4_steer_type steer, 329 */
330 unsigned int index, u32 tqpn) 330static bool promisc_steering_entry(struct mlx4_dev *dev, u8 port,
331 enum mlx4_steer_type steer,
332 unsigned int index, u32 tqpn,
333 u32 *members_count)
331{ 334{
332 struct mlx4_steer *s_steer;
333 struct mlx4_cmd_mailbox *mailbox; 335 struct mlx4_cmd_mailbox *mailbox;
334 struct mlx4_mgm *mgm; 336 struct mlx4_mgm *mgm;
335 struct mlx4_steer_index *entry = NULL, *tmp_entry; 337 u32 m_count;
336 u32 qpn;
337 u32 members_count;
338 bool ret = false; 338 bool ret = false;
339 int i; 339 int i;
340 340
341 if (port < 1 || port > dev->caps.num_ports) 341 if (port < 1 || port > dev->caps.num_ports)
342 return NULL; 342 return false;
343
344 s_steer = &mlx4_priv(dev)->steer[port - 1];
345 343
346 mailbox = mlx4_alloc_cmd_mailbox(dev); 344 mailbox = mlx4_alloc_cmd_mailbox(dev);
347 if (IS_ERR(mailbox)) 345 if (IS_ERR(mailbox))
@@ -350,15 +348,43 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
350 348
351 if (mlx4_READ_ENTRY(dev, index, mailbox)) 349 if (mlx4_READ_ENTRY(dev, index, mailbox))
352 goto out; 350 goto out;
353 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 351 m_count = be32_to_cpu(mgm->members_count) & 0xffffff;
354 for (i = 0; i < members_count; i++) { 352 if (members_count)
355 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; 353 *members_count = m_count;
354
355 for (i = 0; i < m_count; i++) {
356 u32 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
356 if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { 357 if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
357 /* the qp is not promisc, the entry can't be removed */ 358 /* the qp is not promisc, the entry can't be removed */
358 goto out; 359 goto out;
359 } 360 }
360 } 361 }
361 /* All the qps currently registered for this entry are promiscuous, 362 ret = true;
363out:
364 mlx4_free_cmd_mailbox(dev, mailbox);
365 return ret;
366}
367
368/* IF a steering entry contains only promisc QPs, it can be removed. */
369static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
370 enum mlx4_steer_type steer,
371 unsigned int index, u32 tqpn)
372{
373 struct mlx4_steer *s_steer;
374 struct mlx4_steer_index *entry = NULL, *tmp_entry;
375 u32 members_count;
376 bool ret = false;
377
378 if (port < 1 || port > dev->caps.num_ports)
379 return NULL;
380
381 s_steer = &mlx4_priv(dev)->steer[port - 1];
382
383 if (!promisc_steering_entry(dev, port, steer, index,
384 tqpn, &members_count))
385 goto out;
386
387 /* All the qps currently registered for this entry are promiscuous,
362 * Checking for duplicates */ 388 * Checking for duplicates */
363 ret = true; 389 ret = true;
364 list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) { 390 list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
@@ -387,7 +413,6 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
387 } 413 }
388 414
389out: 415out:
390 mlx4_free_cmd_mailbox(dev, mailbox);
391 return ret; 416 return ret;
392} 417}
393 418
@@ -528,7 +553,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
528 struct mlx4_steer *s_steer; 553 struct mlx4_steer *s_steer;
529 struct mlx4_cmd_mailbox *mailbox; 554 struct mlx4_cmd_mailbox *mailbox;
530 struct mlx4_mgm *mgm; 555 struct mlx4_mgm *mgm;
531 struct mlx4_steer_index *entry; 556 struct mlx4_steer_index *entry, *tmp_entry;
532 struct mlx4_promisc_qp *pqp; 557 struct mlx4_promisc_qp *pqp;
533 struct mlx4_promisc_qp *dqp; 558 struct mlx4_promisc_qp *dqp;
534 u32 members_count; 559 u32 members_count;
@@ -572,10 +597,10 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
572 goto out_mailbox; 597 goto out_mailbox;
573 598
574 if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) { 599 if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
575 /* remove the qp from all the steering entries*/ 600 /* Remove the QP from all the steering entries */
576 list_for_each_entry(entry, 601 list_for_each_entry_safe(entry, tmp_entry,
577 &s_steer->steer_entries[steer], 602 &s_steer->steer_entries[steer],
578 list) { 603 list) {
579 found = false; 604 found = false;
580 list_for_each_entry(dqp, &entry->duplicates, list) { 605 list_for_each_entry(dqp, &entry->duplicates, list) {
581 if (dqp->qpn == qpn) { 606 if (dqp->qpn == qpn) {
@@ -600,6 +625,14 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
600 members_count = 625 members_count =
601 be32_to_cpu(mgm->members_count) & 626 be32_to_cpu(mgm->members_count) &
602 0xffffff; 627 0xffffff;
628 if (!members_count) {
629 mlx4_warn(dev, "QP %06x wasn't found in entry %x mcount=0. deleting entry...\n",
630 qpn, entry->index);
631 list_del(&entry->list);
632 kfree(entry);
633 continue;
634 }
635
603 for (i = 0; i < members_count; ++i) 636 for (i = 0; i < members_count; ++i)
604 if ((be32_to_cpu(mgm->qp[i]) & 637 if ((be32_to_cpu(mgm->qp[i]) &
605 MGM_QPN_MASK) == qpn) { 638 MGM_QPN_MASK) == qpn) {
@@ -614,7 +647,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
614 goto out_mailbox; 647 goto out_mailbox;
615 } 648 }
616 649
617 /* copy the last QP in this MGM 650 /* Copy the last QP in this MGM
618 * over removed QP 651 * over removed QP
619 */ 652 */
620 mgm->qp[loc] = mgm->qp[members_count - 1]; 653 mgm->qp[loc] = mgm->qp[members_count - 1];
@@ -1144,10 +1177,13 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
1144 goto out; 1177 goto out;
1145 } 1178 }
1146 1179
1147 /* if this pq is also a promisc qp, it shouldn't be removed */ 1180 /* If this QP is also a promisc QP, it shouldn't be removed only if
1181 * at least one none promisc QP is also attached to this MCG
1182 */
1148 if (prot == MLX4_PROT_ETH && 1183 if (prot == MLX4_PROT_ETH &&
1149 check_duplicate_entry(dev, port, steer, index, qp->qpn)) 1184 check_duplicate_entry(dev, port, steer, index, qp->qpn) &&
1150 goto out; 1185 !promisc_steering_entry(dev, port, steer, index, qp->qpn, NULL))
1186 goto out;
1151 1187
1152 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 1188 members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
1153 for (i = 0; i < members_count; ++i) 1189 for (i = 0; i < members_count; ++i)