Skip to content

Commit

Permalink
IB/mthca: multiple fixes for multicast group handling
Browse files Browse the repository at this point in the history
Multicast group management fixes:
. Fix leak of mailbox memory in error handling on multicast group operations.
. Free AMGM indices at detach and in attach error handling.
. Fix amount to shift for aligning next_gid_index in mailbox: it
  starts at bit 6, not bit 5.
. Allocate AMGM index after end of MGM table, in the range num_mgms to
  multicast table size - 1. Add some BUG_ON checks to catch cases
  where the index falls in the MGM hash area.
. Initialize the list of QPs in a newly-allocated group from AMGM to 0
  This is necessary since when a group is moved from AMGM to MGM (in the
  case where the MGM entry has been emptied of QPs), the AMGM entry is
  not reset to 0 (and we don't want an extra command to do that).

Signed-off-by: Jack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Jack Morgenstein authored and Roland Dreier committed Jan 6, 2006
1 parent 0d3b525 commit 5ceb745
Showing 1 changed file with 35 additions and 19 deletions.
54 changes: 35 additions & 19 deletions drivers/infiniband/hw/mthca/mthca_mcg.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ static int find_mgm(struct mthca_dev *dev,
goto out;
if (status) {
mthca_err(dev, "READ_MGM returned status %02x\n", status);
return -EINVAL;
err = -EINVAL;
goto out;
}

if (!memcmp(mgm->gid, zero_gid, 16)) {
Expand All @@ -126,7 +127,7 @@ static int find_mgm(struct mthca_dev *dev,
goto out;

*prev = *index;
*index = be32_to_cpu(mgm->next_gid_index) >> 5;
*index = be32_to_cpu(mgm->next_gid_index) >> 6;
} while (*index);

*index = -1;
Expand All @@ -153,8 +154,10 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;

if (down_interruptible(&dev->mcg_table.sem))
return -EINTR;
if (down_interruptible(&dev->mcg_table.sem)) {
err = -EINTR;
goto err_sem;
}

err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
Expand All @@ -181,9 +184,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}

memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid->raw, 16);
mgm->next_gid_index = 0;
}

for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
Expand All @@ -209,6 +211,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (status) {
mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
err = -EINVAL;
goto out;
}

if (!link)
Expand All @@ -223,7 +226,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}

mgm->next_gid_index = cpu_to_be32(index << 5);
mgm->next_gid_index = cpu_to_be32(index << 6);

err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
Expand All @@ -234,7 +237,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
}

out:
if (err && link && index != -1) {
BUG_ON(index < dev->limits.num_mgms);
mthca_free(&dev->mcg_table.alloc, index);
}
up(&dev->mcg_table.sem);
err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}
Expand All @@ -255,8 +263,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;

if (down_interruptible(&dev->mcg_table.sem))
return -EINTR;
if (down_interruptible(&dev->mcg_table.sem)) {
err = -EINTR;
goto err_sem;
}

err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
Expand Down Expand Up @@ -305,13 +315,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (i != 1)
goto out;

goto out;

if (prev == -1) {
/* Remove entry from MGM */
if (be32_to_cpu(mgm->next_gid_index) >> 5) {
err = mthca_READ_MGM(dev,
be32_to_cpu(mgm->next_gid_index) >> 5,
int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
if (amgm_index_to_free) {
err = mthca_READ_MGM(dev, amgm_index_to_free,
mailbox, &status);
if (err)
goto out;
Expand All @@ -332,9 +340,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
if (amgm_index_to_free) {
BUG_ON(amgm_index_to_free < dev->limits.num_mgms);
mthca_free(&dev->mcg_table.alloc, amgm_index_to_free);
}
} else {
/* Remove entry from AMGM */
index = be32_to_cpu(mgm->next_gid_index) >> 5;
int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
err = mthca_READ_MGM(dev, prev, mailbox, &status);
if (err)
goto out;
Expand All @@ -344,7 +356,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}

mgm->next_gid_index = cpu_to_be32(index << 5);
mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);

err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
Expand All @@ -354,22 +366,26 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
BUG_ON(index < dev->limits.num_mgms);
mthca_free(&dev->mcg_table.alloc, index);
}

out:
up(&dev->mcg_table.sem);
err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}

int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
{
int err;
int table_size = dev->limits.num_mgms + dev->limits.num_amgms;

err = mthca_alloc_init(&dev->mcg_table.alloc,
dev->limits.num_amgms,
dev->limits.num_amgms - 1,
0);
table_size,
table_size - 1,
dev->limits.num_mgms);
if (err)
return err;

Expand Down

0 comments on commit 5ceb745

Please sign in to comment.