aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2014-11-19 04:08:58 -0500
committerRoland Dreier <roland@purestorage.com>2014-12-15 21:10:13 -0500
commit514f3ddffe7c366af7921fdddaae3811e3efce03 (patch)
tree5f158d4b840b917060e26115b46c01895aff735b /drivers/infiniband/core
parentc1bd6cde8efda081af9d4f1fa4105e114b9b5cf5 (diff)
IB/core: Fix mgid key handling in SA agent multicast data-base
Applications can request that the SM assign an MGID by passing a mcast member request containing MGID = 0. When the SM responds by sending the allocated MGID, this MGID replaces the 0-MGID in the multicast group. However, the MGID field in the group is also the key field in the IB core multicast code rbtree containing the multicast groups for the port. Since this is a key field, correct handling requires that the group entry be deleted from the rbtree and then re-inserted with the new key, so that the table structure is properly maintained. The current code does not do this correctly. Correct operation requires that if the key-field gid has changed at all, it should be deleted and re-inserted. Note that when inserting, if the new MGID is zero (not the case here but the code should handle this correctly), we allow duplicate entries for 0-MGIDs. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Acked-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r--drivers/infiniband/core/multicast.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index d2360a8ef0b2..fa17b552ff78 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -525,17 +525,22 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
525 if (status) 525 if (status)
526 process_join_error(group, status); 526 process_join_error(group, status);
527 else { 527 else {
528 int mgids_changed, is_mgid0;
528 ib_find_pkey(group->port->dev->device, group->port->port_num, 529 ib_find_pkey(group->port->dev->device, group->port->port_num,
529 be16_to_cpu(rec->pkey), &pkey_index); 530 be16_to_cpu(rec->pkey), &pkey_index);
530 531
531 spin_lock_irq(&group->port->lock); 532 spin_lock_irq(&group->port->lock);
532 group->rec = *rec;
533 if (group->state == MCAST_BUSY && 533 if (group->state == MCAST_BUSY &&
534 group->pkey_index == MCAST_INVALID_PKEY_INDEX) 534 group->pkey_index == MCAST_INVALID_PKEY_INDEX)
535 group->pkey_index = pkey_index; 535 group->pkey_index = pkey_index;
536 if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) { 536 mgids_changed = memcmp(&rec->mgid, &group->rec.mgid,
537 sizeof(group->rec.mgid));
538 group->rec = *rec;
539 if (mgids_changed) {
537 rb_erase(&group->node, &group->port->table); 540 rb_erase(&group->node, &group->port->table);
538 mcast_insert(group->port, group, 1); 541 is_mgid0 = !memcmp(&mgid0, &group->rec.mgid,
542 sizeof(mgid0));
543 mcast_insert(group->port, group, is_mgid0);
539 } 544 }
540 spin_unlock_irq(&group->port->lock); 545 spin_unlock_irq(&group->port->lock);
541 } 546 }